当前位置: 首页 > news >正文

Android Intent详解

在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通过一系列属性描述操作意图,核心属性包括ActionCategoryDataTypeExtraFlag等。

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/jpegtext/plain),若Data已包含类型信息(如http对应text/html),Type可省略。

注意DataType会相互覆盖,若需同时设置,需用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" // 此操作会清除data
4. Extra(附加数据)

键值对形式的附加数据,用于在组件间传递数据(如传递用户ID、文本内容)。支持基本类型、数组、集合,以及实现SerializableParcelable的对象。

存储与获取数据

// 存储数据
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,建议用其他方式(如全局变量、文件)。
  • ParcelableSerializable效率更高(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个条件(全部匹配):

  1. Action匹配:Intent的Action必须在过滤器的action列表中(或过滤器无Action,Intent也无Action)。
  2. Category匹配:Intent的所有Category必须在过滤器的category列表中(过滤器至少包含CATEGORY_DEFAULT,否则隐式启动失败)。
  3. 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_VIEWCATEGORY_DEFAULTimage/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) {// 处理广播}}
}

六、注意事项

  1. 隐式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 {// 提示用户无可用应用
    }
    
  2. 数据大小限制:Intent传递数据通过Binder机制,总大小限制约1MB,超过会导致TransactionTooLargeException,建议用文件或跨进程通信(IPC)替代。

  3. PendingIntent的 FLAG 选择:Android 12(API 31)后,创建PendingIntent需指定FLAG_IMMUTABLEFLAG_MUTABLE

    • FLAG_IMMUTABLE:Intent不可修改(推荐,安全性高)。
    • FLAG_MUTABLE:允许修改Intent(仅在需要动态更新Intent时使用)。

总结

Intent 是Android组件通信的“桥梁”,通过显式/隐式方式连接组件,支持数据传递和操作描述。掌握其核心属性(Action、Category、Data、Extra)、过滤器匹配规则,以及特殊用法(PendingIntent、Activity Result),是实现组件交互和跨应用功能的基础。合理使用Intent能大幅提升应用的灵活性和扩展性。

http://www.dtcms.com/a/553232.html

相关文章:

  • llamafactory lora体验
  • 安卓深度链接安全研究基于Metasploit的QR码攻击模块开发实践
  • 哪个网站做推广比较好厦门网站制作报价
  • 湛江企业网站建设流程网站界面排版好看
  • VSCode插件开发实战:从入门到精通
  • 【JavaWeb学习 | 第二篇】CSS(1) - 基础语法与核心概念
  • 物联网设备只能局域网控制?EMQX+cpolar让远程管理“零延迟”!
  • 婚纱摄影 网站关键词 优化青海西宁网页网站制作
  • MLGO微算法科技发布多用户协同推理批处理优化系统,重构AI推理服务效率与能耗新标准
  • 企业网站托管多少钱租房合同模板免费下载
  • 学习threejs,基于噪声函数的顶点着色器动态插桩技术实现模型形变
  • USB PD协议:不止是快充,更是电子设备的“电力 Esperanto”
  • JavaSE知识分享——继承(上)
  • 破解流程内耗,金智维流程自动化平台如何激活企业效率?
  • 做电影资讯网站算侵权吗网站开发需求分析怎么写
  • 网站建设小江网页设计网站建设北京个人
  • macOS 一键免密登录阿里云 ECS:SSH 密钥对认证完整指南
  • F043 vue+flask天气预测可视化系统大数据+机器学习+管理端+爬虫+超酷界面+顶级可视化水平 【黑色版】
  • 依赖spring-cloud-starter-gateway与spring-cloud-gateway-dependencies的区别
  • 详解 JVM 中的对象创建过程:类加载检查、内存分配、初始化的完整流程
  • 千博企业网站管理系统营销旗舰版山东网站seo设计
  • JVM 中的内存泄漏:常见场景(静态集合、线程池)与检测工具(MAT)使用
  • 安徽网站建设公司排名网站外链发布
  • 达梦数据库适配遇到的一些问题
  • 电话交换机软件 3CX iOS 应用 V5.4 Beta 更新
  • 做高端企业网站建设公司北京精兴装饰公司
  • FONE为万帮数字能源打造全面预算管理系统
  • Lua VM 跳转指令设计:条件跳转、无条件跳转的底层逻辑
  • 等级保护标准体系再完善:六项新技术公安行标正式发布
  • 光储充微电网零碳园区解决方案:引领园区能源革命,赋能绿色低碳未来