首页 / Android 入门教程 / Intent 基础

Android 入门教程

Intent 基础

本教程共 100 篇 · 第 29 篇 · 更新于 2026-07-28 · 约 8 分钟阅读

AndroidAndroid 入门教程Intent意图显式 Intent隐式 Intent组件通信

29. Intent 基础

本节目标:理解 Intent 是什么、显式和隐式 Intent 的区别、Intent 的六大组成部分,会用 Intent 启动组件和传递数据。

Intent 是什么

Intent(意图)是 Android 组件之间通信的消息对象。它描述「我想干一件事」,由系统负责找到合适的组件来处理。

三大用途:

  1. 启动 ActivitystartActivity(intent)
  2. 启动 ServicestartService(intent)bindService(intent, ...)
  3. 发送广播sendBroadcast(intent)

两种 Intent

显式 Intent

明确指定要启动的组件(类名)。系统直接启动它,不问别人。

val intent = Intent(this, DetailActivity::class.java)
startActivity(intent)

适用:启动自己应用内的组件,你知道确切类名。

隐式 Intent

不指定具体组件,而是声明「我想做什么」(action)和「对什么数据做」(data),让系统找能处理的组件。

val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://example.com"))
startActivity(intent)

系统在所有应用的 Manifest 里找声明了能处理 ACTION_VIEW + https 数据的 Activity,找到多个就弹选择框让用户选。

适用:调用系统功能(打开网页、拨号、分享)或让其他应用处理。

Warning
  • 启动 Service 必须用显式 Intent。Android 5.0 起隐式 Intent 启动 Service 会抛异常。安全考虑:你不知道哪个 Service 会响应。

Intent 的六大组成部分

一个 Intent 能携带这些信息:

1. Component Name(组件名)

目标组件的完整类名。有它就是显式 Intent,没有就是隐式。

intent.setClass(this, DetailActivity::class.java)
// 或构造时传
Intent(this, DetailActivity::class.java)

2. Action(动作)

描述要做什么的字符串。系统定义了很多常量:

Action含义
ACTION_VIEW查看数据(打开网页、看图片)
ACTION_DIAL拨号面板
ACTION_CALL直接拨打电话(要权限)
ACTION_SEND分享/发送数据
ACTION_EDIT编辑数据
ACTION_PICK选择数据(联系人、图片)
ACTION_MAIN应用入口
ACTION_SYNC同步数据
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://example.com"))

自定义 action 加包名前缀避免冲突:"com.example.action.MY_ACTION"

3. Data(数据)

操作的对象,通常是 URI + MIME 类型。

// 网页 URL
Intent(Intent.ACTION_VIEW, Uri.parse("https://example.com"))

// 地理坐标
Intent(Intent.ACTION_VIEW, Uri.parse("geo:39.9,116.4"))

// 电话号码
Intent(Intent.ACTION_DIAL, Uri.parse("tel:10086"))

// 联系人
Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI)

URI scheme(httpstelgeocontentfile)决定系统找哪类组件。

4. Category(类别)

额外描述组件类型的信息。常用:

  • CATEGORY_LAUNCHER:桌面启动入口。
  • CATEGORY_DEFAULT:默认类别,隐式 Intent 必须匹配。
  • CATEGORY_BROWSABLE:能从浏览器/网页调起。
intent.addCategory(Intent.CATEGORY_BROWSABLE)

5. Extras(附加数据)

键值对数据,第 28 章讲过。

intent.putExtra("user_id", 1001L)
intent.putExtra("user_name", "张三")

6. Flags(标志位)

控制启动行为,第 27 章讲过(FLAG_ACTIVITY_NEW_TASK 等)。

intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP

显式 Intent 实战

// 启动 Activity
val intent = Intent(context, DetailActivity::class.java).apply {
    putExtra("user_id", userId)
    flags = Intent.FLAG_ACTIVITY_NEW_TASK
}
context.startActivity(intent)

// 启动 Service(前台服务,Android 8+)
val intent = Intent(context, DownloadService::class.java).apply {
    putExtra("url", downloadUrl)
}
ContextCompat.startForegroundService(context, intent)

// 发送广播
val intent = Intent("com.example.ACTION_DATA_UPDATED").apply {
    putExtra("count", newCount)
}
context.sendBroadcast(intent)

隐式 Intent 实战

打开网页

val url = "https://developer.android.com"
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
startActivity(intent)

拨号

val intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:10086"))
startActivity(intent)
Note
  • ACTION_DIAL 只打开拨号面板,不直接拨出。ACTION_CALL 直接拨号但要 CALL_PHONE 危险权限。

分享文本

val intent = Intent(Intent.ACTION_SEND).apply {
    type = "text/plain"
    putExtra(Intent.EXTRA_TEXT, "快来看这个应用:https://example.com")
    putExtra(Intent.EXTRA_SUBJECT, "推荐")
}
startActivity(Intent.createChooser(intent, "分享到"))

Intent.createChooser 强制弹选择框,即使只有一个目标。

选择图片

val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
    type = "image/*"
}
 startActivityForResult... // 用 Activity Result API

现代写法用 Activity Result API:

val pickImage = registerForActivityResult(
    ActivityResultContracts.GetContent()
) { uri: Uri? ->
    uri?.let { showImage(it) }
}
pickImage.launch("image/*")

检查是否有组件能处理

隐式 Intent 可能找不到能处理的组件,直接 startActivity 会崩。先检查:

val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://example.com"))
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent)
} else {
    Toast.makeText(this, "没有应用能打开网页", Toast.LENGTH_SHORT).show()
}
Warning
  • Android 11+(API 30)起,resolveActivity 对其他应用的 Activity 默认返回 null(包可见性限制)。要在 Manifest 声明 <queries> 才能查到:
<queries>
    <intent>
        <action android:name="android.intent.action.VIEW" />
        <data android:scheme="https" />
    </intent>
</queries>

PendingIntent

PendingIntent 是「延迟执行的 Intent」,把 Intent 的执行权交给别人。别人在某个时刻触发它,相当于你代为执行。

常见用途:

  • 通知点击:NotificationCompat.Builder.setContentIntent(pendingIntent)
  • 桌面小部件点击。
  • AlarmManager 定时任务。
val intent = Intent(context, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
    context,
    0,
    intent,
    PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)

val notification = NotificationCompat.Builder(context, CHANNEL_ID)
    .setContentTitle("新消息")
    .setContentText("点击查看")
    .setSmallIcon(R.drawable.ic_notification)
    .setContentIntent(pendingIntent)
    .build()
Warning
  • Android 12+(API 31)起,PendingIntent 必须指定 FLAG_IMMUTABLEFLAG_MUTABLE。不指定会崩。大多数场景用 FLAG_IMMUTABLE(不可变,更安全)。

Intent 与 Compose

Compose 里启动外部 Activity 仍用 Intent,但配合 LocalContext

@Composable
fun ShareButton(text: String) {
    val context = LocalContext.current
    Button(onClick = {
        val intent = Intent(Intent.ACTION_SEND).apply {
            type = "text/plain"
            putExtra(Intent.EXTRA_TEXT, text)
        }
        context.startActivity(Intent.createChooser(intent, "分享"))
    }) {
        Text("分享")
    }
}

小结

Intent 是组件通信的消息对象。显式 Intent 指定类名,启动自己的组件;隐式 Intent 声明 action + data,让系统找能处理的组件。六大组成:Component、Action、Data、Category、Extra、Flag。隐式 Intent 要检查能否处理,Android 11+ 要声明 <queries>。PendingIntent 用于通知、小部件、定时任务,Android 12+ 要指定可变性 flag。下一节学 Intent Filter。