Android官方文档—User Interface(Notifications)

通知栏

通知是您可以在应用程序的普通UI之外向用户显示的消息。当您告诉系统发出通知时,它首先在通知区域中显示为图标。要查看通知的详细信息,用户将打开通知抽屉。通知区域和通知抽屉都是系统控制的区域,用户可以随时查看。

图1.通知区域中的通知。
图2.通知抽屉中的通知。

注意:除非另有说明,否则本指南引用版本4支持库中的NotificationCompat.Builder类。在Android 3.0(API级别11)中添加了Notification.Builder类。

设计注意事项


通知作为Android用户界面的重要组成部分,有自己的设计指南。 Android 5.0(API级别21)中引入的材料设计更改特别重要,您应该查看Material Design培训以获取更多信息。要了解如何设计通知及其交互,请阅读通知设计指南。

创建通知


您可以在NotificationCompat.Builder对象中指定通知的UI信息和操作。要创建通知本身,请调用NotificationCompat.Builder.build(),它返回包含您的规范的Notification对象。要发出通知,请通过调用NotificationManager.notify()将Notification对象传递给系统。

必填通知内容

Notification对象必须包含以下内容:

  • 一个小图标,由setSmallIcon()设置
  • 标题,由setContentTitle()设置
  • 详细文本,由setContentText()设置

可选的通知内容和设置

所有其他通知设置和内容都是可选的。要了解有关它们的更多信息,请参阅NotificationCompat.Builder的参考文档。

Notification actions

虽然它们是可选的,但您应该在通知中添加至少一个操作。操作允许用户直接从通知转到应用程序中的活动,在那里他们可以查看一个或多个事件或进行进一步的工作。

通知可以提供多个操作。您应始终定义用户单击通知时触发的操作;通常此操作会在您的应用程序中打开一个Activity。您还可以向通知添加按钮,以执行其他操作,例如暂停警报或立即响应文本消息;从Android 4.1开始提供此功能。如果您使用其他操作按钮,则还必须在应用中的“活动”中提供其功能;有关详细信息,请参阅处理兼容性部分。

在通知内部,操作本身由PendingIntent定义,该PendingIntent包含在应用程序中启动Activity的Intent。要将PendingIntent与手势相关联,请调用NotificationCompat.Builder的相应方法。例如,如果要在用户单击通知抽屉中的通知文本时启动Activity,则通过调用setContentIntent()添加PendingIntent。

用户单击通知时启动活动是最常见的操作方案。您还可以在用户解除通知时启动活动。在Android 4.1及更高版本中,您可以从操作按钮启动活动。要了解更多信息,请阅读NotificationCompat.Builder的参考指南。

通知优先权

如果您愿意,可以设置通知的优先级。优先级充当设备UI关于如何显示通知的提示。要设置通知的优先级,请调用NotificationCompat.Builder.setPriority()并传入其中一个NotificationCompat优先级常量。有五个优先级,从PRIORITY_MIN(-2)到PRIORITY_MAX(2);如果未设置,则优先级默认为PRIORITY_DEFAULT(0)。

有关设置适当优先级的信息,请参阅“通知设计指南”中的“正确设置和管理通知优先级”。

创建简单的通知

以下代码段说明了一个简单的通知,指定用户单击通知时要打开的活动。请注意,代码创建了一个TaskStackBuilder对象,并使用它为该操作创建PendingIntent。在启动活动时保留导航部分中更详细地解释了此模式:

NotificationCompat.Builder mBuilder =
        new NotificationCompat.Builder(this)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!");
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, ResultActivity.class);

// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
        stackBuilder.getPendingIntent(
            0,
            PendingIntent.FLAG_UPDATE_CURRENT
        );
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(mId, mBuilder.build());

这样。您的用户现已收到通知。

将扩展布局应用于通知

要在展开视图中显示通知,请首先使用所需的常规视图选项创建NotificationCompat.Builder对象。接下来,使用展开的布局对象作为参数调用Builder.setStyle()。

请记住,在Android 4.1之前的平台上无法使用扩展通知。要了解如何处理Android 4.1和早期平台的通知,请阅读处理兼容性部分。

例如,以下代码段演示了如何更改在上一个代码段中创建的通知以使用展开的布局:

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
    .setSmallIcon(R.drawable.notification_icon)
    .setContentTitle("Event tracker")
    .setContentText("Events received")
NotificationCompat.InboxStyle inboxStyle =
        new NotificationCompat.InboxStyle();
String[] events = new String[6];
// Sets a title for the Inbox in expanded layout
inboxStyle.setBigContentTitle("Event tracker details:");
...
// Moves events into the expanded layout
for (int i=0; i < events.length; i++) {

    inboxStyle.addLine(events[i]);
}
// Moves the expanded layout object into the notification object.
mBuilder.setStyle(inBoxStyle);
...
// Issue the notification here.

处理兼容性

并非所有通知功能都可用于特定版本,即使设置它们的方法位于支持库类NotificationCompat.Builder中也是如此。例如,依赖于扩展通知的操作按钮仅出现在Android 4.1及更高版本上,因为扩展通知本身仅适用于Android 4.1及更高版本。

要确保最佳兼容性,请使用NotificationCompat及其子类(尤其是NotificationCompat.Builder)创建通知。此外,在实施通知时请遵循以下流程:

1.向所有用户提供所有通知功能,无论他们使用何种版本。为此,请验证应用中的活动是否可以使用所有功能。您可能需要添加新的活动来执行此操作。

例如,如果要使用addAction()提供停止和启动媒体播放的控件,请首先在应用程序的“活动”中实现此控件。

2.通过在用户单击通知时启动,确保所有用户都可以访问“活动”中的功能。为此,请为活动创建PendingIntent。调用setContentIntent()将PendingIntent添加到通知中。

3.现在,将要使用的扩展通知功能添加到通知中。请记住,您添加的任何功能也必须在用户单击通知时启动的活动中可用。

管理通知


当您需要为同一类型的事件多次发出通知时,您应该避免发出全新的通知。相反,您应该考虑更新以前的通知,方法是更改​​某些值或添加它,或者两者兼而有之。

例如,Gmail通过增加未读邮件的数量以及向通知添加每封电子邮件的摘要来通知用户新电子邮件已到达。这称为“堆叠”通知;它在Notifications Design指南中有更详细的描述。

注意:此Gmail功能需要“收件箱”展开式布局,这是扩展通知功能的一部分。

以下部分介绍了如何更新通知以及如何删除通知。

更新通知

要设置通知以便更新,请通过调用NotificationManager.notify()向通知ID发出通知。要在发出通知后更新此通知,请更新或创建NotificationCompat.Builder对象,从中构建Notification对象,并使用先前使用的相同ID发出通知。如果先前的通知仍然可见,则系统会从Notification对象的内容中更新它。如果先前的通知已被取消,则会创建新通知。

以下代码段演示了一个更新的通知,以反映已发生的事件数。它堆叠通知,显示摘要:

mNotificationManager =
        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Sets an ID for the notification, so it can be updated
int notifyID = 1;
mNotifyBuilder = new NotificationCompat.Builder(this)
    .setContentTitle("New Message")
    .setContentText("You've received new messages.")
    .setSmallIcon(R.drawable.ic_notify_status)
numMessages = 0;
// Start of a loop that processes data and then notifies the user
...
    mNotifyBuilder.setContentText(currentText)
        .setNumber(++numMessages);
    // Because the ID remains unchanged, the existing notification is
    // updated.
    mNotificationManager.notify(
            notifyID,
            mNotifyBuilder.build());
...

删除通知

在发生以下情况之一之前,通知仍然可见:

  • 用户单独或使用“全部清除”(如果可以清除通知)解除通知。
  • 用户单击通知,并在创建通知时调用setAutoCancel()。
  • 您可以为特定通知ID调用cancel()。此方法还会删除正在进行的通知。
  • 您调用cancelAll(),它会删除您之前发出的所有通知。

回复通知


从Android 7.0(API级别24)开始,用户可以直接响应文本消息或从通知对话框中更新任务列表。在手持设备上,内联回复操作显示为通知中显示的附加按钮。当用户通过键盘回复时,系统会将文本响应附加到您为通知操作指定的意图,并将意图发送到掌上电脑应用程序。

图1.“回复”操作按钮。

添加内联回复操作

要创建支持直接回复的通知操作:

1.创建一个可以添加到通知操作的RemoteInput.Builder实例。此类的构造函数接受系统用作文本输入键的字符串。稍后,您的掌上电脑应用程序使用该键来检索输入的文本。

// Key for the string that's delivered in the action's intent.
private static final String KEY_TEXT_REPLY = "key_text_reply";
String replyLabel = getResources().getString(R.string.reply_label);
RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
        .setLabel(replyLabel)
        .build();

2.使用addRemoteInput()将RemoteInput对象附加到操作。

// Create the reply action and add the remote input.
Notification.Action action =
        new Notification.Action.Builder(R.drawable.ic_reply_icon,
                getString(R.string.label), replyPendingIntent)
                .addRemoteInput(remoteInput)
                .build();

3.将操作应用于通知并发出通知。

// Build the notification and add the action.
Notification newMessageNotification =
        new Notification.Builder(mContext)
                .setSmallIcon(R.drawable.ic_message)
                .setContentTitle(getString(R.string.title))
                .setContentText(getString(R.string.content))
                .addAction(action))
                .build();

// Issue the notification.
NotificationManager notificationManager =
        NotificationManager.from(mContext);
notificationManager.notify(notificationId, newMessageNotification);

系统会在用户触发通知操作时提示用户输入响应。

图2.用户从通知阴影中输入文本。

从内联回复中检索用户输入

要从通知界面接收用户输入您在回复操作的意图中声明的活动:

1.通过将通知操作的intent作为输入参数传递来调用getResultsFromIntent()。此方法返回包含文本响应的Bundle。

Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);

2.使用结果键(提供给RemoteInput.Builder构造函数)查询包。您可以通过创建方法来完成此过程并检索输入文本,如以下代码段所示:

// Obtain the intent that started this activity by calling
// Activity.getIntent() and pass it into this method to
// get the associated string.

private CharSequence getMessageText(Intent intent) {
    Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
    if (remoteInput != null) {
        return remoteInput.getCharSequence(KEY_TEXT_REPLY);
    }
    return null;
 }

3.使用您为先前通知提供的相同通知ID构建并发出另一个通知。进度指示器从通知界面中消失,以通知用户成功回复。使用此新通知时,请使用传递给接收方的onReceive()方法的上下文。

// Build a new notification, which informs the user that the system
// handled their interaction with the previous notification.
Notification repliedNotification =
        new Notification.Builder(context)
                .setSmallIcon(R.drawable.ic_message)
                .setContentText(getString(R.string.replied))
                .build();

// Issue the new notification.
NotificationManager notificationManager =
        NotificationManager.from(context);
notificationManager.notify(notificationId, repliedNotification);

对于交互式应用程序(例如聊天),您可以在处理检索到的文本时包含其他上下文。例如,这些应用可以显示多行聊天记录。当用户通过RemoteInput响应时,您可以使用setRemoteInputHistory()方法更新回复历史记录。

应用程序收到远程输入后,通知必须更新或取消。当用户使用“直接回复”回复远程更新时,请勿取消通知。而是更新通知以显示用户的回复。对于使用MessagingStyle的通知,您应该将回复添加为最新消息。使用其他模板时,您可以将用户的回复附加到远程输入历史记录中。

捆绑通知


从Android 7.0(API级别24)开始,Android为开发人员提供了一种表示通知队列的新方法:捆绑通知。这类似于Android Wear中的Notification Stacks功能。例如,如果您的应用为收到的消息创建通知,则当收到多条消息时,将通知捆绑在一起作为一个组。您可以使用Builder.setGroup()方法捆绑类似的通知。

通知组对包含它的通知强加层次结构。该层次结构的顶部是一个父通知,显示该组的摘要信息。用户可以逐步扩展通知组,并且系统在用户深入钻取时显示更多信息。当用户展开捆绑包时,系统会显示其所有子通知的更多信息;当用户展开其中一个通知时,系统会显示其整个内容。

图3.用户可以逐步扩展通知组。

注意:如果同一个应用程序发送四个或更多通知但未指定分组,系统会自动将它们分组在一起。

要了解如何向组添加通知,请参阅将每个通知添加到组。

捆绑通知的最佳做法

本节提供有关何时使用通知组而不是Android 6.0及以前版本中提供的InboxStyle通知的指南。

何时使用捆绑通知

仅当以下所有条件均适用于您的用例时,才应使用通知组:

  • 子通知是完整的通知,可以单独显示,而无需组摘要。
  • 单独显示儿童通知有一个好处。例如:

1.它们是可操作的,具有针对每个孩子的特定行动。

2.用户想要阅读的孩子有更多信息。

通知组的良好用例示例包括:显示传入消息列表的消息传递应用程序,或显示已接收电子邮件列表的电子邮件应用程序。

优选单个通知的情况的示例包括来自单个人的单个消息,或单行文本项的列表表示。您可以使用(InboxStyle或BigTextStyle)来完成此任务。

显示捆绑的通知

应用程序应始终发布组摘要,即使该组仅包含一个子组。如果仅包含单个通知,系统将禁止摘要并直接显示子通知。这确保了当用户滑动群组的孩子时系统可以提供一致的体验。

展开通知

虽然系统通常将子通知显示为一个组,但您可以将它们设置为临时显示为抬头通知。此功能特别有用,因为它允许立即访问最近的子项以及与之关联的操作。

向后兼容性

自Android 5.0(API级别21)起,通知组和远程输入都是Notification API的一部分,以支持Android Wear设备。如果您已经使用这些API构建了通知,则必须采取的唯一操作是验证应用程序行为是否符合上述指南,并考虑实现setRemoteInputHistory()。

为了支持向后兼容性,支持库的NotificationCompat类提供了相同的API,允许您构建适用于低于5.0的Android版本(API级别21)的通知。在手持设备和平板电脑上,用户只能看到摘要通知,因此应用程序仍应具有收件箱样式或相应的通知代表,以表示该组的整个信息内容。由于Android Wear设备允许用户甚至在较旧的平台级别上查看所有子通知,因此无论API级别如何,都应构建子通知。

启动活动时保留导航


从通知启动活动时,您必须保留用户的预期导航体验。单击“返回”应该让用户将应用程序的正常工作流程返回到主屏幕,单击“最近”应将“活动”显示为单独的任务。要保留导航体验,您应该在新任务中启动活动。如何设置PendingIntent以为您提供新任务取决于您正在启动的Activity的性质。有两种一般情况:

Regular activity

您正在启动一个Activity,它是应用程序正常工作流程的一部分。在这种情况下,设置PendingIntent以启动一个新任务,并为PendingIntent提供一个后备堆栈,以再现应用程序的正常Back行为。

来自Gmail应用的通知证明了这一点。单击单个电子邮件的通知时,您会看到邮件本身。触摸返回会将您向后移动到Gmail主屏幕,就像您从主屏幕输入Gmail而不是通过通知输入Gmail一样。

无论您在触摸通知时所处的应用程序如何,都会发生这种情况。例如,如果您在Gmail中撰写邮件,并且单击了一封电子邮件的通知,则会立即转到该电子邮件。触摸返回会将您带到收件箱,然后显示主屏幕

Special activity

如果用户从通知开始,则只会看到此活动。从某种意义上说,Activity通过提供难以在通知本身中显示的信息来扩展通知。对于这种情况,设置PendingIntent以在新任务中启动。但是,不需要创建后台堆栈,因为启动的Activity不是应用程序活动流的一部分。单击“返回”仍会将用户带到主屏幕。

设置常规活动PendingIntent

1.在清单中定义应用程序的活动层次结构。

a。添加对Android 4.0.3及更早版本的支持。为此,请通过添加<meta-data>元素作为<activity>的子元素来指定您启动的Activity的父级。

对于此元素,请设置android:name =“android.support.PARENT_ACTIVITY”。设置android:value =“<parent_activity_name>”,其中<parent_activity_name>是父<activity>元素的android:name的值。有关示例,请参阅以下XML。

b.还添加对Android 4.1及更高版本的支持。为此,请将android:parentActivityName属性添加到您正在启动的Activity的<activity>元素中。

最终的XML应如下所示:

<activity
    android:name=".MainActivity"
    android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
<activity
    android:name=".ResultActivity"
    android:parentActivityName=".MainActivity">
    <meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value=".MainActivity"/>
</activity>

2.根据启动Activity的Intent创建一个后栈:

a.创建Intent以启动Activity。

b.通过调用TaskStackBuilder.create()创建堆栈构建器。

c.通过调用addParentStack()将后栈添加到堆栈构建器。对于您在清单中定义的层次结构中的每个活动,后堆栈包含启动活动的Intent对象。此方法还添加了在新任务中启动堆栈的标志。

注意:尽管addParentStack()的参数是对已启动的Activity的引用,但方法调用不会添加启动Activity的Intent。相反,这将在下一步中得到解决。

