Android
permission
PermissionsDispatcher

”PermissionDispatcher”でAndroidパーミッションをラクに実装!


概要

Androidアプリにて、端末の様々な情報へのアクセスや機能の利用をユーザーに伝え、そのアクセスや機能の許可を促すための仕組み、「パーミッション」。

ストレージ、カメラ等にアクセスするアプリは、このパーミッション機能を必ず実装する必要があります。で、そのパーミッション機能、ベタで書いたら、案外コード量が多く複雑なものになりがちなのですが、"PermissionDispatcher" というライブラリを使うと、カンタンに実装できることができます。


カメラ・外部ストレージ書き込みのパーミッション実装

Android アプリで頻出しそうなケースであること、そしてkotlinでいいサンプルが見当たらなかったのカメラ(android.permission.CAMERA)と外部ストレージ書き込み(android.permission.WRITE_EXTERNAL_STORAGE) のパーミッションチェックをPermissionDispatcher で実装しました。

https://github.com/rochefort8/PermissionCheck-android-sample


環境

上記GitHub の動作・開発環境です。


Host

MacBook Pro (Retina, 13-inch, Mid 2014)

macOS High Sierra 10.13.6


Android Project


  • Android Studio : 3.3.1

  • Grade : 4.10.1

  • Android Plugin version : 3.3.2

  • Target SDK version : 28


動作確認


  • Xperia XZ1 (Android 8)

  • Nexus 5 (Android 6.0.1)

  • Genymotion Google Pixel


手順

以下の記事に手順、機能詳細が書いてあります。

【Android】 パーミッション判定の複雑なコードを解決!PermissionsDispatcherライブラリを試してみた

以下、この記事に沿って作成したときの手順です。


  • 新規プロジェクト作成


  • PermissionDispatcher ライブラリ利用のための記述


app の方のbuild.gradleに以下を追記してSyncする。


build.gradle


...
// 追記
apply plugin: 'kotlin-kapt'

dependencies {
....
// 以下の4行を追記
implementation ('com.github.hotchemi:permissionsdispatcher:3.3.1'){
exclude module: "support-v13"
}
kapt "com.github.hotchemi:permissionsdispatcher-processor:3.3.1"
}



AndroidManifest.xml


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


  • 新しいActiivty ”PermissionCheckActivity”を作成

    ここにPermission Check を実装。


  • Permission Check で使う文字列の定義



strings.xml

    <string name="alert_diaglog_message_for_permission">アプリがこの操作を実行するには次の権限の許可が必要です。\n

カメラ\nストレージ\n\n権限を許可するには、[アプリ情報]→[許可]に移動してください。</string>
<string name="button_name_app_info">アプリ情報</string>


  • Launcher Activity をPermisshinCheckActivity にする


AndroidManifest.xml


// アクティビティを「入れ替え」
<activity android:name=".MainActivity">
</activity>
<activity android:name=".PermissionCheckActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>



  • PermissionCheckActivity.kt 実装


PermissionCheckActivity.kt

package com.rochefort10.permissiondispatcher_sample

import android.Manifest
.....

@RuntimePermissions
class PermissionCheckActivity : AppCompatActivity() {

var isWriteExternalStorageAllowed = false
var isCameraAllowed = false
val REQUEST_CODE_MAGIC = 1212

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
startPermissionCheck()
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
// NOTE: delegate the permission handling to generated function
onRequestPermissionsResult(requestCode, grantResults)
}

// ---------- WRITE_EXTERNAL_STORAGE ----------
@NeedsPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
fun showWriteExternalStorage() {
isWriteExternalStorageAllowed = true
showCameraWithPermissionCheck()
}

// @OnShowRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)
// fun showWriteExternalStoraga(request: PermissionRequest) {
// showRationaleDialog("Reason to use external storage.",request)
// }

@OnPermissionDenied(Manifest.permission.WRITE_EXTERNAL_STORAGE)
fun onWriteExternalStorageDenied() {
isWriteExternalStorageAllowed = false
showCameraWithPermissionCheck()
}

@OnNeverAskAgain(Manifest.permission.WRITE_EXTERNAL_STORAGE)
fun onWriteExternalStorageNeverAskAgain() {
isWriteExternalStorageAllowed = false
showCameraWithPermissionCheck()
}

// ----------- CAMERA ----------
@NeedsPermission(Manifest.permission.CAMERA)
fun showCamera() {
isCameraAllowed = true
startNextActivity()
}

// @OnShowRationale(Manifest.permission.CAMERA)
// fun showRationaleForCamera(request: PermissionRequest) {
// showRationaleDialog("Reason to use camera access.",request)
// }

@OnPermissionDenied(Manifest.permission.CAMERA)
fun onCameraDenied() {
isCameraAllowed = false
startNextActivity()
}

@OnNeverAskAgain(Manifest.permission.CAMERA)
fun onCameraNeverAskAgain() {
isCameraAllowed = false
startNextActivity()
}

private fun startPermissionCheck() {
showWriteExternalStorageWithPermissionCheck()
}

private fun startNextActivity() {

if ((isCameraAllowed == true) && (isWriteExternalStorageAllowed == true)) {

// Every permission are set, moving to the next step
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
} else {

// Not enough permissions, finish with some message
if (!isCameraAllowed)
Log.d("CAM", "No")
if (!isWriteExternalStorageAllowed)
Log.d("STO", "No")

AlertDialog.Builder(this)
.setPositiveButton(android.R.string.cancel) { _, _ ->
finish()
}
.setNegativeButton(R.string.button_name_app_info) { _, _ ->
val uriString = "package:$packageName"
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse(uriString))
startActivityForResult(intent, REQUEST_CODE_MAGIC)
}
.setCancelable(false)
.setMessage(R.string.alert_diaglog_message_for_permission)
.show()
}
}

override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
super.onActivityResult(requestCode, resultCode, intent)

if (requestCode == REQUEST_CODE_MAGIC) {
// Start again
startPermissionCheck()
}
}
}



情報源