Efimov Aleksandr
Efimov Aleksandr

Reputation: 175

Gallery picker returns Uri with a file scheme on Android 10, how to read it?

My app has targetSdkVersion = 29 (new scoped storage policy) and has not requestlegacyexternalstorage flag enabled in manifest (i do not want to enable it).

Ways i tried to compose intent:

Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE);

Also tried this

val galleryIntent = Intent(Intent.ACTION_PICK).apply {
    type = PICK_INTENT_TYPE
}
flowInterruptBlocker?.blockFlowInterruption()
startActivityForResult(galleryIntent, GALLERY_INTENT_REQUEST_CODE)

Also tried to add a CATEGORY_OPENABLE to intent. None of these works.

So, when i send intent to pick image from gallery, some apps from play market return me a Uri with a file scheme, for example: file:///storage/emulated/0/Download/sample.jpg

When i try to convert it to bitmap (for setting into imageView) i get EACCES (Permission denied) exception.

I tried to read it with a:

java.File Api

contentResolver.openInpuStream()

contentResolver.openFileDescriptor()

ImageDecoder

Nothing helps. As i can see i can not read Uri with a file scheme on android 10 (targeting 29 sdk) without requestlegacyexternalstorage flag enabled in my manifest.

If i am wrong, please help me to figure out how to read it.

Mysterious thing about it, that android 11 emulator with app targeting 29 sdk CAN read these type of Uri without requestlegacyexternalstorage flag.

And yes, i have granted READ/WRITE_EXTERNAL_STORAGE permissions.

Upvotes: 2

Views: 2961

Answers (2)

Jan Rozenbajgier
Jan Rozenbajgier

Reputation: 634

This works perfectly for me (I've tested it on Android 8, 10, 11 with targeting sdk 29). Doesn't require android:requestLegacyExternalStorage="true" and any permissions.

private static Bitmap readImage(Uri uri, Context context){
   InputStream inputStream = context.getContentResolver().openInputStream(uri);
   Bitmap res = BitmapFactory.decodeStream(inputStream);
   inputStream.close();
   return res;
}

and you use it like this:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
       
    if(data == null || data.getClipData().size() == 0)
       return;

    myImageView.setImageBitmap(readImage(data.getClipData().getItemAt(0).getUri(), this));
                    
}

Upvotes: 1

CommonsWare
CommonsWare

Reputation: 1006564

some apps from play market return me a Uri with a file scheme, for example: file:///storage/emulated/0/Download/sample.jpg

Some apps are written by inexperienced developers.

If i am wrong, please help me to figure out how to read it.

On Android 10, you will not be able to read that Uri without android:requestLegacyExternalStorage="true".

Mysterious thing about it, that android 11 emulator with app targeting 29 sdk CAN read these type of Uri without requestlegacyexternalstorage flag.

The "raw paths" feature introduced in Android 11 means that READ_EXTERNAL_STORAGE works normally again. So, the recommended approach is to request READ_EXTERNAL_STORAGE plus use android:requestLegacyExternalStorage="true", for consistency between Android versions.

Upvotes: 5

Related Questions