一、Intent 是什么?
在 Android 开发中,Intent
(意图)是一个用于在组件之间传递消息和执行操作的对象。它是 Android 应用程序中常用的一种机制,用于启动活动(Activity)、启动服务(Service)、发送广播(Broadcast)、执行后台操作等。
Intent
对象包含了两个主要部分:操作(Action)和数据(Data)。操作定义了要执行的动作类型,例如启动活动、启动服务、发送广播等。数据定义了操作所涉及的数据,例如 URI、Extras 等。
Intent
可以用于以下几个方面:
- 启动活动(Activity):通过创建一个包含启动活动操作的
Intent
对象,并指定目标活动的类名或组件名称,可以启动一个新的活动。 - 启动服务(Service):通过创建一个包含启动服务操作的
Intent
对象,并指定目标服务的类名或组件名称,可以启动一个服务进行后台操作。 - 发送广播(Broadcast):通过创建一个包含发送广播操作的
Intent
对象,并指定广播的动作(Action),可以向其他组件发送广播消息。 - 启动隐式活动(Implicit Activity):通过创建一个包含启动活动操作和匹配的过滤条件的
Intent
对象,可以启动与特定条件匹配的活动,而不需要指定明确的目标活动。 - 启动隐式服务(Implicit Service):通过创建一个包含启动服务操作和匹配的过滤条件的
Intent
对象,可以启动与特定条件匹配的服务,而不需要指定明确的目标服务。 - 传递数据:
Intent
对象可以携带额外的数据(Extras),例如键值对、序列化对象等,以便在组件之间传递数据。
Intent
提供了一种灵活的方式来在 Android 应用程序的组件之间进行通信和交互。通过创建适当的 Intent
对象并指定所需的操作和数据,您可以实现多种场景下的组件间交互和通信。
二、常用意图
2.1、启动活动
- 显示启动:
val intent = Intent(this, TargetActivity::class.java)
startActivity(intent)
- 显示启动一个新的 Activity 并等待结果:
val intent = Intent(this, TargetActivity::class.java)
startActivityForResult(intent, requestCode)
- 显示启动(指定要启动组件的对象):
val componentName = ComponentName("com.example.app", "com.example.app.TargetActivity")
val intent = Intent()
intent.component = componentName
startActivity(intent)
- 使用 Intent 的
setClassName()
方法启动活动:
val intent = Intent()
intent.setClassName("com.example.app", "com.example.app.TargetActivity")
startActivity(intent)
- 使用 Intent 的
setPackage()
方法启动活动:
val intent = Intent()
intent.setPackage("com.example.app")
intent.action = "android.intent.action.MAIN"
intent.addCategory("android.intent.category.LAUNCHER")
- 隐式启动(常用在外部 H5 调用):
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:screenOrientation="fullSensor">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="http"
android:host="example.com" />
</intent-filter>
</activity>
val scheme = "http://example.com"
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(scheme))
intent.`package` = "xx.xx.xxx"
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK;//可选
startActivity(intent)
如果外部调用,
隐式启动的 Activity 不是启动页 Activity:
App 活着,调用完 Intent,App 会被杀死,再调用会拉起目标页面;
隐式启动的 Activity 是启动页 Activity :
App 活着,直接拉起当前页,App 死掉的场景会直接拉起 App。
隐式启动启动页的写法:
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:screenOrientation="fullSensor">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="http"
android:host="example.com" />
</intent-filter>
</activity>
2.2、启动服务
-
使用显式 Intent 启动服务:
val intent = Intent(context, MyService::class.java) context.startService(intent)
-
使用隐式 Intent 启动服务:
val intent = Intent("com.example.app.MY_SERVICE") intent.setPackage("com.example.app") context.startService(intent)
-
使用 Intent 的
setComponent()
方法启动服务:val componentName = ComponentName("com.example.app", "com.example.app.MyService") val intent = Intent() intent.component = componentName context.startService(intent)
-
使用 Intent 的
setClassName()
方法启动服务:val intent = Intent() intent.setClassName("com.example.app", "com.example.app.MyService") context.startService(intent)
注意:在 Android 8.0(API 级别 26)及更高版本中,后台服务的启动受到了限制。如果您的应用程序目标版本是 Android 8.0 及更高版本,您可能需要使用前台服务(Foreground Service)来启动服务。这要求您将服务设置为前台状态,并显示通知给用户。
8.0+
启动前台服务
2.3、启动广播
要启动广播(Broadcast),您可以使用 sendBroadcast()
方法。以下是在 Android 中启动广播的几种常见方法:
-
使用显式 Intent 启动广播:
val intent = Intent(context, MyBroadcastReceiver::class.java) context.sendBroadcast(intent)
-
使用隐式 Intent 启动广播:
val intent = Intent("com.example.app.MY_ACTION") intent.setPackage("com.example.app") context.sendBroadcast(intent)
-
使用 Intent 的
setComponent()
方法启动广播:val componentName = ComponentName("com.example.app", "com.example.app.MyBroadcastReceiver") val intent = Intent() intent.component = componentName context.sendBroadcast(intent)
-
使用 Intent 的
setClassName()
方法启动广播:val intent = Intent() intent.setClassName("com.example.app", "com.example.app.MyBroadcastReceiver") context.sendBroadcast(intent)
N、调用系统
N.1、打开网页
要使用 Intent 打开网页,您可以创建一个 ACTION_VIEW 操作的 Intent,并将目标网页的 URL 作为数据传递给 Intent。以下是使用 Intent 打开网页的示例代码:
val url = "https://www.example.com" // 替换为您要打开的网页 URL
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse(url)
// 检查是否有应用程序可以处理该意图
val packageManager = context.packageManager
val activities = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
if (activities.isNotEmpty()) {
context.startActivity(intent)
} else {
// 如果没有应用程序可以处理该意图,可以在此处执行其他操作
}
在上面的代码中,我们首先指定要打开的网页 URL,并将其存储在 url
变量中。然后,我们创建一个 ACTION_VIEW 操作的 Intent,并使用 Uri.parse(url)
将 URL 转换为 Uri,并将其设置为 Intent 的数据。
接下来,我们使用包管理器的 queryIntentActivities()
方法来检查是否有应用程序可以处理该意图。如果至少有一个应用程序可以处理该意图,我们使用 startActivity()
方法启动该 Intent,系统将尝试使用用户默认的浏览器或其他适当的应用程序打开指定的网页。
请注意,在使用 Intent 打开网页之前,要确保您的应用程序具有适当的网络访问权限,以便能够打开指定的网页。
N.2、浏览器搜索内容
val searchQuery = "Android development" // 替换为您要搜索的内容
val intent = Intent(Intent.ACTION_WEB_SEARCH)
intent.putExtra(SearchManager.QUERY, searchQuery)
// 检查是否有应用程序可以处理该意图
val packageManager = context.packageManager
val activities = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
if (activities.isNotEmpty()) {
context.startActivity(intent)
} else {
// 如果没有应用程序可以处理该意图,可以在此处执行其他操作
}
在上面的代码中,我们首先指定要搜索的内容,并将其存储在 searchQuery 变量中。然后,我们创建一个 ACTION_WEB_SEARCH 操作的 Intent,并使用 putExtra() 方法将搜索内容作为额外的数据添加到 Intent 中。我们使用 SearchManager.QUERY 常量作为键来指定额外数据的名称。
接下来,我们使用包管理器的 queryIntentActivities() 方法来检查是否有应用程序可以处理该意图。如果至少有一个应用程序可以处理该意图,我们使用 startActivity() 方法启动该 Intent,系统将尝试使用用户默认的浏览器打开搜索结果页面,并显示相关的搜索内容。
请注意,这种方法将使用系统的默认浏览器来执行搜索操作。不同设备上的默认浏览器可能会有所不同。
N.3、显示地图
要使用 Intent 在设备上显示地图,您可以创建一个 ACTION_VIEW 操作的 Intent,并设置地图的 URI 数据。以下是使用 Intent 显示地图的示例代码:
val latitude = 37.7749 // 目标位置的纬度
val longitude = -122.4194 // 目标位置的经度
val uri = Uri.parse("geo:$latitude,$longitude") // 创建地图的 URI
val intent = Intent(Intent.ACTION_VIEW, uri)
// 检查是否有应用程序可以处理该意图
val packageManager = context.packageManager
val activities = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
if (activities.isNotEmpty()) {
context.startActivity(intent)
} else {
// 如果没有应用程序可以处理该意图,可以在此处执行其他操作
}
在上面的代码中,我们首先指定了目标位置的纬度和经度,并将其存储在 latitude
和 longitude
变量中。然后,我们使用 Uri.parse()
方法创建一个地图的 URI,格式为 geo:$latitude,$longitude
,其中 $latitude
和 $longitude
分别替换为实际的纬度和经度。
接下来,我们创建一个 ACTION_VIEW 操作的 Intent,并将地图的 URI 设置为 Intent 的数据。使用 Intent(Intent.ACTION_VIEW, uri)
构造函数可以同时指定操作和数据。
请注意,具体的地图应用程序可能因设备和用户的偏好而有所不同。如果您想限制特定的地图应用程序,可以使用地图应用程序的包名或其他相关信息来创建 Intent。
N.4、路径规划
要使用 Intent 进行路线规划,您可以创建一个 ACTION_VIEW 操作的 Intent,并设置地图的 URI 数据,其中包含起点和终点的位置信息。以下是使用 Intent 进行路线规划的示例代码:
val sourceLatitude = 37.7749 // 起点位置的纬度
val sourceLongitude = -122.4194 // 起点位置的经度
val destinationLatitude = 34.0522 // 终点位置的纬度
val destinationLongitude = -118.2437 // 终点位置的经度
val uri = Uri.parse("https://www.google.com/maps/dir/?api=1&origin=$sourceLatitude,$sourceLongitude&destination=$destinationLatitude,$destinationLongitude")
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.setPackage("com.google.android.apps.maps") // 指定使用 Google 地图应用程序
// 检查是否有应用程序可以处理该意图
val packageManager = context.packageManager
val activities = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
if (activities.isNotEmpty()) {
context.startActivity(intent)
} else {
// 如果没有应用程序可以处理该意图,可以在此处执行其他操作
}
在上面的代码中,我们首先指定了起点和终点位置的纬度和经度,并将其存储在相应的变量中。然后,我们使用 Uri.parse()
方法创建一个地图的 URI,其中包含起点和终点的位置信息。URI 的格式可以根据所使用的地图服务提供商而有所不同。
在本例中,我们使用了 Google 地图的 URI 格式,其中使用 https://www.google.com/maps/dir/
表示进行路线规划,origin
参数指定起点位置,destination
参数指定终点位置。
接下来,我们创建一个 ACTION_VIEW 操作的 Intent,并将地图的 URI 设置为 Intent 的数据。使用 Intent(Intent.ACTION_VIEW, uri)
构造函数可以同时指定操作和数据。
然后,我们使用 setPackage()
方法指定使用 Google 地图应用程序处理该意图。这样可以限制只使用指定的地图应用程序进行路线规划。如果未指定包名,系统将弹出选择器,让用户选择要使用的地图应用程序。
N.5、调用电话和直接拨号
要使用 Intent 拨打电话,您可以创建一个 ACTION_DIAL 或 ACTION_CALL 操作的 Intent,并将电话号码作为数据传递给 Intent。以下是使用 Intent 拨打电话的示例代码:
val phoneNumber = "1234567890" // 替换为您要拨打的电话号码
val intent = Intent(Intent.ACTION_DIAL)
intent.data = Uri.parse("tel:$phoneNumber")
// 或者使用 ACTION_CALL 操作拨打电话(需要拨打电话权限)
// val intent = Intent(Intent.ACTION_CALL)
// intent.data = Uri.parse("tel:$phoneNumber")
context.startActivity(intent)
在上面的代码中,我们首先指定要拨打的电话号码,并将其存储在 phoneNumber
变量中。然后,我们创建一个 ACTION_DIAL 操作的 Intent,并使用 Uri.parse()
方法将电话号码转换为 Uri,并将其设置为 Intent 的数据。您还可以使用 ACTION_CALL 操作进行电话拨打,但需要在 AndroidManifest.xml 文件中声明 CALL_PHONE 权限。
最后,我们使用 startActivity()
方法启动该 Intent,系统将尝试使用默认的电话应用程序打开拨号界面,并将电话号码自动填充到拨号界面中。
请注意,使用 ACTION_CALL 操作进行电话拨打需要 CALL_PHONE 权限。在 AndroidManifest.xml 文件中添加以下权限声明:
<uses-permission android:name="android.permission.CALL_PHONE" />
另外,如果您只是想显示拨号界面并让用户手动拨打电话,而不直接拨打电话,则可以使用 ACTION_DIAL 操作。这样做可以避免直接拨打电话而不经用户确认的风险。
N.6、发短信
要使用 Intent 发送短信,您可以创建一个 ACTION_SENDTO 操作的 Intent,并将接收方的电话号码和短信内容作为数据传递给 Intent。以下是使用 Intent 发送短信的示例代码:
val phoneNumber = "1234567890" // 替换为接收方的电话号码
val message = "Hello, this is a test message." // 替换为要发送的短信内容
val intent = Intent(Intent.ACTION_SENDTO)
intent.data = Uri.parse("smsto:$phoneNumber")
intent.putExtra("sms_body", message)
context.startActivity(intent)
在上面的代码中,我们首先指定了接收方的电话号码,并将其存储在 phoneNumber
变量中。然后,我们创建一个 ACTION_SENDTO 操作的 Intent,并使用 Uri.parse()
方法将电话号码转换为 Uri,并将其设置为 Intent 的数据。smsto:
是用于指定短信的 URI 方案。
接下来,我们使用 putExtra()
方法将短信内容作为额外的数据添加到 Intent 中。我们使用 “sms_body” 键来指定短信内容的名称。
最后,我们使用 startActivity()
方法启动该 Intent,系统将尝试使用默认的短信应用程序打开短信编辑界面,并将电话号码和短信内容自动填充到相应的字段中。
请注意,使用 ACTION_SENDTO 操作发送短信并不直接发送短信,而是打开短信编辑界面并将短信内容预填到短信应用程序中。用户仍然需要手动点击发送按钮才能真正发送短信。
N.7、发送Email
要使用 Intent 发送电子邮件,您可以创建一个 ACTION_SEND 操作的 Intent,并设置电子邮件的相关信息,例如收件人、主题和正文。以下是使用 Intent 发送电子邮件的示例代码:
val recipientEmail = "recipient@example.com" // 替换为收件人的电子邮件地址
val subject = "Hello" // 替换为电子邮件的主题
val body = "This is the body of the email." // 替换为电子邮件的正文
val intent = Intent(Intent.ACTION_SEND)
intent.type = "message/rfc822"
intent.putExtra(Intent.EXTRA_EMAIL, arrayOf(recipientEmail))
intent.putExtra(Intent.EXTRA_SUBJECT, subject)
intent.putExtra(Intent.EXTRA_TEXT, body)
context.startActivity(Intent.createChooser(intent, "Send Email"))
在上面的代码中,我们首先指定了收件人的电子邮件地址,并将其存储在 recipientEmail
变量中。然后,我们创建一个 ACTION_SEND 操作的 Intent,并设置 Intent 的类型为 “message/rfc822”,表示发送电子邮件。
接下来,我们使用 putExtra()
方法将收件人、主题和正文作为额外的数据添加到 Intent 中。我们使用 Intent.EXTRA_EMAIL
键指定收件人的电子邮件地址,Intent.EXTRA_SUBJECT
键指定电子邮件的主题,Intent.EXTRA_TEXT
键指定电子邮件的正文。
最后,我们使用 startActivity()
方法启动该 Intent,并使用 Intent.createChooser()
方法创建一个选择器,让用户选择要使用的电子邮件应用程序。选择器将显示包含可用电子邮件应用程序的列表。
N.8、播放多媒体
要使用 Intent 播放音乐,您可以创建一个 ACTION_VIEW 或 ACTION_MAIN 操作的 Intent,并设置音乐文件的 URI 或指定要使用的音乐应用程序。以下是使用 Intent 播放音乐的示例代码:
val musicUri = Uri.parse("file:///path/to/music.mp3") // 替换为音乐文件的实际 URI
val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(musicUri, "audio/mp3")
context.startActivity(intent)
在上面的代码中,我们首先指定了音乐文件的 URI,并将其存储在 musicUri
变量中。这里使用了 file:///path/to/music.mp3
格式的 URI,您需要将其替换为实际音乐文件的 URI。
然后,我们创建一个 ACTION_VIEW 操作的 Intent,并使用 setDataAndType()
方法将音乐文件的 URI 和 MIME 类型设置为 Intent 的数据和类型。在示例代码中,我们使用了 “audio/mp3” 作为音乐文件的 MIME 类型。
最后,我们使用 startActivity()
方法启动该 Intent,系统将尝试使用默认的音乐应用程序打开并播放指定的音乐文件。
请注意,具体的音乐应用程序可能因设备和用户的偏好而有所不同。如果您想限制特定的音乐应用程序,可以使用音乐应用程序的包名或其他相关信息来创建 Intent。
N.9、安装APK
要使用 Intent 安装 APK 文件,您可以创建一个 ACTION_VIEW 操作的 Intent,并设置 APK 文件的 URI 和 MIME 类型为 “application/vnd.android.package-archive”。以下是使用 Intent 安装 APK 的示例代码:
val apkUri = Uri.parse("file:///path/to/app.apk") // 替换为 APK 文件的实际 URI
val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(apkUri, "application/vnd.android.package-archive")
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
context.startActivity(intent)
在上面的代码中,我们首先指定了 APK 文件的 URI,并将其存储在 apkUri
变量中。这里使用了 file:///path/to/app.apk
格式的 URI,您需要将其替换为实际 APK 文件的 URI。
然后,我们创建一个 ACTION_VIEW 操作的 Intent,并使用 setDataAndType()
方法将 APK 文件的 URI 和 MIME 类型设置为 Intent 的数据和类型。在示例代码中,我们使用了 “application/vnd.android.package-archive” 作为 APK 文件的 MIME 类型,表示安装包。
接下来,我们使用 addFlags()
方法添加两个标志,FLAG_ACTIVITY_NEW_TASK
和 FLAG_GRANT_READ_URI_PERMISSION
。FLAG_ACTIVITY_NEW_TASK
标志将启动一个新的任务栈来安装 APK,FLAG_GRANT_READ_URI_PERMISSION
标志将授予读取 APK URI 的权限。
最后,我们使用 startActivity()
方法启动该 Intent,系统将尝试使用默认的应用程序安装器来安装指定的 APK 文件。
N.9、续安装 APK(7.0+)
如果想在 Android 7.0(API 级别 24)及更高版本上使用 Intent 安装 APK 文件,需要使用 File Provider 来获取 APK 文件的 URI,并授予其他应用程序访问该 URI 的权限。以下是使用 File Provider 安装 APK 的示例代码:
首先,在您的应用的 AndroidManifest.xml
文件中,添加 File Provider 的配置。在 <application>
标签内添加以下内容:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="your.package.name.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
其中,将 your.package.name
替换为您的应用程序的包名。
接下来,创建一个名为 file_paths.xml
的 XML 文件,放在 res/xml/
目录下(如果该目录不存在,请手动创建)。在 file_paths.xml
文件中,定义用于访问 APK 文件的路径,例如:
<paths>
<external-path name="external_files" path="." />
</paths>
上述示例配置了对应用程序的外部存储目录的访问。您可以根据您的需求自定义路径。
现在,您可以使用 File Provider 来获取 APK 文件的 URI,并创建 Intent 安装应用。以下是示例代码:
val apkFile = File("/path/to/app.apk") // 替换为 APK 文件的实际路径
val apkUri = FileProvider.getUriForFile(context, "your.package.name.fileprovider", apkFile)
val intent = Intent(Intent.ACTION_INSTALL_PACKAGE)
intent.setData(apkUri)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
context.startActivity(intent)
在上面的代码中,我们首先指定了 APK 文件的路径,并将其存储在 apkFile
变量中。然后,使用 FileProvider.getUriForFile()
方法获取 APK 文件的内容 URI。将 "your.package.name.fileprovider"
替换为您在 AndroidManifest.xml 文件中定义的 File Provider 的 authorities。
接下来,我们创建一个 ACTION_INSTALL_PACKAGE 操作的 Intent,并将 APK 文件的 URI 设置为 Intent 的数据。使用 addFlags()
方法添加 FLAG_GRANT_READ_URI_PERMISSION
标志,以授予其他应用程序访问 APK 文件的权限。
最后,我们使用 startActivity()
方法启动该 Intent,系统将尝试使用默认的应用程序安装器来安装指定的 APK 文件。
使用 File Provider 可以确保在 Android 7.0 及更高版本上正确处理文件访问权限。
N.10、卸载APK
要使用 Intent 卸载应用程序,您可以创建一个 ACTION_DELETE 操作的 Intent,并设置要卸载的应用程序的包名。以下是使用 Intent 卸载应用程序的示例代码:
val packageName = "com.example.app" // 替换为要卸载的应用程序的包名
val intent = Intent(Intent.ACTION_DELETE)
intent.data = Uri.parse("package:$packageName")
context.startActivity(intent)
在上面的代码中,我们首先指定了要卸载的应用程序的包名,并将其存储在 packageName
变量中。然后,我们创建一个 ACTION_DELETE 操作的 Intent,并使用 Uri.parse()
方法将包名转换为 Uri,并将其设置为 Intent 的数据。在示例代码中,我们使用了 “package:” 作为 URI 方案。
最后,我们使用 startActivity()
方法启动该 Intent,系统将尝试打开应用程序管理器界面,并显示要卸载的应用程序的信息。用户需要确认卸载操作才能卸载应用程序。
请注意,只有用户授予了足够的权限,才能成功卸载应用程序。
N.11、调用相机
要使用 Intent 调用相机应用程序,您可以创建一个 ACTION_IMAGE_CAPTURE 或 ACTION_VIDEO_CAPTURE 操作的 Intent,并使用 startActivityForResult()
方法启动该 Intent。以下是使用 Intent 调用相机的示例代码:
调用照相机拍照:
val captureImageIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
startActivityForResult(captureImageIntent, REQUEST_IMAGE_CAPTURE)
调用相机录制视频:
val captureVideoIntent = Intent(MediaStore.ACTION_VIDEO_CAPTURE)
startActivityForResult(captureVideoIntent, REQUEST_VIDEO_CAPTURE)
在上面的示例代码中,我们分别创建了 ACTION_IMAGE_CAPTURE 和 ACTION_VIDEO_CAPTURE 操作的 Intent。您可以根据需要选择要使用的 Intent。
接下来,我们使用 startActivityForResult()
方法启动相机应用程序,并传递相应的 Intent 和请求代码(requestCode)。这样,在相机应用程序完成拍照或录制视频后,将返回结果到调用者的 Activity 中。
您需要在调用者的 Activity 中重写 onActivityResult()
方法来处理相机返回的结果。例如:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) {
// 处理拍照完成的结果
val imageBitmap = data?.extras?.get("data") as Bitmap
imageView.setImageBitmap(imageBitmap)
} else if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == Activity.RESULT_OK) {
// 处理视频录制完成的结果
val videoUri = data?.data
// 执行其他操作,如保存视频或显示视频预览
}
}
在上面的示例代码中,我们检查返回结果的 requestCode 和 resultCode,以确定是从拍照还是录制视频返回的结果。然后,我们根据需要处理相应的结果数据。
请注意,相机应用程序的行为可能因设备和用户的偏好而有所不同。您可以根据需要添加其他参数或设置,以满足您的具体要求。
N.11、续相机(7.0+)
如果想在 Android 7.0(API 级别 24)及更高版本上使用 Intent 调用相机并获取拍摄的照片或视频,需要使用 File Provider 来获取文件的 URI,并授予其他应用程序访问该 URI 的权限。以下是使用 File Provider 配合 Intent 调用相机的示例代码:
首先,在您的应用的 AndroidManifest.xml
文件中,添加 File Provider 的配置。在 <application>
标签内添加以下内容:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="your.package.name.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
其中,将 your.package.name
替换为您的应用程序的包名。
接下来,创建一个名为 file_paths.xml
的 XML 文件,放在 res/xml/
目录下(如果该目录不存在,请手动创建)。在 file_paths.xml
文件中,定义用于访问文件的路径,例如:
<paths>
<external-path name="external_files" path="." />
</paths>
上述示例配置了对应用程序的外部存储目录的访问。您可以根据您的需求自定义路径。
现在,您可以使用 File Provider 来获取相机拍摄的照片或视频的 URI,并创建 Intent 调用相机。以下是示例代码:
调用相机拍照:
val captureImageIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
val photoFile = createImageFile()
val photoUri = FileProvider.getUriForFile(context, "your.package.name.fileprovider", photoFile)
captureImageIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)
startActivityForResult(captureImageIntent, REQUEST_IMAGE_CAPTURE)
调用相机录制视频:
val captureVideoIntent = Intent(MediaStore.ACTION_VIDEO_CAPTURE)
val videoFile = createVideoFile()
val videoUri = FileProvider.getUriForFile(context, "your.package.name.fileprovider", videoFile)
captureVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, videoUri)
startActivityForResult(captureVideoIntent, REQUEST_VIDEO_CAPTURE)
在上面的示例代码中,我们首先创建一个文件(照片或视频文件)来保存相机拍摄的内容。您可以使用您自己的逻辑来创建文件。
然后,我们使用 FileProvider.getUriForFile()
方法获取文件的内容 URI。将 "your.package.name.fileprovider"
替换为您在 AndroidManifest.xml 文件中定义的 File Provider 的 authorities。
接下来,我们将文件的 URI 设置为相应的 Intent 的 EXTRA_OUTPUT
参数。这样,相机应用程序将保存拍摄的照片或视频到指定的文件中。
最后,我们使用 startActivityForResult()
方法启动相机应用程序,并传递相应的 Intent 和请求代码(requestCode)。这样,在相机应用程序完成拍照或录制视频后,将返回结果到调用者的 Activity 中。
请注意,您需要在调用者的 Activity 中重写 onActivityResult()
方法来处理相机返回的结果。例如:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) {
// 处理拍照完成的结果
// ...
} else if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == Activity.RESULT_OK) {
// 处理视频录制完成的结果
// ...
}
}
在上面的示例代码中,我们检查返回结果的 requestCode 和 resultCode,以确定是从拍照还是录制视频返回的结果。然后,我们根据需要处理相应的结果数据。
使用 File Provider 可以确保在 Android 7.0 及更高版本上正确处理文件访问权限。
N.12、打开录音机
要使用 Intent 打开录音机应用程序,您可以创建一个 ACTION_GET_CONTENT 操作的 Intent,并设置其类型为 “audio/*”。以下是使用 Intent 打开录音机的示例代码:
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "audio/*"
intent.addCategory(Intent.CATEGORY_OPENABLE)
startActivityForResult(intent, REQUEST_AUDIO_CAPTURE)
在上面的示例代码中,我们创建了一个 ACTION_GET_CONTENT 操作的 Intent,并将其类型设置为 “audio/*”,表示我们要获取音频文件。
接下来,我们通过调用 addCategory(Intent.CATEGORY_OPENABLE)
方法添加了一个 CATEGORY_OPENABLE 类别,以指示我们要获取可打开的文件。
最后,我们使用 startActivityForResult()
方法启动该 Intent,并传递相应的请求代码(requestCode)。这样,当用户在录音机应用程序中完成录音后,应用程序会返回录音文件的相关信息,例如文件的路径、URI 或其他标识符。您可以使用返回的信息来访问或处理录音文件。
您需要在调用者的 Activity 中重写 onActivityResult()
方法来处理录音机返回的结果。例如:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_AUDIO_CAPTURE && resultCode == Activity.RESULT_OK) {
// 处理录音完成的结果
val audioUri = data?.data
// 执行其他操作,如保存录音文件或处理录音数据
}
}
在上面的示例代码中,我们检查返回结果的 requestCode 和 resultCode,以确定是从录音机返回的结果。然后,我们可以通过获取返回的音频文件的 URI 进一步处理录音数据或进行其他操作。
需要注意的是,
不同的录音机应用程序可能会返回不同的数据格式和信息。因此,您需要根据您使用的录音机应用程序的文档或开发者指南,了解返回结果的结构和内容,以正确处理录音文件。
使用 Intent 打开录音机应用程序时,并不需要配合 File Provider。因为录音机应用程序通常会自动保存录音文件到其自己的目录中,而不需要您指定保存位置。
三、应用链接和深层链接
待续
四、版本更新对 Intent 的影响
版本 | 变更点影响 |
---|---|
Android 12 | Android App Links 、网络 intent 解析、无法关闭系统对话框 |
Android 11 | 动态 intent 过滤器 |
Android 12
系统广播 intent(API 级别 31)
通用应用 intent(API 级别 31)
Android 11
系统广播 intent(API 级别 30)
通用应用 intent(API 级别 30)
参考地址:
ChatGPT 和 官方资料