【问题标题】:java.lang.SecurityException when using "grantUriPermission" on URI在 URI 上使用“grantUriPermission”时出现 java.lang.SecurityException
【发布时间】:2018-01-28 09:34:33
【问题描述】:

我的应用收到了几份崩溃报告,邮件为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

【问题讨论】:

  • Noguat 设备崩溃??如果是这样,请查看此博客link
  • 你的uri 喜欢什么?尝试致电Log.d 并观看日志猫
  • 我无法检查导致崩溃的设备中的 URI。在我的开发设备上,URI 类似于: content://com.android.providers.media.documents/document/image%3A796
  • 您不拥有 com.android.providers.media.documents 内容提供者,因此您无法授予该 uri 的任何权利
  • 但在我的开发设备上它运行良好(3 个智能手机和 1 个平板电脑)。您的意思是 URI 在其他设备中有所不同吗? content://com.android.providers.media.documents/document/ima‌​ge%3A796 是关于我的一台设备的示例,但我认为它会在其他制造商的设备上发生变化。

标签: android android-intent android-permissions android-image


【解决方案1】:

您不能向自己授予权限。

您要求其他应用(例如 Gallery)为您提供资源的 Uri,如果该应用编写得很好,它将在返回时授予您的应用对该 Uri 的读取权限。

很遗憾,某些图库应用(包括知名 Android 手机制造商的应用)并没有为您提供任何帮助。

这就是我们最终不得不请求READ_EXTERNAL_STORAGE 许可的方式。这也意味着您需要在适当的时候请求 Android 6+ 上的运行时权限。

我最终抓住了SecurityException 并在那一刻请求运行时权限 - 当我绝对需要它的时候。

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

【讨论】:

  • 图像选择是使用画廊或我想的其他 Android 内部方式执行的。我使用a.startActivityForResult(Intent.createChooser(intent,"Select Picture"), Communication.REQUEST_SELECT_IMAGES_FROM_GALLERY); 实现它,您可以在主帖中阅读。
  • @Noisemaker 我知道,该画廊负责授予您 Uri 权限。您显然不能向自己授予 Uri 权限。要么您有权读取任何内容(在 Android 6+ 上的清单和运行时),要么您在请求 Uri 时被另一个应用程序(如 Gallery)授予读取 Uri 的权限,或者您没有完全许可。当您没有权限时,您无法将其授予自己。那有意义吗? 你不要打电话给grantUriPermission,画廊应该这样做。
  • 如果其他应用程序在您的应用程序中向您的内容提供商请求图像,您调用grantUriPermission。不是相反。
  • 当我阅读此页面https://developer.android.com/guide/topics/providers/document-provider.html 时,虽然我的应用程序应该调用方法grantUriPermission 以实现对这些文件的持久权限。
  • @Noisemaker 在该页面上没有提到grantUriPermission。它只提到了 takePersistableUriPermission,但只有在另一个应用程序调用 grantUriPermission 时才有效,事实并非如此。
猜你喜欢
  • 2018-06-19
  • 2011-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-19
相关资源
最近更新 更多