针对特定文件扩展名的Android意图过滤器?

Cur*_*ous 88 android android-manifest android-intent

我希望能够从'net下载具有特定扩展名的文件,并将其传递给我的应用程序来处理它,但我无法找出intent过滤器.文件类型不包含在mimetypes中,我尝试使用

<data android:path="*.ext" />
Run Code Online (Sandbox Code Playgroud)

但我无法让它发挥作用.

Bri*_*lin 117

以下是我在AndroidManifest.xml中定义活动的方法.

<activity android:name="com.keepassdroid.PasswordActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="file" />
        <data android:mimeType="*/*" />
        <data android:pathPattern=".*\\.kdb" />
        <data android:host="*" />
    </intent-filter>
</activity>
Run Code Online (Sandbox Code Playgroud)

schemefile表明,当一个本地文件被打开(而不是像HTTP协议),这应该发生.

mimeType可以设置为\*/\*匹配任何mime类型.

pathPattern您可以在其中指定要匹配的扩展名(在此示例中.kdb).在.*开头的任何字符匹配SQUENCE.这些字符串需要双重转义,因此\\\\.匹配文字句点.然后,您以文件扩展名结束.对pathPattern的一个警告是,.*如果这是一个正则表达式,那就不像你期望的那样贪婪匹配.此模式将无法匹配包含.之前的路径.kdb.有关此问题的更详细讨论和解决方法,请参见此处

最后,根据Android文档,属性需要两个hostscheme属性pathPattern才能工作,因此只需将其设置为通配符即可匹配任何内容.

现在,如果您.kdb在Linda文件管理器等应用程序中选择文件,我的应用程序将显示为一个选项.我应该注意,仅此一项不允许您在浏览器中下载此文件类型,因为它只注册文件方案.在手机上安装像Linda File Manager这样的应用程序可以自行恢复,允许您下载任何文件类型.

  • 这在这里不起作用.首先使用mimeType ="*",软件包不能安装在Android 2.1上,我得到一个MalformedMimeTypeException.使用"*/*"修复此问题,但此过滤器无效.我目前正在测试Skyfire浏览器,它不像标准Android浏览器那样保留mime类型的下载.当点击Skyfire下载列表中的文件时,将使用文件数据广播简单的VIEW意图.而这个意图过滤器不匹配. (3认同)
  • 如果`\\\\.`匹配一个文字句点,你为什么不用它来形成`.kdb`扩展名:`\\\\.kdb`? (3认同)
  • 为了清楚起见,mimeType应该是"\*/\*"我觉得有些人忘了逃避他们的\*s (2认同)

Dav*_*nty 28

关于这个话题有很多错误的信息,尤其是谷歌自己的文档.最好的,鉴于奇怪的逻辑,可能唯一真正的文档是源代码.

意图过滤器的实现具有几乎无法描绘的逻辑.该解析器代码是其他相关的一块拼图.

以下过滤器非常接近合理的行为.对于"文件"方案意图,路径模式确实适用.

只要文件扩展名匹配,全局mime类型模式匹配将匹配所有类型.这并不完美,但它是匹配文件管理器(如ES文件资源管理器)行为的唯一方法,并且仅限于URI /文件扩展名匹配的意图.

我没有在这里包含其他方案,如"http",但它们可能适用于所有这些过滤器.

奇数方案是"内容",扩展名不适用于过滤器.但只要提供商声明您的MIME类型(例如Gmail将无阻碍地传递附件的MIME类型),过滤器就会匹配.

需要注意的是:

  1. 请注意,过滤器中没有任何表现一致,这是一个特殊情况的迷宫,并将违反最小意外原则的行为视为设计目标.所有模式匹配算法都不遵循相同的语法或行为.缺少某个领域有时是一个通配符,有时则不是.数据元素中的属性有时必须结合在一起,有时会忽略分组.它本来可以做得更好.
  2. 必须为要匹配的路径规则指定方案和主机(与Google的API指南相反,当前).
  3. 至少ES文件资源管理器生成MIME类型为""的意图,它以非常不同的方式过滤为null,无法明确匹配,并且只能由有风险的"*/*"过滤器匹配.
  4. "*/*"过滤器将不匹配具有空MIME类型的Intents - 这需要针对此特定情况的单独过滤器,根本不具有MIME类型.
  5. "内容"方案只能与MIME类型匹配,因为原始文件名在intent中不可用(至少使用Gmail).
  6. 单独的"数据"元素中的属性分组(几乎)与解释无关,除了主机和端口之外 - 它们组合在一起.其他所有内容在"数据"元素或"数据"元素之间没有特定的关联.

