💬

Jetpack Compose で Quick Settings の開閉を検知する

2022/09/21に公開

はじめに

Quick Settings は画面の上部を下にスワイプした時に出てくるメニュー画面のことです. [1]
Quick Settings を使うとスマートフォンのどの画面からもインターネット接続や位置情報をはじめとしたした設定を変えたり通知を確認したりすることができます.

しかし Quick Settings を開閉したとしても onResume()onPause() 等のライフサイクル コールバックは呼ばれることはありません.
そのため, Quick Settings 上で端末の位置情報の権限の許諾を変更した場合にすぐさま UI を更新したい場合などには別の方法を検討する必要があります.

そこで今回は Jetpack ComposeQuick Settings の開閉を検知する方法について調べてみました.

Activity における Quick Settings の開閉の検知

Jetpack Compose の前に Activity における Quick Settings の開閉の検知の方法について調べてみます.
上述の通り, Quick Settings の開閉で onResume()onPause() 等のライフサイクル コールバックは呼ばれることがありません.

Stack Overflow で探してみると Activity においては Activity の現在の Window がフォーカスを得たり失ったりする時に呼ばれる Activity.onWindowFocusChanged() で検知が可能との投稿がありました. [2]

onWindowFocusChanged のドキュメントをみると

As a general rule, however, a foreground activity will have window focus... unless it has displayed other dialogs or popups that take input focus, in which case the activity itself will not have focus when the other windows have it.
Likewise, the system may display system-level windows (such as the status bar notification panel or a system alert) which will temporarily take window input focus without pausing the foreground activity.

とあり,

  • ダイアログやポップアップが表示された時は Activity のフォーカスが外れる
  • (Quick Settings のような)システムレベルのウィンドウが表示された時は Activity のフォーカスが外れるが foreground activity は停止しない

という趣旨の文言が記載されています. [3]

確認をしてみるとダイアログが表示/非表示になったタイミングや Quick Settings の開閉時, さらにアプリがフォアグラウンド/バックグラウンドに移動したタイミングで Activity.onWindowFocusChanged() が呼び出されることがわかります.

そのため一部ライフサイクル コールバックの呼び出しと重複することがあることに注意する必要があるが, 基本的には Activity.onWindowFocusChanged()Quick Settings の開閉を検知することができそうです.

Compose における Quick Settings の開閉の検知

次に Jetpack Compose における Quick Settings の開閉の検知の方法について調べてみます.

Activity の時と同様に onWindowFocusChanged() に当たるものが Compose にないかどうか調べてみると androidx.compose.ui.platformWindowInfo.isWindowFocused というものが用意されていました. [4] [5]

ドキュメントには

Indicates whether the window hosting this compose hierarchy is in focus.

とあり Compose をホストしている Window にフォーカスがあるかどうかを検知することができるとあります.

そして Compose で WindowInfoLocalWindowInfo.current によって取得をすることができるので以上を踏まえると次のようなコードで Quick Settings の開閉を検知することができます.

val windowInfo = LocalWindowInfo.current

LaunchedEffect(windowInfo.isWindowFocused) {
    // windowInfo.isWindowFocused の値に応じて処理
}

上記のコードでも Activity.onWindowFocusChanged() と同様にダイアログやポップアップに相当する Composable を表示した時やアプリがフォアグラウンド/バックグラウンドに移動したタイミングで windowInfo.isWindowFocused の値が切り替わるので注意が必要です.

まとめ

WindowInfo.isWindowFocused を用いることで Compose においても Quick Settings を開閉を検知することができそうです.
また余力があれば LocalWindowInfo を提供する Owner についても記事にまとめてみたいなと思っています.

脚注
  1. Change settings quickly on your Android phone ↩︎

  2. Are there any callback methods for when the quick settings dropdown menu is opened? ↩︎

  3. onWindowFocusChanged ↩︎

  4. isWindowFocused ↩︎

  5. Add an API to check if the window is in focus ↩︎

Discussion