27 / 41 / 13
Регистрация: 15.05.2013
Сообщений: 1,313
1

На эмуляторе работает, а в смартфоне нет

07.05.2014, 15:03. Показов 3658. Ответов 5
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Подскажите, в чём ошибка?
В android sdk работает, а в смарте нет.
А должен просто появится один символ на экране, и переместиться слева на право.
Смартфон почему-то зависает, начинает тормозить
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.SurfaceView;
import android.view.SurfaceHolder;
import android.widget.TextView;
import android.graphics.*;
 
public class MainSurface extends Activity{
    
    MySurface mysurface;
    
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        mysurface = new MySurface(this);
        setContentView(mysurface);
    }
    
    public void onResume(){
        super.onResume();
        mysurface.onResume();
    }
    
    public class MySurface extends SurfaceView{
        
        SurfaceHolder holder;
        Thread thread;
        TextView txt;
        Paint pt;
        boolean running;
        int x,y;
        
        MySurface(Context context){
            super(context);
            holder = getHolder();
            txt = new TextView(context);
            pt = new Paint();
            x = 10; y = 100;
        }
        
        public void onResume(){
            thread = new Thread(mrun);
            thread.start();
            running = true;
        }
        
        Runnable mrun = new Runnable() {
            public void run() {
                pt.setColor(Color.GREEN);
                while (running) {
                    Canvas canv = null;
                    canv = holder.lockCanvas();
                    if (canv == null)
                        continue;
                    canv.drawRGB(0, 0, 0);
                    canv.drawText("O", x, y, pt);
                    x += 10;
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {}
 
                    holder.unlockCanvasAndPost(canv);
                }
            }
        };
    }
    
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
07.05.2014, 15:03
Ответы с готовыми решениями:

Сравнение координат: на эмуляторе - работает, на устройстве - нет
Добрый день. запускаю на эмуляторе - он считывает мои координаты. посылаю через эмулятор новые...

Нет приложения в эмуляторе
Привет. Такая проблема: создал пустое приложение Android, но когда начинаю отладку, то запускается...

Xamarin, приложение устанавливается на телефон, но не работает, хотя работает на эмуляторе
Приложения не запускаются на телефоне, хотя в эмуляторе работают нормально. а манифесте по версиям...

Netbeans: приложения нет в эмуляторе
Вот такая проблема: Работаю в Netbeans. Эмулятор запускается нормально, но созданного приложения...

5
2343 / 499 / 22
Регистрация: 01.04.2009
Сообщений: 2,200
07.05.2014, 15:55 2
Поток создаётся в OnResume и нигде не убивается.
Грубо говоря, получив десяток OnResume, Activity создает десяток потоков, которые одновременно пытаются что-то делать.

Обычно запуск потока ставят в surfaceCreated, а убийство - в surfaceDestroyed.
0
27 / 41 / 13
Регистрация: 15.05.2013
Сообщений: 1,313
07.05.2014, 20:58  [ТС] 3
Цитата Сообщение от Patch Посмотреть сообщение
Грубо говоря, получив десяток OnResume, Activity создает десяток потоков
это если несколько раз запустить приложение, и несколько раз с ним что-то делать: например сворачивать и разворачивать, тогда OnResume запустится несколько раз!
А тут прога сразу глючит, при первом запуске и перемещение символа не отображается
0
2343 / 499 / 22
Регистрация: 01.04.2009
Сообщений: 2,200
07.05.2014, 21:23 4
Да я что-то не вижу, чтобы ты его на весь экран развернул.
А это значит, что служебная часть экрана - та, где, антивирусы и подключение к вай-фаю отображаются, еще как могут захватывать экран.
Упс!
Вот так вот.
Загрузил в телефон приложение, антивирус его поставил на паузу, проверил и сообщил об этом... и возобновил. И пошло у тебя ДВА потока, конкурирующих за экран.