考虑到所有这些,这里有一个评论的例子:

<!--
     Capture content by MIME type, which is how Gmail broadcasts
     attachment open requests.  pathPattern and file extensions
     are ignored, so the MIME type *MUST* be explicit, otherwise
     we will match absolutely every file opened.
-->
<intent-filter
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:priority="50" >
    <action android:name="android.intent.action.VIEW" />

    <category android:name="android.intent.category.BROWSABLE" />
    <category android:name="android.intent.category.DEFAULT" />

    <data android:scheme="file" />
    <data android:scheme="content" />
    <data android:mimeType="application/vnd.my-type" />
</intent-filter>

<!--
     Capture file open requests (pathPattern is honoured) where no
     MIME type is provided in the Intent.  An Intent with a null
     MIME type will never be matched by a filter with a set MIME
     type, so we need a second intent-filter if we wish to also
     match files with this extension and a non-null MIME type
     (even if it is non-null but zero length).
-->
<intent-filter
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:priority="50" >
    <action android:name="android.intent.action.VIEW" />

    <category android:name="android.intent.category.BROWSABLE" />
    <category android:name="android.intent.category.DEFAULT" />

    <data android:scheme="file" />
    <data android:host="*" />

    <!--
         Work around Android's ugly primitive PatternMatcher
         implementation that can't cope with finding a . early in
         the path unless it's explicitly matched.
    -->
    <data android:pathPattern=".*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.my-ext" />
</intent-filter>

<!--
     Capture file open requests (pathPattern is honoured) where a
     (possibly blank) MIME type is provided in the Intent.  This
     filter may only be necessary for supporting ES File Explorer,
     which has the probably buggy behaviour of using an Intent
     with a MIME type that is set but zero-length.  It's
     impossible to match such a type except by using a global
     wildcard.
-->
<intent-filter
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:priority="50" >
    <action android:name="android.intent.action.VIEW" />

    <category android:name="android.intent.category.BROWSABLE" />
    <category android:name="android.intent.category.DEFAULT" />

    <data android:scheme="file" />
    <data android:host="*" />
    <data android:mimeType="*/*" />

    <!--
         Work around Android's ugly primitive PatternMatcher
         implementation that can't cope with finding a . early in
         the path unless it's explicitly matched.
    -->
    <data android:pathPattern=".*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.my-ext" />
</intent-filter>
Run Code Online (Sandbox Code Playgroud)

  • 我非常感谢你,@David Sainty。你结束了我 24 小时试图弄清楚如何处理它的痛苦。我尝试了 /sf/ask/1300450231/ 、 /sf/answers/601994501/ 以及更多类似的内容。这是唯一有效的。 (2认同)

oma*_*ena 24

我必须承认,从Android上的文件系统打开电子邮件和文件附件的简单任务一直是令人抓狂的经历之一.处理太多文件或太少文件很容易.但要做到恰到好处是很难的.stackoverflow上发布的大多数解决方案对我来说都不正常.

我的要求是:

  • 让我的应用程序处理我的应用程序共享的附件
  • 让我的应用程序处理由我的应用程序生成并具有特定扩展名的filestorage上的文件

执行此任务的最佳方法可能是为附件指定自定义MIME类型.您可能还会选择自定义文件扩展名.所以,假设我们的应用程序被称为"酷应用程序",我们生成的文件附件最后有".cool".

这是我最接近我的目标,它的工作原理......令人满意.

<!-- Register to handle email attachments -->
<!-- WARNING: Do NOT use android:host="*" for these as they will not work properly -->
<intent-filter>
    <!-- needed for properly formatted email messages -->
    <data
        android:scheme="content"
        android:mimeType="application/vnd.coolapp"
        android:pathPattern=".*\\.cool" />
    <!-- needed for mangled email messages -->
    <data
        android:scheme="content"
        android:mimeType="application/coolapp"
        android:pathPattern=".*\\.cool" />
    <!-- needed for mangled email messages -->
    <data
        android:scheme="content"
        android:mimeType="application/octet-stream"
        android:pathPattern=".*\\.cool" />

    <action android:name="android.intent.action.VIEW" />

    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
</intent-filter>

