AndroidX に追加された ResultAPI を使って実行時権限をリクエストする処理を書き方をご紹介したいと思います。
ResultAPI とは
ResultAPI とは、androidx.activity のバージョン 1.2.0-alpha02 と androidx.fragment のバージョン 1.3.0-alpha02 で追加された API です。
これを使うことで非推奨となった onActivityResult
や onPermissionRequest
などの処理を置き換えるとともに簡潔に書き直すことができるようになります。
今回は onPermissionRequest
が実現できる実行時権限をリクエストしてその結果を受け取る処理を ResultAPI を使って書いていきたいと思います。
環境
Android Studio:2020.3.1 Patch 4
kotlin:1.5.31
targetSdkVersion:31
minSdkVersion:27
準備
まずは gradle にライブラリを追加します。
dependencies {
...
implementation 'androidx.activity:activity-ktx:1.4.0'
implementation 'androidx.fragment:fragment-ktx:1.4.0'
}
次に AndroidManifest にリクエストする権限を追加します。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.resultapisample">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
...
</manifest>
レイアウトファイルのコードも記載しておきます。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/button1"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="button1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/button2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/button2"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="button2"
android:layout_marginTop="20dp"
app:layout_constraintTop_toBottomOf="@+id/button1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
権限をリクエスト(一つ)
ResultAPI を使って一つだけ権限をリクエストしてみます。
まずはリクエスト結果を受け取る処理を registerForActivityResult
メソッドを使って実装します。
第一引数には ActivityResultContracts.RequestPermission
クラスを、第二引数にはコールバック関数を指定します。
コールバック関数の引数は権限を許可したか否かの結果が入る Boolean 型の変数です。
private val permissionResult = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
Log.d("permission result", isGranted.toString())
if (isGranted) {
Toast.makeText(this, "位置情報が許可されました。", Toast.LENGTH_SHORT).show()
} else {
AlertDialog.Builder(this)
.setMessage("この機能を使用するために位置情報の権限を許可してください。")
.setCancelable(false)
.setPositiveButton("OK") { dialog, _ ->
dialog.dismiss()
}
.setNegativeButton("キャンセル") { dialog, _ ->
dialog.cancel()
}
.create().show()
}
}
位置情報の権限が許可されたらトーストを表示し、許可されなかったら設定アプリから権限を許可するように促すダイアログを表示します。
リクエストするときは launch
メソッドを使い、引数にリクエストする権限を指定します。
button1.setOnClickListener {
permissionResult.launch(Manifest.permission.ACCESS_FINE_LOCATION)
}
権限をリクエストする(複数)
権限を複数リクエストすることも可能です。
メソッドは権限が一つの時と同じように registerForActivityResult
メソッドを使うのですが、引数が変わります。
第一引数には ActivityResultContracts.RequestPermissions
を指定します。
第二引数にはコールバック関数を指定するのですが、引数の型は Map<String, Boolean>
となります。
String型の変数は権限名、Boolean型の変数はその権限が許可されたかどうかの結果を表します。
以下はカメラと位置情報の権限をリクエストする例です。
private val permissionResults = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result: Map<String, Boolean> ->
Log.d("permission result", it.toString())
it.forEach { (permission, isGrant) ->
val perm = when (permission) {
Manifest.permission.ACCESS_FINE_LOCATION -> "位置情報の権限"
Manifest.permission.CAMERA -> "カメラの権限"
else -> ""
}
if (isGrant) {
Toast.makeText(this, "${perm}が許可されました。", Toast.LENGTH_SHORT).show()
} else {
AlertDialog.Builder(this)
.setMessage("この機能を使用するために${perm}を許可してください。")
.setCancelable(false)
.setPositiveButton("OK") { dialog, _ ->
dialog.dismiss()
}
.setNegativeButton("キャンセル") { dialog, _ ->
dialog.cancel()
}
.create().show()
}
}
}
コールバック関数の Map型の引数から forEach
メソッドによって権限名とリクエスト結果のペアを取り出して権限ごとに日本語のメッセージを生成してダイアログやトーストに表示するようにしています。
権限をリクエストするときは launch
メソッドの引数に配列形式で権限名を指定します。
button2.setOnClickListener {
permissionResults.launch(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CAMERA))
}
参考
[Android] Activity Result API を使う
アプリの権限をリクエストする | Android デベロッパー | Android Developers
ActivityResultContractsの仕組みを調べてみる - Qiita