Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
phpk
25 / 25 / 6
Регистрация: 15.05.2013
Сообщений: 1,005
07.05.2014, 15:03     На эмуляторе работает, а в смартфоне нет #1
Подскажите, в чём ошибка?
В 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);
                }
            }
        };
    }
    
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.05.2014, 15:03     На эмуляторе работает, а в смартфоне нет
Посмотрите здесь:

Android eclipsе (в эмуляторе нет моей программы)
Netbeans: приложения нет в эмуляторе Android
Нужно ли что - нибуть устанавливать на смартфоне для запуска Native Activity? Android
Android VideoView на эмуляторе
Приложение в телефоне работает корректно только в эмуляторе Android
Запуск другой активности работает на 2.3.3, а на 4.2.2 нет Android
Вспышка на смартфоне Android
Android OpenGL ES 2.0 Шейдер работает только на эмуляторе
Почему нет кнопок навигации в эмуляторе? Android
Android Отображение программы в эмуляторе
Android Layout-large не работает в эмуляторе
DPI в эмуляторе Android

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

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Patch
2276 / 491 / 11
Регистрация: 01.04.2009
Сообщений: 2,178
07.05.2014, 15:55     На эмуляторе работает, а в смартфоне нет #2
Поток создаётся в OnResume и нигде не убивается.
Грубо говоря, получив десяток OnResume, Activity создает десяток потоков, которые одновременно пытаются что-то делать.

Обычно запуск потока ставят в surfaceCreated, а убийство - в surfaceDestroyed.
phpk
25 / 25 / 6
Регистрация: 15.05.2013
Сообщений: 1,005
07.05.2014, 20:58  [ТС]     На эмуляторе работает, а в смартфоне нет #3
Цитата Сообщение от Patch Посмотреть сообщение
Грубо говоря, получив десяток OnResume, Activity создает десяток потоков
это если несколько раз запустить приложение, и несколько раз с ним что-то делать: например сворачивать и разворачивать, тогда OnResume запустится несколько раз!
А тут прога сразу глючит, при первом запуске и перемещение символа не отображается
Patch
2276 / 491 / 11
Регистрация: 01.04.2009
Сообщений: 2,178
07.05.2014, 21:23     На эмуляторе работает, а в смартфоне нет #4
Да я что-то не вижу, чтобы ты его на весь экран развернул.
А это значит, что служебная часть экрана - та, где, антивирусы и подключение к вай-фаю отображаются, еще как могут захватывать экран.
Упс!
Вот так вот.
Загрузил в телефон приложение, антивирус его поставил на паузу, проверил и сообщил об этом... и возобновил. И пошло у тебя ДВА потока, конкурирующих за экран.

Делай по-человечески.
phpk
25 / 25 / 6
Регистрация: 15.05.2013
Сообщений: 1,005
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);
                }
            }
        };
    }
    
}
Patch
2276 / 491 / 11
Регистрация: 01.04.2009
Сообщений: 2,178
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) {
                 }
          });
         
         
}
}
Правильность всех запятых и прочего не проверял - главное, чтобы ты понял идею верного построения приложения.
По-хорошему, поток надо вообще в отдельный класс вынести.
Yandex
Объявления
08.05.2014, 08:33     На эмуляторе работает, а в смартфоне нет
Ответ Создать тему
Опции темы

Текущее время: 09:39. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru