Форум программистов, компьютерный форум, киберфорум
Наши страницы
Программирование Android
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.86/7: Рейтинг темы: голосов - 7, средняя оценка - 4.86
phpk
26 / 29 / 13
Регистрация: 15.05.2013
Сообщений: 1,152
#1

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

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

Подскажите, в чём ошибка?
В 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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.05.2014, 15:03
Ответы с готовыми решениями:

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

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

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

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

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

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

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

Делай по-человечески.
1
phpk
26 / 29 / 13
Регистрация: 15.05.2013
Сообщений: 1,152
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
Patch
2336 / 492 / 22
Регистрация: 01.04.2009
Сообщений: 2,181
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
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.05.2014, 08:33

Layout-large не работает в эмуляторе
Использую стандартный эмулятор который шел в Android Studio, создал доп папки...

OpenGL ES 2.0 Шейдер работает только на эмуляторе
Здравствуйте! Возникла проблема с шейдером "тайлинг с отражением". На...

Приложение работает на эмуляторе но вылетает на телефоне
Происходит такая ошибка: При тестировании приложении на эмуляторе, все...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru