okuzawatsの日記

Android / Kotlin / GitHub Actions Enthusiast 🤖

[Android] ライブラリを使ってRuntime Permissionをリクエストする

profile

書いている人 モバイルアプリケーションアーキテクト(Android)として働いています。モバイルアプリケーションのアーキテクチャ、自動テスト、CI/CDに興味があります。もっと詳しく

ライブラリを使ってAndroidのRuntime Permissionをリクエストする方法をまとめます。Runtime Permissionをリクエストするために使える有名なライブラリには、PermissionsDispatcherとRxPermissionsがあります。

PermissionsDispatcherを用いたRuntime Permissionのリクエスト

PermissionsDispatcherを使ってRuntime Permissionをリクエストする方法を示します。

とりあえずAndroidManifest.xmlにパーミッションを追加します。

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

app/build.gradleにPermissionDispatcherとkaptを追加します。

apply plugin: 'kotlin-kapt'

dependencies {
    // PermissionDispatcher
    implementation "org.permissionsdispatcher:permissionsdispatcher:4.5.0"
    kapt "org.permissionsdispatcher:permissionsdispatcher-processor:4.5.0"
}

Fragmentに @RuntimePermissions というアノテーションを付けます。PermissionsDispatcherによって自動生成されるメソッドがあるので、以下、適宜ビルドしながら進めます。

@RuntimePermissions
class StartFragment : Fragment() {
   // do something here
}

READ_EXTERNAL_STORAGE のパーミッションを得て、ギャラリーを表示するみたいな実装を想定して、パーミッション周りの処理を実装していきます。

/** Permission Dispatcher */
@NeedsPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
fun showGallery() {
    findNavController().navigate(R.id.action_start_to_gallery)
}

@OnShowRationale(Manifest.permission.READ_EXTERNAL_STORAGE)
fun onShowRationaleForReadExternalStorage(request: PermissionRequest) {
    showRationaleDialog(
        requireContext(),
        request,
        R.string.start_request_permission_for_read_external_storage
    )
}

@OnPermissionDenied(Manifest.permission.READ_EXTERNAL_STORAGE)
fun onReadExternalStorageDenied() {
    Toast.makeText(requireContext(), "Permission denied!", Toast.LENGTH_LONG).show()
}

@OnNeverAskAgain(Manifest.permission.READ_EXTERNAL_STORAGE)
fun onReadExternalStorageNeverAskAgain() {
    Toast.makeText(requireContext(), "Never ask again!", Toast.LENGTH_LONG).show()
}

onRequestPermissionsResult() をoverrideして、この中でPermissionsDispatcherによって自動生成される onRequestPermissionsResult() を呼び出せば、パーミッションの許可周りを適切にハンドリングしてくれます。

override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    onRequestPermissionsResult(requestCode, grantResults)
}

showRationaleDialog() は拡張関数で定義しました。

fun Fragment.showRationaleDialog(
    context: Context,
    request: PermissionRequest,
    @StringRes messageResId: Int
) {
    AlertDialog.Builder(context)
        .setPositiveButton(R.string.ok) { _, _ -> request.proceed() }
        .setNegativeButton(R.string.cancel) { _, _ -> request.cancel() }
        .setMessage(messageResId)
        .show()
}

最後に、PermissionsDispatcherによって自動生成された showGalleryWithPermissionCheck() を呼び出せば、パーミッションのチェックが走ります。

showGalleryWithPermissionCheck()

RxPermissionsを用いたRuntime Permissionのリクエスト

RxPermissionsを使ってRuntime Permissionをリクエストする方法を示します。

プロジェクトレベルの build.gradle にJitPackのリポジトリを追加します。

allprojects {
    repositories {
        maven { url 'https://jitpack.io' }
    }
}

アプリレベルの build.gradle にRxJavaとRxPermissionsを追加します。

dependencies {
    // RxJava
    implementation 'io.reactivex.rxjava2:rxjava:2.2.13'

    // RxPermissions
    implementation 'com.github.tbruyelle:rxpermissions:0.10.2'
}

AndroidManifest.xmlにパーミッションを追加します。

<uses-permission android:name="android.permission.CAMERA" />

RxPermissionsによるRuntime Permissionの実装は簡単です。以下はFragmentでの実装になります。

val rxPermissions = RxPermissions(this)

rxPermissions
    .request(Manifest.permission.CAMERA)
    .subscribe { granted ->
        if (granted) {
            // permission granted
        } else {
            // permission denied
        }
    }

Related