I'm currently creating my own gallery app. I use a custom object which holds all required information for a gallery including urls of the images from the local android gallery.
public class GalleryDTO {
private Long id;
private String name;
private List<Uri> photos = new ArrayList<>();
I store this gallery object in a sql lite db.
I have an activity to view this gallery objects. In this activity I load the gallery I want do display - this works.
But when try to load the images:
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);
Then the following exception is thrown :
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
even I declared the required rights in the manifest:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
This exception does not occur for galleries which where just saved before viewing them. But when I close my app (e.g. with the task manager) and reopen it then the exception is thrown for these new galleries too.
What do I am wrong?
I store this gallery object in a sql lite db.
That is not going to work in many cases.
Think of a Uri
as being akin to a user-authenticated URL in a Web app. The URL may be useful now, but as soon as the user's session times out, the URL becomes useless. The same thing holds true here: by default, a Uri
may only be useful until your process terminates.
Then the following exception is thrown :
That is because your rights to that Uri
expired, probably because your process was terminated.
Also, bear in mind that the Uri
may become invalid for other reasons, such as:
The user deleted the content
The user moved the content, and the Uri
would now be different
The app that gave you the Uri
is only keeping a local cache of content, and it eventually evicts this content out of that cache, requiring it to be downloaded again
What do I am wrong?
You are assuming that a Uri
lives forever.
You can try takePersistableUriPermission()
. This will require a minSdkVersion
of 19 (Android 4.4+), may not work on many Uri
values (because the provider is not offering persistable permissions), and it will not solve all of the problems (e.g., user deleted the content).
Or, you can make your own local copy of the content as soon as you get a Uri
, rather than relying upon Uri
values from other apps.