【问题标题】:Can't ACTION_VIEW a file on external storage无法 ACTION_VIEW 外部存储上的文件
【发布时间】:2014-10-30 20:29:28
【问题描述】:

我的 Android 手机的外部存储中有一个文件(在本例中是模拟的)。知道它的路径和/或有一个代表它的File 对象,我如何使用Intent 在适当的应用程序中打开它?

我尝试的第一件事是:

startActivity(new Intent(Intent.ACTION_VIEW, Uri.fromFile(file)));

我确信这在某一点上是有效的,因为我对其进行了测试并转移到了应用程序的另一部分。现在它总是抛出ActivityNotFoundException。该文件确实存在,因为file.exists() 返回true 并且我知道它是正确的文件,但没有应用程序自愿打开它。

我仍然可以以这种方式打开的唯一文件类型是 .pdf,为此选择了 Adob​​e Reader,尽管它不是我的设备上安装的唯一 PDF 阅读器,也没有设置为默认值。我注意到 Adob​​e Reader 还提供打开在线 pdf 文件的功能(它似乎可以替代使用 Chrome 下载 pdf)。这向我表明,只有 Adob​​e Reader 被发现与 Intent 匹配,因为该位置被认为是远程位置(虽然不是在线,因为 Chrome 和其他文件下载应用程序未列为替代应用程序)。

我也尝试过明确说明 MIME 类型:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/msword");
startActivity(intent);

这会导致Intent 与正确的应用程序匹配,但它们都无法真正打开文件。我已经使用 MIME 类型的硬编码字符串和使用MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) 进行了测试,并传递了文件扩展名。对于多种文件类型,推荐了正确的应用程序,但它们都无法打开文件。

编辑:

明确设置 MIME 类型会起作用,但我犯了一个非常愚蠢的错误,我应该在答案中解释一下。

我尝试打开的文件来自互联网,是在DownloadManager 的帮助下下载到我的应用程序中的。我使用它的功能在下载完成时显示通知。单击其中一个通知可以完美打开文件。我试图找到在单击DownloadManager 完成通知时触发的Intent 的源代码,但没有运气。

此外,ES File Explorer 等应用程序可以导航到我的文件下载到的位置并毫无问题地打开它们。我做错了什么?

仅仅是因为不再可能 ACTION_VIEW 外部存储上的文件吗?我的应用程序也会临时将文件下载到内部存储,这些文件仍然可以打开,没有这样的问题:

//This works for files on internal storage:
Uri uri = FileProvider.getUriForFile(context, AUTHORITY, file);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);

至于它在过去的工作,更新 Eclipse、SDK 工具插件和 Android SDK 本身是否会阻止我原来的解决方案工作?

【问题讨论】:

  • 我建议您对字符串“VIEW”运行 logcat 过滤,看看当您使用您提到的一些工作应用程序时,您会以 Intent 的方式触发什么。然后与您的尝试进行比较。
  • @ChrisStratton 感谢您的非常有帮助的评论。我比较了 LogCat 中的 Intents 并注意到我的错误,所以我编辑/回答了这个问题。

标签: android android-intent android-external-storage


【解决方案1】:

当我尝试setDataAndType时,我一定是因为懒惰而离开了:

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.fromFile(file));

刚刚添加了另一行:

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.fromFile(file));
intent.setType(theMimeType);

...假设它与以下内容相同:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), theMimeType);

然后我一定忘记了我实际上并没有尝试过setDataAndType 并继续写这个问题。单独使用setType 似乎删除了我作为参数传递给构造函数的Uri。使用 LogCat 查看记录的意图详细信息,我看到将 MIME 类型留给推断导致没有类型,在已经设置 Uri 之后使用 setType 导致由于某种原因没有指定 Uri,并且使用 setDataAndType 意味着它们都被指定,导致 Intent 正常工作。

所以我做错的是分别设置类型和数据,而不是使用setDataAndType

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-21
    • 1970-01-01
    • 1970-01-01
    • 2014-04-17
    • 2016-07-27
    • 1970-01-01
    • 2020-12-24
    • 1970-01-01
    相关资源
    最近更新 更多