1

在 Android os 5.11(可能还有其他操作系统)上,当使用 Intent.ACTION_GET_CONTENT 列出带有 Android 系统文件选择器的文件时,

Intent openIntent = new Intent(Intent.ACTION_GET_CONTENT);
openIntent.addCategory(Intent.CATEGORY_OPENABLE);
openIntent.setType("*/*");
startActivityForResult(openIntent, ANDROID_FILE_PICKER);

在 void onActivityResult() 中,它得到了 SecurityException:

“权限拒绝:打开提供程序 com.google.android.apps.docs.storagebackend.StorageBackendContentProvider... 需要 android.permission.MANAGE_DOCUMENTS”

该异常的解决方法是:

Intent openIntent = new Intent(Intent.ACTION_GET_CONTENT);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        openIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        openIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }
    openIntent.addCategory(Intent.CATEGORY_OPENABLE);
    openIntent.setType("*/*");
    startActivityForResult(openIntent, ANDROID_FILE_PICKER);

在 onActivityResult() 中,执行:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
     int takeFlags = data.getFlags();
     takeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
     getContentResolver().takePersistableUriPermission(uri, takeFlags);

它解决了权限问题。

但更糟糕的是,从使用 Intent.ACTION_GET_CONTENT 更改为 Intent.ACTION_OPEN_DOCUMENT 会导致 Android 的系统文件选择器菜单不显示内容提供者,如 Dropbox、Photos 等。

(正如谁在使用 ACTION_OPEN_DOCUMENT 显示更多提供者中指出的那样)。

所以问题是它是否必须使用 Intent.ACTION_GET_CONTENT 列出 Dropbox 等,但是如何避免出现 SecurityException?

4

1 回答 1

1

似乎这有效。如果有人知道,必须有更好的解决方案:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    try {
        this.grantUriPermission(
                this.getPackageName(),
                uri,
                Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
        );
    } catch (IllegalArgumentException e) {
        this.grantUriPermission(
                this.getPackageName(),
                uri,
                Intent.FLAG_GRANT_READ_URI_PERMISSION
        );  // kikat api only 0x3 are
        // allowed FLAG_GRANT_READ_URI_PERMISSION = 1 | FLAG_GRANT_WRITE_URI_PERMISSION = 2;
    } catch (SecurityException e) {
        // ignore
    }

    int takeFlags = data.getFlags();
    takeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

    try {
        getContentResolver().takePersistableUriPermission(uri, takeFlags);
    } catch (SecurityException e) {
        // ignore
    }
}
于 2017-04-18T12:51:39.807 回答