Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Picking images in Android Q #104

Open
BorisLaskov opened this issue Sep 4, 2019 · 9 comments
Open

Picking images in Android Q #104

BorisLaskov opened this issue Sep 4, 2019 · 9 comments

Comments

@BorisLaskov
Copy link

Picking images from gallery in Android Q does not work (probably due to the changes regarding external storage access). Tested on the emulator with Android Q.

@JakubObornik
Copy link

Picking images from gallery in Android Q does not work (probably due to the changes regarding external storage access). Tested on the emulator with Android Q.

Quick fix could be add this line to your manifest:
<application android:requestLegacyExternalStorage="true" ... >

or follow guidelines as mention there:
https://developer.android.com/training/data-storage/files/external-scoped

@droidluv
Copy link

droidluv commented Oct 2, 2019

@JakubObornik can you explain on the guidelines to follow with RxPapparazo? I have no idea how to fix this and using android:requestLegacyExternalStorage="true" doesn't help

@JakubObornik
Copy link

@droidluv You have to modify storage scope for saving pictures using RxPaparazzo, because in default it's counting on the external store. Enabled request legacy external storage should fix this problem, are you sure you have the same problem as 145k0v mention? (check your logcat)

Problem is described in "Opt out of scoped storage" part of the documentation

@droidluv
Copy link

droidluv commented Oct 2, 2019

@JakubObornik sorry android:requestLegacyExternalStorage="true" did actually work, in my panic I didn't realize it, thanks for the support, scoped storage seems like a nightmare, because I was having issues just reading a file from a filepath even though I have both read and write external permissions, and the 'quickfix' helps for now, but Google is going to enforce this strictly from the next Android versions and its going to create waves of nightmares for developer's.

Just an extra question, wouldn't working with scoped storage require us to always copy the content however large because the FileDescriptor returning an InputStream only?

Like I am assuming when we get the uri from ACTION_GET_CONTENT or ACTION_OPEN_DOCUMENT for suppose mime types image/* and extra mime types video/*

the onActivityResult gives use the uri and from the uri we can do the following
val parcelFileDescriptor: ParcelFileDescriptor = contentResolver.openFileDescriptor(uri, "r")

but from here on out can I directly access the media content atleast just to read? Or do I have to write it to a temp file(which might take a long time if its a large video file) in my app directory and proceed? Would like some enlightenment on how I can proceed in a fast manner.

@miguelbcr any plans on making things easier for people using the scoped storage? Because Android 11 is going to strictly enforce this and there will be no other workaround like android:requestLegacyExternalStorage to rely on

@JakubObornik
Copy link

@JakubObornik sorry android:requestLegacyExternalStorage="true" did actually work, in my panic I didn't realize it, thanks for the support, scoped storage seems like a nightmare, because I was having issues just reading a file from a filepath even though I have both read and write external permissions, and the 'quickfix' helps for now, but Google is going to enforce this strictly from the next Android versions and its going to create waves of nightmares for developer's.

Just an extra question, wouldn't working with scoped storage require us to always copy the content however large because the FileDescriptor returning an InputStream only?

Like I am assuming when we get the uri from ACTION_GET_CONTENT or ACTION_OPEN_DOCUMENT for suppose mime types image/* and extra mime types video/*

the onActivityResult gives use the uri and from the uri we can do the following
val parcelFileDescriptor: ParcelFileDescriptor = contentResolver.openFileDescriptor(uri, "r")

but from here on out can I directly access the media content atleast just to read? Or do I have to write it to a temp file(which might take a long time if its a large video file) in my app directory and proceed? Would like some enlightenment on how I can proceed in a fast manner.

@miguelbcr any plans on making things easier for people using the scoped storage? Because Android 11 is going to strictly enforce this and there will be no other workaround like android:requestLegacyExternalStorage to rely on

You can copy the media file or just use MediaStore instead of use ExternalFileDir (everything is explained in documentation (check the table in the first part of doc).

And about the second question for Miquel, I think he already works on the new version, but it is not publicly released yet (check the source code, there is "2.x-SNAPSHOT" version for maven repository)

@droidluv
Copy link

droidluv commented Oct 2, 2019

@JakubObornik thanks for your advice the thing is the documentation is not clear how I can access a file from the retrieved uri for example I understand this step

  val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
    addCategory(Intent.CATEGORY_OPENABLE)
    type = "image/*"
}
startActivityForResult(intent, READ_REQUEST_CODE)

and in onActivityResult I have

   override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
     if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
        resultData?.data?.also { uri ->
        Log.i(TAG, "Uri: $uri")
        showImage(uri)
       }
    }
  }

the showImage(uri) method is

   val parcelFileDescriptor: ParcelFileDescriptor = contentResolver.openFileDescriptor(uri, "r")
    val fileDescriptor: FileDescriptor = parcelFileDescriptor.fileDescriptor

and in the documentation they show how to retrieve a bitmap like

val image: Bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor)
parcelFileDescriptor.close();

where image is a Bitmap, this all fine but how can I access the actual file directly for read? an filepath I retrieve from the url is valid but I'll get an FileNotFound exception with an access denied error just like how they mentioned in the documentation, how can I access the media file

how can I identify whether the retrieved file is a video or image mime type?
Thanks for all your help, sorry for bothering you, if there is a detailed documentation or article that would be helpful

@ikurek
Copy link

ikurek commented May 11, 2020

I've run across this issue today. Using android:requestLegacyExternalStorage="true" is just an override, and library should be updated to use recommended file access method, most probably openFileDescriptor()

@Shubham178046
Copy link

if i capture image or pick image from gallery using RxPaparazzo in android 11 device than I got Error 1 Exception Occurred message

@Vij3n
Copy link

Vij3n commented Apr 20, 2021

Took a while to find an example for replacement of the deprecated MediaStore.Images.Media.DATA. Finally found the suggestion from @droidluv above which worked - thanks @droidluv. Copying my working onActivityResult method here incase anyone else needs it.

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        Log.d("Event: ","onActivityResult")

        if (requestCode == PICK_IMAGE_CODE && data != null && resultCode == RESULT_OK){
            Log.d("Event: ","onActivityResult is satisfied")
            val selectedImage = data.data
            val parcelFileDescriptor: ParcelFileDescriptor? = contentResolver.openFileDescriptor(selectedImage!!,"r")
            val fileDescriptor: FileDescriptor = parcelFileDescriptor!!.fileDescriptor
            val image:Bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor)
            parcelFileDescriptor.close()

            ivImagePerson.setImageBitmap(image)
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants