はじめに
- Androidのパーミッション処理を便利に実装してくれるPermissionsDispatcherってなかなか便利ですよね。
使っている方もいるかと思いますが、PermissionsDispatcherを外して、PermissionsDispatcher風に実装する方法を書いていこうと思います。
ここでは
PermissionsDispatcher
の使い方についてはふれませんので、気になる方はQiitaの他の記事を読んでみると良いかと
PermissionsDispatcher風とは?
PermissionsDispatcher
では、メソッドにAnnotation
を付与し、kapt(kotlin-annotation-processing tools)を利用しコード生成を行います。PermissionsDispatcher
には以下のAnnotation
が用意されています。
- この
Annotation
の処理と、AndroidDevelopersGuilde:アプリの権限をリクエストする の内容をベースに実装を考えていきます。
実装イメージ
- Permissionの判定処理は、
androidx.activity:activity-ktx
とandroidx.fragment:fragment-ktx
を利用します。 - Permission判定は以下の処理をハンドリング出来るようにします。
処理名 | タイミング |
---|---|
onGranted | ユーザーが処理を許可した場合に呼び出されます。 |
onShowRationale | ユーザーが処理を一度拒否した後に、リクエストされた際に呼び出されます。 |
onDenied | ユーザーが処理を拒否した場合際に呼び出されます。 |
OSS
androidx.activity:activity-ktx
を利用します。
build.gradle
dependencies {
implementation 'androidx.activity:activity-ktx:1.2.0-beta01'
}
Permission判定処理
- 判定処理は
ActivityResultContracts.RequestPermission()
を元に、判定処理を実装します。 -
ActivityResultContracts.RequestPermission()
はActivity間パーミッション判定を実装してくれています。
Permissionの状態管理
- パーミッション判定と、処理のハンドリングを以下のクラスで制御します。
PermissionChecker.kt
class PermissionChecker(
private val activity: ComponentActivity,
private val permission: String,
private val onDenied: () -> Unit = {},
private val onShowRationale: (onRequest: () -> Unit) -> Unit = {}
) {
private var onGranted: () -> Unit = {}
private val launcher =
activity.registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
when {
isGranted -> onGranted()
else -> onDenied()
}
}
fun runWithPermission(onGranted: () -> Unit) {
this.onGranted = onGranted
when {
activity.shouldShowRequestPermissionRationale(permission) -> onShowRationale {
launcher.launch(permission)
}
else -> {
launcher.launch(permission)
}
}
}
}
-
activity.registerForActivityResult(ActivityResultContracts.RequestPermission())
は、パーミッションの判定処理を実施しています。- Boolean でパーミッションの状態を返却してくれます。
-
shouldShowRequestPermissionRationale()
ユーザーがパーミッション判定に回答したかを返却します。
利用ケース
SampleActivity.kt
class SampleActivity : AppCompatActivity(){
・・・省略
// ファイルストレージのPermission判定
private val externalStrageAccessPermissionChecker = PermissionChecker(this, WRITE_EXTERNAL_STORAGE,
onDenied = {
// 拒否した際の、通知処理
Toast.makeText(this, "アクセス拒否しているから、処理できませんでした。", Toast.LENGTH_LONG).show()
},
onShowRationale = { onRequest ->
// 一度拒否した後の、処理実施時の処理の説明を実施
AlertDialog.Builder(this)
.setPositiveButton("次へ")
{ _, _ -> onRequest() }
.setCancelable(false)
.setMessage("ファイルアクセス許可が必要なんです。")
.show()
}
)
// ファイルダウンロード処理
fun downloadFile(url: String, name: String) {
externalStrageAccessPermissionChecker.runWithPermission(
onGranted = {
// ダウンロード処理を実施
}
)
}
}
-
PermissionChecker
は、registerForActivityResult()
の処理を実装しています。この処理はonCreate()前に呼び出す必要があります。 -
runWithPermission()
のonGranted()
はユーザーが許可した際に呼び出されます。 -
onShowRationale()
は一度処理を拒否した後に呼び出されます。onRequest()
を呼び出すことで、中断した処理を実施します。 -
onDenied()
は拒否された際に通知されます。
まとめ
-
registerForActivityResult(ActivityResultContracts.RequestPermission())
を利用する事で、いままで実装が大変だった、処理が大幅に楽になります。 -
PermissionsDispatcher
も便利ですが、Android 11 対応時には、利用箇所でワーニングが多く表示されるケースがあります。 - ワーニングをなくす為には処理の置き換えが必要かな
追記(2020/11/11)
-
PermissionChecker
の作者 @hotchemi さんから ktx版の情報をいただいたので追記しておきます! - ライブラリの置き換えであれば、こちらのktx版を利用するのが楽そうですね
https://github.com/permissions-dispatcher/PermissionsDispatcher/tree/master/ktx