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.
startActivity(FLAG_ACTIVITY_REORDER_TO_FRONT, ActivityB.class).
startActivity(FLAG_ACTIVITY_REORDER_TO_FRONT, ActivityA.class).
onResume()
is called as expected and everything looks fine (I can see Activity A content again).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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With