Intent匹配和解析

来自:https://developer.android.com/guide/components/intents-filters.html


当系统收到隐式Intent以启动 Activity 时,它根据以下三个方面将该 Intent 与 Intent 过滤器进行比较,搜索该Intent的最佳Activity:

  • Intent 操作
  • Intent 数据(URI 和数据类型)
  • Intent 类别

下文根据如何在应用的清单文件中声明 Intent 过滤器,描述 Intent 如何与相应的组件匹配。

操作测试

要指定接受的Intent操作,Intent过滤器既可以不声明任何<action>元素,也可以声明多个此类元素。例如:


    
    
    ...

要通过此过滤器,您在Intent中指定的操作必须与过滤器中列出的某一操作匹配。

如果该过滤器未列出任何操作,则Intent 没有任何匹配项,因此所有Intent均无法通过测试。但是,如果Intent未指定操作,则会通过测试(只要过滤器至少包含一个操作)。

类别测试

要指定接受的 Intent 类别,Intent过滤器既可以不声明任何<category>元素,也可以声明多个此类元素。例如:


    
    
    ...

若要Intent通过类别测试,则Intent中的每个类别均必须与过滤器中的类别匹配。反之则未必然,Intent 过滤器声明的类别可以超出Intent中指定的数量,且Intent仍会通过测试。因此,不含类别的Intent应当始终会通过此测试,无论过滤器中声明何种类别均是如此。

注意:Android 会自动将CATEGORY_DEFAULT类别应用于传递给startActivity()startActivityForResult()的所有隐式 Intent。因此,如需 Activity 接收隐式 Intent,则必须将"android.intent.category.DEFAULT"的类别包括在其Intent过滤器中(如上文的<intent-filter>示例所示)。

数据测试

要指定接受的Intent 数据,Intent过滤器既可以不声明任何<data>元素,也可以声明多个此类元素。例如:


    
    
    ...

每个元素均可指URI结构和数据类型(MIME 介质类型)。URI的每个部分均包含单独的schemehostportpath属性:

://:/

例如:

content://com.example.project:200/folder/subfolder/etc

在此URI中,架构是content,主机是com.example.project,端口是200,路径是folder/subfolder/etc

在<data>元素中,上述每个属性均为可选,但存在线性依赖关系:

  • 如果未指定架构,则会忽略主机。
  • 如果未指定主机,则会忽略端口。
  • 如果未指定架构和主机,则会忽略路径。

将 Intent 中的 URI 与过滤器中的 URI 规范进行比较时,它仅与过滤器中包含的部分 URI 进行比较。例如:

  • 如果过滤器仅指定架构,则具有该架构的所有 URI 均与该过滤器匹配。
  • 如果过滤器指定架构和权限、但未指定路径,则具有相同架构和权限的所有 URI 都会通过过滤器,无论其路径如何均是如此。
  • 如果过滤器指定架构、权限和路径,则仅具有相同架构、权限和路径 的 URI 才会通过过滤器。

注意:路径规范可以包含星号通配符 (*),因此仅需部分匹配路径名即可。

数据测试会将 Intent 中的 URI 和 MIME 类型与过滤器中指定的 URI 和 MIME 类型进行比较。规则如下:

  1. 仅当过滤器未指定任何 URI 或 MIME 类型时,不含 URI 和 MIME 类型的 Intent 才会通过测试。
  2. 对于包含 URI、但不含 MIME 类型(既未显式声明,也无法通过 URI 推断得出)的 Intent,仅当其 URI 与过滤器的 URI 格式匹配、且过滤器同样未指定 MIME 类型时,才会通过测试。
  3. 仅当过滤器列出相同的 MIME 类型且未指定 URI 格式时,包含 MIME 类型、但不含 URI 的 Intent 才会通过测试。
  4. 仅当 MIME 类型与过滤器中列出的类型匹配时,包含 URI 和 MIME 类型(通过显式声明,或可以通过 URI 推断得出)的 Intent 才会通过测试的 MIME 类型部分。如果 Intent 的 URI 与过滤器中的 URI 匹配,或者如果 Intent 具有 content: 或 file: URI 且过滤器未指定 URI,则 Intent 会通过测试的 URI 部分。换而言之,如果过滤器仅列出 MIME 类型,则假定组件支持 content: 和 file: 数据。

最后一条规则,即规则 (d),反映了期望组件能够从文件中或内容提供商处获得本地数据。因此,其过滤器可以仅列出数据类型,而不必显式命名content: 和 file: 架构。这是一个典型的案例。例如,下文中的<data>元素向 Android 指出,组件可从内容提供商处获得并显示图像数据:


    
    ...

由于大部分可用数据均由内容提供商分发,因此指定数据类型(而非 URI)的过滤器也许最为常见。

另一常见的配置是具有架构和数据类型的过滤器。例如,下文中的<data>元素向 Android 指出,组件可从网络中检索视频数据以执行操作:


    
    ...

Intent 匹配

通过 Intent 过滤器匹配 Intent,这不仅有助于发现要激活的目标组件,还有助于发现设备上组件集的相关信息。例如,主页应用通过使用指定ACTION_MAIN操作和CATEGORY_LAUNCHER类别的 Intent 过滤器查找所有 Activity,以此填充应用启动器。

您的应用可以采用类似的方式使用 Intent 匹配。PackageManager提供了一整套query...()方法来返回所有能够接受特定 Intent 的组件。此外,它还提供了一系列类似的resolve...()方法来确定响应 Intent 的最佳组件。例如,queryIntentActivities()将返回能够执行那些作为参数传递的 Intent 的所有 Activity 列表,而queryIntentServices()则可返回类似的服务列表。这两种方法均不会激活组件,而只是列出能够响应的组件。对于广播接收器,有一种类似的方法:queryBroadcastReceivers()




你可能感兴趣的:(Android进阶)