[Android 从零到一] Intent 与 IntentFilter
1. 背景
Activity 之间怎么通信?答案是 Intent。Intent 是 Android 中连接各组件的「信使」——启动 Activity、发送广播、绑定 Service 都要靠它。而 IntentFilter 决定了哪些 Intent 能被接收。很多新手分不清显式隐式、搞不懂为什么 Intent 发出去没响应,今天说清楚。
2. Intent 是什么
Intent 是一个消息对象,包含要执行的操作和操作涉及的数据。
2.1 核心组成
- ComponentName — 目标组件(显式)
- Action — 动作字符串(ACTION_VIEW、ACTION_SEND 等)
- Data — 操作的数据 URI + MIME 类型
- Category — 额外分类信息
- Extras — 携带的附加数据(Bundle)
- Flags — 控制行为的标志位
3. 显式 Intent vs 隐式 Intent
3.1 显式 Intent
直接指定目标组件,精确查找:
// 方式一:指定类名
startActivity(Intent(this, DetailActivity::class.java))
// 携带数据
val intent = Intent(this, DetailActivity::class.java).apply {
putExtra("user_id", 1001)
putExtra("user_name", "小明")
}
startActivity(intent)
// 接收端取值
class DetailActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val userId = intent.getIntExtra("user_id", -1)
val userName = intent.getStringExtra("user_name")
}
}
3.2 隐式 Intent
声明 Action 和 Data,系统根据 IntentFilter 匹配目标:
// 打开网页
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com")))
// 发送文本
val intent = Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
putExtra(Intent.EXTRA_TEXT, "分享一段文字")
}
startActivity(Intent.createChooser(intent, "分享到"))
// 拨号
val intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:10086"))
startActivity(intent)
4. IntentFilter 匹配规则
IntentFilter 是隐式 Intent 的「门牌号」,声明在 AndroidManifest.xml 中:
4.1 三大匹配规则
| 规则 | 说明 | 注意点 |
|---|---|---|
| Action 匹配 | 完全一致(字符串匹配) | Filter 可声明多个 action |
| Category 匹配 | Intent 所有 category 在 Filter 中有对应项 | 默认带 CATEGORY_DEFAULT,Filter 必须声明 |
| Data 匹配 | URI + MIME type | 最容易被忽视的坑 |
4.2 常见陷阱
// ❌ 这样会匹配失败(缺 CATEGORY_DEFAULT)
val intent = Intent("com.example.ACTION_MY_CUSTOM")
startActivity(intent)
// ✅ 加 CATEGORY_DEFAULT
val intent = Intent("com.example.ACTION_MY_CUSTOM").apply {
addCategory(Intent.CATEGORY_DEFAULT)
}
startActivity(intent)
5. 踩坑指南
- ActivityNotFoundException:隐式 Intent 启动前用
intent.resolveActivity(packageManager)检查 - FileUriExposedException:Android 7.0+ 禁止 file:// 跨应用共享,用 FileProvider
- PendingIntent 不可变性:Android 12+ 必须指定 FLAG_IMMUTABLE 或 FLAG_MUTABLE
- exported 声明:targetSdk 31+ 必须显式设置 android:exported
6. 总结
- 显式 Intent — 自己 App 内跳转,精确高效
- 隐式 Intent — 跨应用调用,系统匹配 Action+Category+Data
- IntentFilter 三要素缺一不可,CATEGORY_DEFAULT 是最大陷阱

浙公网安备 33010602011771号