本页介绍了如何为手表创建通知,还介绍了如何为从关联手机桥接到手表的每条通知提供附加内容。
手表上的通知采用的结构与手机上的通知相同。 此外,为了给用户提供最佳体验,Wear OS by Google 谷歌还提供了用于向通知中添加穿戴式设备专属功能的 API。
从应用发出通知时,每条通知都显示为通知流中的一张卡片。

图 1. 在手机和手表上显示的同一通知。
手表和手机都可以作为通知的来源。您可以使用 NotificationCompat.Builder
类为穿戴式设备创建通知。当您使用此类构建通知时,系统负责正确显示通知。
注意:使用 RemoteViews
的通知的自定义布局会被去掉,穿戴式设备仅显示文本和图标。但是,您可以通过创建在手表上运行的穿戴式设备应用,创建使用自定义卡片布局的自定义通知。
通常,所有通知均从手机桥接至手表。但是,在以下情况下,系统不会桥接通知:
-
使用
Notification.Builder.setLocalOnly(boolean)
设置的“仅限本地”通知。 -
使用
Notification.Builder.setOngoing(boolean)
或Notification.FLAG_ONGOING_EVENT
设置的持续性通知。 -
使用
Notification.FLAG_NO_CLEAR
设置的不可清除通知。 - 对应穿戴式设备应用已禁用通知桥接的通知。
导入必要的类
要导入必要的软件包,请将以下代码行添加到 build.gradle
文件中:
implementation 'androidx.core:core:1.2.0'
现在您的项目可以访问必要的软件包,接下来从支持库导入必要的类:
Kotlin
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationCompat.WearableExtender
Java
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationCompat.WearableExtender;
使用通知构建器创建通知
借助 Jetpack 核心库,您可以使用操作按钮和图标等最新通知功能创建通知,同时保持与 Android 1.6(API 级别 4)及更高版本的兼容性。
注意:从 Android 8.0(API 级别 26)开始,您需要为要显示的每种类型的通知创建通知渠道。
如需创建通知,请执行以下操作:
-
创建一个
NotificationCompat.Builder
实例。Kotlin
val notificationId = 1 // The channel ID of the notification. val id = "my_channel_01" // Build intent for notification content val viewPendingIntent = Intent(this, ViewEventActivity::class.java).let { viewIntent -> viewIntent.putExtra(EXTRA_EVENT_ID, eventId) PendingIntent.getActivity(this, 0, viewIntent, 0) } // Notification channel ID is ignored for Android 7.1.1 // (API level 25) and lower. val notificationBuilder = NotificationCompat.Builder(this, id) .setSmallIcon(R.drawable.ic_event) .setContentTitle(eventTitle) .setContentText(eventLocation) .setContentIntent(viewPendingIntent)
Java
int notificationId = 001; // The channel ID of the notification. String id = "my_channel_01"; // Build intent for notification content Intent viewIntent = new Intent(this, ViewEventActivity.class); viewIntent.putExtra(EXTRA_EVENT_ID, eventId); PendingIntent viewPendingIntent = PendingIntent.getActivity(this, 0, viewIntent, 0); // Notification channel ID is ignored for Android 7.1.1 // (API level 25) and lower. NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, id) .setSmallIcon(R.drawable.ic_event) .setContentTitle(eventTitle) .setContentText(eventLocation) .setContentIntent(viewPendingIntent);
-
通过将带通知 ID 的 Notification 对象传递给
notify()
以发出通知。Kotlin
NotificationManagerCompat.from(this).apply { notify(notificationId, notificationBuilder.build()) }
Java
// Get an instance of the NotificationManager service NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); // Issue the notification with notification manager. notificationManager.notify(notificationId, notificationBuilder.build());
当该通知显示在手机上时,用户可以轻触通知,以调用由 setContentIntent()
方法指定的 PendingIntent
。当此通知出现在穿戴式设备上时,它会出现在通知流中。对于桥接通知,用户可以点击通知以查看展开式通知并触发任何定义的操作,如打开操作。通常,这些操作会打开您的手机应用上的某个 Activity。
构建展开式通知
展开式通知可以为每条通知提供大量的附加内容和操作。 如果您为通知指定附加内容页面和操作,这些页面和操作会在展开式通知中呈现给用户。每条展开式通知都遵循适用于 Wear OS 的 Material Design 规范,因此用户会获得类似应用的体验。
如果展开式通知中的第一项操作具有 RemoteInput
(例如,回复操作),您使用 setChoices()
设置的选项会出现在展开式通知中的第一项操作下。
当符合以下任一条件时,用户可以点按通知以查看展开式通知:
- 通知由配对手机上的应用生成并桥接到 Wear。
-
通知没有
contentIntent
。
注意:仅当您展开通知时,才会显示使用 setColor()
方法为通知设置的应用专属背景颜色。
展开式通知最佳做法
如需决定何时使用展开式通知,请遵循以下准则:
- 从配对手机桥接到 Wear 设备的所有通知都使用展开式通知。
-
如果通知是由在 Wear 设备上本地运行的应用生成的,就应通过调用
setContentIntent()
,让通知的轻触目标在您的应用内启动带通知 ID 的 Notification 对象。我们建议您不要对由在 Wear 设备上本地运行的应用生成的通知使用展开式通知。
添加展开式通知
通过展开式通知,您可以为通知添加附加内容和操作。您可以选择应用通知所提供信息的详细程度;但是,请慎重考虑要在通知中包含多少详细信息。

