我正在运行一个屏幕保护程序活动,一个小动画。当用户触摸屏幕时,他们将移至我的MainActivity。为此,我重写了方法“ onUserInteraction()”。如果您不熟悉,只要触摸设备的屏幕或其按钮,即可触发此方法。
每次点击屏幕都会成功进入主要活动。但是,如果按“后退”按钮或“音量”按钮,则会发生以下一系列事件。
在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()被调用。它对我来说值得注意的唯一原因是,我的布尔值更新实际上是在更新Singleton类中的静态变量,该类用于后台服务和其他一些类中的弹出式管理。否则,它可能不会引起注意。
编辑(2019年3月22日)
用于MainActivity的Android清单
<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);
}
}
答案 0 :(得分:0)
如果您不小心使用onUserInteraction()函数,可能会导致一些问题。在KeyDown和KeyUp事件期间,按一个按钮实际上将两次触发该方法。如果使用此方法开始活动,则点击屏幕将正常工作。但是,按一个键将调用该方法两次,并尝试同时启动两次活动。
当同时启动两个活动时,android会识别出该错误并杀死其中一个克隆。如日志所示,第一个实例将被清除,但要等到第二个实例完全创建并具有窗口焦点之后,才能清除。因此,在onCreate()之后,我能够看到在启动的活动中调用了onDestroy()。