简介
IntentFilter可以理解为Intent的过滤器,作用是在利用隐式Intent启动组件时过滤掉不匹配的组件,找到能够正确完成任务的组件。一个Intent想要通过IntentFilter,需要完成三项测试:操作测试、数据测试、类别测试。
一个组件可以拥有多个IntentFilter,但只需要通过其中之一即可启动该组件。
IntentFilter既可以在Manifest文件中利用<intent-filter>标签进行静态声明,也可以在代码中创建IntentFilter对象实现动态声明。
Android要求Service始终需要由显式Intent启动,因此不应当为Service组件声明IntentFilter。
操作测试(Action)
要指定接受的 Intent 操作,IntentFilter既可以不声明任何 <action> 元素,也可以声明多个此类元素。
- Intent中未声明<action>元素,IntentFilter中也未声明<action>元素:无法通过。
- Intent中声明了<action>元素,IntentFilter中未声明<action>元素:无法通过。
- Intent中未声明<action>元素,IntentFilter中声明了<action>元素:无条件通过。
- Intent中声明了<action>元素,IntentFilter中也声明了<action>元素:只要Intent中的任意一个<action>元素与IntentFilter中的<action>元素匹配就能通过测试。
类别测试(Category)
要指定接受的 Intent 类别,IntentFilter既可以不声明任何 <category>元素,也可以声明多个此类元素。
- Intent中未声明<category>元素,IntentFilter中也未声明<category>元素:系统会自动把CATEGORY_DEFAULT赋给所有隐式Intent,所以无法通过。
- Intent中声明了<category>元素,IntentFilter中未声明<category>元素:无法通过。
- Intent中未声明<category>元素,IntentFilter中声明了<category>元素:只要IntentFilter中声明了CATEGORY_DEFAULT就无条件通过,否则不通过。
- Intent中声明了<category>元素,IntentFilter中也声明了<category>元素:Intent中的<category>元素集是IntentFilter中的<category>元素集的子集就能通过测试。
数据测试(Data)
(1)URL结构与MIME数据类型
标准URL格式:<scheme>://<host>:<port>/<path>
例:content://com.example.project:200/folder/subfolder/etc
在此 URI 中,架构是 content,主机是com.example.project,端口是 200,路径是 folder/subfolder/etc。
(2)URL与IntentFilter匹配规则
要指定接受的 Intent 数据, Intent 过滤器既可以不声明任何 <data>元素,也可以声明多个此类元素。
<data>元素声明示例:<data android:mimeType="video/mpeg" android:scheme="http" ... />
每个<data>元素均可指定 URI 结构和数据类型(MIME 媒体类型)。 URI 的每个部分均包含单独的 scheme、host、port 和 path 。
在<data>元素中,上述每个属性均为可选,但存在线性依赖关系:
- 如果未指定架构,则会忽略主机。
- 如果未指定主机,则会忽略端口。
- 如果未指定架构和主机,则会忽略路径。
将 Intent 中的 URI 与过滤器中的 URI 规范进行比较时,它仅与过滤器中包含的部分 URI 进行比较。例如:
- 如果过滤器仅指定架构,则具有该架构的所有 URI 均与该过滤器匹配。
- 如果过滤器指定架构和权限,但未指定路径,则具有相同架构和权限的所有 URI 均与该过滤器匹配。
- 如果过滤器指定架构、权限和路径,则仅具有相同架构、权限和路径的 URI 才会通过过滤器。路径规范可以包含星号通配符 (*),因此仅需部分匹配路径名即可。
(3)数据测试具体规则
数据测试会将 Intent 中的 URI 和 MIME 类型与过滤器中指定的 URI 和 MIME 类型进行比较。 规则如下:
- 仅当过滤器未指定任何 URI 或 MIME 类型时,不含 URI 和 MIME 类型的 Intent 才会通过测试。
- 对于包含 URI 但不含 MIME 类型(既未显式声明,也无法通过 URI 推断得出)的 Intent,仅当其 URI 与过滤器的 URI 格式匹配、且过滤器同样未指定 MIME 类型时,才会通过测试。
- 仅当过滤器列出相同的 MIME 类型且未指定 URI 格式时,包含 MIME 类型、但不含 URI 的 Intent 才会通过测试。
- 仅当 MIME 类型与过滤器中列出的类型匹配时,同时包含 URI 类型和 MIME 类型(通过显式声明,或可以通过 URI 推断得出)的 Intent 才会通过测试的 MIME 类型部分。 如果 Intent 的 URI 与过滤器中的 URI 匹配,或者如果 Intent 具有 content: 或 file: 抬头的URI 且过滤器未指定 URI,则 Intent 会通过测试的 URI 部分。 换言之,如果过滤器只是列出 MIME 类型,则假定组件支持 content: 和 file: 数据。
简而言之,数据测试以IntentFilter为核心,Intent的数据部分(URL、MIME)只有在IntentFilter的要求之内才能通过。IntentFilter未声明的话,Intent也不能有,否则就无法通过。唯一例外:第四条规则中,同时包含URL(content:或file:抬头)和MIME的Intent,若MIME匹配,且IntentFilter未定义URL的话就能匹配。