Делай по-человечески.
1
27 / 41 / 13
Регистрация: 15.05.2013
Сообщений: 1,313
07.05.2014, 23:18  [ТС] 5
Цитата Сообщение от Patch Посмотреть сообщение
Делай по-человечески
научусь, конечно буду делать! Тем более если так настаиваеш.
А пока у меня опыта нет.

Кстати я добавил метод onResume и onDestroy, теперь приложение то работает, то нет.
Т.е. если несколько раз позапускать прогу, то бывает показывает перемещающийся символ, а бывает глючит, и даже кнопка назад не работает!
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
public class MainActivity extends Activity{
    
    MySurface mysurface;
    
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                             WindowManager.LayoutParams.FLAG_FULLSCREEN);
        
        mysurface = new MySurface(this);
        setContentView(mysurface);
    }
    
    public void onResume(){
        super.onResume();
        mysurface.resume();
    }
 
    @Override
    protected void onPause()
    {
        // TODO: Implement this method
        super.onPause();
        mysurface.pause();
        
    }
 
    @Override
    protected void onDestroy()
    {
        // TODO: Implement this method
        super.onDestroy();
        mysurface.destroy();
    }
    
    
 
 
    public class MySurface extends SurfaceView
{
          //  implements Runnable{
        
        SurfaceHolder holder;
        Thread thread;
        TextView txt;
        Paint pt;
        boolean running;
        int x,y;
        
        MySurface(Context context){
            super(context);
            holder = getHolder();
            txt = new TextView(context);
            pt = new Paint();
            x = 10; y = 100;
        }
        
        public void resume(){
            thread = new Thread(mrun);
            thread.start();
            running = true;
        }
        
        public void pause(){
            running = false;
        }
        
        public void destroy(){
            running = false;
            thread.interrupt();
        }
        
        Runnable mrun = new Runnable() {
            public void run() {
                pt.setColor(Color.GREEN);
                while (running) {
                    if(!holder.getSurface().isValid())
                        continue;         
                    Canvas canv = null;
                    canv = holder.lockCanvas();
                    if (canv == null)
                        continue;
                    canv.drawRGB(0, 0, 0);
                    canv.drawText("O", x, y, pt);
                    x += 10;
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {}
 
                    //if(canv != null)
                        holder.unlockCanvasAndPost(canv);
                }
            }
        };
    }
    
}
0
2343 / 499 / 22
Регистрация: 01.04.2009
Сообщений: 2,200
08.05.2014, 08:33 6
Цитата Сообщение от phpk Посмотреть сообщение
Кстати я добавил метод onResume и onDestroy, теперь приложение то работает, то нет.
Молодец.

И вот прикинь, как оно теперь работает:
Стартует Activity.
Срабатывает Activity.onCreate(): создается SurfaceView()
Срабатывает SurfaceView.surfaceCreated()
Срабатывает Activity.OnStart()
Срабатывает Activity.OnResume() - вызывает SurfaceView.resume(): создаётся второй поток
Запускается процедура run() второго потока, и в половине случаев тут-же выходит, поскольку переменная running на этот момент еще НЕ ИНИЦИАЛИЗИРОВАНА и находиться в хрен-знает-каком состоянии - и цикл обработки может вообще не запуститься
Затем в SurfaceView.resume() срабатывает running = true; но уже поздно - второй поток, скорее всего, уже закрылся.

Если тебе повезло, и поток вошел в цикл - срабатывает любой случайный чих на экран.
От активности сервисов, до случайного взмаха рукой, да мало ли от чего...
У меня вот смартфон беситься начинает, если рядом с ним на зарядке старый телефон лежит.
Ток в проводе зарядки воспринимается иногда как нажатия и жесты.

При этом
Срабатывает Activity.OnPause() - вызывает SurfaceView.pause()
А там - running = false;
Но поток-то никуда не делся.
Снова срабатывает Activity.OnResume() - вызывает SurfaceView.resume()
Создаётся третий поток, в котором тоже running в хрен-знает-каком состоянии.

И вот ты пытаешься всю эту фигню закрыть и тут...
Срабатывает Activity.OnDestroy() - вызывает SurfaceView.destroy()
А в нем:
Java
1
2
 running = false;
            thread.interrupt();
