Android – 选择并查看任何类型的文件

我想让用户能够在手机中选择任何文件类型,然后再用意图查看。

选择文件项目我写这个(我正在使用Kotlin,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) } 

并显示选择的项目:

  fun showDocumentPreviewer(uri: Uri) { val i = Intent(Intent.ACTION_VIEW) i.data = uri mContext.startActivity(i) } 

文档选取器工作正常,在onActivityResult我可以接收所选文档的Uri对象,但文档预览器无法打开对象。 已经尝试将mime-type设置为预览者的意图,但不成功。 我使用不正确的方式在Android中打开文件? 任何通用的方式来显示Android中的任何文件类型? (因为我想支持多种文件类型)

采摘Uri: content://com.android.providers.media.documents/document/image:80

更新:基于@ CommonsWare的评论,我编辑了如下的预览功能:

 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") } 

现在应用程序总是与下面的崩溃日志崩溃:

java.lang.SecurityException:UID 10202没有权限0 u @ content://com.android.providers.media.documents/document/audio:17915

更新2:我的应用程序崩溃在行mContext.startActivity(chooser) 。 这里是完整的崩溃日志:

致命例外:主进程:com.makeit.lite,PID:12851 java.lang.SecurityException:Uid 10477没有权限0 u @ content://com.android.providers.media.documents/document/image:24776在android.app.Android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2514)android.os.Parcel.readException(Parcel.java:1493)android.os.Parcel.readException(Parcel.java:1540)。 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)在android.app.Activity.startActivityForResult(Activity.java:3860)在android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859)在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)

更新3:如果我将mimeType设置为intent: intent.type = mimeType ,应用程序不会再崩溃。 mimeType是我从picker intent(在content: uri旁边)得到的字符串。 mimeType值可以是image/jpeg或任何基于选定文件类型的东西。 虽然它不会崩溃,但在给定的URI里的文件也不会显示。 如果我从Intent-Chooser中选择Gallery ,图库将打开并显示所有图像。 我想第三个应用程序不知道如何确定在给定的uri文件。

这里是我的功能的最新来源:

 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") } 

我使用不正确的方式在Android中打开文件?

首先,可能没有能够查看文件类型的应用程序。

其次,您尚未授予应用程序查看内容的权限。 在ACTION_VIEW Intent上使用addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)

如果您想要使用该文件执行完美的功能,则应该使用任何第三方库来实现此功能。

你应该检查下面的链接文件采摘最常见的库: –

https://android-arsenal.com/tag/35?sort=created

  val intent = Intent(Intent.ACTION_VIEW, uri) intent.type = mimeType 

改成

  val intent = Intent(Intent.ACTION_VIEW); intent.setDataAndType (uri, mimeType ); 

你应该设置一个语句的URI和MIME类型。 否则,接收的应用程序将收到null为uri。 大多数应用程序不会告诉你,他们没有收到一个URI。 图库应用程序实例不。

我不知道Kotlin的确切函数名称。

首先,我要对@GreenApps,@Ankit和@CommonsWare表示感谢。 谁花时间调查我的问题。

我终于找到将源提取到分离的简单项目的根本原因。 这是因为我这样解析uri-string到uri-instance(根本原因的代码没有包括在我的问题中,我的道歉):

 val uri = Uri.parse(URLDecoder.decode(uriString, "UTF-8")) as Uri 

当我改为val uri = Uri.parse(uriString)他们的问题就解决了。

顺便说一句,我想分享我的Github中的选择器和预览器的示例代码,有人可能需要看看。 java源代码位于master分支上,Kotlin源代码位于kotlin-version分支上。 使用这个简单的代码,现在我可以选择任何文件类型(图像,音频,视频,PDF,XLSX,…),然后通过Intent.ACTION_VIEW打开它。

这里是:

https://github.com/IHNEL/UriPickerPreviewer