LoginSignup
4
6

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-04-18

概要

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()
        }
    }
}

情報源

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6