e.如果需要,可以通过调用TaskStackBuilder.editIntentAt()为堆栈上的Intent对象添加参数。当用户使用Back导航到目标Activity时,有时需要确保目标Activity显示有意义的数据。

f.通过调用getPendingIntent()获取此堆栈的PendingIntent。然后,您可以将此PendingIntent用作setContentIntent()的参数。

以下代码段演示了该过程:

Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent to the top of the stack
stackBuilder.addNextIntent(resultIntent);
// Gets a PendingIntent containing the entire back stack
PendingIntent resultPendingIntent =
        stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
...
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, builder.build());

设置特殊活动PendingIntent

以下部分介绍如何设置特殊活动PendingIntent。

特殊的Activity不需要后台堆栈,因此您不必在清单中定义其Activity层次结构,也不必调用addParentStack()来构建后台堆栈。相反,使用清单设置Activity任务选项,并通过调用getActivity()创建PendingIntent:

1.在清单中,将以下属性添加到Activity的<activity>元素

android:name="activityclass"

活动的完全限定类名。

android:taskAffinity=""

结合您在代码中设置的FLAG_ACTIVITY_NEW_TASK标志,这可确保此活动不会进入应用程序的默认任务。具有应用程序默认亲缘关系的任何现有任务都不会受到影响。

android:excludeFromRecents="true"

从“最近”中排除新任务,以便用户不会意外导航回到它。

此代码段显示了该元素:

<activity
    android:name=".ResultActivity"
...
    android:launchMode="singleTask"
    android:taskAffinity=""
    android:excludeFromRecents="true">
</activity>
...

2.构建并发布通知:

a.创建一个启动Activity的Intent。

b.通过使用标志FLAG_ACTIVITY_NEW_TASK和FLAG_ACTIVITY_CLEAR_TASK调用setFlags(),将Activity设置为在新的空任务中启动。

c.设置Intent所需的任何其他选项。

d.通过调用getActivity()从Intent创建PendingIntent。然后,您可以将此PendingIntent用作setContentIntent()的参数。

以下代码段演示了该过程:

// Instantiate a Builder object.
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Creates an Intent for the Activity
Intent notifyIntent =
        new Intent(this, ResultActivity.class);
// Sets the Activity to start in a new, empty task
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Creates the PendingIntent
PendingIntent notifyPendingIntent =
        PendingIntent.getActivity(
        this,
        0,
        notifyIntent,
        PendingIntent.FLAG_UPDATE_CURRENT
);

// Puts the PendingIntent into the notification builder
builder.setContentIntent(notifyPendingIntent);
// Notifications are issued by sending them to the
// NotificationManager system service.
NotificationManager mNotificationManager =
    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Builds an anonymous Notification object from the builder, and
// passes it to the NotificationManager
mNotificationManager.notify(id, builder.build());

显示通知中的进度


通知可以包括动画进度指示器,向用户显示正在进行的操作的状态。如果您可以随时估计操作需要多长时间以及完成多少操作,请使用指标的“确定”形式(进度条)。如果无法估计操作的长度,请使用指标的“不确定”形式(活动指示器)。

使用平台的ProgressBar类实现显示进度指示器。

要在从Android 4.0开始的平台上使用进度指示器,请调用setProgress()。对于以前的版本,您必须创建自己的自定义通知布局,其中包括ProgressBar视图。

以下部分介绍如何使用setProgress()显示通知中的进度。

显示固定持续时间进度指示器

要显示确定的进度条,请通过调用setProgress(max,progress,false)将栏添加到通知中,然后发出通知。随着操作的进行,增加进度并更新通知。在操作结束时,进度应该等于最大值。调用setProgress()的常用方法是将max设置为100,然后将progress作为操作的“完成百分比”值递增。

您可以在操作完成时退出进度条,也可以将其删除。在任何一种情况下,请记住更新通知文本以显示操作已完成。要删除进度条,请调用setProgress(0,0,false)。例如:

...
mNotifyManager =
        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentTitle("Picture Download")
    .setContentText("Download in progress")
    .setSmallIcon(R.drawable.ic_notification);
