My app uses the new \"immersive mode\" by calling (in onCreate
):
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGAT
More succinctly - in K, users will see the confirmation when entering immersive mode if:
Really interesting question! Thanks to your clear instructions, reproducing the issue wasn't a problem.
Alright, after digging through the source for almost 30-minutes and saying why would they do this?
a bunch of times, I think I finally get it. I'll try to explain the best I can, but this is only my interpretation, and may not be correct:
Someone at android realized that the Immersive Mode will send people into a state of panic: how do i exit? (_sorry, I don't know what else the panic would be about_)
.
In this state of panic, the user will turn to the POWER BUTTON
.... > Power button --> User turns screen off (at x
milliseconds since EPOCH)
.... > Praying that the navigation bar comes back
.... > Power button --> User turns screen on (at y
milliseconds since EPOCH)
Now, the duration y - x
is of significance. We'll discuss it a bit later, but first, let's look at how panic
is defined:
panic
happens when Praying the navigation bar comes back
lasts less than 5 seconds. This value is held by:
mPanicThresholdMs = context.getResources()
.getInteger(R.integer.config_immersive_mode_confirmation_panic);
<!-- Threshold (in ms) under which a screen off / screen on will be considered
a reset of the immersive mode confirmation prompt.-->
<integer name="config_immersive_mode_confirmation_panic">5000</integer>
Ah, okay. So, it doesn't matter if the user has already acknowledged once, the prompt will be back if the above-mentioned criterion is met - even on the 100th launch.
And here's where the action happens:
public void onPowerKeyDown(boolean isScreenOn, long time, boolean inImmersiveMode) {
if (mPanicPackage != null && !isScreenOn && (time - mPanicTime < mPanicThresholdMs)) {
// turning the screen back on within the panic threshold
unconfirmPackage(mPanicPackage);
}
if (isScreenOn && inImmersiveMode) {
// turning the screen off, remember if we were in immersive mode
mPanicTime = time;
mPanicPackage = mLastPackage;
} else {
mPanicTime = 0;
mPanicPackage = null;
}
}
(time - mPanicTime < mPanicThresholdMs) ==> ( y - x ) < 5000
unconfirmPackage(mPanicPackage)
removes mPanicPackage
(yours) from the list of packages stored under Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS
.
Needless to say, I find this strange... and wrong. Even if the user is in panic, and takes the power button route, s/he won't see the helpful reminder until next launch. So, what's the point?
Or may be, I am wrong about the definition of panic.
so there's nothing I can do to change this situation, correct?
Correct. To fix this, you would have to add your package-name to value held by Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS
. But, to write to a secure setting, your app requires WRITE_SECURE_SETTINGS
permission - not for use by third-party applications.
Links:
ImmersiveModeConfirmation (helper class that manages showing/hiding of confirmation prompt)