apache / cordova-plugin-file

Apache Cordova File Plugin
https://cordova.apache.org/
Apache License 2.0
740 stars 757 forks source link

Android 13 - Write Permissions - open question #585

Closed MauriceFrank closed 9 months ago

MauriceFrank commented 9 months ago

Is there any alternative to request MANAGE_APP_ALL_FILES_ACCESS_PERMISSION to grant an application to delete files in the gallery(pictures) folder?

I did not find any working cordova-plugin using the SAF or Media-Store API so far.

I am happy for any help, thank you!

chiraganand commented 9 months ago

The MediaStore API has CreateDeleteRequest. Usage is described here: https://developer.android.com/training/data-storage/shared/media#remove-item

MauriceFrank commented 9 months ago

Hey! Thanks!

Do you also know if I can use the PermissionHelper in the file-plugin itself to request the following? MANAGE_EXTERNAL_STORAGE

I tried in the file-plugin:

private void getWritePermission(String rawArgs, int action, CallbackContext callbackContext) {
    int requestCode = pendingRequests.createRequest(rawArgs, action, callbackContext);
    // MANAGE_EXTERNAL_STORAGE on SDK33
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
      PermissionHelper.requestPermission(this, requestCode, Manifest.permission.MANAGE_EXTERNAL_STORAGE);
    } else {
      PermissionHelper.requestPermission(this, requestCode, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }
}

private boolean hasWritePermission() {
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
      return PermissionHelper.hasPermission(this, Manifest.permission.MANAGE_EXTERNAL_STORAGE);
    } else {
      return PermissionHelper.hasPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }
}

And in the remove-action:

else if (action.equals("remove")) {
    threadhelper(new FileOp() {
        public void run(JSONArray args)
            throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException, InvalidModificationException, MalformedURLException {
          String fname = args.getString(0);
          String nativeURL = resolveLocalFileSystemURI(fname).getString("nativeURL");
          if (needPermission(nativeURL, WRITE)) {
            getWritePermission(rawArgs, ACTION_WRITE, callbackContext);
          } else {
            boolean success = remove(fname);
            if (success) {
              callbackContext.success();
            } else {
              callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR);
            }
          }
        }
      }, rawArgs, callbackContext);
}

And in the config.xml file: `

`

What did I forget? It throws "vendor.js:90891 ERROR Error: Uncaught (in promise): FileError: {"code":2,"message":"SECURITY_ERR"}" when triggering the remove-action.

Expected would be the native popup/view which will ask the user to grant the MANAGE_EXTERNAL_STORAGE.

MauriceFrank commented 9 months ago

I think I found a proposal. Seems like it is only possible via intent, not requesting as permission: https://ourcodeworld.com/articles/read/1559/how-does-manage-external-storage-permission-work-in-android

breautek commented 9 months ago

Two things about MANAGE_EXTERNAL_STORAGE

  1. The permission is suppose to allow broad programmatic access to files, similar to older API levels. Declaring the permisison is not enough however. The user must explicitly configure your app to allow broad filesystem access. This isn't done through a permission prompt. What the MANAGE_EXTERNAL_STORAGE permission declaration effectively does is make the Android OS produce settings UI to allow your app to have broad filesystem access. The user must still enable your app in the android settings.

The app can produce an Intent to direct users to this settings screen:

Use the ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION intent action to direct users to a system settings page where they can enable the following option for your app: Allow access to manage all files.

Examples of such apps that Google will deem acceptable is:

  1. MANAGE_EXTERNAL_STORAGE is protected, which means if you declare this permission then Google expects justification. If you intend to deploy through the Google Play store, you'll have to provide Google an explanation on why you need the permission.

So depending on the nature of the app, using MANAGE_EXTERNAL_STORAGE may not be viable, in which case you need to use the MediaStore API as noted here.

The file plugin doesn't make use of the MediaStore API and for the limitations noted above, it also cannot make use of MANAGE_EXTERNAL_STORAGE permission.

I'm closing because there is nothing actionable for the file plugin here. A better area for open-ended discussions is Apache Cordova Discussions.