添加附加内容
如需在展开式通知中显示附加文本,请使用 BigTextStyle
。
如需在展开式通知中添加图片,可以使用 BigPictureStyle
。如果要在展开式通知中添加多张图片,请使用 addPage()
方法以及 BigPictureStyle
。
主要操作
展开式通知将包含一项主要操作,除非使用 setContentAction()
指定了其他操作,否则该操作将是通知中的第一项操作。
附加操作
如需指定附加操作,请使用 addAction()
或 addActions()
。展开式通知的操作抽屉式导航栏包含所有可执行的操作。
添加通知操作
除由 setContentIntent()
定义的主要内容操作之外,您还可以通过将 PendingIntent
传递给 addAction()
方法以添加其他操作。
例如,以下代码展示的通知类型与上述通知相同,但添加了一项用于在地图上查看事件地点的操作。
Kotlin
// Build an intent for an action to view a map val mapIntent = Intent(Intent.ACTION_VIEW) // The channel ID of the notification. val id = "my_channel_01" val mapPendingIntent = Intent(Intent.ACTION_VIEW).let { mapIntent -> mapIntent.data = Uri.parse("geo:0,0?q=" + Uri.encode(location)) PendingIntent.getActivity(this, 0, mapIntent, 0) } val notificationBuilder = NotificationCompat.Builder(this, id) .setSmallIcon(R.drawable.ic_event) .setContentTitle(eventTitle) .setContentText(eventLocation) .setContentIntent(viewPendingIntent) .addAction(R.drawable.ic_map, getString(R.string.map), mapPendingIntent)
Java
// Build an intent for an action to view a map Intent mapIntent = new Intent(Intent.ACTION_VIEW); // The channel ID of the notification. String id = "my_channel_01"; Uri geoUri = Uri.parse("geo:0,0?q=" + Uri.encode(location)); mapIntent.setData(geoUri); PendingIntent mapPendingIntent = PendingIntent.getActivity(this, 0, mapIntent, 0); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, id) .setSmallIcon(R.drawable.ic_event) .setContentTitle(eventTitle) .setContentText(eventLocation) .setContentIntent(viewPendingIntent) .addAction(R.drawable.ic_map, getString(R.string.map), mapPendingIntent);
在手机上,操作以附加到通知的附加按钮的形式显示。在穿戴式设备上,操作出现在展开式通知中的内容文本后面。当用户点按操作时,系统会调用手机上的关联 intent。
提示:如果通知包含“回复”操作(例如,对于短信应用),您可以启用直接从穿戴式设备进行语音输入回复的功能,从而增强这一行为。如需了解详情,请参阅将语音输入添加为通知操作。
添加内嵌操作

通过内嵌操作,用户可以从通知流卡片中对通知执行操作。在 Wear 设备上,内嵌操作以附加按钮的形式显示在通知底部。
内嵌操作是可选的,但如果用户在查看通知流卡片中的内容后可能会对通知执行操作(而不转到展开式通知),建议添加该操作。例如,适合在通知中添加内嵌操作的用例包括:回复短信、停止健身运动或归档电子邮件。
一条通知只能提供一项内嵌操作。要将内嵌操作显示为通知中的附加按钮,请将 setHintDisplayActionInline()
方法设为 true。当用户点按内嵌操作时,系统会调用您在通知操作中指定的 Intent。
以下代码段添加了说明以内嵌方式显示某项操作的提示,并使用 addAction
方法将该内嵌操作添加到通知中。
Kotlin
//Wear OS requires a hint to display the reply action inline. val actionExtender = NotificationCompat.Action.WearableExtender() .setHintLaunchesActivity(true) .setHintDisplayActionInline(true) wearableExtender.addAction(actionBuilder.extend(actionExtender).build())
Java
//Wear OS requires a hint to display the reply action inline. Action.WearableExtender actionExtender = new Action.WearableExtender() .setHintLaunchesActivity(true) .setHintDisplayActionInline(true); wearableExtender.addAction(actionBuilder.extend(actionExtender).build());
向通知中添加穿戴式设备专属功能
如果您需要向通知中添加穿戴式设备专属功能(如在穿戴式设备通知中隐藏应用图标,或让用户使用语音输入口述文本回复),可以使用 NotificationCompat.WearableExtender
类指定选项。如需使用此 API,请执行以下操作:
-
创建一个
WearableExtender
实例,为通知设置穿戴式设备专属选项。 -
创建一个
NotificationCompat.Builder
实例,为通知设置所需属性,如本课程前面所述。 -
对通知调用
extend()
并传入WearableExtender
。该操作会将穿戴式设备选项应用于通知。 -
调用
build()
以构建通知。
注意:如果您使用框架的 NotificationManager
,NotificationCompat.WearableExtender
的某些功能将不起作用,因此请务必使用 NotificationCompat
。
您可以在用户的设备之间同步通知的关闭(取消)行为。要同步关闭行为,请使用 setDismissalId()
方法。当您调用 setDismissalId()
方法时,为每条通知传递一个字符串形式的全局唯一 ID。相应通知关闭后,手表和配套手机上的其他所有具有同一关闭 ID 的通知也会关闭。如需检索关闭 ID,请使用 getDismissalId()
。
注意:Wear 2.0 不支持 setBackground()
方法。您可以对包含图片的通知使用 NotificationCompat.BigPictureStyle
。
Wear 2.0 也不支持 setHintHideIcon()
方法。
指定仅限穿戴式设备的操作
如果您希望穿戴式设备上提供的操作不同于手机上的操作,请使用 WearableExtender.addAction()
。您使用该函数添加操作后,穿戴式设备不会显示任何其他使用 NotificationCompat.Builder.addAction()
添加的操作。使用 WearableExtender.addAction()
添加的操作只会出现在穿戴式设备上,而不会出现在手机上。
将语音输入添加为通知操作
语音操作是穿戴式设备体验的重要组成部分。要创建支持语音输入的操作,请创建一个可添加到通知操作的 RemoteInput.Builder
实例。
此类的构造函数接受一个字符串,系统将该字符串用作语音输入的键,您稍后将使用该字符串检索手机应用中的输入文本。

例如,以下代码段展示了如何创建一个为语音输入提示提供自定义标签的 RemoteInput
对象:
Kotlin
// Key for the string that's delivered in the action's intent const val EXTRA_VOICE_REPLY = "extra_voice_reply" ... val remoteInput = resources.getString(R.string.reply_label).let { replyLabel -> RemoteInput.Builder(EXTRA_VOICE_REPLY) .setLabel(replyLabel) .build() }
Java
// Key for the string that's delivered in the action's intent private static final String EXTRA_VOICE_REPLY = "extra_voice_reply"; String replyLabel = getResources().getString(R.string.reply_label); RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY) .setLabel(replyLabel) .build();
添加预定义的文本回复

