LoginSignup
7
2

More than 3 years have passed since last update.

react-native-permmisionsを使用したパーミッションリクエストについて

Last updated at Posted at 2021-02-19

環境

ReactNative 0.63.4
react-native-permissions 3.0.0

インストール

$ npm i react-native-permissions
$ cd ios
$ pod install

iOS設定

Podfileに追加。今回はカメラを追加します。

ios/Podfile
  permissions_path = '../node_modules/react-native-permissions/ios'
    pod 'Permission-Camera', :path => "#{permissions_path}/Camera"

Info.plistに必要なパーミッションの説明文を追加します。

ios/project/Info.plist
    <key>NSCameraUsageDescription</key>
    <string>カメラへのアクセスを許可することでこのアプリの機能を使用することができます。</string>

Android設定

android/app/src/main/AndroidManifest.xml
  <uses-permission android:name="android.permission.CAMERA" />

パーミッションフローの理解

下記フローチャートは公式より
checkメソッドでアプリのパーミッションステータスを確認して返り値に応じてrequestメソッドでリクエストするという流れになります。

iOS flow

iOSは一度ユーザに「許可しない」を選択されるとリクエストすることができません。

   ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
   ┃ check(PERMISSIONS.IOS.CAMERA) ┃
   ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
                   │
       デバイスで機能が利用できるか?
                   │           ╔════╗
                   ├───────────║ NO ║──────────────┐
                   │           ╚════╝              │
                ╔═════╗                            ▼
                ║ YES ║                 ┌─────────────────────┐
                ╚═════╝                 │ RESULTS.UNAVAILABLE │
                   │                    └─────────────────────┘
       パーミッションリクエストが可能か?
                   │           ╔════╗
                   ├───────────║ NO ║──────────────┐
                   │           ╚════╝              │
                ╔═════╗                            ▼
                ║ YES ║                  ┌───────────────────┐
                ╚═════╝                  │ RESULTS.BLOCKED / │
                   │                     │ RESULTS.LIMITED / │
                   │                     │  RESULTS.GRANTED  │
                   ▼                     └───────────────────┘
          ┌────────────────┐
          │ RESULTS.DENIED │
          └────────────────┘
                   │
                   ▼
  ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
  ┃ request(PERMISSIONS.IOS.CAMERA) ┃
  ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
                   │
         ユーザがリクエストを許可したか?
                   │           ╔════╗
                   ├───────────║ NO ║──────────────┐
                   │           ╚════╝              │
                ╔═════╗                            ▼
                ║ YES ║                   ┌─────────────────┐
                ╚═════╝                   │ RESULTS.BLOCKED │
                   │                      └─────────────────┘
                   ▼
          ┌─────────────────┐
          │ RESULTS.GRANTED │
          └─────────────────┘

Android flow

Androidは一度リクエストが拒否されても「今後は確認しない」にチェックを付けない限り何度でもリクエストすることができましたが、Android11以降はユーザが2回「許可しない」を選択した場合、パーミッションリクエストのダイアログを表示することができなくなりました。
Android 11 での権限に関する更新

 ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
 ┃ check(PERMISSIONS.ANDROID.CAMERA) ┃
 ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
                   │
       デバイスで機能が利用できるか?
                   │           ╔════╗
                   ├───────────║ NO ║──────────────┐
                   │           ╚════╝              │
                ╔═════╗                            ▼
                ║ YES ║                 ┌─────────────────────┐
                ╚═════╝                 │ RESULTS.UNAVAILABLE │
                   │                    └─────────────────────┘
      パーミッションリクエストが可能か?
                   │           ╔════╗
                   ├───────────║ NO ║──────────────┐
                   │           ╚════╝              │
                ╔═════╗                            ▼
                ║ YES ║                  ┌───────────────────┐
                ╚═════╝                  │ RESULTS.BLOCKED / │
                   │                     │  RESULTS.GRANTED  │
                   ▼                     └───────────────────┘
          ┌────────────────┐
          │ RESULTS.DENIED │◀──────────────────────┐
          └────────────────┘                       │
                   │                               │
                   ▼                               │
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓         ╔════╗
┃ request(PERMISSIONS.ANDROID.CAMERA) ┃         ║ NO ║
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛         ╚════╝
                   │                               │
   ユーザがリクエストを許可したか?                     │
                   │                               │
                   │           ╔════╗              │
                   ├───────────║ NO ║─────「今後は確認しない」にチェックを付けたか?
                   │           ╚════╝              │
                ╔═════╗                         ╔═════╗
                ║ YES ║                         ║ YES ║
                ╚═════╝                         ╚═════╝
                   │                               │
                   ▼                               ▼
          ┌─────────────────┐             ┌─────────────────┐
          │ RESULTS.GRANTED │             │ RESULTS.BLOCKED │
          └─────────────────┘             └─────────────────┘

