Android意向过滤器的特定文件扩展名?


92

我希望能够从网络上下载具有特定扩展名的文件,并将其传递给我的应用程序来处理它,但是我无法弄清意图过滤器。文件类型不包含在mimetypes中,我尝试使用

<data android:path="*.ext" />

但我无法解决这个问题。

Answers:


119

这是我在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>

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

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

pathPattern是您指定要匹配的扩展名的位置(在此示例中.kdb)。在.*开头的任何字符匹配SQUENCE。这些字符串需要两次转义,因此\\\\.匹配一个字面量。然后,以文件扩展名结尾。使用pathPattern的一个警告是,.*它不是一个贪婪的匹配项,就像这是一个正则表达式一样。此模式将无法匹配.在之前包含的路径.kdb。有关此问题的更详细讨论和解决方法,请参见此处

最后,根据Android文档,属性必须同时使用hostscheme属性,pathPattern属性才能设置为通配符以匹配任何内容。

现在,如果您.kdb在Linda File Manager之类的应用程序中选择文件,则我的应用程序会显示为一个选项。我应该注意,仅此一项不允许您在浏览器中下载此文件类型,因为这仅在文件方案中注册。通常,在手机上安装类似Linda File Manager的应用程序本身就可以使您下载任何文件类型。


3
这在这里不起作用。首先使用mimeType =“ ”,该软件包未安装在Android 2.1上,我得到了MalformedMimeTypeException。使用“ * / ”可以解决此问题,但是此过滤器无效。我目前正在使用Skyfire浏览器进行测试,该浏览器不像标准的Android浏览器那样保留下载的mime类型。当单击“ Skyfire下载”列表中的文件时,将与文件数据一起广播一个简单的VIEW意图。而且这个意图过滤器不匹配。
olivierg

@Brian Pellin:我实际上是在寻找一种将mime类型绑定到.kdbx扩展名的方法,以使ES文件资源管理器在指向此职位时可以打开kdbx文件。显然,如果该意图具有空的MIME类型,则该意图过滤器将不起作用!而且,可能有一个意图,其中包含一个EMPTY字符串作为操作,而仅有一个URI。Google文档对此意图做出了回应,因此该意图必须有效。
billc.cn 2011年

2
只是要清楚一点,mimeType应该为“ * / *”,我认为有些人忘记了逃脱他们的* s
Brian Pellin 11/12/22

1
不适用于Android4。您应该使用<data>具有四个属性的on 标签。具有4个标签是合乎逻辑的“或”(与Android 2兼容),但Android 4更为严格。参见stackoverflow.com/questions/20650378/…–
马丁

3
如果\\\\.匹配一个立即数,为什么不使用它来形成.kdb扩展名\\\\.kdb呢?
Lealo

34

关于此主题的信息有很多误导,尤其是来自Google自己的文档。最好的,再加上奇怪的逻辑,可能唯一真正的文档是源代码。

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

以下过滤器非常接近明智的行为。路径模式确实适用于“文件”方案的意图。

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

我这里没有包括“ http”之类的其他方案,但是它们可能在所有这些过滤器上都能正常工作。

奇怪的方案是“内容”,其扩展名不适用于过滤器。但是,只要提供商指定您的MIME类型(例如,Gmail将不受阻碍地传递MIME类型),过滤器就会匹配。

