In the beginning the user can select files with the new Storage Access Framework (Assuming the app is API>19):
https://developer.android.com/guide/topics/providers/document-provider.html
Then I save references to those chosen files by saving the URI`s which looks like:
content://com.android.providers.downloads.documments/document/745
(in this case the file is from the default downloads dir`).
Later, I want let the user to open those files (For example they names displayed in UI list, and the user selects one).
I want to do this with the Android famous intent chooser feature, and all I have is the above URI object...
Thanks,
Well the solution has already been provided on the SO and you only needed to search for it.
This is the answer by Paul Burke. He has written a utility class which returns complete file path for such a content path.
He says:
and
FileUtils.java is the place where Paul Burke has written the method you're looking for.
Edit: I have revised this answer to include the example code of approach I have initially referred to as "writing a specialized ContentProvider". This should fully satisfy requirements of the question. Probably makes the answer too big, but it has internal code dependencies now, so let's leave it as whole. The main point still holds true: use the ContentPrvder below if you want, but try to give
file://
Uris to apps, that support them, unless you want to be blamed for someone's app crashing.Original answer
I would stay away from Storage Access Framework as it is now. It's insufficiently backed by Google, and the support in apps is abysmal, making it is hard to tell between bugs in those apps and SAF itself. If you are confident enough (which really means "can use try-catch block better then average Android developer"), use Storage Access Framework yourself, but pass to others only good-old
file://
paths.You can use the following trick to get filesystem path from ParcelFileDescriptor (you can get it from ContentResolver by calling openFileDescriptor):
You must be prepared, that the method above will return null (the file is a pipe or socket, which is perfectly legitimate) or an empty path (no read access to file's parent directory). If this happens copy the entire stream to some directory you can access.
Complete solution
If you really want to stick with content provider Uris, here you go. Take the code of ContentProvider below. Paste into your app (and register it in AndroidManifest). Use
getShareableUri
method below to convert received Storage Access Framework Uri into your own. Pass that Uri to other apps instead of the original Uri.The code below is insecure (you can easily make it secure, but explaining that would expand the length of this answer beyond imagination). If you care, use
file://
Uris—Linux file systems are widely considered secure enough.Extending the solution below to provide arbitrary file descriptors without corresponding Uri is left as exercise for reader.