主なAPI

check

パーミッション状態を確認する。

返り値 説明
RESULTS.UNAVAILABLE デバイスで使用不可
RESULTS.DENIED パーミッションリクエストされていない/リクエストできるが拒否された
RESULTS.GRANTED パーミッションが許可されている
RESULTS.LIMITED パーミッションが許可されているが制限されている
RESULTS.BLOCKED パーミッションが許可されていないかつリクエスト不可

request

パーミッションリクエストを送る。
第2引数のrationalはパーミッションが許可されず再度リクエストされた際になぜその権限が必要なのかユーザに説明するための表示として使用されます(Androidのみ)。
https://reactnative.dev/docs/permissionsandroid#request

openSettings

アプリの設定画面を開く。パーミッションリクエストが許可されなかったときに、ユーザに設定画面から許可してもらうよう促す際に使用する。

サンプル

App.js
import React from 'react';
import {SafeAreaView, Button, Alert, Platform} from 'react-native';
import {
  check,
  openSettings,
  PERMISSIONS,
  request,
  RESULTS,
} from 'react-native-permissions';

const App: () => React$Node = () => {
  return (
    <SafeAreaView
      style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
      <Button
        title="request camera permission"
        onPress={async () => {
          const result =
            Platform.OS === 'ios' ? await requestIOS() : await requestAndroid();
          console.log(result);
        }}
      />
    </SafeAreaView>
  );
};

const promptForPermission = () => {
  Alert.alert(
    'カメラを使用する',
    '設定からカメラのアクセスを許可してください',
    [
      {
        text: '設定画面を開く',
        onPress: async () => await openSettings(),
      },
      {
        text: '閉じる',
      },
    ],
  );
};

const requestIOS = async () => {
  const cameraPermissionStatus = await check(PERMISSIONS.IOS.CAMERA);

  if (cameraPermissionStatus === RESULTS.UNAVAILABLE) {
    Alert.alert('デバイスのカメラを使用することが出来ません');
    return false;
  }

  // リクエスト不可
  if (cameraPermissionStatus === RESULTS.BLOCKED) {
    // アプリの機能を利用できるように設定から権限を変更するようユーザに促すダイアログを表示させる
    promptForPermission();
    return false;
  }

  // リクエスト可能
  if (cameraPermissionStatus === RESULTS.DENIED) {
    // リクエスト結果
    const cameraPermissionRequestResult = await request(PERMISSIONS.IOS.CAMERA);

    return cameraPermissionRequestResult === RESULTS.GRANTED;
  }

  return true;
};

const requestAndroid = async () => {
  const cameraPermissionStatus = await check(PERMISSIONS.ANDROID.CAMERA);

  if (cameraPermissionStatus === RESULTS.UNAVAILABLE) {
    Alert.alert('デバイスのカメラを使用することが出来ません');
    return false;
  }

  // リクエスト不可
  if (cameraPermissionStatus === RESULTS.BLOCKED) {
    promptForPermission();
    return false;
  }

  // リクエスト可能(初回パーミッションリクエスト)
  if (cameraPermissionStatus === RESULTS.DENIED) {
    const cameraPermissionRequestResult = await request(
      PERMISSIONS.ANDROID.CAMERA,
    );
    // 許可する
    if (cameraPermissionRequestResult === RESULTS.GRANTED) {
      return true;
    }
    // 「今後表示しない」にチェックをつけて許可しない
    if (cameraPermissionRequestResult === RESULTS.BLOCKED) {
      promptForPermission();
      return false;
    }
    // 許可しない
    return false;
  }

  return true;
};

export default App;

重要なこと

  • パーミッションを必要最小限にする
  • ユーザが必要とするまでパーミッションをリクエストしない
  • なぜそのパーミッションが必要なのかリクエストする前にユーザに説明する

参考

Request app permissions | Android Developers
Privacy best practices | Android Developers
Requesting Permission - App Architecture - iOS - Human Interface Guidelines - Apple Developer

7
2
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
7
2