常用系统 Intent
本教程共 100 篇 · 第 31 篇 · 更新于 2026-07-28 · 约 8 分钟阅读
31. 常用系统 Intent
本节目标:掌握日常开发最常用的系统 Intent 用法,包括打开网页、拨号、发短信、发邮件、分享、拍照、选联系人、打开设置等。
怎么用这一节
这些 Intent 大多是隐式的,调用前最好检查有没有应用能处理(resolveActivity 或 try-catch),避免崩溃。下面每个例子都给完整可用代码,复制改改就能用。
1. 打开网页
fun openWebPage(context: Context, url: String) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
try {
context.startActivity(intent)
} catch (e: ActivityNotFoundException) {
Toast.makeText(context, "没有浏览器可用", Toast.LENGTH_SHORT).show()
}
}
openWebPage(context, "https://developer.android.com")
URL 没带 https:// 前缀要补上,不然解析失败。
2. 拨打电话
打开拨号面板(不要权限)
fun openDialer(context: Context, phone: String) {
val intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:$phone"))
context.startActivity(intent)
}
openDialer(context, "10086")
直接拨出(要 CALL_PHONE 权限)
<uses-permission android:name="android.permission.CALL_PHONE" />
// 运行时还要请求权限
fun callPhone(context: Context, phone: String) {
val intent = Intent(Intent.ACTION_CALL, Uri.parse("tel:$phone"))
context.startActivity(intent)
}
Note
- 大多数场景用
ACTION_DIAL就够了,让用户确认再拨。ACTION_CALL直接拨号,用户体验突兀,且是危险权限,要用户授权。
3. 发短信
打开短信应用(不要权限)
fun openSmsApp(context: Context, phone: String, message: String) {
val intent = Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:$phone")).apply {
putExtra("sms_body", message)
}
context.startActivity(intent)
}
openSmsApp(context, "10086", "您的验证码是 123456")
直接发送(要 SEND_SMS 权限,少用)
直接发短信要 SEND_SMS 危险权限,且用户体验差(用户不知情就发出去了)。一般用上面的打开短信应用方式。
4. 发邮件
fun sendEmail(context: Context, to: String, subject: String, body: String) {
val intent = Intent(Intent.ACTION_SENDTO).apply {
data = Uri.parse("mailto:") // 只显示邮件应用
putExtra(Intent.EXTRA_EMAIL, arrayOf(to))
putExtra(Intent.EXTRA_SUBJECT, subject)
putExtra(Intent.EXTRA_TEXT, body)
}
context.startActivity(intent)
}
sendEmail(context, "support@example.com", "反馈", "我遇到了一个问题...")
发多个人:
putExtra(Intent.EXTRA_EMAIL, arrayOf("a@x.com", "b@x.com"))
putExtra(Intent.EXTRA_CC, arrayOf("cc@x.com"))
5. 分享文本
fun shareText(context: Context, text: String) {
val intent = Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
putExtra(Intent.EXTRA_TEXT, text)
}
context.startActivity(Intent.createChooser(intent, "分享到"))
}
Intent.createChooser 强制弹选择框,标题自定义。
分享图片
fun shareImage(context: Context, imageUri: Uri) {
val intent = Intent(Intent.ACTION_SEND).apply {
type = "image/*"
putExtra(Intent.EXTRA_STREAM, imageUri)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 临时授权
}
context.startActivity(Intent.createChooser(intent, "分享图片"))
}
Warning
- 分享文件 URI 要用
FileProvider提供content://URI,不能直接用file://(Android 7+ 会崩)。还要加FLAG_GRANT_READ_URI_PERMISSION让接收方有临时读权限。
6. 拍照
用 Intent 调起系统相机
// 用 Activity Result API
val takePicture = registerForActivityResult(
ActivityResultContracts.TakePicture()
) { success: Boolean ->
if (success) {
// 拍照成功,imageUri 里有照片
showImage(imageUri)
}
}
// 准备一个 URI 存照片
val imageUri: Uri = /* 通过 FileProvider 创建 */
takePicture.launch(imageUri)
TakePicture 契约帮你处理了 Intent 构造,传一个 URI 进去存照片,返回是否成功。
旧式 Intent 写法(了解)
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
startActivityForResult(intent, REQUEST_CAMERA)
新项目用 Activity Result API,别用 startActivityForResult。
录像
val intent = Intent(MediaStore.ACTION_VIDEO_CAPTURE)
intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 30) // 限制 30 秒
// 用 ActivityResultContracts.CaptureVideo
7. 选择图片/文件
选单张图片
val pickImage = registerForActivityResult(
ActivityResultContracts.GetContent()
) { uri: Uri? ->
uri?.let { showImage(it) }
}
pickImage.launch("image/*")
Android 13+ 的照片选择器
Android 13 引入 Photo Picker,更安全(不用权限就能选):
val pickPhoto = registerForActivityResult(
ActivityResultContracts.PickVisualMedia()
) { uri: Uri? ->
uri?.let { showImage(it) }
}
// 选单张
pickPhoto.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
// 选多张(PickMultipleVisualMedia)
Tip
- Android 13+ 用 Photo Picker 替代
GetContent选图片,用户只授权选中的图片,隐私更安全。向下兼容用 Google 的 photo picker 库。
选联系人
val pickContact = registerForActivityResult(
ActivityResultContracts.PickContact()
) { uri: Uri? ->
uri?.let { queryContact(it) }
}
pickContact.launch()
读联系人详情要 READ_CONTACTS 权限。
8. 打开系统设置
应用详情页
fun openAppSettings(context: Context) {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
data = Uri.fromParts("package", context.packageName, null)
}
context.startActivity(intent)
}
用于「权限被拒,引导去设置开启」的场景。
其他设置页
// 无线设置
Intent(Settings.ACTION_WIRELESS_SETTINGS)
// 位置设置
Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
// 通知设置(API 26+)
Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
}
// 蓝牙设置
Intent(Settings.ACTION_BLUETOOTH_SETTINGS)
9. 打开地图
显示坐标
fun openMap(context: Context, lat: Double, lng: Double, label: String) {
val uri = Uri.parse("geo:$lat,$lng?q=$lat,$lng($label)")
val intent = Intent(Intent.ACTION_VIEW, uri)
context.startActivity(intent)
}
openMap(context, 39.9042, 116.4074, "天安门")
路径规划
val uri = Uri.parse("google.navigation:q=39.9042,116.4074")
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.setPackage("com.google.android.apps.maps") // 指定 Google 地图
context.startActivity(intent)
国内没装 Google 地图,要用高德/百度地图的 scheme,按目标平台查文档。
10. 打开其他应用
打开应用市场详情页
fun openMarket(context: Context, packageName: String) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=$packageName"))
try {
context.startActivity(intent)
} catch (e: ActivityNotFoundException) {
// 没装应用市场,打开网页版
val webIntent = Intent(Intent.ACTION_VIEW,
Uri.parse("https://play.google.com/store/apps/details?id=$packageName"))
context.startActivity(webIntent)
}
}
openMarket(context, "com.example.app")
打开应用
val intent = packageManager.getLaunchIntentForPackage("com.target.app")
if (intent != null) {
startActivity(intent)
} else {
// 没装,引导去下载
}
11. 安装 APK
fun installApk(context: Context, apkUri: Uri) {
val intent = Intent(Intent.ACTION_VIEW).apply {
data = apkUri
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
// Android 7+ 要用 FileProvider 的 content URI
}
context.startActivity(intent)
}
需要 REQUEST_INSTALL_PACKAGES 权限(API 26+)。
12. 分享多类型内容
fun shareMultiple(context: Context, uris: List<Uri>) {
val intent = Intent(Intent.ACTION_SEND_MULTIPLE).apply {
type = "image/*"
putParcelableArrayListExtra(Intent.EXTRA_STREAM, ArrayList(uris))
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
context.startActivity(Intent.createChooser(intent, "分享多张图片"))
}
常用 Intent 速查表
| 功能 | Action | Data / Extra |
|---|---|---|
| 打开网页 | ACTION_VIEW | https://... |
| 拨号面板 | ACTION_DIAL | tel:10086 |
| 直接拨号 | ACTION_CALL | tel:10086(要权限) |
| 发短信 | ACTION_SENDTO | smsto:10086,sms_body |
| 发邮件 | ACTION_SENDTO | mailto:,EXTRA_EMAIL |
| 分享文本 | ACTION_SEND | text/plain,EXTRA_TEXT |
| 分享图片 | ACTION_SEND | image/*,EXTRA_STREAM |
| 拍照 | ACTION_IMAGE_CAPTURE | EXTRA_OUTPUT |
| 选图片 | ACTION_GET_CONTENT | image/* |
| 选联系人 | ACTION_PICK | Contacts URI |
| 应用设置 | ACTION_APPLICATION_DETAILS_SETTINGS | package:你的包名 |
| 地图 | ACTION_VIEW | geo:lat,lng |
小结
系统 Intent 让你的应用能调用系统和其他应用的功能,不用自己实现。常用:打开网页(VIEW + https)、拨号(DIAL + tel)、发短信(SENDTO + smsto)、发邮件、分享(SEND)、拍照、选图片(Photo Picker)、打开设置。分享文件用 FileProvider,Android 11+ 注意 <queries> 声明。第 5 部分结束,下一部分学 Service。