〈kotlin〉Android studio使い方メモ12:Runtime Permission②

金宏和實さんの「作ればわかる!Androidプログラミング kotlin対応」を参考に
Android studioでkotlinを使ってAndroidアプリ作成。


前回書いた記事の続き。
本書ではrequestPermissions / onRequestPermissionsResultを使用していたが、
ActivityResultContractsを使うとリクエストコードなしで実装できる。

従来のコード

ActivityCompatのrequestPermissionsで許可を求め、
onRequestPermissionResultで結果を受け取るコード。
この場合、許可を求める際に自分でリクエストコードを設定して引数として渡し、
コールバックでもリクエストコードを確認する必要がある。

コード例

private val REQUEST_CODE = 1

private fun requestLocationPermission() {
    //一度許可を求めたことがあって拒否されている場合
    if (ActivityCompat.shouldShowRequestPermissionRationale(this,
            android.Manifest.permission.ACCESS_FINE_LOCATION)){
        ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.
        permission.ACCESS_FINE_LOCATION),  REQUEST_CODE)
    }else{
    //まだ許可を求めていない場合
        ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.
        permission.ACCESS_FINE_LOCATION), REQUEST_CODE)
    }
}

override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    when (requestCode){
        REQUEST_CODE ->{
            if (permissions.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                //処理に進む
            }else{
                Toast.makeText(this, "位置情報は表示できません", Toast.LENGTH_LONG).show()
            }
        }
    }

ActivityResultContractsを使用したコード

RequestPermissionを使用するとシステムにリクエストコードの管理を許可することができ、
自分で設定して渡す部分が不要になるためコードが簡単になる。

registerForActivityResultメソッドにRequestPermissionを渡しlauncherとして、
コールバックの登録する。
(registerForActivityResultは ActivityResultContract と ActivityResultCallback を受け取って、
他のアクティビティを開始するために使用する ActivityResultLauncher を返す。)
許可を求めるときはlaunchメソッドにパーミッションを渡せば良い。
1つだけ許可を求めるときはRequestPermissionを使用するが、
複数の許可を求めるときはRequestMultiplePermissionsとし、
launchの引数はArray<String>、返り値はMap<String, Boolean>になる。

コード例

private val launcher = registerForActivityResult(ActivityResultContracts.RequestPermission()
    ){ isGranted: Boolean ->
        if (isGranted) {
            //処理に進む
        } else {
            Toast.makeText(this, "位置情報は表示できません", Toast.LENGTH_LONG).show()
        }
    }

private fun requestLocationPermission() {
    if (ActivityCompat.shouldShowRequestPermissionRationale(
            this,  android.Manifest.permission.ACCESS_FINE_LOCATION)) {
        launcher.launch(Manifest.permission.ACCESS_FINE_LOCATION)

    } else {
        launcher.launch(Manifest.permission.ACCESS_FINE_LOCATION)

}

コード例(複数)

val locationPermissionRequest = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissions ->
        when {
            permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false) -> {
                // 詳細な位置情報が利用できる
            }
            permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false) -> {
                // おおよその位置情報だけ利用できる
            } else -> {
                // 利用できない
            }
        }
    }

locationPermissionRequest.launch(arrayOf(
    Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.ACCESS_COARSE_LOCATION))


参考https://developer.android.com/training/permissions/requesting?hl=ja#request-permission