我有一个屏幕保护程序正在运行,一个小动画。当用户触摸屏幕时,他们会移动到我的 MainActivity。为此,我将覆盖方法“onUserInteraction()”。如果您不熟悉,对设备屏幕或按钮的任何物理触摸都会触发此方法。
每次点击屏幕都会让我成功进入主要活动。但是,如果我按下后退按钮或音量按钮,我会收到以下一系列事件。
- onCreate()
- onResume()
- 暂停()
- onCreate()
- onResume()
- onWindowFocusChanged()
- 停止()
- 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() 时我完全没有问题。所有按钮、菜单项、计时器、后台服务都可以正常工作。除了“破坏”我的布尔逻辑和“破坏”我剩下的骄傲之外……实际上没有任何影响。这是一个错误吗?
使用 Gradle 4.10.1 运行 Android Studio 3.3.2
提前感谢您的帮助。
编辑(2019 年 3 月 21 日)
回答布尔逻辑问题:只要用户在应用程序的主屏幕上,即“MainActivity”,屏幕上就会出现弹出窗口。我还跟踪我是否在屏幕保护程序活动中 - 弹出请求会将用户移动到主屏幕,然后打开弹出窗口。
在 MainActivity.java
onCreate() - isHomeScreenActive = true;
onPause() - isHomeScreenActive = false;
onResume() - isHomeScreenActive = true;
onDestroy() - isHomeScreenActive = false; //Temporarily removed
从 MainActivity 移至 ScreenSaver 不是问题,但我在此处添加了代码以防万一。
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
}
根据要求,我在日志中添加了“this”。结果如下:
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。很好的电话@David Wasser。看起来我们离解决这个问题又近了一步。
MainActivity@be81228 (started first, gets Destroyed)
MainActivity@d0faced (started second, stays alive)
因为看起来我们要启动 MainActivity 两次,所以我添加了启动 MainActivity 的 ScreenSaver 代码。
@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 和主页按钮,我什至没有想过要测试。
现在,我做了一个简单的解决方法,它可以工作。但是,我觉得应该有一个更优雅的方法。欢迎任何想法。
private boolean runOnce = false;
@Override
public void onUserInteraction(){
if(!runOnce){
runOnce = true;
// Start MainActivity
}
}
所以,我猜这个故事的寓意是,同时启动同一个活动两次,可能会导致 onDestroy() 在“幸存”克隆活动创建后被调用。我注意到它的唯一原因是因为我的布尔值更新实际上是在更新单例类中的静态变量,用于后台服务和其他一些类中的弹出管理。否则,它可能会被忽视。
编辑(2019 年 3 月 22 日)
MainActivity 的 Android 清单
<activity
android:name=".MainActivity"
android:screenOrientation="sensorLandscape" />
屏幕保护程序类,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);
}
}