// Start a lengthy operation in a background thread
new Thread(
    new Runnable() {
        @Override
        public void run() {
            int incr;
            // Do the "lengthy" operation 20 times
            for (incr = 0; incr <= 100; incr+=5) {
                    // Sets the progress indicator to a max value, the
                    // current completion percentage, and "determinate"
                    // state
                    mBuilder.setProgress(100, incr, false);
                    // Displays the progress bar for the first time.
                    mNotifyManager.notify(0, mBuilder.build());
                        // Sleeps the thread, simulating an operation
                        // that takes time
                        try {
                            // Sleep for 5 seconds
                            Thread.sleep(5*1000);
                        } catch (InterruptedException e) {
                            Log.d(TAG, "sleep failure");
                        }
            }
            // When the loop is finished, updates the notification
            mBuilder.setContentText("Download complete")
            // Removes the progress bar
                    .setProgress(0,0,false);
            mNotifyManager.notify(ID, mBuilder.build());
        }
    }
// Starts the thread by calling the run() method in its Runnable
).start();

显示持续活动指标

要显示不确定的活动指示符,请使用setProgress(0,0,true)将其添加到通知中(忽略前两个参数),然后发出通知。结果是一个与进度条具有相同样式的指示器,但其动画正在进行中。

在操作开始时发出通知。动画将一直运行,直到您修改通知为止。操作完成后,调用setProgress(0,0,false),然后更新通知以删除活动指示符。总是这样做;否则,即使操作完成,动画也会运行。还要记住更改通知文本以指示操作已完成。

要了解活动指标的工作原理,请参阅前面的代码段。找到以下行:

// Sets the progress indicator to a max value, the current completion
// percentage, and "determinate" state
mBuilder.setProgress(100, incr, false);
// Issues the notification
mNotifyManager.notify(0, mBuilder.build());

用以下行替换您找到的行:

 // Sets an activity indicator for an operation of indeterminate length
mBuilder.setProgress(0, 0, true);
// Issues the notification
mNotifyManager.notify(0, mBuilder.build());

通知元数据


可以根据您使用以下NotificationCompat.Builder方法分配的元数据对通知进行排序:

  • setCategory()告诉系统当设备处于优先级模式时如何处理应用程序通知(例如,如果您的通知代表来电,即时消息或警报)。
  • 如果通知也有声音或振动,setPriority()会将优先级字段设置为PRIORITY_MAX或PRIORITY_HIGH的通知显示在小浮动窗口中。
  • addPerson()允许您向通知添加人员列表。您的应用可以使用此功能向系统发出信号,告知系统应将来自指定人员的通知组合在一起,或者将来自这些人的通知排名为更重要。

抬头通知


使用Android 5.0(API级别21),当设备处于活动状态时(即设备已解锁且其屏幕处于打开状态),通知可以显示在小型浮动窗口(也称为抬头通知)中。这些通知看起来类似于通知的紧凑形式,除了抬头通知还显示操作按钮。用户可以在不离开当前应用的情况下处理或解除提前通知。

可能触发抬头通知的条件示例包括:

  • 用户的活动处于全屏模式(应用程序使用fullScreenIntent),或
  • 通知具有高优先级并使用铃声或振动

锁定屏幕通知


随着Android 5.0(API级别21)的发布,通知现在可能会出现在锁定屏幕上。您的应用可以使用此功能来提供媒体播放控件和其他常见操作。用户可以通过“设置”选择是否在锁定屏幕上显示通知,还可以指定是否在锁定屏幕上显示应用程序的通知。

设置可见性

您的应用可以控制安全锁定屏幕上显示的通知中可见的详细程度。您调用setVisibility()并指定以下值之一:

  • VISIBILITY_PUBLIC显示通知的完整内容。
  • VISIBILITY_SECRET在锁定屏幕上不显示此通知的任何部分。
  • VISIBILITY_PRIVATE显示基本信息,例如通知的图标和内容标题,但隐藏通知的完整内容。

设置VISIBILITY_PRIVATE后,您还可以提供隐藏某些详细信息的备用通知内容版本。例如,SMS应用程序可能会显示一条通知,显示您有3条新短信,但会隐藏邮件内容和发件人。要提供此备用通知,请首先使用NotificationCompat.Builder创建替换通知。创建私有通知对象时,通过setPublicVersion()方法将替换通知附加到该对象。

控制锁定屏幕上的媒体播放

在Android 5.0(API级别21)中,锁定屏幕不再显示基于RemoteControlClient的媒体控件,该控件现已弃用。而是将NotificationCompat.MediaStyle模板与addAction()方法一起使用,该方法将操作转换为可单击的图标。

