web-dev-qa-db-ja.com

没入型モードの指示は、デバイスがこのモードに入るたびに再表示されます

私のアプリは、(onCreateで)を呼び出すことにより、新しい「没入型モード」を使用します。

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

これはうまく機能しますが、ユーザーがユーザーであっても、アクティビティが起動されるたびに(アクティビティの表示中に電話がロックされている場合)、「ハウツー」ポップアップ(「上から下にスワイプして全画面を終了する」)が表示されます。ポップアップを確認しました。私の知る限り、ポップアップはシステムによって自動的に生成されるので、この状況を変えるために私にできることは何もありませんよね?

この問題は次のように再現できます。

  1. 没入型アクティビティを起動します[ポップアップは表示されず、最初の起動時にのみ(正しく)]
  2. アクティビティの表示中に電源ボタンを押して画面をオフにします
  3. 電源ボタンをもう一度押すと、画面がオンになります
  4. Finish()を呼び出してアクティビティを閉じます。例:ボタンまたはメニューオプションから
  5. アクティビティを再度起動します-ポップアップが再表示されます

アクティビティが起動され、閉じられ、間に電源ボタンを押さずに再起動された場合、ポップアップは再表示されません。また、電源ボタンが押されているときにアクティビティが最上位にある場合にのみ再表示されます。

訂正:「finish()」を呼び出してアクティビティを閉じる必要があります(ボタンやメニューオプションなどから)。アクティビティがバックキーで閉じられている場合は正しく機能します。

ここにサンプルアプリをアップロードしました: https://github.com/niko001/com.greatbytes.immersivebug/tree/master/Test5

[〜#〜] edit [〜#〜]:「パニックモード」を無効にする Xposedモジュール があります。だから私はこれが迷惑だと思っているのは私だけではないと思います;)

13
Nick

本当に面白い質問です!明確な指示のおかげで、問題の再現は問題ではありませんでした。

了解しました。ソースを30分近く掘り下げて、_why would they do this?_を何度も言った後、ようやく理解できたと思います。私はできる限りのことを説明しようとしますが、これは私の解釈に過ぎず、正しくない可能性があります。

Android 実現の誰かがイマーシブモードで人々をパニック状態にすることを知っています:how do i exit? (_sorry, I don't know what else the panic would be about_)

このパニック状態では、ユーザーは電源ボタンをオンにします

....>電源ボタン->ユーザーが画面をオフにします(エポックからxミリ秒)

....>ナビゲーションバーが戻ってくることを祈る

....>電源ボタン->ユーザーが画面をオンにします(エポックからyミリ秒)

さて、期間_y - x_は重要です。これについては少し後で説明しますが、最初に、panicがどのように定義されているかを見てみましょう。

panicは、_Praying 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>
_

あ、そう。したがって、ユーザーがすでに1回確認したかどうかは関係ありません。上記の基準が満たされると、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)は、_Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS_の下に保存されているパッケージのリストからmPanicPackage(yours)を削除します。

言うまでもなく、私はこれが奇妙だと思います...そして間違っています。ユーザーがパニック状態にあり、電源ボタンのルートを使用している場合でも、次の起動まで役立つリマインダーは表示されません。それで、ポイントは何ですか?

あるいは、パニックの定義について間違っているかもしれません。

ですから、この状況を変えるために私にできることは何もありませんよね?

正しい。これを修正するには、_Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS_が保持する値にパッケージ名を追加する必要があります。ただし、安全な設定に書き込むには、アプリに_WRITE_SECURE_SETTINGS_権限が必要です。サードパーティのアプリケーションでは使用できません。

リンク:

ImmersiveModeConfirmation(確認プロンプトの表示/非表示を管理するヘルパークラス)

36
Vikram

より簡潔に-Kでは、次の場合に没入型モードに入るときに確認が表示されます。

  • そのアプリ(パッケージ)についてはまだ確認していません。
  • 前回イマーシブモードになっていたとき、彼らは「パニック」になりました。この場合の「パニック」とは、画面をオフに切り替えてから、5秒以内にオンに戻すことを意味します(デフォルト)。
3
jspurlock