当使用Intent.ACTION_GET_CONTENT时如何避免" SecurityException"

时间:2017-03-03 16:46:47

标签: android android-intent android-contentprovider android-securityexception

在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,照片等。

(正如Who to show more providers with ACTION_OPEN_DOCUMENT所述)。

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

1 个答案:

答案 0 :(得分: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) {

                            }

                            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
                            }
相关问题