除允许语音输入之外,您还可以提供多达五条文本回复,以供用户快速回复。您可以调用 setChoices()
并向其传递一个字符串数组。
例如,您可以在资源数组中定义一些回复:
res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="reply_choices"> <item>Yes</item> <item>No</item> <item>Maybe</item> </string-array> </resources>
然后,扩充该字符串数组,并将其添加到 RemoteInput
中:
Kotlin
// Key for the string that's delivered in the action's intent const val EXTRA_VOICE_REPLY = "extra_voice_reply" ... val remoteInput = resources.getString(R.string.reply_label).let { replyLabel -> resources.getStringArray(R.array.reply_choices).let { replyChoices -> RemoteInput.Builder(EXTRA_VOICE_REPLY) .setLabel(replyLabel) .setChoices(replyChoices) .build() } }
Java
public static final String EXTRA_VOICE_REPLY = "extra_voice_reply"; ... String replyLabel = getResources().getString(R.string.reply_label); String[] replyChoices = getResources().getStringArray(R.array.reply_choices); RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY) .setLabel(replyLabel) .setChoices(replyChoices) .build();
接收字符串形式的语音输入
如需在您于回复操作的 Intent 中声明的 Activity 中接收用户的转录消息,请调用 getResultsFromIntent()
,传入“回复”操作的 Intent。此方法将返回一个包含文本回复 Bundle
。然后,您可以查询该 Bundle
以获取回复。
注意:请勿使用 Intent.getExtras()
获取语音结果,因为语音输入以 ClipData
形式存储。getResultsFromIntent()
方法提供了一种便捷的方式,让您可以接收字符序列,而不必自行处理 ClipData
。
以下代码展示的方法接受一个 Intent 并返回语音回复,该语音回复由前面示例中使用的 EXTRA_VOICE_REPLY
键引用:
Kotlin
/** * Obtain the intent that started this activity by calling * Activity.getIntent() and pass it into this method to * get the associated voice input string. */ private fun getMessageText(intent: Intent): CharSequence? = RemoteInput.getResultsFromIntent(intent)?.run { getCharSequence(EXTRA_VOICE_REPLY) }
Java
/** * Obtain the intent that started this activity by calling * Activity.getIntent() and pass it into this method to * get the associated voice input string. */ private CharSequence getMessageText(Intent intent) { Bundle remoteInput = RemoteInput.getResultsFromIntent(intent); if (remoteInput != null) { return remoteInput.getCharSequence(EXTRA_VOICE_REPLY); } return null; }
Kotlin
// Create an intent for the reply action val actionPendingIntent = Intent(this, ActionActivity::class.java).let { actionIntent -> PendingIntent.getActivity(this, 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT) } // Create the action val action = NotificationCompat.Action.Builder( R.drawable.ic_action, getString(R.string.label), actionPendingIntent ).build() // Build the notification and add the action via WearableExtender var notification = NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_message) .setContentTitle(getString(R.string.title)) .setContentText(getString(R.string.content)) .extend(NotificationCompat.WearableExtender().addAction(action)) .build()
Java
// Create an intent for the reply action Intent actionIntent = new Intent(this, ActionActivity.class); PendingIntent actionPendingIntent = PendingIntent.getActivity(this, 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT); // Create the action NotificationCompat.Action action = new NotificationCompat.Action.Builder(R.drawable.ic_action, getString(R.string.label), actionPendingIntent) .build(); // Build the notification and add the action via WearableExtender Notification notification = new NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_message) .setContentTitle(getString(R.string.title)) .setContentText(getString(R.string.content)) .extend(new WearableExtender().addAction(action)) .build();
从独立穿戴式设备应用启动通知
从独立手表应用创建通知与创建桥接通知没有什么不同。来自独立 Wear 应用的通知与桥接通知看起来相似,但它们的行为略有差异。如果未设置 contentIntent
或者通知从配对手机桥接而来,则点按通知会打开展开式通知。
然而,如果通知来自独立手表应用,点按通知会触发 contentIntent
以打开您的 Wear 应用。如需了解如何从独立应用创建通知并模拟展开式通知的行为,请参阅 Wear 通知示例。
默认情况下,通知从配对手机上的应用桥接到配对手表。如果您构建了独立手表应用,并且还有配套手机应用,这些应用可能会创建重复的通知。如需了解如何处理重复通知的问题,请参阅通知的桥接模式。