Reputation: 24423
I want to lets users able to pick any file type in their phones, then view it again using intent.
To pick file item I write this ( I'm using Kotlin, same issue in Java):
fun goToDocumentPicker() {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "*/*"
if (intent.resolveActivity(mContext.packageManager) != null)
mContext.startActivityForResult(intent, REQUEST_DOCUMENT)
}
And to show the picked item:
fun showDocumentPreviewer(uri: Uri) {
val i = Intent(Intent.ACTION_VIEW)
i.data = uri
mContext.startActivity(i)
}
The document picker works fine, in the onActivityResult
I can receive the Uri object of selected document, but the document previewer can't open the object. Already try to set mime-type to the previewer's intent but not success. Did I use incorrect way to open file in Android? Any generic way to show any file type in Android? (Because I want to support many file types)
picked Uri: content://com.android.providers.media.documents/document/image:80
Update: Base on @CommonsWare's comment, I edited the preview function like below:
fun showAttachmentPreviewer(uri: Uri, mimeType: String?) {
Log.d("TEST", "Preview " + uri.toString())
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
val chooser = Intent.createChooser(intent, "Open with")
if (intent.resolveActivity(mContext.packageManager) != null)
mContext.startActivity(chooser)
else
mContext.showSnackBar("No suitable application to open file")
}
Now the app always crash with below crash-log:
java.lang.SecurityException: Uid 10202 does not have permission to uri 0 @ content://com.android.providers.media.documents/document/audio:17915
Update 2:
My app crash at line mContext.startActivity(chooser)
. Here is the full crash-log:
FATAL EXCEPTION: main Process: com.makeit.lite, PID: 12851 java.lang.SecurityException: Uid 10477 does not have permission to uri 0 @ content://com.android.providers.media.documents/document/image:24776 at android.os.Parcel.readException(Parcel.java:1540) at android.os.Parcel.readException(Parcel.java:1493) at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2514) at android.app.Instrumentation.execStartActivity(Instrumentation.java:1494) at android.app.Activity.startActivityForResult(Activity.java:3913) at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50) at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79) at android.app.Activity.startActivityForResult(Activity.java:3860) at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859) at android.app.Activity.startActivity(Activity.java:4184) at android.app.Activity.startActivity(Activity.java:4152) at com.makeit.lite.attachment.AttachmentNavigator.showAttachmentPreviewer(AttachmentNavigator.kt:92) at com.makeit.lite.attachment.list.AttachmentListPresenter.onAttachmentClicked(AttachmentListPresenter.kt:37) at com.makeit.lite.attachment.list.AttachmentListFragment$onViewCreated$1.onItemClick(AttachmentListFragment.kt:39) at eu.davidea.viewholders.FlexibleViewHolder.onClick(FlexibleViewHolder.java:121) at android.view.View.performClick(View.java:5156) at android.view.View$PerformClick.run(View.java:20755) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:145) at android.app.ActivityThread.main(ActivityThread.java:5835) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Update 3:
If I set mimeType to intent: intent.type = mimeType
and the app won't crash anymore. The mimeType
is the string I get from the picker intent (beside the content:
uri). The mimeType value canbe image/jpeg
or anything base on selected file type. Although it won't crash, the file at given uri won't display as well. If I choose the Gallery
from Intent-Chooser, the Gallery open and show all images. I guess the 3rd app don't know how to determinate the file at given uri.
Here is the latest source of my function:
fun showAttachmentPreviewer(uri: Uri, mimeType: String?) {
Log.d("TEST", "Preview " + uri.toString() + " For type" + mimeType)
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.type = mimeType //Can be "image/jpeg" or sth corresponding to the filetype.
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
val chooser = Intent.createChooser(intent, "Open with")
if (intent.resolveActivity(mContext.packageManager) != null)
mContext.startActivity(chooser)
else
mContext.showSnackBar("No suitable application to open file")
}
Upvotes: 4
Views: 5575
Reputation: 24423
Fist of all, I want to say thank-you to @GreenApps, @Ankit, and @CommonsWare. Who spent time to investigate my issue.
I finally found the root cause when extracting the source to separated simple project. It's because I parse uri-string into uri-instance this way (the code of root-cause didn't included in my question. My apologies):
val uri = Uri.parse(URLDecoder.decode(uriString, "UTF-8")) as Uri
when I changed to val uri = Uri.parse(uriString)
them problem solved.
Btw, I want to share the sample code for picker and previewer in my Github for someone may need to take a look. The java source is on master
branch, and the Kotlin source is on kotlin-version
branch. Using this simple code, now I can pick any file type (image, audio, video, pdf, xlsx,...) and then open it later via Intent.ACTION_VIEW.
Here it is:
Upvotes: 1
Reputation: 11214
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.type = mimeType
Change to
val intent = Intent(Intent.ACTION_VIEW);
intent.setDataAndType (uri, mimeType );
You should set uri and mime type with one statement. Otherwise the receiving app will receive null for the uri. Most apps will not tell you that they did not receive an uri. The Gallery app for instance does not.
And i do not know the exact function name for Kotlin.
Upvotes: 3
Reputation: 9225
If you want to perform a perfect functionality with the file you should use any third party library for this functionality.
you should check the below link for the most common libraries for the file pickers:-
https://android-arsenal.com/tag/35?sort=created
Upvotes: 0
Reputation: 1006604
Did I use incorrect way to open file in Android?
First, there may not be an app capable of viewing the file type.
Second, you have not granted permission for the app to view the content. Use addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
on the ACTION_VIEW
Intent
.
Upvotes: 3