要在Android 5.0的锁定屏幕上显示媒体播放控件,请将可见性设置为VISIBILITY_PUBLIC,如上所述。然后添加操作并设置NotificationCompat.MediaStyle模板,如以下示例代码中所述:

Notification notification = new NotificationCompat.Builder(context)
    // Show controls on lock screen even when user hides sensitive content.
    .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
    .setSmallIcon(R.drawable.ic_stat_player)
    // Add media control buttons that invoke intents in your media service
    .addAction(R.drawable.ic_prev, "Previous", prevPendingIntent) // #0
    .addAction(R.drawable.ic_pause, "Pause", pausePendingIntent)  // #1
    .addAction(R.drawable.ic_next, "Next", nextPendingIntent)     // #2
    // Apply the media style template
    .setStyle(new NotificationCompat.MediaStyle()
        .setShowActionsInCompactView(1 /* #1: pause button */)
        .setMediaSession(mMediaSession.getSessionToken()))
    .setContentTitle("Wonderful music")
    .setContentText("My Awesome Band")
    .setLargeIcon(albumArtBitmap)
    .build();

注意:RemoteControlClient的弃用对控制媒体有进一步的影响。有关用于管理媒体会话和控制播放的新API的详细信息,请参阅媒体播放控制。

自定义通知布局


通知框架允许您定义自定义通知布局,该布局定义通知在RemoteViews对象中的外观。自定义布局通知与普通通知类似,但它们基于XML布局文件中定义的RemoteView。

自定义通知布局的可用高度取决于通知视图。普通视图布局限制为64 dp,扩展视图布局限制为256 dp。

要定义自定义通知布局,请首先实例化一个扩展XML布局文件的RemoteViews对象。然后,调用setContent()而不是调用setContentTitle()等方法。要在自定义通知中设置内容详细信息,请使用RemoteViews中的方法设置视图子项的值:

1.在单独的文件中为通知创建XML布局。您可以使用任何所需的文件名,但必须使用扩展名.xml

2.在您的应用程序中,使用RemoteViews方法定义通知的图标和文本。通过调用setContent()将此RemoteViews对象放入NotificationCompat.Builder中。避免在RemoteViews对象上设置背景Drawable,因为文本颜色可能变得不可读。

RemoteViews类还包括可用于轻松地将Chronometer或ProgressBar添加到通知布局的方法。有关为通知创建自定义布局的更多信息,请参阅RemoteViews参考文档。

警告:使用自定义通知布局时,请特别注意确保自定义布局使用不同的设备方向和分辨率。虽然此建议适用于所有View布局,但对于通知尤为重要,因为通知抽屉中的空间非常有限。不要使自定义布局过于复杂,并确保以各种配置进行测试。

使用样式资源自定义通知文本

始终将样式资源用于自定义通知的文本。通知的背景颜色可能因设备和版本而异,使用样式资源可帮助您解决此问题。从Android 2.3开始,系统为标准通知布局文本定义了一种样式。如果您在面向Android 2.3或更高版本的应用程序中使用相同的样式,则可以确保您的文本在显示背景下可见。

自定义视图

从Android 7.0(API级别24)开始,您可以自定义通知视图,并仍然可以获取通知标题,操作和可扩展布局等系统装饰。

要启用此功能,Android会提供以下API来设置自定义视图的样式:

DecoratedCustomViewStyle()

除媒体通知之外的样式通知。

DecoratedMediaCustomViewStyle()

样式媒体通知。

要使用此API,请调用setStyle()方法,并向其传递所需的自定义视图样式。

此代码段显示如何使用DecoratedCustomViewStyle()方法构造自定义通知对象。

Notification notification = new Notification.Builder()
           .setSmallIcon(R.drawable.ic_stat_player)
           .setLargeIcon(albumArtBitmap))
           .setCustomContentView(contentView);
           .setStyle(new Notification.DecoratedCustomViewStyle())
           .build();

消息风格

从Android 7.0(API级别24)开始,Android提供了一个用于自定义通知样式的API。使用MessagingStyle类,您可以更改通知上显示的多个标签,包括会话标题,其他消息和通知的内容视图。

以下代码段演示了如何使用MessagingStyle类自定义通知的样式。

  Notification notification = new Notification.Builder()
             .setStyle(new Notification.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();

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值