1

I've already declared READ_EXTERNAL_STORAGE under the Android Manifest using both the tag uses-permission and uses-permission-sdk-23. I've also requested from the user READ_EXTERNAL_STORAGE permissions. I've also, used the flag FLAG_GRANT_READ_URI_PERMISSION.

Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
            photoPickerIntent.setType("image/*");
            photoPickerIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            if (photoPickerIntent.resolveActivity(getPackageManager()) != null) {
                startActivityForResult(photoPickerIntent, REQUEST_IMAGE_GALLERY);
            }

This is how I'm requesting a photo from the user to be retrieved in onActivityResult. I'm also using the glide library to retrieve the photo from the user.

requestMgr.load(new File(uri.getPath())).into(imageView);

That's what's written after I check if the intent I get back from onActivityResult is null.

 if(intent != null){
     Uri uri = intent.getData();
     requestMgr.load(new File(uri.getPath())).into(imageView);
 } else {
     displayImageStorageErrorMessage();
     loadProfileImage();
} 

loadProfileImage() is just a fallback in case anything happens when I try to load the image. Glide.with() is written before the intent is checked because I also use it for when the user wants to take a selfie.

However, the imageView does not display the image that was selected by the user. The result, after I attach a requestlistener to Glide is the following:

java.io.FileNotFoundException: open failed: EACCES (Permission denied)
        at android.os.ParcelFileDescriptor.openInternal(ParcelFileDescriptor.java:315)
        at android.os.ParcelFileDescriptor.open(ParcelFileDescriptor.java:220)
        at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1498)
        at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1420)
        at com.bumptech.glide.load.data.AssetFileDescriptorLocalUriFetcher.loadResource(AssetFileDescriptorLocalUriFetcher.java:20)
        at com.bumptech.glide.load.data.AssetFileDescriptorLocalUriFetcher.loadResource(AssetFileDescriptorLocalUriFetcher.java:11)
        at com.bumptech.glide.load.data.LocalUriFetcher.loadData(LocalUriFetcher.java:44)
        at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:70)
        at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63)
        at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
        at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherFailed(DecodeJob.java:408)
        at com.bumptech.glide.load.engine.SourceGenerator.onLoadFailedInternal(SourceGenerator.java:160)
        at com.bumptech.glide.load.engine.SourceGenerator$1.onLoadFailed(SourceGenerator.java:83)
        at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.startNextOrFail(MultiModelLoader.java:167)
        at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.onLoadFailed(MultiModelLoader.java:154)
        at com.bumptech.glide.load.data.LocalUriFetcher.loadData(LocalUriFetcher.java:49)
        at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.loadData(MultiModelLoader.java:100)
        at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:70)
        at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63)
        at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
        at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherFailed(DecodeJob.java:408)
        at com.bumptech.glide.load.engine.SourceGenerator.onLoadFailedInternal(SourceGenerator.java:160)
        at com.bumptech.glide.load.engine.SourceGenerator$1.onLoadFailed(SourceGenerator.java:83)
        at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.startNextOrFail(MultiModelLoader.java:167)
        at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.onLoadFailed(MultiModelLoader.java:154)
        at com.bumptech.glide.load.data.LocalUriFetcher.loadData(LocalUriFetcher.java:49)
        at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.loadData(MultiModelLoader.java:100)
        at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:70)
        at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63)
        at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
        at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:279)
        at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:234)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
        at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:393)

Is there something I'm missing about permissions that I haven't done yet?

midnightstar
  • 572
  • 5
  • 13
  • Need to use `FileProvider` check [How to pick image for crop from camera or gallery in Android 7.0?](https://stackoverflow.com/questions/39313752/how-to-pick-image-for-crop-from-camera-or-gallery-in-android-7-0) – ρяσѕρєя K Jan 10 '20 at 00:11
  • `photoPickerIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)`. Remove that line. It makes no sense. You cannot grant anything here. – blackapps Jan 10 '20 at 00:34
  • 2
    `requestMgr.load(new File(uri.getPath())).into(imageView);`. You should not use the File class on that uri. You should use code like `requestMgr.load(uri).into(imageView);`. – blackapps Jan 10 '20 at 00:35

1 Answers1

1

Problem #1: ACTION_PICK does not use a MIME type

Problem #2: ACTION_PICK does use a Uri indicating the collection that you are picking from, and you are not providing one

Problem #3: ACTION_PICK is likely to return a content Uri via onActivityResult(), not something with a filesystem path

Problem #4: setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) is pointless, as you are not supplying a content Uri to another app, let alone one for which you have read permission that you could grant

To address these, replace your first code snippet with something like:

        Intent photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT);
        photoPickerIntent.setType("image/*");

        if (photoPickerIntent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(photoPickerIntent, REQUEST_IMAGE_GALLERY);
        }

Replace your second code snippet with something like:

if(intent != null){
     Uri uri = intent.getData();
     requestMgr.load(uri).into(imageView);
 } else {
     displayImageStorageErrorMessage();
     loadProfileImage();
} 
CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491