У меня работает скринсейвер, небольшая анимация. Когда пользователь прикасается к экрану, он перемещается в мой MainActivity. Для этого я переопределяю метод "onUserInteraction ()". Если вы не знакомы, любое физическое прикосновение к экрану устройства или к его кнопкам вызывает этот метод.
Нажатие на экран каждый раз успешно переводит меня на основную деятельность. Однако, если я нажму кнопку «Назад» или «Громкость», я получу серию событий ниже.
- OnCreate ()
- onResume ()
- OnPause ()
- OnCreate ()
- onResume ()
- onWindowFocusChanged ()
- OnStop ()
- OnDestroy ()
В onCreate () и onResume () я устанавливаю логическое значение true. В onPause () и onDestroy () логическое значение имеет значение false. Итак, у меня есть серьезная проблема, когда onDestroy () вызывается последним. В то же время я могу установить, что мой логический параметр должен изменяться только во время onPause (), так как он вызывается каждый раз, когда я меняю экраны, но эта проблема все еще беспокоит меня.
В моем Logcat, перед вызовом onDestroy (), я вижу следующую строку:
[MainActivity] Surface release
MainActivity в моем манифесте:
<activity
android:name=".MainActivity"
android:screenOrientation="sensorLandscape" />
Я указал выше, когда читал (где-то), что изменение запрошенной ориентации внутри onCreate () может вызвать мою проблему. Тем не менее, я добавляю флаги:
protected void onCreate(Bundle savedInstanceState){
getWindow.addFlags(WindowManager.LayaoutParams.FLAG_TURN_SCREEN_ON);
getWindow.addFlags(WindowManager.LayaoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_main);
// other code...
}
Что мне действительно смешно, так это то, что у меня нет проблем при вызове onDestroy (). Все кнопки работают правильно, пункты меню, таймеры, фоновые сервисы. Кроме того, что это «уничтожает» мою логическую логику и «уничтожает» то, что я оставил от своей гордости ... на самом деле ничто не влияет. Это ошибка?
Запуск Android Studio 3.3.2 с Gradle 4.10.1
Заранее спасибо за любую помощь.
РЕДАКТИРОВАТЬ (21 марта 2019 г.)
Чтобы ответить на вопрос логической логики: у меня есть всплывающие окна, которые появляются на экране, пока пользователь находится на главном экране приложения, которое называется «MainActivity». Я также отслеживаю активность экрана-заставки - всплывающий запрос переместит пользователя на домашний экран, а затем откроет всплывающее окно.
В MainActivity.java
onCreate() - isHomeScreenActive = true;
onPause() - isHomeScreenActive = false;
onResume() - isHomeScreenActive = true;
onDestroy() - isHomeScreenActive = false; //Temporarily removed
Переход на ScreenSaver из MainActivity не является проблемой, но я добавил код на всякий случай.
public void startScreenSaverTimer(){
// Restarts the timer when method is called.
// Touch events, onResume(), onCreate() call this
if(timer != null){
timer.cancel();
}
// Start Timer
timer = new Timer();
timer.schedule(new TimerTask(){
@Override
public void run(){
finish();
Intent ScreenSaver = new Intent(this, ScreenSaver.class);
ScreenSaver.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(ScreenSaver);
}
}, 60000); //Set to 1 minute
}
По запросу я добавил «это» в свои журналы. Результаты ниже:
E/Tracker: onCreate() Boolean Value = true
E/Tracker: onCreate() called from com.x.x.MainActivity@be81228
E/Tracker: onResume() Boolean Value = true
E/Tracker: onResume() called from: com.x.x.MainActivity@be81228
E/Tracker: onPause() Boolean Value = false
E/Tracker: onPause() called from com.x.x.MainActivity@be81228
E/Tracker: onCreate() Boolean Value = true
E/Tracker: onCreate() called from com.x.x.MainActivity@d0faced
E/Tracker: onResume() Boolean Value = true
E/Tracker: onResume() called from: com.x.x.MainActivity@d0faced
E/Tracker: onWindowFocusChanged() called from com.x.x.MainActivity@d0faced
E/Tracker: onStop() called from com.x.x.MainActivity@be81228
E/Tracker: onDestroy() called from: com.x.x.MainActivity@be81228
Глядя на вышесказанное, похоже, что мы запускаем MainActivity дважды. Хороший звонок @ Дэвид Вассер. Похоже, мы на шаг ближе к решению этой проблемы.
MainActivity@be81228 (started first, gets Destroyed)
MainActivity@d0faced (started second, stays alive)
Поскольку похоже, что мы запускаем MainActivity дважды, я добавил код ScreenSaver, который запускает MainActivity.
@Override
public void onUserInteraction(){
super.onUserInteraction();
// Boolean for tracking screensaver
isScreenSaverActive = false;
if(animation != null){
if(animation.isRunning(){
animation.stop();
}
}
finish();
Intent i = new Intent(this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i)
Log.e("Tracker", "ScreenSaver onUserInteraction() starting MainActivity);
}
Лог в вышеупомянутой функции, который я только что добавил, дает нам полезную подсказку:
E/Tracker: ScreenSaver onUserInteraction starting MainActivity
E/Tracker: ScreenSaver onUserInteraction starting MainActivity
E/Tracker: onCreate() Boolean Value = true
E/Tracker: onCreate() called from com.x.x.MainActivity@bcb1a2c
E/Tracker: onResume() Boolean Value = true
E/Tracker: onResume() called from: com.x.x.MainActivity@bcb1a2c
E/Tracker: onPause() Boolean Value = false
E/Tracker: onPause() called from com.x.x.MainActivity@bcb1a2c
E/Tracker: onCreate() Boolean Value = true
E/Tracker: onCreate() called from com.x.x.MainActivity@6ad37bf
E/Tracker: onResume() Boolean Value = true
E/Tracker: onResume() called from: com.x.x.MainActivity@6ad37bf
E/Tracker: onWindowFocusChanged() called from com.x.x.MainActivity@6ad37bf
E/Tracker: onStop() called from com.x.x.MainActivity@bcb1a2c
E/Tracker: onDestroy() called from: com.x.x.MainActivity@bcb1a2c
Похоже, onUserInteraction () дважды отвечает на KeyEvent. Возможно onKeyDown () и onKeyUp (). Поэтому, конечно, я тоже это записал:
E/Tracker: ScreenSaver onUserInteraction starting MainActivity
E/Tracker: ScreenSaver onKeyDown() BACK BUTTON
E/Tracker: ScreenSaver onUserInteraction starting MainActivity
E/Tracker: ScreenSaver onKeyUp() BACK BUTTON
// Same as above for the remainder of logs
Похоже, что KeyDown / KeyUp должны быть проблемой - для кнопки назад, кнопок громкости ... и, вероятно, для просмотра карты, bixby и кнопки home, которые я даже не думал проверять.
Пока что я сделал простой обходной путь, и он работает. Однако я чувствую, что должен быть более изящный подход. Любые идеи приветствуются.
private boolean runOnce = false;
@Override
public void onUserInteraction(){
if(!runOnce){
runOnce = true;
// Start MainActivity
}
}
Итак, я предполагаю, что мораль этой истории состоит в том, что запуск одного и того же действия дважды одновременно может вызвать вызов onDestroy () после создания действия "выжившего" клона. Единственная причина, по которой это было заметно для меня, заключалась в том, что мои обновления логических значений фактически обновляли статическую переменную в классе Singleton, используемом для управления всплывающими окнами в фоновых службах и некоторых других классах. В противном случае это, вероятно, осталось бы незамеченным.
РЕДАКТИРОВАТЬ (22 марта 2019 г.)
Манифест Android для MainActivity
<activity
android:name=".MainActivity"
android:screenOrientation="sensorLandscape" />
Класс ScreenSaver, onUserInteraction ()
@Override
public void onUserInteraction(){
super.onUserInteraction();
if(!runOnce){
runOnce = true;
SingletonScreenSaverTracker.isScreenSaverActive = false;
if(animation != null){
if(animation.isRunning()){
animation.stop();
}
}
finish();
Intent i = new Intent(this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
}