2023/01/05

Android の権限ダイアログで2度「許可しない」が選択されたことを検知する方法

Android 6.0 (API Level 23) 以降、マイクの使用許可などプライバシーに関わるような権限はアプリの中から個別に許可を求めなければいけなくなりました。具体的には以下のようなコードを実行すると上記のようなダイアログが表示されます1。(permissionLauncher の実装は後半を参照)

1
2
3
4
5
6
val granted = ContextCompat.checkSelfPermission(
    requireContext(), Manifest.permission.RECORD_AUDIO
)
if (granted != PackageManager.PERMISSION_GRANTED) {
    permissionLauncher.launch(Manifest.permission.RECORD_AUDIO)
}

以前は毎回このコードを実行することでダイアログを表示することが出来ていたのですが、Android 11 (API Level 30) 以降、ユーザーが2度「許可しない」を選択すると、次からはダイアログが表示されなくなってしまいました。

自分がユーザーの立場からすると、今は使いたくないからとりあえず「許可しない」を選択しておくことは結構あると思うのです。しかし、いざ使いたいと思った時に反応しなくなるのは困ります。 これを回避する方法は無いものかと調べてみたのですが、結論から言うと回避する方法はなさそうです。

では、どういう実装にするのが良いのでしょうか?少し調べてみました。

参考

アプリの権限をリクエストする |  Android Developers

how to determine if the user checked "Never ask again"? | Stack Overflow

以上の情報をまとめると、 ActivityResultCallback の中で shouldShowRequestPermissionRationale を確認して処理を分けるのが良さそうです。

1
2
3
4
5
6
7
8
9
10
11
12
private val permissionLauncher =
    registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
        if (!granted) {
            if (shouldShowRequestPermissionRationale(Manifest.permission.RECORD_AUDIO)) {
                // 普通の「許可しない」が選択された
                // 独自ダイアログ等を表示してパーミッションがなぜ必要なのかを説明する
            } else {
                // 「許可しない(次回から表示しない)」が選択された
                // Preference に保存するなどする
            }
        }
    }

開発者の視点からすると、 shouldShowRequestPermissionRationale の値に関わらず独自ダイアログ等を表示して何とか許可させたいと思うのですが、それはこの変更の意図を無視した方法なのでお勧めできません。

例えば Preferences に保存する等、2度拒否されたことを記録するだけにし、その情報を元にして以下のような施策を入れるのが良さそうです。

  • アイコンを非表示にする
  • アイコンを設定画面に移す(それをクリックしたときは独自ダイアログ)
  • 設定画面等に説明文とともに「アプリ情報」へのリンクを表示する

なお、「アプリ情報」画面への遷移は以下のようにリクエストすることができます。

1
2
3
4
5
val intent = Intent().apply {
    action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
    data = Uri.parse("package:$packageName")
}
startActivity(intent)
  1. AndroidManifest.xmluses-permission の記述も必要 
?

0 件のコメント: