📝

React-Native(expo)でMANAGE EXTERNAL STORAGE権限を要求する方法

2022/02/01に公開

概要

Android11移行からストレージ権限が一種類追加されており、
expo-media-libraryのgetAssetAsyncやreact-native-fsのreadDirでxlsxファイルやpdfファイル等を取得する事が出来なくなっている。
※後日ファイル取得方法も記載予定

MANAGE_EXTERNAL_STORAGE権限の取得方法

AndroidManifest.xmlの修正

AndroidManifest.xml
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

を以下のように修正する。

AndroidManifest.xml
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

上記修正完了後アプリをビルドし直し起動するとアプリのストレージ権限許可欄に「すべてのファイルの管理を許可」という項目が追加される。

Nativeモジュールの作成

MANAGE_EXTERNAL_STORAGEはReact-Native公式でまだサポートされていないため、
ネイティブモジュールで権限問い合わせと権限をリクエストするモジュールの作成が必須である。

以下のディレクトリに今回作成するモジュールを新規作成する。

  • ディレクトリ
    • 「project-name/android/app/src/main/java/projectname」
  • モジュール
    • 「ManagePermissionModule.java」
    • 「ManagePermissionPackage.java」
ManagePermissionModule.java
public class ManageStorageModule extends ReactContextBaseJavaModule {

    private final ReactApplicationContext reactContext;
    private ReactApplicationContext mApplicationContext;

    ManageStorageModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
        mApplicationContext = getReactApplicationContext();
    }

    @Override
    public String getName() {
        return "ManagePermission";
    }

    /**
     * MANAGE_EXTERNAL_STORAGE権限問い合わせ関数
     */
    @RequiresApi(api = Build.VERSION_CODES.R)
    @ReactMethod
    private void getManageStoragePermission(Promise promise) {
        try {
            // true:許可 false:拒否
            promise.resolve(Environment.isExternalStorageManager());
        } catch (Exception error) {
            promise.reject(error);
        }
    }

    /**
     * MANAGE_EXTERNAL_STORAGE権限リクエスト関数
     */
    @RequiresApi(api = Build.VERSION_CODES.R)
    @ReactMethod
    private void requestManageStoragePermission(Promise promise) {
        try {
            Intent intent = new Intent();
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
            Uri uri = Uri.fromParts("package", this.reactContext.getPackageName(), null);
            intent.setData(uri);
            this.reactContext.startActivity(intent);
            promise.resolve(true);
        } catch (Exception error) {
            promise.reject(error);
        }
    }
}
ManagePermissionPackage.java
public class ManagePermissionPackage implements ReactPackage {

  @Override
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    return Collections.emptyList();
  }

  @Override
  public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
    List<NativeModule> modules = new ArrayList<>();
    modules.add(new ManageStorageModule(reactContext));
    return modules;
  }
}

React-Native側での実装

manage-permission.ts
import { NativeModules, Platform } from 'react-native'
if (Platform.OS === 'android') {
  var { ManagePermission } = NativeModules
}

// 権限をネイティブ側に問い合わせる
export async function getManagePermission():Promise<boolean> {
	return await ManagePermission.getManagePermission()
}

// 権限をネイティブ側に要求
export async function requestManageStoragePermission():Promise<boolean> {
	return await ManagePermission.requestManageStoragePermission()
}

上記の関数を実行する事で権限の問い合わせ及び、権限のリクエストを行う事ができる。

Discussion