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

问题描述:

我希望能够从网上下载一个特定扩展名的文件,并将它传递给我的应用程序来处理它,但我一直无法弄清楚意图过滤器。文件类型不包括在mimetypes中,并且我尝试使用针对特定文件扩展名的Android意图过滤器?

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

但我无法让它工作。

不是android:path,尝试android:mimeType,用MIME类型这个特定内容片段的的值。此外,android:path不接受通配符 - 为此使用android:pathPattern

+0

“的文件类型为不包括在MIME类型”?即使不使用相同的单词,仍然应该为您正在下载的内容的类型设置MIME类型。 – Konklone 2009-11-15 17:24:17

+0

内容类型有一个mimetype,但该文件是由第三方应用程序生成的,该应用程序在其上放置了不同的扩展名,所以我认为它不会被识别为该mimetype。 – Curyous 2009-11-16 23:58:08

这是我如何定义我在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> 

filescheme表示当本地文件被打开(而不是像HTTP协议)是这样的话。

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

pathPattern是您指定要匹配(在这个例子中.kdb)什么扩展。开头的.*匹配任何字符序列。这些字符串需要双重转义,因此\\\\.与文字周期匹配。然后,你以文件扩展名结束。与pathPattern的一个警告是.*不是像你期望的贪婪的比赛,如果这是一个正则表达式。该模式将无法匹配在.kdb之前包含.的路径。对于这个问题和解决方法的更详细的讨论,请参阅here

最后,根据Android文档,既hostscheme属性是必需的pathPattern属性的工作,所以才设置为通配符匹配任何东西。

现在,如果你选择一个.kdb文件中像琳达文件管理器应用程序,我的应用程序显示为一个选项。我应该注意到,这本身并不允许你在浏览器中下载这个文件类型,因为这只能在文件方案中注册。在您的手机上安装一个类似Linda文件管理器的应用程序,一般可以让您下载任何文件类型。

+2

这在这里不起作用。首先用mimeType =“*”,该包不安装在Android 2.1上,我得到一个MalformedMimeTypeException。使用“*/*”解决了这个问题,但是这个过滤器没有效果。我目前正在使用Skyfire浏览器进行测试,该浏览器不像标准的Android浏览器那样保留MIME类型的下载。当点击Skyfire下载列表中的文件时,会通过文件数据广播简单的VIEW意图。而这个意图过滤器不匹配。 – olivierg 2011-02-08 12:43:41

+0

@Brian Pellin:我实际上正在寻找一种方法将mime类型绑定到'.kdbx'扩展名,以便ES文件浏览器可以在指向这篇文章时打开kdbx文件。显然,如果意图有一个空的MIME类型,这个意图过滤器将不起作用!另外,可以将EMPTY字符串作为动作并且只是一个URI。 Google文档对该意图做出了回应,因此它必须有效。 – 2011-09-06 01:50:34

+0

作为另一张海报下面提到(+1他,他值得),改为mimeType =“*/*”的作品。 – Nick 2011-12-16 16:54:27

上述Brian的回答让我90%的方式出现。为了完成它,对于MIME类型我用

android:mimeType="*/*" 

我怀疑以前的海报已经尝试发布相同的细节,但withough qoting明星斜线明星作为代码,计算器diplays它只是一个斜线。

+1

有了这个,你将处理所有的文件类型,这是非常恼人的(当然,除非你的应用程序确实处理一切)... – 2016-09-02 20:56:59

布赖恩的答案是非常接近,但这里有一个清洁,无差错的方式有试图打开一个文件,用自己的自定义扩展(无需计划或主机)当你的应用程序调用:

<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属性是唯一有意义的,我已经验证了这一点:http://developer.android.com/guide/topics/manifest/data-element.html – 2011-09-28 18:35:35

+4

-1;这将匹配*任何*文件; Brian的评论是正确的,并且对mimeType =“*/*”的小修改,他的原始示例是完美的。 – Nick 2011-12-16 16:52:39

+0

这篇文章如果很久以前,但没有“/”不安装。你需要“\ */\ *”,它将匹配任何文件类型(不确定,如果你打算这么说)。所以你的程序可能会被要求打开视频或MP3。我还没有找到解决办法。 – Rene 2012-01-22 10:01:04

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

我找不到任何适当的解决方案,而没有将mime和后缀添加到Android mime数据库,到目前为止,我还没有找到一种方法来做到这一点。如果有人知道,指针会非常棒。

在Android 4上,规则变得越来越严格,他们以前就是这样。用途:

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

