我希望能够从网络上下载具有特定扩展名的文件,并将其传递给我的应用程序来处理它,但是我无法弄清意图过滤器。文件类型不包含在mimetypes中,我尝试使用
<data android:path="*.ext" />
但我无法解决这个问题。
Answers:
这是我在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>
在scheme
中file
表明,当一个本地文件被打开(而不是像HTTP协议),这应该发生。
mimeType
可以设置为\*/\*
匹配任何mime类型。
pathPattern
是您指定要匹配的扩展名的位置(在此示例中.kdb
)。在.*
开头的任何字符匹配SQUENCE。这些字符串需要两次转义,因此\\\\.
匹配一个字面量。然后,以文件扩展名结尾。使用pathPattern的一个警告是,.*
它不是一个贪婪的匹配项,就像这是一个正则表达式一样。此模式将无法匹配.
在之前包含的路径.kdb
。有关此问题的更详细讨论和解决方法,请参见此处
最后,根据Android文档,属性必须同时使用host
和scheme
属性,pathPattern
属性才能设置为通配符以匹配任何内容。
现在,如果您.kdb
在Linda File Manager之类的应用程序中选择文件,则我的应用程序会显示为一个选项。我应该注意,仅此一项不允许您在浏览器中下载此文件类型,因为这仅在文件方案中注册。通常,在手机上安装类似Linda File Manager的应用程序本身就可以使您下载任何文件类型。
.kdbx
扩展名的方法,以使ES文件资源管理器在指向此职位时可以打开kdbx文件。显然,如果该意图具有空的MIME类型,则该意图过滤器将不起作用!而且,可能有一个意图,其中包含一个EMPTY字符串作为操作,而仅有一个URI。Google文档对此意图做出了回应,因此该意图必须有效。
<data>
具有四个属性的on 标签。具有4个标签是合乎逻辑的“或”(与Android 2兼容),但Android 4更为严格。参见stackoverflow.com/questions/20650378/…–
\\\\.
匹配一个立即数,为什么不使用它来形成.kdb
扩展名\\\\.kdb
呢?
关于此主题的信息有很多误导,尤其是来自Google自己的文档。最好的,再加上奇怪的逻辑,可能唯一真正的文档是源代码。
该意图过滤器的实现具有几乎无法描绘的逻辑。该解析器代码是其他相关的一块拼图。
以下过滤器非常接近明智的行为。路径模式确实适用于“文件”方案的意图。
只要文件扩展名匹配,全局mime类型模式匹配将匹配所有类型。这不是完美的方法,但是是匹配文件管理器(如ES File Explorer)行为的唯一方法,并且仅限于URI /文件扩展名匹配的意图。
我这里没有包括“ http”之类的其他方案,但是它们可能在所有这些过滤器上都能正常工作。
奇怪的方案是“内容”,其扩展名不适用于过滤器。但是,只要提供商指定您的MIME类型(例如,Gmail将不受阻碍地传递MIME类型),过滤器就会匹配。
要了解的注意事项:
考虑到所有这些,下面是一个带有注释的示例:
<!--
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>
<data android:mimeType="*/*" />
所有三个选项中的MimeType ,它对于包括Google Drive和Gmail在内的所有应用程序都具有吸引力。
我必须承认,在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仅对某些模式做出响应,我将非常高兴地看到如何。android:host="*"
属性,。intent-filter
合并了块,但我尚未对此进行验证。android:scheme="http"
可以使用下载文件时处理浏览器的请求。请注意,某些浏览器可能会搞砸,android:mimeType
因此请进行试验android:mimeType="*/*"
并检查调试器实际通过了什么,然后加强过滤,以免最终成为处理所有问题的烦人应用程序。intent-filter
已在Galaxy S3上使用三星的“我的文件”应用进行了测试。FX Explorer仍然拒绝正确打开文件,我还注意到该文件未使用应用程序图标。再说一次,如果有人让它起作用,请在下面评论。我希望您会发现这很有用,并且不必浪费时间进行所有可能的组合。有改进的空间,欢迎发表评论。
android:label
意图过滤器的字符串是用户将在选择器菜单中看到的字符串。默认情况下,使用应用程序名称。
而不是android:path
尝试android:mimeType
使用此特定内容的MIME类型的值。另外,android:path
也不接受通配符,请使用通配符android:pathPattern
。
我一直在尝试使它工作一段时间,并且基本上尝试了所有建议的解决方案,但仍然无法让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中的普遍程度以及开发人员体验的混乱程度,但是我将省去我的愤怒。希望我能给别人省些麻烦。
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>
<data>
带有四个属性的标签。您的解决方案可能适用于Android 2-但规则变得更加严格:stackoverflow.com/questions/20650378/…–
host
和scheme
需要!
我一直在为自定义文件扩展名而苦苦挣扎。经过大量搜索后,我发现了该网页,发布者发现当路径的路径中包含匹配模式的第一个字符时,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>
与自定义文件扩展名匹配时,尤其会发出此消息。
当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=>
.*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>
如果您希望直接从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版,数据过滤器必须使用一条语句编写
使用以下过滤器从浏览器,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>
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="*/*"/>
我的意图过滤器,我找不到通过文件浏览器启动我的应用程序的任何方法。我无法使用它,因为每当用户单击手机上的任何文件(不仅是自定义文件扩展名的文件)时,它都会启动我的应用程序。我不建议将此添加到您的意图过滤器中。