android – 使用FLAG_ACTIVITY_REORDER_TO_FRONT在持续运行的UI活动之间切换会导致“无窗口焦点”错误

我的目标是保持两个UI活动,并在它们之间来回切换,而不必杀死/重启其中任何一个.但是使用FLAG_ACTIVITY_REORDER_TO_FRONT执行此操作会产生严重的副作用:当我恢复上一个活动(当前正在后台运行)时,会失去窗口焦点.

我通过花费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%的时间.

解决方法

https://code.google.com/p/android/issues/detail?id=63570#c15中提供的解决方法对我来说非常有效,可以解决Activity没有获得窗口焦点的问题:
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秒.如果您指定了非默认根匹配器,则可能会选择一个永远不会成为焦点的根.否则,有些事情是严重错误的.

相关文章

ADB Remote ATV Android TV 的遥控器,基于 ADB Shell 命令 ...
使用Flutter自带的SearchDelegate组件实现搜索界面,通过魔改...
上篇文章讲解了怎么使用Kotlin的协程配合Retrofit发起网络请...
安卓开发——WebView+Recyclerview文章详情页,解决高度...
Android 如何解决dialog弹出时无法捕捉Activity的back事件 在...