使用FLAG_ACTIVITY_REORDER_TO_FRONT在永久运行的UI活动之间切换导致“无窗焦点”错误 [英] Using FLAG_ACTIVITY_REORDER_TO_FRONT to switch among persistently running UI activities leads to "no window focus" error
问题描述
我用5分钟的时间用两个Hello World活动创建了一个简单的应用程序,证明了这个问题。
$ b
- 应用程序从Activity A开始,它只是显示一个按钮(没有别的),叫做Launch B。
- 按下这个按钮 - 执行
startActivity(FLAG_ACTIVITY_REORDER_TO_FRONT,ActivityB .class)。
- 活动B变为活动状态,显示一个名为Launch A的按钮。按下此按钮 - 执行
startActivity(FLAG_ACTIVITY_REORDER_TO_FRONT,ActivityA.class)。
- 活动A的
onResume )
按预期的方式调用,一切都很正常(我可以再次看到Activity A的内容)。
- 按下设备的Back键,错误将发生在100%的时间:
lockquote
E / ActivityManager(513):原因:输入调度超时(等待
,因为没有窗口有焦点,但有一个专注的应用程序
最终可能会在完成启动时添加一个窗口。)
I / WindowState(513):WIN DEATH:窗口{5294687c u0
com.android.launcher / com.android.launcher2.Launcher}
ViewRootImpl(8066):由于没有窗口焦点而丢失事件:
KeyEvent {action = ACTION_DOWN,keyCode = KEYCODE_BACK,scanCode = 0,
metaState = 0,flags = 0xc8, repeatCount = 1,eventTime = 14965546,
downTime = 14965045,deviceId = -1,source = 0x101}
从用户的角度来看,窗口死亡的实际结果本质上是一个崩溃 - Android将用户从应用程序抛出回主屏幕,尽管技术上应用程序仍然在后台运行。
我调试了这个,发现Activity A是可见的,但没有焦点的原因是因为Activity A的 onWindowFocusChanged()不叫就像通常那样(即使调用onResume())。 这与事实有关,即活动B在后台仍处于活动状态(尽管B明显失去了重点 - 为B调用了onWindowFocusChanged(false),以及onStop()) 。 我知道这是因为在步骤4之后,如果我立即在Activity B上调用finish(),则将调用Activity A的onWindowFocusChanged(true),并且一切正常。事件B仍然是活动的,但不是集中在某种程度上会干扰活动A重新获得应有的焦点。这是一个Android的错误,或者我错过了什么?
请注意,如果活动A有多个视图,并在上面的步骤6后触摸其中一个视图,我会得到相同的由于没有窗口焦点的下降事件的错误,虽然不是100%的时间出于某种原因。 中提供的解决方法 详细信息?id = 63570#c15rel =nofollow> https://code.google.com/p/android/issues/detail?id=63570#c15 对我来说很好,可以解决问题活动没有得到窗口焦点:$ b
$ b pre $保护无效的onNewIntent(意图意图){
super.onNewIntent(intent); ((intent.getFlags()| Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)> 0){
if(android.os.Build.VERSION.SDK_INT> = 19&&!isTaskRoot()) {
ActivityManager tasksManager =(ActivityManager)getSystemService(ACTIVITY_SERVICE);
tasksManager.moveTaskToFront(getTaskId(),ActivityManager.MOVE_TASK_NO_USER_ACTION);
这也需要权限
AndroidManifest.xml
< uses-permission android:name = android.permission.REORDER_TASKS/>
我在
Espresso
测试得到这样的错误:
$ bjava.lang.RuntimeException:等待视图层次结构的根具有窗口焦点,而不是请求布局超过10秒。如果你指定了一个非默认的根匹配器,它可能会选择一个永远不会关注的根。否则,一些事情是严重错误的。
My objective is to keep two UI activities alive and to switch back and forth between them at will without having to kill/restart either of them. But there is a serious side effect of using FLAG_ACTIVITY_REORDER_TO_FRONT to do this: a loss of window focus when I resume a previous activity (that is currently running in the background).
I proved this issue by spending 5 minutes creating a simple application with two "Hello World" activities.
- The app starts with Activity A, which simply shows a button (nothing else) called "Launch B".
- Press this button -- this executes
startActivity(FLAG_ACTIVITY_REORDER_TO_FRONT, ActivityB.class).
- Activity B becomes active, which shows simply shows a button called "Launch A".
- Press this button -- this executes
startActivity(FLAG_ACTIVITY_REORDER_TO_FRONT, ActivityA.class).
- Activity A's
onResume()
is called as expected and everything looks fine (I can see Activity A content again). - Press the device's Back key and this set of errors will occur 100% of the time:
E/ActivityManager( 513): Reason: Input dispatching timed out (Waiting because no window has focus but there is a focused application that may eventually add a window when it finishes starting up.)
I/WindowState( 513): WIN DEATH: Window{5294687c u0 com.android.launcher/com.android.launcher2.Launcher}
W/ViewRootImpl( 8066): Dropping event due to no window focus: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_BACK, scanCode=0, metaState=0, flags=0xc8, repeatCount=1, eventTime=14965546, downTime=14965045, deviceId=-1, source=0x101 }
(The practical result of the window death is essentially a "crash" from the user's point of view -- Android throws the user out of the app back to the Home screen, though technically the application remains running in the background.)
I debugged this and found that the reason Activity A is visible but doesn't have focus is because activity A's onWindowFocusChanged() is NOT called like it normally does (even though onResume() is called). This has something to do with the fact with Activity B is still active in the background (even though clearly B has lost focus -- onWindowFocusChanged(false) was called for B, as well as onStop()). I know this because after step 4 above if I immediately call finish() on Activity B, Activity A's onWindowFocusChanged(true) WILL be called and everything is normal. The fact that Activity B is still active but not focused somehow interferes with Activity A regaining focus like it should. Is this an Android bug or am I missing something?
Note that if Activity A had multiple views in it and I were to touch one of those views after step 6 above, I would get the same "Dropping event due to no window focus" error, though not 100% of the time for some reason.
解决方案The workaround provided in https://code.google.com/p/android/issues/detail?id=63570#c15 worked pretty well for me to resolve the issue of Activity not getting window focus:
protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if ((intent.getFlags() | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) > 0) { if (android.os.Build.VERSION.SDK_INT >= 19 && !isTaskRoot()) { ActivityManager tasksManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); tasksManager.moveTaskToFront(getTaskId(), ActivityManager.MOVE_TASK_NO_USER_ACTION); } } }
This will also need the permission in
AndroidManifest.xml
<uses-permission android:name="android.permission.REORDER_TASKS" />
I actually run into this issue in
Espresso
test getting such error:java.lang.RuntimeException: Waited for the root of the view hierarchy to have window focus and not be requesting layout for over 10 seconds. If you specified a non default root matcher, it may be picking a root that never takes focus. Otherwise, something is seriously wrong.
这篇关于使用FLAG_ACTIVITY_REORDER_TO_FRONT在永久运行的UI活动之间切换导致“无窗焦点”错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!