<!-- Register to handle file opening -->
<intent-filter>
    <data android:scheme="file"
          android:mimeType="*/*"
          android:pathPattern=".*\\.cool"
          android:host="*"/>

    <action android:name="android.intent.action.VIEW" />

    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
Run Code Online (Sandbox Code Playgroud)

笔记:

  • pathPattern似乎或多或少地忽略了附件(使用时android:scheme="content").如果某人得到pathPattern只响应某些模式,我会很高兴看到如何.
  • 如果我添加了该android:host="*"属性,Gmail应用拒绝在选择器中列出我的应用.
  • 如果intent-filter合并这些块,它可能仍然有效,但我还没有验证这一点.
  • 要在下载文件时处理来自浏览器的请求,android:scheme="http"可以使用它.请注意,某些浏览器可能会搞乱android:mimeType这样的实验android:mimeType="*/*"并检查调试器实际传递的内容,然后收紧过滤以最终成为处理所有内容的烦人应用程序.
  • 某些文件浏览器也会破坏文件的MIME类型.以上intent-filter是在Galaxy S3上使用三星的"我的文件"应用程序进行测试的.FX Explorer仍然拒绝正确打开文件,我也注意到应用程序图标不用于文件.再次,如果有人得到这个工作,请在下面评论.

我希望你会发现这很有用,你不必浪费时间来完成所有可能的组合.有改进的余地,欢迎提出意见.


小智 10

布莱恩上面给出的回答让我90%的回答.为了完成它,我使用的是mime类型

android:mimeType="*/*"
Run Code Online (Sandbox Code Playgroud)

我怀疑之前的海报曾试图发布相同的细节,但是很快就将星形斜线作为代码,stackoverflow将它作为斜线.

  • 有了它,您将可以处理所有文件类型,这确实很烦人(嗯,除非您的应用确实可以处理一切)。 (2认同)
  • 这不好。请不要在您的应用程序内执行此操作。 (2认同)

Com*_*are 8

而不是android:path尝试android:mimeType使用此特定内容的MIME类型的值.此外,android:path不接受通配符 - android:pathPattern用于此.


小智 8

2020 年更新

Android 已转向用于意图过滤器的内容 URI 和 MIME 类型。

问题

内容 URI 不一定必须包含文件的扩展名或名称,并且在提供内容/文件的不同应用程序之间会有所不同。

以下是来自不同电子邮件应用程序的同一电子邮件附件的一些示例内容 URI :

Gmail -> content://com.google.android.gm.sapi/some_email@gmail.com/message_attachment_external/%23thread-a%3Ar332738858767305663/%23msg-a%3Ar-5439466788231005876/0.1?account_type=com.google&mimeType=application%2Foctet-stream&rendition=1

展望-> content://com.microsoft.office.outlook.fileprovider/outlookfile/data/data/com.microsoft.office.outlook/cache/file-download/file--2146063402/filename.customextention

三星电子邮件应用程序 -> content://com.samsung.android.email.attachmentprovider/1/1/RAW

正如所见,它们都是不同的,并且不能保证包含与您的实际文件相关的任何内容。因此,您不能使用android:pathPattern大多数人建议的方式。

电子邮件附件的变通解决方案

<intent-filter>
    <action android:name="android.intent.action.VIEW"/>

    <category android:name="android.intent.category.BROWSABLE"/>
    <category android:name="android.intent.category.DEFAULT"/>

    <data android:scheme="content"/>
    <data android:host="*"/>

    <!--  Required for Gmail and Samsung Email App  -->
    <data android:mimeType="application/octet-stream"/>

    <!--  Required for Outlook  -->
    <data android:mimeType="application/my-custom-extension"/>
</intent-filter>
Run Code Online (Sandbox Code Playgroud)

通过测试,我找到了 Gmail、Outlook 和 Samsung Email 使用的 MIME 类型,并将它们添加到我的意图过滤器中。

注意事项/问题

  • 我发现使用上述解决方案,如果我打开任何二进制类型的文件,它会自动启动我的应用程序。如果我们无法解析文件,我会在我的活动中通过显示失败状态来处理这个问题。我认为这是一个非常罕见的事件,所以它是可以接受的。

  • 我找不到任何方法来通过文件浏览器启动我的应用程序而不添加<data android:mimeType="*/*"/>到我的意图过滤器。我无法使用它,因为它会在用户单击手机上的任何文件(不仅仅是自定义文件扩展名)时启动我的应用程序。我不建议将此添加到您的意图过滤器中。

