如何在没有权限拒绝的情况下通过存储在数据库中的URI从库中加载图像

时间:2016-03-30 18:46:19

标签: android android-contentprovider android-bitmap

我目前正在创建自己的图库应用。我使用一个自定义对象,它包含一个库的所有必需信息,包括来自本地android库的图像的URL。

public class GalleryDTO {
   private Long id;
   private String name;
   private List<Uri> photos = new ArrayList<>();

我将此图库对象存储在sql lite db中。

我有一个活动来查看此图库对象。在这个活动中,我加载了我想要显示的图库 - 这很有用。

但是当试图加载图片时:

   GalleryDTO galleryDTO=vrGalleryApp.getGalleryService().loadGalleryById(displayedGalleryId);

    if(galleryDTO.getPhotos()!=null&&!galleryDTO.getPhotos().isEmpty()){
        for(int i=0;i<galleryDTO.getPhotos().size();i++){
            Uri imageUrl = galleryDTO.getPhotos().get(i);
            try {
                Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(),  imageUrl);

然后抛出以下异常:

java.lang.SecurityException: Permission Denial: opening provider com.google.android.apps.photos.contentprovider.MediaContentProvider from ProcessRecord{3585e48d 8727:at....vrgallery.vrgallery/u0a137} (pid=8727, uid=10137) that is not exported from uid 10071

即使我在清单中声明了所需的权利:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

在查看之前刚刚保存的图库不会发生此异常。但是当我关闭我的应用程序(例如使用任务管理器)并重新打开它时,这些新画廊也会抛出异常。

我错了什么?

1 个答案:

答案 0 :(得分:1)

  

我将此图库对象存储在sql lite db中。

在许多情况下,这不会起作用。

export function func1() { ... } export function func2() { ... } // or if you need to rename them: export default { funcA: func1, funcB: func2 }; 视为类似于Web应用中用户身份验证的URL。该网址可能很有用现在,但只要用户的会话超时,网址就会变得无用。同样的事情也适用于此:默认情况下,Uri可能只有在您的流程终止之前才有用。

  

然后抛出以下异常:

这是因为您对Uri的权利已过期,可能是因为您的流程已终止。

另外,请注意Uri可能因其他原因而无效,例如:

  • 用户删除了内容

  • 用户移动了内容,Uri现在不同了

  • 为您提供Uri的应用只保留内容的本地缓存,最终将此内容从该缓存中删除,要求再次下载

  

我错了什么?

您假设Uri永远存在。

你可以try takePersistableUriPermission()。这将需要Uri 19(Android 4.4+),可能无法处理许多minSdkVersion值(因为提供商不提供持久权限),并且它不会解决所有问题(例如,用户删除了内容)。

或者,您可以在获得Uri后立即制作自己的内容本地副本,而不是依赖其他应用的Uri值。