Closed6

Flutter の permission_handler の学習

高田 晴彦高田 晴彦

概要

Flutter でカメラを使った機能を開発するにあたり、その前提となる実行時の権限について学習する。
Android エンジニアなので Android については厚めに書いている一方、iOS については記述が薄め。

実行時の権限とは

Android

権限の種類

種類 解説
インストール時の権限 ユーザーのプライバシーや他のアプリのオペレーションへのリスクはほとんど無い。 インターネット接続
実行時の権限 プライバシーにアクセスする権限 カメラ
特別な権限 プライバシーに関係しないが、システムに対して特別なアクセスを行う アラーム、他のアプリの上に重ねて表示

インストール時の権限

インストールしたときに許可されたことになっている。Google Play でインストール前に確認することができる。

※ スクリーンショットは前々職で担当していたアプリ「CODE

実行時の権限

実行時の権限をシステムにリクエストすると、このようなダイアログが表示される。

  • ユーザが「アプリ使用時のみ」または「今回のみ」をクリックすれば権限を取得できる。
  • 「今回のみ」で得た権限は一度アプリのプロセスが終了すると失効する。

iOS

Android のような権限の種類は無い。カメラなど、プライバシーにアクセスする場合は、システムに許可を求めて、表示されたダイアログでユーザが「許可」をクリックする必要がある。

高田 晴彦高田 晴彦

Flutter の permission_handler パッケージ

クロスプラットフォームな実行時の権限を得るためのパッケージ。非公式なパッケージだが ChatGPT 情報では公式のものは無く、事実上のデファクトスタンダードとして扱われていそう。

高田 晴彦高田 晴彦

実装方法

permission_handler パッケージを追加

flutter pub add permission_handler

Android

android/app/src/main/AndroidManifest.xml ファイルにカメラ権限を追加

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 略 -->
    <uses-permission android:name="android.permission.CAMERA"/>
</manifest>

実行時の権限を取得する Dart コード

await Permission.camera
  .onGrantedCallback(() {
    // 権限取得できた、または、すでにしている。
  })
  .onDeniedCallback(() {
    // 今回は拒否された
  })
  .onPermanentlyDeniedCallback(() {
    // 永久に拒否されている
  })
  .request();

onRestrictedCallback, onLimitedCallback, onProvisionalCallback もあるが、今回は割愛

iOS

公式ドキュメントの Setup > iOS (click to expand) に従い設定する。

Info.plist

Podfile

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    # 追記
    target.build_configurations.each do |config|
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
         '$(inherited)',
         'PERMISSION_CAMERA=1',
       ]
    end
  end
end

app/ios ディレクトリで pod install コマンドを実行する。

高田 晴彦高田 晴彦

各コールバックが呼ばれる条件

Android

onGrantedCallback

  • 「アプリ使用時のみ」または「今回のみ」が選択されたときに呼ばれる。
  • 一度、選択された場合は、次回以降、ダイアログ無しで、こちらのコールバックが呼ばれる。

onDenitedCallback

  • 初めて「許可しない」が選択されたときに呼ばれる。

onPermanentlyDeniedCallback

  • 「許可しない」が2度が選択されたときに呼ばれる。
  • 3回目以降は「許可しますか?」ダイアログは表示されず、すぐにこちらのコールバックが呼ばれる。

iOS

onGrantedCallback

  • 「許可」が選択されたときに呼ばれる。
  • 一度、選択された場合は、次回以降、ダイアログ無しで、こちらのコールバックが呼ばれる。

onPermanentlyDeniedCallback

  • 「許可しない」が選択されたときに呼ばれる。
  • 一度許可した後、本体設定で許可を OFF にしても呼ばれる。

  • 本体設定 - アプリ設定の「カメラ」項目は1度「カメラへのアクセスを求めています」ダイアログを出さないと表示されない。
高田 晴彦高田 晴彦

onPermanentlyDeniedCallback が呼ばれてしまうときの対処方法

ユーザに本体設定のアプリ情報画面で権限を付与することを案内した上で、その画面を呼び出す。

Flutter では permission_handler パッケージの openAppSettings() メソッドで呼び出すことができる。

高田 晴彦高田 晴彦

参考・Android ネイティブの場合の実装方法

結果受け取り可能な Launcher を作成する。

class SomeActivity : AppCompatActivity() {

    val requestPermissionLauncher = registerForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) { isGranted: Boolean ->
        if (isGranted) {
            // 権限取得できた、または、すでにしている。
        } else if (ActivityCompat.shouldShowRequestPermissionRationale(
                this,
                Manifest.permission.CAMERA
            )
        ) {
            // 永久に拒否されている
        } else {
            // 今回は拒否された
        }
    }
}

権限要求

requestPermissionLauncher.launch(Manifest.permission.CAMERA)

アプリ設定画面を開く

// アプリ設定画面を開く
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
intent.data = Uri.parse("package:$packageName")
startActivity(intent)
このスクラップは2025/02/14にクローズされました