最后的想法

  • 目前没有优雅的解决方案可以将您的应用与 Android 中的特定扩展类型相关联。这是我在我的情况下能做的最好的事情。

  • 非常感谢,它可以工作,于 2020 年 10 月从 Android 7 进行测试 (2认同)
  • 我不明白这么简单的功能怎么在Android上不可能实现。 (2认同)

小智 6

我一直在尝试使它工作一段时间,并且基本上尝试了所有建议的解决方案,但仍然无法让Android识别特定的文件扩展名。我有一个"*/*"模仿类型的Intent过滤器,这似乎是唯一可行的方法,文件浏览器现在将我的应用程序列为打开文件的选项,但是即使将我的应用程序也显示为打开任何种类的文件的选项,即使我已经使用pathPattern标记指定了特定的文件扩展名。到目前为止,即使当我尝试查看/编辑联系人列表中的联系人时,Android也会询问我是否要使用我的应用程序查看联系人,而这只是发生这种情况的许多情况之一,非常令人讨厌。

最终,我发现这个Google网上论坛帖子中有一个实际的Android框架工程师回答的类似问题。她解释说,android根本不了解文件扩展名,而只知道MIME类型(https://groups.google.com/forum/#!topic/android-developers/a7qsSl3vQq0)。

因此,从我所看到,尝试和阅读的内容来看,Android根本无法区分文件扩展名,而pathPattern标签基本上是对时间和精力的巨大浪费。如果您足够幸运,只需要某种mime类型的文件(例如文本,视频或音频),则可以将intent-filter用于mime类型。如果您需要特定的文件扩展名或Android不知道的mime类型,那么您就不走运了。

如果我对此有任何疑问,请告诉我,到目前为止,我已经阅读了每篇文章,并尝试了所有可以找到的建议解决方案,但没有一个起作用。

我可以再写一两页关于这类事情在Android中的普遍程度以及开发人员体验的混乱程度,但是我将省去我的愤怒。希望我救了一些麻烦。

  • 给你投了赞成票,因为你的答案提供了有用的链接,而投反对票的人没有留下评论。抱歉,有时这样可能会不友好,但不要放弃。 (2认同)

jim*_*qaz 5

当意图满足 a 时intent-filter,需要满足以下条件intent-filter:(想象一个清单)。

  • 任意搭配<action>
  • 任意搭配<category>
  • 任何匹配<data mimeType>(简单修复:“ / ”)
  • 可选:

    • 任何匹配<data scheme>(简单修复<data android:scheme="file" /> <data android:scheme="content" />:)

    • 任何匹配<data host>(简单修复:“*”)

    • 任何匹配<data pathPattern/etc.>(例如.*\\.0cc

定义多个<data $type="">元素会检查 $type 框,前提是任何<data $type=>元素与Intent.

省略 mimeType 会破坏你的intent-filter,即使它看起来是多余的。省略<data scheme/host/pathPattern>会使您的过滤器匹配所有内容。

https://f-droid.org/en/packages/de.k3b.android.intentintercept/是一个旨在接收所有意图的应用程序,并允许您检查意图。我了解到通过简单文件管理器打开的无法识别的文件扩展名是通过 MIME 类型传递的application/octet-stream

/sf/answers/323489911/报告<data pathPattern=> .*xyz在第一次x看到时中止,如果后面不跟着yz. 所以除非你尝试,否则/sdcard/.hidden/foo.0cc不会通过。.*\\.0cc.*\\..*\\.0cc

  • 我没有验证这个解决方法是否有必要。

最终结果:

<activity android:name=".Ft2NsfActivity">

    <intent-filter>
        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <data android:scheme="file" />
        <data android:scheme="content" />
        <data android:host="*" />
        <data android:pathPattern=".*\\.ftm"/>
        <data android:pathPattern=".*\\..*\\.ftm"/>
        <data android:pathPattern=".*\\..*\\..*\\.ftm"/>
        <data android:pathPattern=".*\\..*\\..*\\..*\\.ftm"/>
        <data android:pathPattern=".*\\.0cc"/>
        <data android:pathPattern=".*\\..*\\.0cc"/>
        <data android:pathPattern=".*\\..*\\..*\\.0cc"/>
        <data android:pathPattern=".*\\..*\\..*\\..*\\.0cc"/>
        <data android:mimeType="*/*" />
    </intent-filter>

</activity>
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

71101 次

最近记录:

7 年,2 月 前