PR

[Flutter]Flutter2系での権限(Permission)のリクエスト方法

Flutter

はじめに

以前、「権限(Permission)のリクエスト方法」の記事を書きましたがFlutter2になって試したところ全く動かなくなっていました

なので、今回は改めて権限のリクエストをFlutter2系で実装してみたいと思います。

前回の記事はこちら

環境

  • Flutter 2.2.3
  • permission_handler 8.1.4+2

準備

プラグインの最新バージョンを確認

下記のサイトにアクセスし、バージョンを確認します。

permission_handler | Flutter package
Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions...

記事作成の時点では8.1.4+2が最新バージョンでした

プラグインのインストール

pubspec.yamldependenciesに「permission_handler: ^8.1.4+2」を追記します。もしくは常に最新版を使う設定の「permission_handler: any」を追記します。

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  permission_handler: ^8.1.4+2

その後、プロジェクト配下で「flutter pub get」コマンドを実行

よくわからない場合はAndroid Studiopubspec.yamlファイルを開くと右上に「Pub get」ボタンがあるのでそれを押してください。

これでプラグインのインストールは完了です。

アプリの設定を追加および変更

次にアプリの設定を追加及び変更を行います。

この対応をしないと予期せぬタイミングでアプリがクラッシュするので絶対に対応を行ってください

OS毎に対応する必要があります。

Android

gradle.propertiesに追記

gradle.propertiesに以下を追記してください。

Flutter2系でプロジェクトを作成した場合は既に記述がある場合もあります。

android.useAndroidX=true
android.enableJetifier=true

compileSdkVersionの変更

android/app/build.gradleを開き、compileSdkVersion30に変更してください。

ただし、Flutter2系でプロジェクトを作成した場合は既に変更されている場合もあります。

android {
  compileSdkVersion 30
  ...
}

android.の依存関係を修正

Androidで使われているandroid.の依存関係を全てAndroidX(androidx.)へ変更してください。

Flutter2系でプロジェクトを作成した場合は既に対応されているので特に何もする必要はありません

やり方はAndroidの公式のサイトを参考にしてください

Migrate to AndroidX  |  Jetpack  |  Android Developers

AndroidManifest.xmlに必要な権限(Permission)を追加

android/app/src/main/AndroidManifest.xmlに使いたい権限を追加してください。

debugprofileフォルダにもAndroidManifest.xmlはありますが、基本的にはmainフォルダのものに対応すれば平気です。

例えばカメラBluetoothの権限を付与したい場合は、以下のように記述します。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.test">

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

    <application
        android:name="io.flutter.app.FlutterApplication"
        android:icon="@mipmap/ic_launcher"
...

下記のGitHubには全ての権限(Permission)が入ったサンプルがありますので参考にしてみてください。

File not found · Baseflow/flutter-permission-handler
Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions...

これでAndroidは完了です。

iOS

Info.plistに権限(Permission)に説明文を追加

Android StudioでiOSフォルダを右クリックして[Flutter]→[Open iOS module in Xcode]を選択して、Xcodeを開きます。

Xcodeが開いたら、Runner/Runner/Info.plistを開きます。

そこに利用する権限の説明文を追加します。ここに入力する内容はユーザー表示されます。

例えばカメラロールカメラマイクを利用するのであれば以下の3つを追加します。

  • Privacy – Photo Library Usage Description
  • Privacy – Camera Usage Description
  • Privacy – Microphone Usage Description

(オプション)Podfileを編集

多分ですが、この項目はやらなくても平気ですがやることをオススメします。

iOSでアプリを提出する際には利用している全ての権限がInfo.plistには必要です。

この対応をすることで、Info.plistに漏れが合った場合にAssertを表示してくれる仕組みだそうです。

ios/Podfileを開きます。

そしてこの部分を

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
  end
end

下記のようにまずは書き換えます

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)

    target.build_configurations.each do |config|
      # Here are some configurations automatically generated by flutter

      # You can enable the permissions needed here. For example to enable camera
      # permission, just remove the `#` character in front so it looks like this:
      #
      # ## dart: PermissionGroup.camera
      # 'PERMISSION_CAMERA=1'
      #
      #  Preprocessor definitions can be found in: https://github.com/Baseflow/flutter-permission-handler/blob/master/permission_handler/ios/Classes/PermissionHandlerEnums.h
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        '$(inherited)',

        ## dart: PermissionGroup.calendar
        # 'PERMISSION_EVENTS=1',

        ## dart: PermissionGroup.reminders
        # 'PERMISSION_REMINDERS=1',

        ## dart: PermissionGroup.contacts
        # 'PERMISSION_CONTACTS=1',

        ## dart: PermissionGroup.camera
        # 'PERMISSION_CAMERA=1',

        ## dart: PermissionGroup.microphone
        # 'PERMISSION_MICROPHONE=1',

        ## dart: PermissionGroup.speech
        # 'PERMISSION_SPEECH_RECOGNIZER=1',

        ## dart: PermissionGroup.photos
        # 'PERMISSION_PHOTOS=1',

        ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
        # 'PERMISSION_LOCATION=1',

        ## dart: PermissionGroup.notification
        # 'PERMISSION_NOTIFICATIONS=1',

        ## dart: PermissionGroup.mediaLibrary
        # 'PERMISSION_MEDIA_LIBRARY=1',

        ## dart: PermissionGroup.sensors
        # 'PERMISSION_SENSORS=1',

        ## dart: PermissionGroup.bluetooth
        # 'PERMISSION_BLUETOOTH=1',

        ## dart: PermissionGroup.appTrackingTransparency
        # 'PERMISSION_APP_TRACKING_TRANSPARENCY=1',

        ## dart: PermissionGroup.criticalAlerts
        # 'PERMISSION_CRITICAL_ALERTS=1'
      ]

    end
  end
