Immersive mode instructions reappear every time the device enters this mode

前端 未结 2 863
醉酒成梦
醉酒成梦 2020-12-24 15:33

My app uses the new \"immersive mode\" by calling (in onCreate):

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGAT

相关标签:
2条回答
  • 2020-12-24 15:44

    More succinctly - in K, users will see the confirmation when entering immersive mode if:

    • They have not yet confirmed it for that app (package).
    • They "panicked" last time they were in immersive mode. "Panic" in this case means toggling the screen off, then back on in under 5 seconds (by default).
    0 讨论(0)
  • 2020-12-24 15:51

    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)

    0 讨论(0)
提交回复
热议问题