CameraX 是一个 Jetpack 支持库,旨在帮助您简化相机应用的开发工作。它提供一致且易于使用的 API 界面,适用于大多数 Android 设备,并可向后兼容至 Android 5.0(API 级别 21)。
CameraX Extensions 是可选插件,通过该插件,您可以在支持的设备上向自己的应用中添加人像、HDR、夜间模式和美颜等效果。
CameraX 引入了多个用例,使您可以专注于需要完成的任务,而无需花时间处理不同设备之间的细微差别
自动化 CameraX 测试实验室可确保在多种类型的设备和多个制造商之间实现一致的 API 体验。
CameraX 有一个名为 Extensions 的可选插件,您只需两行代码,便可借助该插件使用与设备自带的原生相机应用相同的特性和功能。
首批可用功能包括人像、HDR、夜间模式和美颜。这些功能可在受支持的设备上使用。
CameraX 使用入门
官方 CameraX 示例应用
略
在 Android 中,您可以从零开始构建自己的播放器,也可以从以下选项中进行选择:
MediaPlayer
中未提供。您可以自定义 ExoPlayer 代码,从而轻松添加新组件。ExoPlayer 只能用于 Android 4.1 及更高版本。media-compat 库包含可帮助您构建音频和视频应用的类。这些类与运行 Android 2.3(API 级别 9)及更高版本的设备兼容。它们还可与其他 Android 功能配合使用,以打造舒适亲切的 Android 体验。
媒体会话和媒体控制器的建议实现方式是 MediaSessionCompat和
MediaControllerCompat 类,它们在 media-compat 支持库中定义。它们取代了 Android 5.0(API 级别 21)中引入的早期版本的 MediaSession
和 MediaController
类。compat 类提供相同的功能,但可让您更轻松地开发应用,因为您只需写入一个 API。该库通过将媒体会话方法转换为更低版本平台上的等效方法(可用时)来保证向后兼容性。
如果您已经有使用旧类的实际应用,我们建议更新到 compat 类
在 Android 8.0(API 级别 26)及更高版本中,getMetrics() 方法可用于某些媒体类。它会返回一个包含配置和性能信息的 PersistableBundle 对象(表示为属性和值的对应关系)。可以为这些媒体类定义 getMetrics()
方法:
通知的设计由系统模板决定,您的应用只需定义模板各部分的内容。通知的某些详细信息仅在展开视图中显示。
图 7. 包含基本详情的通知
图 7 展示了通知最常见的部分,具体如下所示:
从 Android 7.0(API 级别 24)开始,您可以添加操作来回复消息,或者直接从通知中输入其他文本。
从 Android 10(API 级别 29)开始,平台可以自动生成操作按钮,此类按钮包含基于 Intent 的建议操作。
在 Android 8.0 及更高版本上,用户可以更改每个渠道的重要性
可能的重要性级别如下:
紧急:发出声音并以浮动通知的形式显示。
高:发出声音。
中:不发出声音。
低:不发出声音,也不在状态栏中显示。
以下是最明显的 Android 通知行为变化的摘要。
引入了展开式通知模板(称为通知样式),可以提供较大的通知内容区域来显示信息。用户可以使用单指向上/向下滑动的手势来展开通知。
还支持以按钮形式向通知添加其他操作。
允许用户在设置中按应用关闭通知。
向 API 中添加了通知侦听器服务
API 级别 20 中添加了对 Android Wear(现称为 Wear OS)的支持。
引入了锁定屏幕和浮动通知。
用户现在可以将手机设置为“请勿打扰”模式,并配置当设备处于“仅限优先事项”模式时,哪些通知可以打扰他们。
向 API 集添加了通知是否在锁定屏幕上显示的方法 (setVisibility()),以及指定通知文本的“公开”版本的方法。
添加了 setPriority() 方法,告知系统该通知应具有的“干扰性”(例如,将其设置为“高”,可使该通知以浮动通知的形式显示)。
Android Wear(现称为 Wear OS)设备添加了通知堆栈支持。使用 setGroup() 将通知放入堆栈。请注意,平板电脑和手机尚不支持通知堆栈。通知堆栈以后会称为组或 Bundle。
重新设计了通知模板的样式,以强调主打图像和头像。
添加了三个通知模板:一个用于消息应用,另外两个用于使用可扩展选项和其他系统装饰来装饰自定义内容视图。
向手持设备(手机和平板电脑)添加了对通知组的支持。使用与 Android 5.0(API 级别 21)中引入的 Android Wear(现称为 Wear OS)通知堆栈相同的 API。
用户可以使用内联回复直接在通知内回复(用户可以输入文本,然后将其发送给通知的父级应用)。
现在必须将单个通知放入特定渠道中。
用户现在可以按渠道关闭通知,而不是关闭应用的所有通知。
包含活动通知的应用会在主屏幕/启动器屏幕上的应用图标上方显示通知“标志”。
现在,用户可以暂停抽屉式通知栏中的通知。您可以为通知设置自动超时。
您还可以设置通知的背景颜色。
与通知行为相关的部分 API 已从 Notification 移至 NotificationChannel。例如,对 Android 8.0 及更高版本使用 NotificationChannel.setImportance(),而不是 NotificationCompat.Builder.setPriority()。
dependencies {
implementation "com.android.support:support-compat:28.0.0"
}
//CHANNEL_ID:渠道 ID
var builder = NotificationCompat.Builder(this, CHANNEL_ID)
//小图标
.setSmallIcon(R.drawable.notification_icon)
//标题
.setContentTitle(textTitle)
//正文
.setContentText(textContent)
//更长的可展开的通知
//创建包含可展开详情的通知(https://developer.android.google.cn/training/notify-user/expanded)。
.setStyle(NotificationCompat.BigTextStyle()
.bigText("Much longer text that cannot fit one line..."))
//优先级
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
private fun createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = getString(R.string.channel_name)
val descriptionText = getString(R.string.channel_description)
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
description = descriptionText
}
// Register the channel with the system
val notificationManager: NotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
// Create an explicit intent for an Activity in your app
val intent = Intent(this, AlertDetails::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
// Set the intent that will fire when the user taps the notification
.setContentIntent(pendingIntent)
.setAutoCancel(true)
请注意,该代码会调用 setAutoCancel(),它会在用户点按通知后自动移除通知。
要显示通知,请调用 NotificationManagerCompat.notify(),并将通知的唯一 ID 和 NotificationCompat.Builder.build()的结果传递给它。例如:
with(NotificationManagerCompat.from(this)) {
// notificationId is a unique int for each notification that you must define
notify(notificationId, builder.build())
}
要添加操作按钮,请将 PendingIntent 传递给 addAction() 方法。这就像是设置通知的默认点按操作,不同的是不会启动 Activity,而是可以完成各种其他任务
例如启动在后台执行作业的 BroadcastReceiver,这样该操作就不会干扰已经打开的应用。
val snoozeIntent = Intent(this, MyBroadcastReceiver::class.java).apply {
action = ACTION_SNOOZE
putExtra(EXTRA_NOTIFICATION_ID, 0)
}
val snoozePendingIntent: PendingIntent =
PendingIntent.getBroadcast(this, 0, snoozeIntent, 0)
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.addAction(R.drawable.ic_snooze, getString(R.string.snooze),
snoozePendingIntent)
Android 7.0(API 级别 24)中引入的直接回复操作允许用户直接在通知中输入文本,然后会直接提交给应用
1、创建 RemoteInput.Builder 的实例以便您添加到通知操作
// Key for the string that's delivered in the action's intent.
private val KEY_TEXT_REPLY = "key_text_reply"
var replyLabel: String = resources.getString(R.string.reply_label)
var remoteInput: RemoteInput = RemoteInput.Builder(KEY_TEXT_REPLY).run {
setLabel(replyLabel)
build()
}
2、为回复操作创建 PendingIntent
// Build a PendingIntent for the reply action to trigger.
var replyPendingIntent: PendingIntent =
PendingIntent.getBroadcast(applicationContext,
conversation.getConversationId(),
getMessageReplyIntent(conversation.getConversationId()),
PendingIntent.FLAG_UPDATE_CURRENT)
3、使用 addRemoteInput() 将 RemoteInput 对象附加到操作。
// Create the reply action and add the remote input.
var action: NotificationCompat.Action =
NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
getString(R.string.label), replyPendingIntent)
.addRemoteInput(remoteInput)
.build()
4、对通知应用操作并发出通知。
// Build the notification and add the action.
val newMessageNotification = Notification.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_message)
.setContentTitle(getString(R.string.title))
.setContentText(getString(R.string.content))
.addAction(action)
.build()
// Issue the notification.
with(NotificationManagerCompat.from(this)) {
notificationManager.notify(notificationId, newMessageNotification)
}
要从通知回复界面接收用户输入,请调用 RemoteInput.getResultsFromIntent() 并将 BroadcastReceiver 收到的 Intent 传递给它:
private fun getMessageText(intent: Intent): CharSequence? {
return RemoteInput.getResultsFromIntent(intent)?.getCharSequence(KEY_TEXT_REPLY)
}
处理完文本后,必须使用相同的 ID 和标记(如果使用)调用 NotificationManagerCompat.notify() 来更新通知。若要隐藏直接回复界面并向用户确认他们的回复已收到并得到正确处理,则必须完成该操作。
// Build a new notification, which informs the user that the system
// handled their interaction with the previous notification.
val repliedNotification = Notification.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_message)
.setContentText(getString(R.string.replied))
.build()
// Issue the new notification.
NotificationManagerCompat.from(this).apply {
notificationManager.notify(notificationId, repliedNotification)
}
在处理这个新通知时,请使用传递给接收者的 onReceive() 方法的上下文。
您还应通过调用 setRemoteInputHistory() 将回复附加到通知底部。但如果要构建消息应用,应创建消息式通知,并在会话中附加新消息。
有关来自消息应用的通知的更多建议,请参阅消息应用的最佳做法。
通过调用 setProgress(max, progress, false) 使用指示器。
第一个参数是“完成”值(如 100);第二个参数是当前完成的进度,最后一个参数表明这是一个确定性进度条。
val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {
setContentTitle("Picture Download")
setContentText("Download in progress")
setSmallIcon(R.drawable.ic_notification)
setPriority(NotificationCompat.PRIORITY_LOW
}
val PROGRESS_MAX = 100
val PROGRESS_CURRENT = 0
NotificationManagerCompat.from(this).apply {
// Issue the initial notification with zero progress
builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false)
notify(notificationId, builder.build())
// Do the job here that tracks the progress.
// Usually, this should be in a
// worker thread
// To show progress, update PROGRESS_CURRENT and update the notification with:
// builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
// notificationManager.notify(notificationId, builder.build());
// When done, update the notification one more time to remove the progress bar
builder.setContentText("Download complete")
.setProgress(0, 0, false)
notify(notificationId, builder.build())
}
操作结束时,progress
应等于 max
。您可以在操作完成后仍保留显示进度条,也可以将其移除。要移除进度条,请调用 setProgress(0, 0, false)。
要显示不确定性进度条(不指示完成百分比的进度条),请调用 setProgress(0, 0, true)。
结果会产生一个与上述进度条样式相同的指示器,区别是这个进度条是一个持续动画,不指示完成情况。
在您调用 setProgress(0, 0, false) 之前,进度动画会一直运行,调用后系统会更新通知以移除 Activity 指示器。
如果您的通知属于 NotificationCompat 中定义的预定义通知类别之一
(例如 CATEGORY_ALARM、CATEGORY_REMINDER、CATEGORY_EVENT 或 CATEGORY_CALL),
您应通过将相应类别传递到 setCategory() 来进行声明。
var builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
注意:如果应用的目标平台是 Android 10(API 级别 29)或更高版本,必须在应用清单文件中请求 USE_FULL_SCREEN_INTENT
权限,以便系统启动与时效性通知关联的全屏 Activity。
以下代码段展示了如何将通知与全屏 Intent 关联:
val fullScreenIntent = Intent(this, ImportantActivity::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)
var builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setFullScreenIntent(fullScreenPendingIntent, true)
要控制锁定屏幕中通知的可见详情级别,请调用 setVisibility() 并指定以下值之一:
要在发出此通知后对其进行更新,请再次调用 NotificationManagerCompat.notify(),并将之前使用的具有同一 ID 的通知传递给该方法。如果之前的通知已被关闭,则系统会创建一个新通知。
您可以选择性调用 setOnlyAlertOnce(),这样通知只会在通知首次出现时打断用户(通过声音、振动或视觉提示),而之后更新则不会再打断用户。
从 Android 7.0(API 级别 24)起,Android 提供了专用于消息内容的通知样式模板。使用 NotificationCompat.MessagingStyle 类,您可以更改在通知中显示的多个标签,包括会话标题、其他消息和通知的内容视图。
以下代码段展示了如何使用 MessagingStyle 类自定义通知的样式。
var notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setStyle(NotificationCompat.MessagingStyle("Me")
.setConversationTitle("Team lunch")
.addMessage("Hi", timestamp1, null) // Pass in null for user.
.addMessage("What's up?", timestamp2, "Coworker")
.addMessage("Not much", timestamp3, null)
.addMessage("How about lunch?", timestamp4, "Coworker"))
.build()
从 Android 8.0(API 级别 26)起,使用 NotificationCompat.MessagingStyle 类的通知会在采用折叠形式时显示更多内容
略
**注意:**本指南介绍如何使用 AndroidX Preference Library。自 Android 10 开始,系统已弃用 android.preference
库平台。
<PreferenceScreen
xmlns:app="http://schemas.android.com/apk/res-auto">
<SwitchPreferenceCompat
app:key="notifications"
app:title="Enable message notifications"/>
<Preference
app:key="feedback"
app:title="Send feedback"
app:summary="Report technical issues or suggest new features"/>
</PreferenceScreen>
class MySettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences, rootKey)
}
}
然后,与您对其他 Fragment 进行的操作一样,您可以将此 Fragment 添加到您的 Activity:
class MySettingsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportFragmentManager
.beginTransaction()
.replace(R.id.settings_container, MySettingsFragment())
.commit()
}
}
Android 应用的一大优点是它们能够互相通信和集成。如果某一功能并非应用的核心,而且已存在于另一个应用中,为何要重新开发它?
本节说明如何借助 Intent对象使用 Android Sharesheet 和 Intent Resolver 在不同应用之间发送和接收简单数据(如文本、图像和文件)的一些常用方法。
Android 为用户提供了两种在应用之间分享数据的方式:
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
type = "text/plain"
}
val shareIntent = Intent.createChooser(sendIntent, null)
startActivity(shareIntent)
val shareIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_STREAM, uriToImage)
type = "image/jpeg"
}
startActivity(Intent.createChooser(shareIntent, resources.getText(R.string.send_to)))
您应该为要发送的数据提供最具体的 MIME 类型。例如,分享纯文本时,应使用 text/plain。以下是在 Android 中发送简单数据时一些常用的 MIME 类型。
要分享多份内容,请将 ACTION_SEND_MULTIPLE 操作与指向该内容的一系列 URI 一起使用
val imageUris: ArrayList<Uri> = arrayListOf(
// Add your image URIs here
imageUri1,
imageUri2
)
val shareIntent = Intent().apply {
action = Intent.ACTION_SEND_MULTIPLE
putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris)
type = "image/*"
}
startActivity(Intent.createChooser(shareIntent, "Share images to.."))
从 Android 10(API 级别 29)开始,Android Sharesheet 可以显示分享的文本的预览。
如果要预览文本,您可以设置标题和/或缩略图。在调用 Intent.createChooser() 之前,先添加 Intent.EXTRA_TITLE 的说明。通过 ClipData 添加相关的缩略图。
val share = Intent.createChooser(Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, "https://developer.android.com/training/sharing/")
// (Optional) Here we're setting the title of the content
putExtra(Intent.EXTRA_TITLE, "Introducing content previews")
// (Optional) Here we're passing a content URI to an image to be displayed
setClipData(contentUri);
setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}, null)
startActivity(share)
在调用 Intent.createChooser() 之后,向您的分享 intent 添加 Intent.EXTRA_CHOOSER_TARGETS
和 Intent.EXTRA_INITIAL_INTENTS
。
val share = Intent.createChooser(myShareIntent, null).apply {
putExtra(Intent.EXTRA_CHOOSER_TARGETS, myChooserTargetArray)
putExtra(Intent.EXTRA_INITIAL_INTENTS, myInitialIntentArray)
}
在调用 Intent.createChooser() 之后,向您的 intent 添加 Intent.EXTRA_EXCLUDE_COMPONENTS
val share = Intent.createChooser(myShareIntent, null).apply {
// Only use components you have control over
share.putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, myComponentArray)
}
var share = new Intent(Intent.ACTION_SEND);
...
val pi = PendingIntent.getBroadcast(myContext, requestCode, Intent(myContext, MyBroadcastReceiver.class),
Intent.FLAG_UPDATE_CURRENT)
share = Intent.createChooser(share, null, pi.intentSender);
然后,在 MyBroadcastReceiver 中接收回调,并查看 Intent.EXTRA_CHOSEN_COMPONENT
override fun onReceive(context: Context, intent: Intent) {
...
val clickedComponent : ComponentName = intent.getParcelableExtra(EXTRA_CHOSEN_COMPONENT);
}
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
type = "text/plain"
}
startActivity(sendIntent)
您的应用可以通过三种方式接收其他应用发送的数据:
您的应用应支持接收尽可能广泛的 MIME 类型。例如,用于发送文本、图像和视频的短信应用应支持接收 text/、image/ 和 video/*。以下是在 Android 中发送简单数据时常见的一些 MIME 类型。
text/,发送方通常会发送 text/plain、text/rtf、text/html、text/json
image/,发送方通常会发送 image/jpg、image/png、image/gif
video/*,发送方通常会发送 video/mp4、video/3gp
接收方应注册受支持的文件扩展名,发送方通常会发送 application/pdf
<activity android:name=".ui.MyActivity" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
要处理 Intent 传送的内容,请调用 getIntent() 以获取 Intent 对象
override fun onCreate(savedInstanceState: Bundle?) {
...
when {
intent?.action == Intent.ACTION_SEND -> {
if ("text/plain" == intent.type) {
handleSendText(intent) // Handle text being sent
} else if (intent.type?.startsWith("image/") == true) {
handleSendImage(intent) // Handle single image being sent
}
}
intent?.action == Intent.ACTION_SEND_MULTIPLE
&& intent.type?.startsWith("image/") == true -> {
handleSendMultipleImages(intent) // Handle multiple images being sent
}
else -> {
// Handle other intents, such as being started from the home screen
}
}
...
}
private fun handleSendText(intent: Intent) {
intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
// Update UI to reflect text being shared
}
}
private fun handleSendImage(intent: Intent) {
(intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri)?.let {
// Update UI to reflect image being shared
}
}
private fun handleSendMultipleImages(intent: Intent) {
intent.getParcelableArrayListExtra<Parcelable>(Intent.EXTRA_STREAM)?.let {
// Update UI to reflect multiple images being shared
}
}
从 Android 10(API 级别 29)开始,Android Sharesheet 将仅使用清单中的 application 标签上设置的图标。在 intent-filter 和 activity 标签上设置的图标将被忽略。
直接共享于 Android 6.0(API 级别 23)中引入,支持应用通过 ChooserTargetService 提供 ChooserTarget 对象。在此机制下,系统会根据需要被动检索结果,从而造成目标加载缓慢。
在 Android 10(API 级别 29)中,新的 Sharing Shortcuts API 取代了 ChooserTargetService Direct Share API。
要查看发布共享快捷方式的示例,请参阅共享快捷方式代码示例。
val person = Person.Builder()
...
.setName(fullName)
.setKey(staticPersonIdentifier)
.setUri("tel:$phoneNumber") // alternatively "mailto:$email" or CONTENT_LOOKUP_URI
.build()
val shortcutInfo = ShortcutInfoCompat.Builder(myContext, staticPersonIdentifier)
...
.setShortLabel(firstName)
.setLongLabel(fullName)
.setPerson(person)
//通过调用 setLongLived(true)确保快捷方式长期存在。
.setLongLived(true)
.setRank(personRank)
.build()
val notif = NotificationCompat.Builder(myContext, channelId)
...
//确保所有 shortcutId 独一无二,且不在不同的目标上重复使用。
.setShortcutId(staticPersonIdentifier)
.build()
要制作共享快捷方式,您需要通过 setIcon() 添加图像。
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<share-target android:targetClass="com.example.android.sharingshortcuts.SendMessageActivity">
<data android:mimeType="text/plain" />
<category android:name="com.example.android.sharingshortcuts.category.TEXT_SHARE_TARGET" />
</share-target>
</shortcuts>
<activity
android:name=".SendMessageActivity"
android:label="@string/app_name"
android:theme="@style/SharingShortcutsDialogTheme">
<!-- This activity can respond to Intents of type SEND -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<!-- Only needed if you import the sharetarget AndroidX library that
provides backwards compatibility with the old DirectShare API.
The activity that receives the Sharing Shortcut intent needs to be
taken into account with this chooser target provider. -->
<meta-data
android:name="android.service.chooser.chooser_target_service"
android:value="androidx.sharetarget.ChooserTargetServiceCompat" />
</activity>
Android Jetpack 内置了对切片的支持,并且可以向后一直扩展到 Android 4.4,覆盖约 95% 的 Android 用户。