lightbulb_outline Help shape the future of the Google Play Console, Android Studio, and Firebase. Start survey

为穿戴式设备创建通知

随着独立 Wear 应用的推出,手表和手机都可以成为通知的来源。可以使用 NotificationCompat.Builder 类为穿戴式设备创建通知。当您使用该类生成通知时,系统负责让无论是出现在手持式设备上还是穿戴式设备上的通知都能正常显示。

本文第一部分向您介绍如何为穿戴式设备创建和发出通知。下一部分说明如何为每个从连接的手持式设备桥接到穿戴式设备的通知提供更多内容。第三部分向您介绍如何为通知添加操作和穿戴式设备专属功能。本文最后说明从独立 Android Wear 应用启动时,通知风格上表现出的微小差异。

:使用 RemoteViews 的通知的自定义布局会被去掉,穿戴式设备只会显示文本和图标。不过,您可以通过创建在穿戴式设备上运行的穿戴式设备应用,创建使用自定义卡布局的自定义通知

导入必要的类

要导入必要的软件包,请在您的 build.gradle 文件中添加以下这行代码:

compile "com.android.support:support-v4:25.0.+"

现在您的项目具有对必要软件包的访问权,请从支持库导入必要的类:

import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.app.NotificationCompat.WearableExtender;

使用通知生成器创建通知

v4 支持库允许您使用操作按钮和图标等最新通知功能创建通知,同时保持与 Android 1.6(API 级别 4)及更高版本的兼容性。

要创建带支持库的通知,请执行下列操作:

  1. 您创建一个 NotificationCompat.Builder 实例。
    int notificationId = 001;
    // 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);
    
    NotificationCompat.Builder notificationBuilder =
        new NotificationCompat.Builder(this)
            .setSmallIcon(R.drawable.ic_event)
            .setContentTitle(eventTitle)
            .setContentText(eventLocation)
            .setContentIntent(viewPendingIntent);
    
  2. 通过将带通知 ID 的 Notification 对象传递给 notify() 发出通知。
    // 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。当此通知出现在 Android 穿戴式设备上时,会出现在通知卡片信息流中。对于桥接通知,用户可以点按通知来查看扩展通知,以及触发任何定义的操作,例如打开操作。通常,这些操作会打开您的手持式设备应用上的某个 Activity

构建扩展通知

扩展通知为每个通知提供大量附加内容和操作。当您为通知指定附加内容页面和操作时,这些内容可供用户在扩展通知内使用。每个扩展通知都遵循 Material Design for Android Wear,因此用户都会获得类应用体验。

如果扩展通知中的第一个操作具有 RemoteInput(例如,一个回复操作),则您使用 setChoices() 设置的选项会出现在扩展通知内的第一个操作下。

符合以下任一条件时,用户可以通过点按通知查看扩展通知:

  • 通知由应用在配对手机上生成,并桥接到 Wear。
  • 通知没有 contentIntent

:仅当您扩展通知时,才会显示使用 setColor() 函数为通知设置的应用专属背景色。

扩展通知最佳做法

要决定使用扩展通知的时机,请遵循以下宗旨:

  • 所有从配对手机桥接至 Wear 设备的通知都使用扩展通知。
  • 如果通知是由在 Wear 上本地运行的应用生成,您应该通过调用 setContentIntent()让通知的触摸目标使用通知 ID 在您的应用内启动 Notification 对象。我们建议您不要为由在 Wear 上本地运行的应用生成的通知使用扩展通知。

添加扩展通知

扩展通知允许您为通知提供附加内容和操作。您可以选择应用的通知提供信息的详细程度;但请慎重考虑您在通知中加入的详细程度。

添加附加内容

要在您的扩展通知中显示附加文本,请使用 BigTextStyle

要在您的扩展通知中添加图像,您可以使用 BigPictureStyle。如果您想在扩展通知中添加多个图像,请结合使用 addPage() 函数和 BigPictureStyle

主要操作

扩展通知将包含一个主要操作,除非使用 setContentAction() 指定了其他操作,否则该操作将是通知中的第一个操作。

附加操作

要指定附加操作,请使用 addAction()addActions()。扩展通知的操作抽屉式导航栏包含所有可用操作。

添加通知操作

除了 setContentIntent() 定义的主要内容操作外,您还可以通过将 PendingIntent 传递给 addAction() 函数,添加其他操作。

例如,以下代码显示与以上相同类型的通知,但添加了一个在地图上查看活动位置的操作。

// Build an intent for an action to view a map
Intent mapIntent = new Intent(Intent.ACTION_VIEW);
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)
        .setSmallIcon(R.drawable.ic_event)
        .setContentTitle(eventTitle)
        .setContentText(eventLocation)
        .setContentIntent(viewPendingIntent)
        .addAction(R.drawable.ic_map,
                getString(R.string.map), mapPendingIntent);

在手持式设备上,操作的出现形式是与通知相连的附加按钮。在穿戴式设备上,操作出现在扩展通知中的内容文本之后。当用户点按操作时,会调用手持式设备上的相关 intent。

提示:如果您的通知包括一个“Reply”操作(例如,对于消息传递应用),您可以通过启用直接从 Android 穿戴式设备进行语音输入来改善这一行为。如需了解详细信息,请阅读添加语音输入作为通知操作

添加内联操作

内联操作允许用户在通知卡片信息流卡片内对通知执行操作。在 Wear 上,内联操作的出现形式是显示在通知底部的一个附加按钮。

内联操作为可选操作,但对于用户可能在通知卡片信息流卡片中查看内容(并不转至扩展通知)后即对通知执行操作的情况,建议使用该操作。举例来说,适合在通知上使用内联操作的用例包括:回复短信、停止健身 Activity 以及存档电子邮件。

一个通知只能提供一个内联操作。要将内联操作显示为通知中的一个附加按钮,请将 setHintDisplayActionInline() 函数设置为 true。当用户点按内联操作时,系统调用您在通知操作中指定的 intent。

下面这段代码添加显示内联操作的提示,并使用 addAction 函数向通知添加内联操作。

//Android Wear 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,请执行下列操作:

  1. 创建一个 WearableExtender 实例,为通知设置穿戴式设备专属选项。
  2. 创建一个 NotificationCompat.Builder 实例,按照本课程前文所述为您的通知设置所需属性。
  3. 对通知调用 extend() 并传入 WearableExtender。这会对通知应用穿戴式设备选项。
  4. 调用 build() 以生成通知。

:如果您使用框架的 NotificationManagerNotificationCompat.WearableExtender 中的某些功能不起作用,因此请务必使用 NotificationCompat

例如,以下代码调用 setHintHideIcon() 函数从通知卡中移除应用图标。

// Create a WearableExtender to add functionality for wearables
NotificationCompat.WearableExtender wearableExtender =
        new NotificationCompat.WearableExtender()
        .setHintHideIcon(true)
        .setBackground(mBitmap);

// Create a NotificationCompat.Builder to build a standard notification
// then extend it with the WearableExtender
Notification notif = new NotificationCompat.Builder(mContext)
        .setContentTitle("New mail from " + sender)
        .setContentText(subject)
        .setSmallIcon(R.drawable.new_mail)
        .extend(wearableExtender)
        .build();

setHintHideIcon()setBackground() 函数不过是随 NotificationCompat.WearableExtender 提供的新通知功能的两个示例。

:您配合 setBackground() 使用的位图非滚动背景的分辨率应为 400x400,支持视差滚动的背景分辨率应为 640x400。将这些位图图像放入 res/drawable-nodpi 目录。将穿戴式设备通知的其他非位图资源(例如配合 setContentIcon() 函数使用的资源)放入 res/drawable-hdpi 目录。

如果您稍后需要读取穿戴式设备专属选项,请使用选项对应的 get 函数。此示例调用 getHintHideIcon() 函数来获取该通知是否隐藏图标的信息:

NotificationCompat.WearableExtender wearableExtender =
        new NotificationCompat.WearableExtender(notif);
boolean hintHideIcon = wearableExtender.getHintHideIcon();

指定穿戴式设备专用操作

如果您希望穿戴式设备上提供的操作不同于手持式设备上的操作,则使用 WearableExtender.addAction()。您使用该函数添加操作后,穿戴式设备不会显示任何其他使用 NotificationCompat.Builder.addAction()添加的操作。使用 WearableExtender.addAction() 添加的操作只出现在穿戴式设备上,不会出现在手持式设备上。

添加语音输入作为通知操作

语音操作是穿戴式设备体验的重要组成部分。要创建支持语音输入的操作,请创建可添加到通知操作的 RemoteInput.Builder 实例。该类的构造函数接受一个被系统用作语音输入密钥的字符串,您稍后将使用这个字符串来检索您的手持式设备应用中的输入文本。

例如,以下代码展示的是如何创建为语音输入提示提供自定义标签的 RemoteInput 对象:

// 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 中:

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(),传入“Reply”操作的 intent。该函数返回含有文本回复的 Bundle。然后您就可以查询 Bundle 来获得回复。

:请勿使用 Intent.getExtras() 来获得语音结果,因为语音输入以 ClipData 形式存储。getResultsFromIntent() 函数提供了一种便捷的方式,让您不必亲自处理 ClipData 便可接收字符序列。

以下代码显示的函数接受一个 intent 并返回语音回复,该回复由先前示例中使用的 EXTRA_VOICE_REPLY 密钥引用:

/**
 * 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;
}
// 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(mContext)
                .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 通知示例。

默认情况下,通知从配套手机上的应用桥接至配对手表。如果您构建了独立手表应用,并且还有配套手机应用,这些应用可能会创建重复的通知。如需了解有关处理重复通知问题的信息,请参阅通知的桥接模式