我通过花费5分钟创建一个包含两个“Hello World”活动的简单应用程序来证明这个问题.
>应用程序以活动A开始,活动A只显示一个名为“启动B”的按钮(没有别的).
>按此按钮 – 执行startActivity(FLAG_ACTIVITY_REORDER_TO_FRONT,ActivityB.class).
>活动B变为活动状态,只显示一个名为“启动A”的按钮.
>按此按钮 – 执行startActivity(FLAG_ACTIVITY_REORDER_TO_FRONT,ActivityA.class).
> Activity A的onResume()按预期调用,一切看起来都很好(我再次看到Activity A内容).
>按设备的返回键,这组错误将在100%的时间内发生:
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 }
(从用户的角度来看,窗口死亡的实际结果本质上是“崩溃” – Android会将用户从应用程序中抛回主屏幕,尽管技术上应用程序仍然在后台运行.)
我调试了这个并发现Activity A可见但没有焦点的原因是因为活动A的onWindowFocusChanged()没有像通常那样调用(即使调用onResume()).这与活动B在后台仍处于活动状态的事实有关(即使B已经失去焦点 – 为B调用onWindowFocusChanged(false),以及onStop()).我知道这是因为在上面的第4步之后如果我立即调用活动B上的finish(),将调用活动A的onWindowFocusChanged(true)并且一切正常.活动B仍然活跃但不集中的事实干扰了活动A重新获得焦点.这是一个Android错误还是我错过了什么?
请注意,如果活动A中有多个视图,并且我在上面的步骤6之后触摸其中一个视图,我会得到相同的“由于没有窗口焦点而丢弃事件”错误,尽管由于某种原因不是100%的时间.
解决方法
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); } } }
这还需要AndroidManifest.xml中的权限
<uses-permission android:name="android.permission.REORDER_TASKS" />
我在Espresso测试中遇到这个问题实际上遇到了这样的错误:
java.lang.RuntimeException:等待视图层次结构的根目录具有窗口焦点,而不是请求布局超过10秒.如果您指定了非默认根匹配器,则可能会选择一个永远不会成为焦点的根.否则,有些事情是严重错误的.