14

我的应用程序通过调用 (in ) 使用新的“沉浸式模式” onCreate

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);

这很好用,但是每次启动 Activity 时都会出现“操作方法”弹出窗口(“从顶部向下滑动以退出全屏”)(如果在显示 Activity 时手机被锁定),即使用户已确认弹出。据我了解,弹窗是系统自动生成的,所以我无法改变这种情况,对吗?

此问题可重现如下:

  1. 启动沉浸式活动 [不出现弹出窗口,仅在第一次启动时(正确)]
  2. 显示活动时按电源按钮关闭屏幕
  3. 再次按下电源按钮以打开屏幕
  4. 通过调用完成()关闭活动,例如从按钮或菜单选项
  5. 再次启动活动 - 再次出现弹出窗口

如果 Activity 被启动、关闭和重新启动,而中间没有按电源按钮,则弹出窗口不会重新出现。此外,仅当按下电源按钮时活动处于最顶部时,它才会重新出现。

更正:需要通过调用“finish()”来关闭活动(例如,通过按钮或菜单选项)。如果 Activity 被返回键关闭,它可以正常工作。

我在这里上传了一个示例应用程序:https ://github.com/niko001/com.greatbytes.immersivebug/tree/master/Test5

编辑:现在有一个Xposed 模块来禁用“恐慌模式”,所以我想我并不孤单看到这是一个烦恼;)

4

2 回答 2

38

真的很有趣的问题!感谢您的明确指示,重现该问题不是问题。

好吧,在挖了将近30分钟的源码,说why would they do this?了一堆之后,我想我终于明白了。我会尽力解释,但这只是我的解释,可能不正确:

android 的某个人意识到沉浸式模式会让人们陷入恐慌状态:how do i exit? (_sorry, I don't know what else the panic would be about_).

在这种恐慌状态下,用户将转向电源按钮

.... > 电源按钮 --> 用户关闭屏幕(x自 EPOCH 以来的毫秒数)

.... > 祈祷导航栏回来

.... > 电源按钮 --> 用户打开屏幕(y自 EPOCH 以来的毫秒数)

现在,持续时间y - x很重要。我们稍后会讨论它,但首先,让我们看看它是如何panic定义的:

panicPraying the navigation bar comes back持续时间少于 5 秒时发生。该值由以下人员持有:

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>

啊好吧。因此,无论用户是否已经确认过一次,只要满足上述条件,提示就会返回——即使在第 100 次启动时也是如此。

这就是行动发生的地方:

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;
    }
}

(时间 - mPanicTime < mPanicThresholdMs) ==> ( y - x ) < 5000

unconfirmPackage(mPanicPackage)mPanicPackage存储在Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS.

不用说,我觉得这很奇怪……而且是错误的。即使用户处于恐慌状态,并采用电源按钮路线,她/他也不会在下次启动之前看到有用的提醒。那么,有什么意义呢?

或者可能是,我对恐慌的定义是错误的。

所以我无法改变这种情况,对吗?

正确的。要解决此问题,您必须将您的包名称添加到Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS. 但是,要写入安全设置,您的应用程序需要WRITE_SECURE_SETTINGS权限 - 不供第三方应用程序使用。

链接:

ImmersiveModeConfirmation(管理确认提示的显示/隐藏的帮助类)

于 2013-12-01T07:17:19.693 回答
4

更简洁 - 在 K 中,如果出现以下情况,用户将在进入沉浸式模式时看到确认:

  • 他们尚未确认该应用程序(包)。
  • 上次他们处于沉浸式模式时,他们“惊慌失措”。在这种情况下,“恐慌”意味着关闭屏幕,然后在 5 秒内重新打开(默认情况下)。
于 2013-12-17T16:36:11.693 回答