Intent Filter 是 AndroidManifest.xml 中的声明性声明,它向系统指示应用程序组件可以处理哪些隐式意图。根据 Android 开发者指南,过滤器包含 action、category 和 data,系统基于这些信息路由来自其他应用程序和系统事件的调用。Android 开发使用 Intent Filter 作为不同应用程序组件之间松散耦合的主要机制。
要点
Intent Filter 是 Android 应用程序的一个配置元素,它告诉系统组件能够处理特定类型的隐式意图。与指定具体类的显式 Intent 不同,隐式 Intent 仅包含所需操作的描述,系统根据注册的过滤器自动找到合适的组件。
过滤器在组件内部声明 — Activity、Service 或 BroadcastReceiver — 在 AndroidManifest.xml 文件中。每个过滤器可以包含多个 action、category 和 data 元素。一个组件可以有无限数量的 Intent Filter,每个过滤器描述一个单独的处理场景。
Intent Filter 实现了应用程序组件之间的松散耦合原则。应用程序 A 不需要知道应用程序 B 的存在 — 它只需发送带有操作描述的 Intent,系统根据过滤器进行路由。这个机制是 Share Sheet、浏览器选择以及 deep link 处理的基础。
显式 Intent 指定要启动的组件的具体类。它们用于同一应用程序内的内部导航,当开发者确切知道应该打开哪个 Activity 时。隐式 Intent 仅包含操作描述,组件由系统动态确定。
Intent Filter 仅与隐式 Intent 一起工作。如果在 Intent 中指定了具体类,系统会忽略所有过滤器并直接启动指定的组件。过滤器仅在解析隐式调用时检查,这使它们成为应用间通信的关键元素。
| 特性 | 显式 Intent | 隐式 Intent |
|---|---|---|
| 组件 | 显式指定 (className) | 由系统确定 |
| Intent Filter | 不需要 | 必需 |
| 示例 | startActivity(Intent(this, ProfileActivity::class.java)) | Intent(ACTION_VIEW, Uri.parse(“https://example.com”)) |
| 安全性 | 更高(无拦截) | 较低(可能存在冲突) |
每个 Intent Filter 由三组元素组成 — action、category 和 data — 它们的组合决定了组件将接收哪些 Intent。如果 Intent 与每组中至少一个元素匹配,则认为过滤器已通过。
Action 描述执行的操作 — 查看、编辑、发送。Category 添加额外的处理上下文 — 例如,从浏览器启动的能力。Data 通过 URI 或 MIME 类型定义处理信息的格式。
用于打开用户个人资料链接的 Activity 的 Intent Filter 示例。过滤器包括所有三组元素以实现精确路由。
<activity android:name=".ProfileActivity">
<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="myapp"
android:host="profile" />
</intent-filter>
</activity>
请注意必须指定 category DEFAULT — 没有它,系统将不会向组件传递隐式 Intent。如果链接应该从浏览器处理,则添加 BROWSABLE 类别。
Android 上的 Deep link 通过包含 action VIEW 和包含架构、主机和路径的 data 标签的 Intent Filter 进行配置。当打开 myapp://profile/42 形式的链接时,系统找到具有匹配过滤器的 Activity 并使用传递的 URI 启动它。正确配置 pathPrefix、pathPattern 或 path 以实现精确匹配非常重要。
从 Android 6(API 23)开始,支持 App Links — 通过 HTTPS 验证的 deep link。对于 App Links,使用相同的 Intent Filter,但需要通过 Digital Asset Links 进行额外的域验证。验证后,系统会自动打开应用程序,无需选择对话框。
用于通过 HTTPS 链接进行验证的 App Link 过滤器示例。在这种情况下,架构始终为 https,主机对应于 Digital Asset Links 中指定的域。
<intent-filter android:autoVerify="true">
<action
android:name="android.intent.action.VIEW" />
<category
android:name="android.intent.category.DEFAULT" />
<category
android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="example.com"
android:pathPrefix="/profile" />
</intent-filter>
autoVerify 属性指示系统在安装应用程序时检查 Digital Asset Links。如果验证成功,应用程序将自动成为指定域和路径的默认处理器。
在系统选择处理 Intent 的组件后,开发者必须从目标组件内的传入意图中提取数据。对于 Activity,使用 onCreate() 中的 getIntent() 方法;对于 BroadcastReceiver,使用 onReceive() 方法,其中 Intent 作为参数传递。
数据提取包括获取 action 以确定操作类型、data 以获取 URI 以及 extra 参数以获取附加信息。这些元素中的每一个都可能缺失,因此在使用前必须进行 null 检查。
在 Kotlin 的 Activity 中处理传入 deep link 的示例。代码从 Intent 中提取 URI,并根据主机和路径决定导航。
class ProfileActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val uri = intent?.data
if (uri?.host == "profile") {
val userId = uri.lastPathSegment
loadProfile(userId)
}
}
}
建议使用 safe call 操作符检查 intent 和 data 是否为 null,因为 Activity 可能在没有传入 deep link 的情况下启动。同时,在使用 host 和 pathSegment 进行导航之前,应检查它们是否为 null。
如果多个应用程序注册了匹配同一隐式 Intent 的 Intent Filter,系统会向用户显示选择对话框。用户可以选择一次性使用的应用程序或设置默认处理器。从 Android 10 开始,选择对话框仅在首次调用时显示,之后系统会记住用户的选择。
优先级管理使用 intent-filter 标签中的 android:priority 属性。值越高,组件在冲突解决中的优先级越高。但是,优先级不适用于来自不同应用程序的过滤器 — 在这种情况下,如果没有设置默认应用程序,始终会显示选择对话框。
开发者可以通过 Intent.createChooser() 以编程方式调用选择对话框,传递目标 Intent 和标题。当应用程序希望明确建议用户选择处理器时,即使已设置默认应用程序,这也很有用。例如,通过 ACTION_SEND 将图像发送到社交网络时,createChooser 保证无论默认设置如何都显示对话框。
最常见的错误之一是 Intent Filter 中缺少 DEFAULT 类别。开发者从示例中复制配置,但忘记添加此类别,导致 Activity 无法接收隐式 Intent。系统根本看不到隐式调用的过滤器,尽管显式 Intent 仍然有效。
第二个常见错误是在 data 标签中错误指定 scheme 而没有完整 URI。如果只指定了架构但没有指定主机,过滤器将接受来自任何源的具有此架构的所有链接,这可能导致来自未经验证来源的不必要调用。建议始终至少指定架构和主机。
第三个错误是在 Activity 代码中缺少对 intent.data 的 null 检查。如果 Activity 不是通过 deep link 而是通过启动器以标准方式启动,则 Intent 不包含 URI。未经检查就访问 intent.data 会导致 NullPointerException 和应用程序崩溃。始终使用带有 safe call 操作符的 intent?.data?.toString()。
常见问题
是的,要接收隐式 Intent,DEFAULT 类别是必需的。没有它,系统将不会向组件传递隐式调用,Intent Filter 将仅适用于显式 Intent,而显式 Intent 本身不会检查过滤器。
没有限制。一个 Activity 可以包含任意数量的 Intent Filter。每个过滤器描述一个单独的处理场景,例如一个过滤器用于 deep link,另一个用于文件处理,第三个用于 Share Sheet。
Intent Filter 是处理隐式 Intent 的通用机制。App Link 是 Intent Filter 的一种特殊情况,通过 Digital Asset Links 进行验证,自动将应用程序设置为指定域上 HTTPS 链接的默认处理器。
可以,Intent Filter 不仅可以为 Activity 声明,还可以为 Service 和 BroadcastReceiver 声明。对于 Service,这允许从其他应用程序启动后台服务;对于 BroadcastReceiver,则允许接收系统广播。
MIME 类型通过 mimeType 属性在 data 标签中指定。过滤器确定组件可以处理哪些数据类型 — 例如,image/* 用于所有图像,或 text/plain 仅用于纯文本。MIME 类型可以与 URI 架构组合。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。