end

そして、必要な権限の部分のコメントアウトを解除(#を取り除く)します。

仮に必要な権限がカメラマイクならばPERMISSION_CAMERAとPERMISSION_MICROPHONEのコメントを解除して以下のようにします。

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)

    target.build_configurations.each do |config|
      # Here are some configurations automatically generated by flutter

      # You can enable the permissions needed here. For example to enable camera
      # permission, just remove the `#` character in front so it looks like this:
      #
      # ## dart: PermissionGroup.camera
      # 'PERMISSION_CAMERA=1'
      #
      #  Preprocessor definitions can be found in: https://github.com/Baseflow/flutter-permission-handler/blob/master/permission_handler/ios/Classes/PermissionHandlerEnums.h
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        '$(inherited)',

        ## dart: PermissionGroup.calendar
        # 'PERMISSION_EVENTS=1',

        ## dart: PermissionGroup.reminders
        # 'PERMISSION_REMINDERS=1',

        ## dart: PermissionGroup.contacts
        # 'PERMISSION_CONTACTS=1',

        ## dart: PermissionGroup.camera
        'PERMISSION_CAMERA=1',

        ## dart: PermissionGroup.microphone
        'PERMISSION_MICROPHONE=1',

        ## dart: PermissionGroup.speech
        # 'PERMISSION_SPEECH_RECOGNIZER=1',

        ## dart: PermissionGroup.photos
        # 'PERMISSION_PHOTOS=1',

        ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
        # 'PERMISSION_LOCATION=1',

        ## dart: PermissionGroup.notification
        # 'PERMISSION_NOTIFICATIONS=1',

        ## dart: PermissionGroup.mediaLibrary
        # 'PERMISSION_MEDIA_LIBRARY=1',

        ## dart: PermissionGroup.sensors
        # 'PERMISSION_SENSORS=1',

        ## dart: PermissionGroup.bluetooth
        # 'PERMISSION_BLUETOOTH=1',

        ## dart: PermissionGroup.appTrackingTransparency
        # 'PERMISSION_APP_TRACKING_TRANSPARENCY=1',

        ## dart: PermissionGroup.criticalAlerts
        # 'PERMISSION_CRITICAL_ALERTS=1'
      ]

    end
  end
end

そして、その後プロジェクト配下で「flutter clean」を実行してください。

よくわからない場合はAndroid Studioから[Tools]→[Flutter]→[Flutter Clean]を実行してください。

これでiOSは完了です。

使い方

権限(Permission)の状態を確認するには以下のようなコードを書きます。

    // カメラの権限の状態を調べる.
   final status = await Permission.camera.status;

statusの種類は

PermissionStatus内容
deniedユーザーが拒否した状態。
grantedユーザーが許可した状態。
restrictedOSによって拒否された状態。iOSのみサポート。
limitedユーザーが制限付きで許可した状態。iOSのみサポート。
permanentlyDeniedユーザーが拒否した状態。この許可を要求する際は許可ダイアログが表示されない。Androidのみサポート

次に許可ダイアログを表示する方法は以下のような2パターンです。

ただし、許可ダイアログは最初の1回しか表示されません

    // カメラの権限をリクエスト
    final status = await Permission.camera.request();

    // カメラの権限をリクエストかつ許可がもらえたかどうかを判定する.
    if (await Permission.camera.request().isGranted) {
        // ここは権限の許可がある状態の処理を書く.
    }

また、複数同時に権限をリクエストすることもできます。

    // カメラとマイクの権限を一気にリクエスト.
    Map<Permission, PermissionStatus> statuses = await [
      Permission.camera,
      Permission.microphone,
    ].request();

他におすすめなのは端末の設定画面を開くこともできます。

openAppSettings();

サンプルコード

import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  void requestPermission() async {
    final status = await Permission.photos.request();
    if (!status.isGranted) {
      await Future.delayed(Duration(seconds: 1));
      openAppSettings();
      return;
    }
    // ここにphotoを使う処理を書く.
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'TEST',
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: requestPermission,
        tooltip: 'Permission',
        child: Icon(Icons.security),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

さいごに

プラグインのメインのバージョンが上がると、とたんに動かなくなるから焦りますよね?

おすすめ参考書

コメント

タイトルとURLをコピーしました