Прям вот так и написано.

Прикинь просто:
вот сделал ты running = false;
А в этот момент твой второй поток что-то там рисовал на экране
отрабатывал canv.drawRGB(0, 0, 0), например.
Не может он мгновенно завершиться и до проверки условия while (running) дойти - ему дорисовать надо, да еще и твое Thread.sleep(100) в конце отработать.
А тут ты ему такой бац!! thread.interrupt()
И экран твоего девайса зависает нафиг, просто потому, что канва захвачена потоком, который что-то там рисовал, а ты это поток уже убил к чертовой матери.
И как рисовать что-то твой андроид уже не знает - получить канву экрана он не может, и освободить ее некому.

Вот такую вот фигню ты написал.

А по-человечески это будет примерно так:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
public class MySurface extends SurfaceView {
 
    private SurfaceHolder holder;
    private Thread gameLoopThread;
    private TextView txt;
    private Paint pt;
    boolean running;
    int x,y;
    
    Runnable mrun = new Runnable() {
      public void run() {
    long ticksPS = 1000 / 20; //установка отрисовки на 20 кадров в секунду
    long startTime;
    long sleepTime;
   
    while (running) {
           Canvas c = null;
           startTime = System.currentTimeMillis();
                        try { 
                          c = getHolder().lockCanvas();
                          synchronized (getHolder()) {
                              c.drawRGB(0, 0, 0);
                                c.drawText("O", x, y, pt);
                                x += 10;
                  }
           } finally {
                  if (c != null) {
                         getHolder().unlockCanvasAndPost(c);
                  }
           }
           sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
           try {
                  if (sleepTime > 0)
                    Thread.sleep(sleepTime);
                  else
                    Thread.sleep(10);
           } catch (Exception e) {}
        }
      }
      
  };
 
 
    public MySurface(Context context) {
        
            super(context);
            txt = new TextView(context);
            pt = new Paint();
            x = 10; y = 100;
          gameLoopThread = new Thread(mrun);
          holder = getHolder();
          holder.addCallback(new SurfaceHolder.Callback() {
 
                 @Override
                 public void surfaceDestroyed(SurfaceHolder holder) {
                        boolean retry = true;
                        running = false;
                        while (retry) {
                               try {
                                     gameLoopThread.join();
                                     retry = false;
                               } catch (InterruptedException e) {
                               }
                        }
                 }
 
                 @Override
                 public void surfaceCreated(SurfaceHolder holder) {
                        running = true;
                        gameLoopThread.start();
 
                 }
 
                 @Override
                 public void surfaceChanged(SurfaceHolder holder, int format,
                               int width, int height) {
                 }
          });
         
         
}
}
Правильность всех запятых и прочего не проверял - главное, чтобы ты понял идею верного построения приложения.
По-хорошему, поток надо вообще в отдельный класс вынести.
1
08.05.2014, 08:33
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
08.05.2014, 08:33
Помогаю со студенческими работами здесь

Нет ярлыка приложения в эмуляторе
Здравствуйте. Абсолютный новичок в android разработке, но не новичок в разработке вообще. Установил...

RSS-читалка - работает на эмуляторе, не работает на реальном девайсе
День добрый. Есть несложная читалка на основе вот этой вот, для парсинга используется Android SAX....

eclipsе (в эмуляторе нет моей программы)
Здравствуйте! Поставил эклипс по след схеме: 1)скачать классик с офф сайта 2)через прогу поставил...

Почему нет кнопок навигации в эмуляторе?
Android Studio, только что установил, новый стандартный проект, первый запуск. При компиляции...

Работает wi-fi на ноуте но не работает на смартфоне lg p970
Доброго времени суток проблема следующая, есть модем 4 портовый tenda w548d, интернет работает как...

Не работает флешка в смартфоне
Имеется подопытный смартфон Samsung Galaxy Fame 6810 с версией Android 4.1.2. Вставил флешку...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru