android - 使用 FLAG_ACTIVITY_REORDER_TO_FRONT 在持续运行的 UI Activity 之间切换会导致 "no window focus"错误

标签 android window focus

我的目标是让两个 UI Activity 保持 Activity 状态,并在它们之间随意来回切换,而不必终止/重新启动其中任何一个。但是使用 FLAG_ACTIVITY_REORDER_TO_FRONT 有一个严重的副作用:当我恢复之前的 Activity (当前在后台运行)时失去窗口焦点。

我花了 5 分钟创建了一个包含两个“Hello World” Activity 的简单应用程序,从而证明了这个问题。

  1. 应用程序从 Activity A 开始,它只显示一个名为“Launch B”的按钮(仅此而已)。
  2. 按下此按钮 -- 这将执行 startActivity(FLAG_ACTIVITY_REORDER_TO_FRONT, ActivityB.class)。
  3. Activity B 变为 Activity 状态,它只显示一个名为“启动 A”的按钮。
  4. 按下此按钮 -- 这将执行 startActivity(FLAG_ACTIVITY_REORDER_TO_FRONT, ActivityA.class)。
  5. Activity A 的 onResume() 按预期调用,一切正常(我可以再次看到 Activity A 的内容)。
  6. 按设备的返回键,这组错误将在 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 可见但没有焦点的原因是因为 Activity A 的 onWindowFocusChanged() 没有像往常一样被调用(即使调用了 onResume() ). 这与 Activity B 在后台仍然处于 Activity 状态有关(尽管显然 B 失去了焦点——为 B 调用了 onWindowFocusChanged(false),以及 onStop()) . 我知道这一点,因为在上面的第 4 步之后,如果我立即在 Activity B 上调用 finish(),Activity A 的 onWindowFocusChanged(true) 将被调用,并且一切正常。 Activity B 仍然处于 Activity 状态但不活动的事实focused 会以某种方式干扰 Activity A 重新获得焦点。这是 Android 错误还是我遗漏了什么?

请注意,如果 Activity A 中有多个 View ,并且我在上面的第 6 步之后触摸其中一个 View ,我会得到相同的“由于没有窗口焦点而丢弃事件”错误,尽管不是 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:WAITING View 层次结构的根获得窗口焦点并且超过 10 秒未请求布局。如果您指定了一个非默认根匹配器,它可能会选择一个永远不会获得焦点的根。否则,就会出现严重错误。

关于android - 使用 FLAG_ACTIVITY_REORDER_TO_FRONT 在持续运行的 UI Activity 之间切换会导致 "no window focus"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29111320/

相关文章:

android - 如何更改 PreferenceScreen 中的字体大小

java - 如何将 Java 放入 GameMaker Studio?

java - 我应该将基本 Activity 添加到 list 文件中吗?

python - 为什么窗口显示后位置仍然为零?

Android点击EditText不会显示软键盘

android - 选择项目后永久 NavigationView 失去焦点

android - 如何让 exoplayer 播放 Drive 中的视频

javascript - 需要解释 : Cannot understand javascript returning a function

c++ - 没有合适的默认构造函数可用,但声明了构造函数

javascript - focus() 在 IE 11 中不起作用