如何在没有权限拒绝的情况下通过存储在数据库中的 URI 从库中加载图像
How can I load Images from the Gallery by URIs stored in the db without permission denial
我目前正在创建自己的图库应用程序。我使用一个自定义对象,它包含画廊的所有必需信息,包括来自本地 android 画廊的图像的 url。
public class GalleryDTO {
private Long id;
private String name;
private List<Uri> photos = new ArrayList<>();
我将这个图库对象存储在 sql 精简版数据库中。
我有一个 activity 可以查看此图库对象。在此 activity 中,我加载了我想要显示的画廊 - 这有效。
但是当尝试加载图像时:
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" />
对于在查看之前刚刚保存的画廊,不会发生此异常。但是当我关闭我的应用程序(例如使用任务管理器)并重新打开它时,这些新画廊也会抛出异常。
我哪里错了?
I store this gallery object in a sql lite db.
这在很多情况下是行不通的。
将 Uri
视为类似于网络应用程序中经过用户验证的 URL。 URL 现在可能有用 ,但是一旦用户的会话超时,URL 就变得无用了。同样的道理在这里也适用:默认情况下,Uri
可能只有在您的进程终止之前才有用。
Then the following exception is thrown :
那是因为您对该 Uri
的权利已过期,可能是因为您的进程已终止。
此外,请记住 Uri
可能会因其他原因而失效,例如:
用户删除了内容
用户移动了内容,Uri
现在会有所不同
给你 Uri
的应用程序只保留本地内容缓存,它最终会将该内容从缓存中逐出,要求重新下载
What do I am wrong?
你假设 Uri
永远存在。
你可以try takePersistableUriPermission()
。这将需要 minSdkVersion
19 (Android 4.4+),可能不适用于许多 Uri
值(因为提供者不提供持久权限),并且它不会解决所有问题问题(例如,用户删除了内容)。
或者,您可以在获得 Uri
后立即制作自己的内容本地副本,而不是依赖其他应用程序的 Uri
值。
我目前正在创建自己的图库应用程序。我使用一个自定义对象,它包含画廊的所有必需信息,包括来自本地 android 画廊的图像的 url。
public class GalleryDTO {
private Long id;
private String name;
private List<Uri> photos = new ArrayList<>();
我将这个图库对象存储在 sql 精简版数据库中。
我有一个 activity 可以查看此图库对象。在此 activity 中,我加载了我想要显示的画廊 - 这有效。
但是当尝试加载图像时:
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" />
对于在查看之前刚刚保存的画廊,不会发生此异常。但是当我关闭我的应用程序(例如使用任务管理器)并重新打开它时,这些新画廊也会抛出异常。
我哪里错了?
I store this gallery object in a sql lite db.
这在很多情况下是行不通的。
将 Uri
视为类似于网络应用程序中经过用户验证的 URL。 URL 现在可能有用 ,但是一旦用户的会话超时,URL 就变得无用了。同样的道理在这里也适用:默认情况下,Uri
可能只有在您的进程终止之前才有用。
Then the following exception is thrown :
那是因为您对该 Uri
的权利已过期,可能是因为您的进程已终止。
此外,请记住 Uri
可能会因其他原因而失效,例如:
用户删除了内容
用户移动了内容,
Uri
现在会有所不同给你
Uri
的应用程序只保留本地内容缓存,它最终会将该内容从缓存中逐出,要求重新下载
What do I am wrong?
你假设 Uri
永远存在。
你可以try takePersistableUriPermission()
。这将需要 minSdkVersion
19 (Android 4.4+),可能不适用于许多 Uri
值(因为提供者不提供持久权限),并且它不会解决所有问题问题(例如,用户删除了内容)。
或者,您可以在获得 Uri
后立即制作自己的内容本地副本,而不是依赖其他应用程序的 Uri
值。