在android开发中,intent 是组件间通信的核心机制,用于在activity、service、broadcastreceiver等组件之间传递消息、启动组件或共享数据。它相当于一个“意图”载体,描述了操作的目的、数据和附加信息,是android组件解耦的关键。
一、intent 核心作用
- 启动组件:启动activity(
startactivity())、启动service(startservice()/bindservice())、发送广播(sendbroadcast())。 - 传递数据:在组件间传递基本类型、对象、集合等数据。
- 指定操作:通过“动作”“数据”等描述要执行的操作(如“打开网页”“发送邮件”),实现跨应用交互。
二、intent 类型
根据目标组件的指定方式,intent分为显式intent和隐式intent,适用场景不同。
1. 显式 intent(explicit intent)
特点:直接指定目标组件的完整类名(componentname),明确告诉系统要启动哪个组件。
适用场景:启动应用内部组件(如本应用的activity、service),因为开发者明确知道目标组件的类名。
示例:启动应用内的secondactivity
// kotlin val intent = intent(this, secondactivity::class.java) startactivity(intent)
// java intent intent = new intent(this, secondactivity.class); startactivity(intent);
进阶:通过componentname指定
如需动态指定组件(如跨进程启动已知类名的组件),可通过componentname构造:
val component = componentname(packagename, "com.example.app.secondactivity") val intent = intent().setcomponent(component) startactivity(intent)
2. 隐式 intent(implicit intent)
特点:不直接指定目标组件,而是通过“动作(action)”“类别(category)”“数据(data)”等描述操作意图,由系统根据这些信息匹配最合适的组件(如系统浏览器、邮件应用)。
适用场景:启动跨应用组件(如调用系统浏览器打开网页、调用相机拍照),无需知道目标组件的类名。
示例:打开指定网页(调用系统浏览器)
val intent = intent(intent.action_view) // 动作:查看内容
intent.data = uri.parse("https://www.example.com") // 数据:网页地址
startactivity(intent)系统会匹配所有声明了action_view且支持http协议的组件(通常是浏览器),并让用户选择打开方式。
三、intent 核心属性
intent通过一系列属性描述操作意图,核心属性包括action、category、data、type、extra、flag等。
1. action(动作)
一个字符串,描述要执行的操作(如“查看”“发送”“编辑”)。系统预定义了大量action,也可自定义。
常用系统action:
| action常量 | 含义 | 适用场景 |
|---|---|---|
intent.action_view | 查看数据 | 打开网页、图片、文档等 |
intent.action_send | 发送数据 | 分享文本、图片(调用分享面板) |
intent.action_call | 拨打电话 | 需要call_phone权限 |
intent.action_edit | 编辑数据 | 编辑联系人、图片等 |
intent.action_main | 应用入口 | launcher启动应用的主activity |
自定义action:
需使用全限定名(避免冲突),如com.example.app.action_custom,用于应用内组件通信或跨应用约定。
2. category(类别)
对action的补充,描述组件的额外特性(如“默认组件”“ launcher入口”)。一个intent可包含多个category,系统会匹配所有声明的类别。
常用系统category:
intent.category_default:默认类别,隐式启动activity时必须包含(否则匹配失败)。intent.category_launcher:标记应用的主入口(与action_main配合,显示在 launcher 上)。
示例:隐式启动时添加默认类别
val intent = intent(intent.action_view)
intent.data = uri.parse("https://www.example.com")
intent.addcategory(intent.category_default) // 必须添加,否则可能匹配失败
startactivity(intent)3. data 与 type(数据与类型)
data:通过uri指定操作的数据(如content://contacts/people/1表示某个联系人,http://example.com表示网页)。type:指定数据的mime类型(如image/jpeg、text/plain),若data已包含类型信息(如http对应text/html),type可省略。
注意:data和type会相互覆盖,若需同时设置,需用setdataandtype()而非分别调用setdata()和settype():
// 正确:同时设置data和type
intent.setdataandtype(uri.parse("content://media/external/images/1"), "image/jpeg")
// 错误:settype()会覆盖data的类型信息
intent.data = uri.parse("content://media/external/images/1")
intent.type = "image/jpeg" // 此操作会清除data4. extra(附加数据)
键值对形式的附加数据,用于在组件间传递数据(如传递用户id、文本内容)。支持基本类型、数组、集合,以及实现serializable或parcelable的对象。
存储与获取数据:
// 存储数据
val intent = intent(this, secondactivity::class.java)
intent.putextra("userid", 123) // 基本类型
intent.putextra("username", "张三") // 字符串
intent.putextra("isvip", true) // 布尔值
// 传递对象(需实现parcelable或serializable)
val user = user("张三", 20) // 假设user实现了parcelable
intent.putextra("user", user)
startactivity(intent)// 目标组件中获取数据
val userid = intent.getintextra("userid", -1) // 第二个参数为默认值
val username = intent.getstringextra("username") // 可为null
val isvip = intent.getbooleanextra("isvip", false)
val user = intent.getparcelableextra<user>("user") // 需指定泛型注意:
- 传递大量数据(如大图片)可能导致
transactiontoolargeexception,建议用其他方式(如全局变量、文件)。 parcelable比serializable效率更高(android推荐用parcelable)。
5. flag(标记)
通过addflags()设置,用于控制组件的启动模式、任务栈(task)行为等。
常用flag:
| flag | 作用 |
|---|---|
intent.flag_activity_new_task | 启动新任务栈(常用于service中启动activity) |
intent.flag_activity_clear_top | 若目标activity已在栈中,清除其上方所有activity |
intent.flag_activity_single_top | 若目标activity在栈顶,则复用,不创建新实例 |
intent.flag_grant_read_uri_permission | 授予uri的读权限(跨应用访问文件时需用) |
示例:启动新任务栈中的activity(如从service启动)
val intent = intent(this, notificationactivity::class.java) intent.addflags(intent.flag_activity_new_task) // 必须添加,否则service中启动会崩溃 startactivity(intent)
四、intent 过滤器(intent filter)
隐式intent需要通过intent过滤器匹配目标组件。过滤器在androidmanifest.xml中声明,用于告诉系统“该组件能处理哪些intent”。
一个组件可声明多个过滤器,只要intent匹配其中一个即可启动该组件。
过滤器匹配规则
intent与过滤器的匹配需满足3个条件(全部匹配):
- action匹配:intent的action必须在过滤器的
action列表中(或过滤器无action,intent也无action)。 - category匹配:intent的所有category必须在过滤器的
category列表中(过滤器至少包含category_default,否则隐式启动失败)。 - data/type匹配:intent的data/type需与过滤器的
data规则匹配(如协议、mime类型)。
示例:为activity配置过滤器
声明一个能处理“查看图片”和“编辑图片”的activity:
<activity android:name=".imagehandleractivity">
<intent-filter>
<!-- action:支持查看和编辑图片 -->
<action android:name="android.intent.action.view" />
<action android:name="android.intent.action.edit" />
<!-- category:必须包含默认类别 -->
<category android:name="android.intent.category.default" />
<!-- data:支持图片类型(image/*),协议不限 -->
<data android:mimetype="image/*" />
</intent-filter>
</activity>当其他应用发送包含action_view、category_default、image/jpeg类型的intent时,系统会将该activity列为可选目标。
五、特殊用法
1. 启动组件并获取返回结果
通过activity result api(替代旧版startactivityforresult())启动activity并获取返回数据。
示例:启动相机拍照并获取照片
// 1. 注册结果回调
val takepicturelauncher = registerforactivityresult(activityresultcontracts.takepicture()) { issuccess ->
if (issuccess) {
// 拍照成功,处理照片(photouri为拍照后保存的路径)
imageview.setimageuri(photouri)
}
}
// 2. 启动相机(photouri为提前创建的临时文件路径)
val photouri = createtempphotouri() // 自定义方法:创建保存照片的uri
takepicturelauncher.launch(photouri)2. pendingintent(延迟intent)
一种特殊的intent,用于在未来某个时刻由其他组件(如系统服务)执行。常用于通知(notification)、闹钟(alarmmanager)、快捷方式等场景。
特点:
- 包含触发时的权限和上下文,即使创建它的应用已退出,仍可正常执行。
- 支持三种操作:启动activity(
getactivity())、启动service(getservice())、发送广播(getbroadcast())。
示例:通知中添加pendingintent(点击通知打开activity)
// 创建打开detailactivity的intent
val intent = intent(this, detailactivity::class.java)
intent.putextra("id", 100)
// 创建pendingintent(flag_immutable:不可变,安全性更高)
val pendingintent = pendingintent.getactivity(
this,
0, // 请求码(区分不同pendingintent)
intent,
pendingintent.flag_update_current or pendingintent.flag_immutable
)
// 构建通知
val notification = notificationcompat.builder(this, channel_id)
.setcontenttitle("新消息")
.setcontenttext("点击查看详情")
.setsmallicon(r.drawable.ic_notification)
.setcontentintent(pendingintent) // 绑定pendingintent
.build()
// 显示通知
notificationmanager.notify(notification_id, notification)3. 发送广播 intent
通过sendbroadcast()发送广播,由注册了对应过滤器的broadcastreceiver接收。
示例:发送自定义广播
// 发送广播
val intent = intent("com.example.app.action_custom_broadcast")
// 限制广播仅本应用接收(android 8.0+ 推荐)
intent.setpackage(packagename)
sendbroadcast(intent)<!-- 注册广播接收器(manifest中) -->
<receiver android:name=".myreceiver">
<intent-filter>
<action android:name="com.example.app.action_custom_broadcast" />
</intent-filter>
</receiver>
// 广播接收器实现
class myreceiver : broadcastreceiver() {
override fun onreceive(context: context, intent: intent) {
if ("com.example.app.action_custom_broadcast" == intent.action) {
// 处理广播
}
}
}
六、注意事项
隐式intent的安全性:android 10(api 29)后,隐式启动activity需指定包名(setpackage())或通过resolveactivity()检查是否有匹配组件,否则可能抛出异常:
val intent = intent(intent.action_view, uri.parse("https://example.com"))
if (intent.resolveactivity(packagemanager) != null) { // 检查是否有匹配组件
startactivity(intent)
} else {
// 提示用户无可用应用
}- 数据大小限制:intent传递数据通过binder机制,总大小限制约1mb,超过会导致
transactiontoolargeexception,建议用文件或跨进程通信(ipc)替代。 - pendingintent的 flag 选择:android 12(api 31)后,创建pendingintent需指定
flag_immutable或flag_mutable:flag_immutable:intent不可修改(推荐,安全性高)。flag_mutable:允许修改intent(仅在需要动态更新intent时使用)。
总结
intent 是android组件通信的“桥梁”,通过显式/隐式方式连接组件,支持数据传递和操作描述。掌握其核心属性(action、category、data、extra)、过滤器匹配规则,以及特殊用法(pendingintent、activity result),是实现组件交互和跨应用功能的基础。合理使用intent能大幅提升应用的灵活性和扩展性。
到此这篇关于android intent详解(最新推荐)的文章就介绍到这了,更多相关android intent内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论