Before KitKat (or before the new Gallery) the Intent.ACTION_GET_CONTENT
returned a URI like this
content://media/external/images/media/3951.
Using the ContentResolver
and quering for
MediaStore.Images.Media.DATA
returned the file URL.
In KitKat however the Gallery returns a URI (via "Last") like this:
content://com.android.providers.media.documents/document/image:3951
How do I handle this?
Had the same problem, tried the solution above but though it worked generally, for some reason I was getting permission denial on Uri content provider for some images although I had the
android.permission.MANAGE_DOCUMENTS
permission added properly.Anyway found other solution which is to force opening image gallery instead of KITKAT documents view with :
and then load the image:
EDIT
ACTION_OPEN_DOCUMENT
might require you to persist permissions flags etc and generally often results in Security Exceptions...Other solution is to use the
ACTION_GET_CONTENT
combined withc.getContentResolver().openInputStream(selectedImageURI)
which will work both on pre-KK and KK. Kitkat will use new documents view then and this solution will work with all apps like Photos, Gallery, File Explorer, Dropbox, Google Drive etc...) but remember that when using this solution you have to create image in youronActivityResult()
and store it on SD Card for example. Recreating this image from saved uri on next app launch would throw Security Exception on content resolver even when you add permission flags as described in Google API docs (that's what happened when I did some testing)Additionally the Android Developer API Guidelines suggest:
Try this:
Probably need
for
Just as Commonsware mentioned, you shouldn't assume, that the stream you get via
ContentResolver
is convertable into file.What you really should do is to open the
InputStream
from theContentProvider
, then create a Bitmap out of it. And it works on 4.4 and earlier versions as well, no need for reflection.Of course if you handle big images, you should load them with appropriate
inSampleSize
: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html. But that's another topic.Question
How to get an actual file path from a URI
Answer
To my knowledge, we don't need to get the file path from a URI because for most of the cases we can directly use the URI to get our work done (like 1. getting bitmap 2. Sending a file to the server, etc.)
1. Sending to the server
We can directly send the file to the server using just the URI.
Using the URI we can get InputStream, which we can directly send to the server using MultiPartEntity.
Example
2. Getting a BitMap from a URI
If the URI is pointing to image then we will get bitmap, else null:
Comments
Reference
This requires no special permissions, and works with the Storage Access Framework, as well as the unofficial
ContentProvider
pattern (file path in_data
field).See an up-to-date version of this method here.
Building up on Paul Burke's answer I faced many problems resolving external SD card's URI path as most of the suggested "built-in" functions return paths which do not get resolved to files.
However, this is my approach of his // TODO handle non-primary volumes.
Note it depends on hierarchy which might be different on every phone manufacturer - I have not tested them all (it worked well so far on Xperia Z3 API 23 and Samsung Galaxy A3 API 23).
Please confirm if it does not perform well elsewhere.