要了解的注意事项:

  1. 请注意,过滤器中没有任何东西表现一致,这是特殊情况的迷宫,并且将违反最小惊讶原则的问题视为设计目标。模式匹配算法都没有遵循相同的语法或行为。缺少字段有时是通配符,有时不是通配符。数据元素中的属性有时必须组合在一起,有时会忽略分组。确实可以做得更好。
  2. 必须指定方案和主机,才能匹配路径规则(当前与Google的API指南相反)。
  3. 至少ES File Explorer会生成MIME类型为“”的意图,该意图的过滤方式与null非常不同,不可能显式匹配,并且只能通过有风险的“ * / *”过滤器进行匹配。
  4. “ * / *”过滤器将不与MIME类型为空的Intent匹配-对于这种特定情况,根本不需要MIME类型,则需要一个单独的过滤器。
  5. “内容”方案只能按MIME类型进行匹配,因为原始文件名在意图中不可用(至少在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>

很高兴您能够承受许多反复证明的\\ ..和其他怪癖的证明。Google应该已经通过4.2修复了这个问题,到底是什么。las,我仍然发现您的示例似乎无法修复。6个cha扩展名(例如“ .gblorb”)是否存在某些问题,我的代码可以使用3个字母或更少的字母正常工作?
RoundSparrow hilltx

我认为,此问题和类似问题的最佳答案!可悲的是,只要不能通过文件扩展名匹配内容意图(如您在5中指出的),就不可能在不匹配错误意图的情况下可靠地筛选所有正确的意图。这是在您不能使用自定义mime类型的情况下。因此,只要Android不为此提供解决方案,它将对我来说就是应用程序中的文件选择器...我不想使用户的行为不一致。
本杰明·比辛格

1
非常感谢..您刚刚度过了一天。.就我而言,我必须更改<data android:mimeType="*/*" /> 所有三个选项中的MimeType ,它对于包括Google Drive和Gmail在内的所有应用程序都具有吸引力。
里沙卜·瓦德瓦

1
我非常感谢您,@ David Sainty。您结束了我长达24小时的努力,试图弄清楚如何处理它。我试过stackoverflow.com/q/18577860/6110285stackoverflow.com/a/8599921/6110285等等这是相似的。这是唯一起作用的一个。
pittix

24

我必须承认,在Android上从电子邮件和文件系统中的文件中打开附件的简单任务一直是令人发狂的体验之一。处理太多或太少的文件很容易。但是很难做到正确。我在stackoverflow上发布的大多数解决方案均无法正常工作。

我的要求是:

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

执行此任务的最佳方法可能是为附件指定自定义MIME类型。您可能还会选择具有自定义文件扩展名。假设我们的应用程序称为“ Cool App”,并且生成的文件附件的末尾带有“ .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>

笔记:

  • pathPattern似乎或多或少地忽略了附件(当使用android:scheme="content")。如果有人得到pathPattern仅对某些模式做出响应,我将非常高兴地看到如何。
  • 如果我添加了Gmail应用,则该应用拒绝在选择器中列出我的应用 android:host="*"属性,。
  • 如果这些 intent-filter合并了块,但我尚未对此进行验证。
  • android:scheme="http"可以使用下载文件时处理浏览器的请求。请注意,某些浏览器可能会搞砸,android:mimeType因此请进行试验android:mimeType="*/*"并检查调试器实际通过了什么,然后加强过滤,以免最终成为处理所有问题的烦人应用程序
  • 某些文件浏览器也会弄乱文件的MIME类型。以上内容intent-filter已在Galaxy S3上使用三星的“我的文件”应用进行了测试。FX Explorer仍然拒绝正确打开文件,我还注意到该文件未使用应用程序图标。再说一次,如果有人让它起作用,请在下面评论。

我希望您会发现这很有用,并且不必浪费时间进行所有可能的组合。有改进的空间,欢迎发表评论。


这对我来说是一个可行的解决方案。为Content-Scheme和File-Scheme注册单独的<intent-filter>可以达到目的!谢谢!
Mehlyfication 2015年

谢谢!为我工作。使用您的解决方案,Gmail应用程序和Galaxy S6上的Samsung My Files应用程序都可以使用我的应用程序打开文件!
哈里斯

“应用名称”到底是什么?(就我而言,可读的应用程序名称中包含空格。)
William Jockusch

@WilliamJockusch看起来@DavidSainty只是将应用程序名称存储在字符串资源文件中。空格应该没问题。用于android:label意图过滤器的字符串是用户将在选择器菜单中看到的字符串。默认情况下,使用应用程序名称。
omahena '16

我应如何使用“ Google云端硬盘”应用程序?
Android开发人员

9

布赖恩的上述回答使我有90%的解决方法。为了完成它,我使用了mime类型

android:mimeType="*/*"

我怀疑以前的张贴者曾尝试发布相同的细节,但是尽管将星号斜线星标为代码,但stackoverflow却将其视作斜线。


2
有了它,您将处理所有文件类型,这确实很烦人(嗯,除非您的应用程序确实能够处理一切)...
Tim Autin

这不好。请不要在您的应用程序内执行此操作。
火星

8

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


“文件类型不包含在mimetype中”?即使您下载的内容类型不使用相同的单词,仍然应该有一个模仿类型。
埃里克·米尔

内容类型有一个mimetype,但是该文件是由第三方应用程序生成的,并在其上添加了不同的扩展名,因此我认为它不会被识别为该mimetype。
Curyous

7

我一直在尝试使它工作一段时间,并且基本上尝试了所有建议的解决方案,但仍然无法让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中的普遍程度以及开发人员体验的混乱程度,但是我将省去我的愤怒。希望我能给别人省些麻烦。


1
支持您,因为您的答案提供了有用的链接,而反对者未发表评论。抱歉,这样有时可能会变得不友好,但是请不要退出。
约翰·哈顿

3

Brian的答案非常接近,但是当您尝试使用自己的自定义扩展名打开文件(无需使用方案或主机)时,这是调用应用程序的一种干净且无错误的方法:

<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:mimeType="*/*" />
    <data android:pathPattern="*.*\\.kdb" />
</intent-filter>

2
Android文档指出,仅在指定方案和主机的情况下,pathPattern属性才有意义,并且我已经验证了这一点:developer.android.com/guide/topics/manifest/data-element.html
Brian Pellin

4
-1; 这将匹配任何文件;Brian的评论是正确的,并且对mimeType =“ / ” 进行了少量修改,他的原始示例是完美的。
尼克,

如果从很久以前发布了此帖子,但没有安装“ /”。您需要“ * / *”,它将与任何文件类型匹配(不确定,如果您要说的话)。因此,可能会要求您的程序打开视频或mp3。我还没有找到解决方案。
Rene 2012年

您应该使用一个<data>带有四个属性的标签。您的解决方案可能适用于Android 2-但规则变得更加严格:stackoverflow.com/questions/20650378/…–
Martin

奇怪的pathPattern怎么了?而hostscheme需要!
IgorGanapolsky

3

在Android 4上,规则变得比以前更加严格。用:

    <data
      android:host=""
      android:mimeType="*/*"
      android:pathPattern=".*\\.ext"
      android:scheme="file"
    ></data>

3

我一直在为自定义文件扩展名而苦苦挣扎。经过大量搜索后,我发现了该网页,发布者发现当路径的路径中包含匹配模式的第一个字符时,Android的patternMatcher类(用于Intent-Filters中的pathPattern匹配)具有意外行为。 (就像您要匹配“ * .xyz”一样,如果路径中的前面有一个“ x”,则patternMatcher类将停止)。这是他找到的解决方法,为我工作,尽管有点hack:

PatternMatcher用于IntentFilter的pathPattern但是,PatternMatcher的算法对我来说很奇怪。这是Android PatternMatcher的算法。

如果字符串中间存在“。*”模式的“下一个字符”,则PatternMatcher会在该点停止循环。(请参阅Android框架的PatternMatcher.java。)

例如 字符串:“这是我的附件”模式:“。att。 ”。Android PatternMatcher输入循环以匹配'。'模式,直到遇到模式的下一个字符(在此示例中为'a')。'匹配循环在索引8-'is'和'my'之间的'a'处停止。因此,此匹配的结果返回“ false”。

很奇怪,不是吗。要解决此问题-实际上减少可能性-开发人员应使用烦人的愚蠢pathPattern。

例如 目标:匹配包含“消息”的uri路径。

<intent-filter>
...
<data android:pathPattern=".*message.*" />
<data android:pathPattern=".*m.*message.*" />
<data android:pathPattern=".*m.*m.*message.*" />
<data android:pathPattern=".*m.*m.*m.*message.*" />
<data android:pathPattern=".*m.*m.*m.*m.*message.*" />
...
</intent-filter>

与自定义文件扩展名匹配时,尤其会发出此消息。


对于任何有兴趣的人,问题已记录在code.google.com上
benjamin davis 2014年

3

如果后缀未在Android的system = wide MIME数据库中以MIME类型注册,则对于VIEW或SEND操作,上述方法均无法正常工作。我发现可以触发指定后缀的唯一设置包括android:mimeType="*/*",但是随后对所有文件触发该操作。显然不是您想要的!

如果不将哑剧和后缀添加到Android哑剧数据库中,我将找不到任何合适的解决方案,到目前为止,我还没有找到一种解决办法。如果有人知道,那么指针将是很棒的。


2

当Intent满足时,将满足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

https://stackoverflow.com/a/4621284/2683842报告说<data pathPattern=> .*xyzx它在看到的第一个中止,如果不加,将立即失败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>

1

如果您希望直接从Gmail,Dropbox或任何内置android文件工具打开文件,请使用以下代码(删除“ android:host =“ *”',使gmail无法访问该文件):

<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" android:pathPattern=".*\\.kdb" 
          android:mimeType="application/octet-stream"/>


</intent-filter>

<intent-filter>
    <action android:name="android.intent.action.VIEW"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <data android:scheme="file" android:mimeType="*/*"     
          android:pathPattern=".*\\.kdb"/>
</intent-filter>

根据Android 4.x版,数据过滤器必须使用一条语句编写


我一直在尝试一切尝试使android浏览器下​​载和打开正常工作。您的解决方案适用于android本机浏览器和android chrome,但是android firefox似乎仍然在文本窗口中打开我的文件。这是自定义的mime类型和自定义的扩展名。以前只有扩展名,它只能在Firefox中使用。现在它可以在除firefox(包括gmail)之外的所有地方使用。我仍在测试它,但我只是想标记一个事实,即这里有一系列新的跨浏览器问题。
戴蒙·史密斯,

1

使用以下过滤器从浏览器,gmail和文件浏览器打开(已测试)。注意:请不要合并两个过滤器,这会使浏览器忽略您的应用程序(已测试)。

        <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" android:pathPattern=".*\\.ext" android:mimeType="application/*"/>
            <data android:scheme="content" android:pathPattern=".*\\.ext" android:mimeType="application/*"/>
        </intent-filter>

        <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="http"
                  android:host="*"
                  android:pathPattern=".*\\.ext" />
            <data android:scheme="https"
                  android:host="*"
                  android:pathPattern=".*\\.ext" />
            <data android:scheme="ftp"
                  android:host="*"
                  android:pathPattern=".*\\.ext" />

        </intent-filter>

您是否已使用Gmail附件测试了此答案?
IgorGanapolsky

1

更新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>

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

注意事项/陷阱

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

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

最后的想法

  • 当前尚无优雅的解决方案来将您的应用程序与Android中的特定扩展名类型相关联。这是我所能做的最好的事情。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.