2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

クイック設定タイルでの機能ON/OFFの変化を判定する

Posted at

Androidのクイック設定タイルでは、一部の端末機能のON/OFFを変更できます。
以下のように、マイク・カメラ・位置情報は概ねどの端末でも設定できるかと思います。

ここで機能をOFFにされると、アプリとしてランタイムパーミッションを獲得していても、当該機能へのアクセスができなくなります。
それを判定するには、ContextCompat.checkSelfPermissionではなく、PermissionChecker.checkSelfPermission を利用します。

さて、ランタイムパーミッションの変化を判定する場合、onRequestPermissionsResultやそれに相当するコールバックや、別経路から設定された場合も想定して、onResumeで再評価を行うのが常套手段です。

しかし、クイック設定タイルで機能のON/OFFを行う場合、アプリのライフサイクルはRESUME状態から変化しない場合があります。

クイック設定タイルで機能のON/OFF

クイック設定タイルで機能のON/OFFとは、AppOpsの変更を行っていることになります。
この変更はAppOpsMAnagerで監視することができます。
startWatchingModeで監視開始、stopWatchingModeで監視停止です。停止しないとコールバックがリークしてしまいますので、必ず停止しましょう。

位置情報の変更を監視するには以下のようにします。

val appOpsManager = getSystemService<AppOpsManager>() ?: return
val callback = AppOpsManager.OnOpChangedListener { op, packageName ->
    lifecycleScope.launch {
        checkLocationPermission()
    }
}
appOpsManager.startWatchingMode(AppOpsManager.OPSTR_COARSE_LOCATION, packageName, callback)
lifecycle.addObserver(object : DefaultLifecycleObserver {
    override fun onDestroy(owner: LifecycleOwner) {
        appOpsManager.stopWatchingMode(callback)
    }
})

OnOpChangedListenerは、Binderスレッドで呼ばれるため、メインスレッドにディスパッチしてからパーミッションの判定を行います。
コールバックスレッド上で判定を行うと、OFFは判定できますが、ONが判定できませんでした。

なお上記では、AppOpsManager.OPSTR_COARSE_LOCATIONを使用していますが、以下のようにパーミッション文字列から取得することもできます。

val op = AppOpsManager.permissionToOp(Manifest.permission.ACCESS_COARSE_LOCATION) ?: return

これでアプリを表示したまま、クイック設定タイルで設定変更された場合も変更を即座に反映することができます。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?