如果你想将文件直接从Gmail中,Dropbox的或任何的buildin Android文件的工具打开,然后使用下面的代码(删除“机器人:主机=‘*’”那做出的文件无法访问的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版

+0

我一直在尝试一切尝试让android浏览器下​​载并打开正常工作。你的解决方案适用于android原生浏览器和android chrome,但是android firefox仍然可以在文本窗口中打开我的文件。这是一个自定义MIME类型和自定义扩展。以前只有扩展名,它只能在firefox中工作。现在除了firefox(包括gmail)以外,它都可以工作。我仍在测试它,但我只是想说明这里有一个新的跨浏览器问题。 – 2014-03-20 11:14:00

+0

你确实认识到** android:host **是强制性的,对吧? – 2017-10-18 18:58:49

我一直在为此而努力颇有几分自定义文件扩展名,我自己。经过大量搜索之后,我发现this web page海报发现Android的patternMatcher类(用于Intent-Filters中的PathPattern匹配)在您的路径包含路径中其他位置的匹配模式的第一个字符时具有意外行为(如如果你想匹配“* .xyz”,如果你的路径中有一个“x”,patternMatcher类就会停止)。以下是他找到了一个解决办法,并为我工作,虽然这是一个黑客位的:

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

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

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

很奇怪,不是吗。为了解决这个问题 - 实际上减少了 的可能性 - 开发者应该使用令人讨厌的愚蠢的pathPattern。

Ex。目标:匹配包含'消息'的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> 

自定义文件扩展匹配时,这是特别发出。

+0

对于任何有兴趣的人,问题已记录在[code.google.com](https://code.google.com/p/android/issues/detail?id=69080) – 2014-06-18 15:31:02

+0

并且此答案是否适合您? – 2017-10-18 18:58:09

使用下面的过滤器从浏览器打开,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> 
+0

您是否使用Gmail附件测试过此答案? – 2017-10-18 19:09:40

我必须承认,从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> 

注:

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

我希望你会发现这个有用的,你不会浪费天,经历所有可能的组合。有改进的空间,所以欢迎评论。

+0

这是我的工作解决方案。为Content-Scheme和File-Scheme注册一个单独的做了个窍门!谢谢! – Mehlyfication 2015-01-28 14:53:14

+0

谢谢!为我工作。 Galaxy S6上的Gmail应用程序和Samsung My Files应用程序都可以使用您的解决方案使用我的应用程序打开文件! – Haris 2015-05-29 03:35:52

+0

“应用程序名称”究竟是什么? (就我而言,人类可读的应用程序名称中包含空格。) – 2016-08-18 18:36:15

我一直在试图让这个工作多年,并基本上尝试了所有建议的解决方案,仍然无法让Android识别特定的文件扩展名。我有一个"*/*" MIME类型的意图过滤器,这是唯一的似乎工作和文件浏览器现在列出我的应用程序作为打开文件的选项,但我的应用程序现在显示为一个选项打开任何种类的文件甚至尽管我已经使用pathPattern标签指定了特定的文件扩展名。到目前为止,甚至当我尝试查看/编辑联系人列表中的联系人时,Android会询问我是否想使用我的应用查看联系人,而这只是发生这种情况的许多情况之一,非常非常烦人。

最终我发现这个谷歌群组发布了一个类似的问题,一个实际的Android框架工程师回答。她解释说,android根本不知道任何关于文件扩展名的内容,只知道MIME类型(https://groups.google.com/forum/#!topic/android-developers/a7qsSl3vQq0)。

所以从我所看到的,试图读,安卓根本无法文件的扩展和pathPattern标签区分是basicly的时间和精力浪费巨大。如果您有幸只需要某种特定MIME类型的文件(比如文本,视频或音频),则可以使用MIME类型的意向过滤器。如果你需要一个特定的文件扩展名或者Android不知道的MIME类型,那么你的运气不好。

如果我错了,任何有关这请告诉我,至今我读过每一个岗位,并想尽提出的解决方案,我可以找到,但没有工作过。

我可以另写两页关于这些事情如何共同似乎是在Android和如何搞砸了开发人员的经验是,但我会拯救你我的愤怒咆哮)。希望我救了一些人一些麻烦。

关于此主题有很多错误信息,特别是来自Google自己的文档。最好的,并给予奇怪的逻辑,可能唯一真正的文档是源代码。

intent filter implementation具有几乎无法描绘的逻辑。 parser code是拼图的另一个相关部分。

下面的过滤器非常接近合理的行为。路径模式适用于“文件”方案意图。

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

我还没有包括其他方案,如“HTTP”在这里,但他们可能会在所有这些过滤器正常工作。

奇怪的方案是“内容”,扩展名不适用于过滤器。但只要提供者声明您的MIME类型(例如,Gmail将传递MIME类型以使附件畅通无阻),则过滤器将匹配。

陷阱要注意的:

  1. 要知道,没有在过滤器一贯的行为,它是specal情况下迷宫,以及对待违反了最小惊讶的原则作为设计目标。没有一种模式匹配算法遵循相同的语法或行为。缺少一个字段有时是一个通配符,有时不是。数据元素中的属性有时必须放在一起,有时会忽略分组。它本来可以做得更好。
  2. 该方案和主机必须指定路径规则来匹配(目前与Google的API指南相反)。
  3. 至少ES文件浏览器生成的意图与MIME类型的“”,将其过滤非常不同为null时,不可能明确地匹配,并且只能由有风险的匹配“*/*”过滤器。
  4. “*/*”过滤器不会与空MIME类型的Intents相匹配 - 对于这种特定情况,根本不需要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> 
+0

伟大的,你站起来\\ ..一遍又一遍的许多证据需要和其他怪癖。谷歌应该已经修正了4.2,这到底是什么。唉,我仍然有你的例子似乎无法解决的情况。是否有一些像“.gblorb”这样的6个扩展名的问题,我的代码可以正常工作3个字母或更少? – 2017-02-08 07:00:53

+0

这个问题的最佳答案和我认为类似的问题! 不幸的是,只要无法通过文件扩展匹配内容意图(如您在5中指出的那样),就不可能可靠地筛选出所有正确的意图,而不会匹配错误的意图。这适用于您不能使用自定义MIME类型的情况。 因此,只要Android不提供解决方案,它将成为应用程序内的文件选择器......我不想让用户感到不一致的行为。 – 2017-09-20 10:18:39