Android 使用“java.lang.SecurityException”时发生异常;grantUriPermission“;关于URI

Android 使用“java.lang.SecurityException”时发生异常;grantUriPermission“;关于URI,android,android-intent,android-permissions,android-image,Android,Android Intent,Android Permissions,Android Image,我收到了我的应用程序发出的几个崩溃报告,报告中带有java.lang.SecurityException。当应用程序尝试获取用户从其图像中选择的图像URI的持久权限时,会发生这种情况。 选择图像的方法是通过意图: public static Intent openGalleryToSelectImages(Activity a) { Intent intent = new Intent(); // Set action if( Build.VERSION.SDK_INT

我收到了我的应用程序发出的几个崩溃报告,报告中带有
java.lang.SecurityException
。当应用程序尝试获取用户从其图像中选择的图像URI的持久权限时,会发生这种情况。 选择图像的方法是通过意图:

public static Intent openGalleryToSelectImages(Activity a)
{
    Intent intent = new Intent();
    // Set action
    if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
        intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
    }
    else {
        intent.setAction(Intent.ACTION_GET_CONTENT);
    }
    // Set MIME type and allow multiple selection
    intent.setType("image/*");
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
        intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
    }
    a.startActivityForResult(Intent.createChooser(intent,"Select Picture"), Communication.REQUEST_SELECT_IMAGES_FROM_GALLERY);

    return intent;
}
然后在接收到的URI数组上执行一些操作。 当我尝试获取每个URI的持久读取权限时,就会发生崩溃:

activity.grantUriPermission(activity.getPackageName(), uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
activity.getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
但我不知道这有什么问题。 由于沉迷于此,该应用程序在多部智能手机上运行良好,因此似乎与特定的供应商有关

编辑: 我无法对导致崩溃的设备进行深入分析。 在我的开发设备上,图像的URI类似于:

content://com.android.providers.media.documents/document/image%3A796

您不能向自己授予权限

您要求另一个应用程序(如Gallery)为您提供资源的Uri,如果该应用程序编写良好,它将在返回时授予您的应用程序对该Uri的读取权限

不幸的是,一些图库应用程序(包括一家著名的安卓手机制造商的图库应用程序)没有给你任何东西

这就是为什么我们最终不得不请求
读取外部存储
权限。这还意味着您需要在适当的时候请求Android 6+上的运行时权限

我最终发现了
SecurityException
,并在那一刻请求运行时权限——当时我绝对需要它


惨痛的教训:当您在
onRequestPermissionsResult
中获得积极结果时,您的活动处于停止状态。您无法保存状态,如果立即离开(如在回调中调用
startActivity
),将丢失对成员变量的任何更改。现在将您需要的内容放入成员变量中,但将
startActivity
延迟到
onResume

在Noguat设备中崩溃??如果是这样,请查看此博客。您的
uri
是什么样的?尝试调用
Log.d
并查看日志CATI无法检查导致崩溃的设备中的URI。在我的开发设备上,URI类似于:content://com.android.providers.media.documents/document/image%3A796you 不要拥有
com.android.providers.media.documents
content provider,因此您无法授予该内容提供商任何权限,但在我的开发设备上,它可以正常工作(3部智能手机和1部平板电脑)。您的意思是URI在其他设备中不同吗?
content://com.android.providers.media.documents/document/ima‌​ge%3A796
是关于我的一台设备的一个例子,但我认为它会在其他制造商的设备上发生变化。我认为图像选择是使用Gallery或其他Android内部方式执行的。我使用
a.startActivityForResult(Intent.createChooser(Intent,“Select Picture”),Communication.REQUEST\u Select\u IMAGES\u FROM\u GALLERY)实现它正如你们在主帖中看到的。@Noisemaker我知道,那个画廊负责授予你们Uri权限。显然,您不能向自己授予Uri权限。要么你拥有读取任何内容的权限(在Android 6+上的清单和运行时),要么你在请求Uri时被另一个应用程序(如Gallery)授予读取Uri的权限,要么你根本没有权限。当你没有许可的时候,你不能把它授予你自己。这有意义吗?您不需要调用
grantUriPermission
,Gallery应该这样做。如果其他应用程序请求您的应用程序中的内容提供商提供图像,您可以调用
grantUriPermission
。反之亦然。当我阅读此页面时,我认为我的应用程序应该调用方法
grantUriPermission
,以获得对这些文件的持久权限。@Noisemaker在该页面上没有提到
grantUriPermission
。它只提到了
takePersistableUriPermission
,但只有在另一个名为
grantUriPermission
的应用程序中才起作用,事实并非如此。