【Interface&navigation】创建一个通知(37)

通知可在应用程序未使用时提供有关事件的简短及时的信息。此页面教您如何使用Android 4.0(API级别14)及更高版本的各种功能创建通知。有关通知在Android上的显示方式的介绍,请参阅通知概述。

请注意,此页面上的代码使用NotificationCompatAndroid支持库中的API。这些API允许您添加仅在较新版本的Android上可用的功能,同时仍然提供与Android 4.0(API级别14)的兼容性。但是,一些新功能(如内联回复操作)会导致旧版本的无操作。

添加支持库


尽管使用Android Studio创建的大多数项目都包含必要的依赖项NotificationCompat,但您应该验证模块级build.gradle文件是否包含以下依赖项:

dependencies {
    implementation "com.android.support:support-compat:27.1.1"
}

注意:组中的其他库com.android.support也包含 support-compat作为传递依赖项。因此,如果您已经在使用其他支持库API,则可以访问,NotificationCompat而无需上面显示的确切依赖项。

创建基本通知


最基本和紧凑形式的通知(也称为折叠表单)显示图标,标题和少量内容文本。在本部分中,您将学习如何创建用户可以单击以在应用中启动活动的通知。
【Interface&navigation】创建一个通知(37)
图1.带有标题和文本的通知
有关通知的每个部分的更多详细信息,请阅读有关 通知解剖的信息。

设置通知内容

首先,您需要使用NotificationCompat.Builder对象设置通知的内容和频道 。以下示例显示如何使用以下内容创建通知:

一个小图标,由...设置setSmallIcon()。这是唯一需要的用户可见内容。
标题,由...设定setContentTitle()。
正文设置setContentText()。
通知优先级,由setPriority()。设置。优先级决定了Android 7.1及更低版本通知的侵入程度。(对于Android 8.0及更高版本,您必须设置频道重要性 - 显示在下一部分中。)

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle(textTitle)
        .setContentText(textContent)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT);

请注意,NotificationCompat.Builder 构造函数要求您提供通道ID。这是与Android 8.0(API级别26)及更高版本兼容所必需的,但旧版本会忽略这一点。

默认情况下,通知的文本内容将被截断以适合一行。如果您希望通知更长,可以通过添加样式模板来启用可扩展通知setStyle()。例如,以下代码创建一个更大的文本区域:

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Much longer text that cannot fit one line...")
        .setStyle(new NotificationCompat.BigTextStyle()
                .bigText("Much longer text that cannot fit one line..."))
        .setPriority(NotificationCompat.PRIORITY_DEFAULT);

有关其他大型通知样式的详细信息,包括如何添加图像和媒体播放控件,请参阅 使用可扩展的详细信息创建通知。

创建频道并设置重要性

在Android 8.0及更高版本上发送通知之前,您必须通过传递实例来向 系统注册应用程序的 通知通道。因此,以下代码被版本上的条件阻止 :NotificationChannelcreateNotificationChannel()SDK_INT

private void 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) {
        CharSequence name = getString(R.string.channel_name);
        String description = getString(R.string.channel_description);
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
        channel.setDescription(description);
        // Register the channel with the system; you can't change the importance
        // or other notification behaviors after this
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

由于您必须在Android 8.0及更高版本上发布任何通知之前创建通知渠道,因此您应该在应用启动后立即执行此代码。重复调用此方法是安全的,因为创建现有通知通道不会执行任何操作。

请注意,NotificationChannel构造函数需要importance使用类中的一个常量NotificationManager。此参数确定如何中断用户对属于此的任何通知信道,虽然必须同时设置的优先级与setPriority()支持Android 7.1和下(如上所示)。

虽然您必须如此处所示设置通知重要性/优先级,但系统不保证您将获得警报行为。在某些情况下,系统可能会根据其他因素更改重要性级别,并且用户可以始终重新定义给定通道的重要性级别。

有关不同级别含义的更多信息,请阅读有关 通知重要性级别的信息。

设置通知的点按操作

每个通知都应响应点按,通常是在您的应用中打开与通知相对应的活动。为此,您必须指定使用PendingIntent对象定义的内容意图并将其传递给setContentIntent()。

以下代码段显示了当用户点按通知时如何创建打开活动的基本意图:

// Create an explicit intent for an Activity in your app
Intent intent = new Intent(this, AlertDetails.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

NotificationCompat.Builder mBuilder = new 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(), 当用户点击它时会自动删除该通知。

setFlags()上面显示的方法有助于在用户通过通知打开您的应用后保留用户的预期导航体验。但是,您是否要使用它取决于您正在启动的活动类型,可能是以下之一:

专门用于响应通知的活动。在正常的应用程序使用期间,用户没有理由导航到此活动,因此活动会启动新任务,而不是添加到应用程序的现有 任务和后台堆栈。这是上面示例中创建的意图类型。
应用的常规应用流程中存在的活动。在这种情况下,启动活动应该创建一个后备堆栈,以便保留用户对Back和Up按钮的期望。
有关配置通知意图的不同方法的更多信息,请参阅 从通知中启动活动。

显示通知

要显示通知,请调用NotificationManagerCompat.notify(),向其传递通知的唯一ID和结果NotificationCompat.Builder.build()。例如:

NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);

// notificationId is a unique int for each notification that you must define
notificationManager.notify(notificationId, mBuilder.build());

请记住保存传递给的通知ID,NotificationManagerCompat.notify()因为如果要更新或删除通知,以后需要它 。

注意:从Android 8.1(API级别27)开始,应用程序无法每秒发出超过一次的通知。如果您的应用在一秒钟内发布了多个通知,则它们都会按预期显示,但每秒只有第一个通知发出声音。

添加操作按钮


通知最多可以提供三个操作按钮,允许用户快速响应,例如暂停提醒或甚至回复短信。但是,这些操作按钮不应复制用户点击通知时执行的操作 。
【Interface&navigation】创建一个通知(37)
图2.带有一个操作按钮的通知

要添加操作按钮,请将a传递PendingIntent给 addAction() 方法。这就像设置通知的默认点击操作一样,除了启动活动之外,您还可以执行各种其他操作,例如启动BroadcastReceiver在后台执行作业的操作,以便操作不会中断已打开的应用程序。

例如,以下代码显示如何将广播发送到特定接收器:

Intent snoozeIntent = new Intent(this, MyBroadcastReceiver.class);
snoozeIntent.setAction(ACTION_SNOOZE);
snoozeIntent.putExtra(EXTRA_NOTIFICATION_ID, 0);
PendingIntent snoozePendingIntent =
        PendingIntent.getBroadcast(this, 0, snoozeIntent, 0);

NotificationCompat.Builder mBuilder = new 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);

有关构建BroadcastReceiver 运行后台工作的详细信息,请参阅“ 广播”指南。

如果您尝试使用媒体播放按钮(例如暂停和跳过曲目)来构建通知,请参阅如何使用媒体控件创建通知。

添加直接回复操作


Android 7.0(API级别24)中引入的直接回复操作允许用户直接在通知中输入文本,该通知会在不打开活动的情况下传送到您的应用。例如,您可以使用直接回复操作让用户回复文本消息或从通知中更新任务列表。
【Interface&navigation】创建一个通知(37)
图3.点击“Reply”按钮打开文本输入

直接回复操作在通知中显示为打开文本输入的附加按钮。当用户完成输入时,系统会将文本响应附加到您为通知操作指定的意图,并将意图发送到您的应用程序。

添加回复按钮

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

创建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();

PendingIntent为回复操作创建一个。

// Build a PendingIntent for the reply action to trigger.
PendingIntent replyPendingIntent =
        PendingIntent.getBroadcast(getApplicationContext(),
                conversation.getConversationId(),
                getMessageReplyIntent(conversation.getConversationId()),
                PendingIntent.FLAG_UPDATE_CURRENT);

警告:如果您重新使用a PendingIntent,则用户可能会回复与他们认为的对话不同的对话。您必须为每个对话提供不同的请求代码,或者true在您呼叫equals() 任何其他对话的回复意图时提供不返回的意图。会话ID经常作为intent的extras包的一部分传递,但在您调用时会被忽略equals()。

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

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

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

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

// Issue the notification.
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, newMessageNotification);

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

从回复中检索用户输入

要从通知的回复用户界面接收用户输入,请致电 RemoteInput.getResultsFromIntent(),将其传递给Intent您BroadcastReceiver:

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

处理完文本后,必须NotificationManagerCompat.notify()使用相同的ID和标记(如果使用)来更新通知 。这是隐藏直接回复UI并向用户确认他们的回复已被正确接收和处理所必需的。

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

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

使用此新通知时,请使用传递给接收方onReceive()方法的上下文。

您还应该通过调用将回复附加到通知的底部 setRemoteInputHistory()。但是,如果您正在构建消息传递应用程序,则应创建消息传递样式通知 并将新消息附加到对话。

对于从即时通讯应用的通知的详细建议,请参阅为即时通讯应用的最佳实践。

添加进度条


通知可以包括动画进度指示器,向用户显示正在进行的操作的状态。

【Interface&navigation】创建一个通知(37)
图4.操作期间和之后的进度条。

如果您可以随时估计操作的完成程度,请通过调用使用指标的“确定”形式(如图4所示) setProgress(max, progress, false)。第一个参数是“完整”值(例如100); 第二个是当前完成的数量,最后一个表示这是一个确定的进度条。

随着您的操作继续进行,请持续调用setProgress(max, progress, false)更新的值 progress并重新发出通知

...
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);
mBuilder.setContentTitle("Picture Download")
        .setContentText("Download in progress")
        .setSmallIcon(R.drawable.ic_notification)
        .setPriority(NotificationCompat.PRIORITY_LOW);

// Issue the initial notification with zero progress
int PROGRESS_MAX = 100;
int PROGRESS_CURRENT = 0;
mBuilder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
notificationManager.notify(notificationId, mBuilder.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:
// mBuilder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
// notificationManager.notify(notificationId, mBuilder.build());

// When done, update the notification one more time to remove the progress bar
mBuilder.setContentText("Download complete")
        .setProgress(0,0,false);
notificationManager.notify(notificationId, mBuilder.build());

在操作结束时,progress应该相等 max。您可以在操作完成时退出进度条,也可以将其删除。在任何一种情况下,请记住更新通知文本以显示操作已完成。要删除进度条,请致电setProgress(0, 0, false)。
注意:由于进度条要求您的应用程序不断更新通知,因此此代码通常应在后台服务中运行。

要显示不确定的进度条(未指示完成百分比的栏),请致电 setProgress(0, 0, true)。结果是一个与上面的进度条具有相同样式的指示器,除了进度条是一个不表示完成的连续动画。进度动画将一直运行,直到您调用 setProgress(0, 0, false) 并更新通知以删除活动指示符。

请记住更改通知文本以指示操作已完成。

注意:如果您确实需要下载文件,则应考虑使用 DownloadManager,它会提供自己的通知来跟踪您的下载进度。

设置系统范围的类别


Android使用一些预定义的系统范围类别来确定当用户启用“ 请勿打扰”模式时是否使用给定通知打扰用户 。

如果您的通知属于中定义的预先定义的通知类别之一NotificationCompat-如CATEGORY_ALARM, CATEGORY_REMINDER, CATEGORY_EVENT,或 CATEGORY_CALL-你应该通过合适的类别声明它是这样setCategory()。

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setCategory(NotificationCompat.CATEGORY_MESSAGE);

当设备处于“请勿打扰”模式时,系统将使用有关您的通知类别的信息来决定是否显示通知。

但是,您不需要设置系统范围的类别,并且只有在通知与in中定义的某个类别匹配时才应该这样做 NotificationCompat。

设置锁定屏幕可见性


要控制锁定屏幕中通知中可见的详细程度,请调用setVisibility()并指定以下值之一:

VISIBILITY_PUBLIC 显示通知的完整内容。
VISIBILITY_SECRET 在锁定屏幕上不显示此通知的任何部分。
VISIBILITY_PRIVATE 显示基本信息,例如通知的图标和内容标题,但隐藏通知的完整内容。
当VISIBILITY_PRIVATE被设置时,也可以提供一种隐藏某些细节的通知内容的替代版本。例如,SMS应用程序可能会显示一条通知,显示您有3条新短信,但会隐藏邮件内容和发件人。要提供此备用通知,请首先NotificationCompat.Builder像往常一样创建备用通知。然后将备用通知附加到正常通知中 setPublicVersion()。

但是,用户始终可以最终控制其通知是否在锁定屏幕上可见,甚至可以根据应用的通知渠道控制该通知。

更新通知


要在发出通知后更新此通知,请NotificationManagerCompat.notify()再次呼叫,并向其发送一个通知,其中包含您之前使用的相同ID。如果先前的通知已被取消,则会创建新通知。

您可以选择呼叫, setOnlyAlertOnce()以便您的通知仅在通知第一次出现时才会中断用户(有声音,振动或视觉线索),而不是以后的更新。

警告:Android在更新通知时应用速率限制。如果过于频繁地发布通知更新(许多不到一秒钟),系统可能会删除一些更新。

删除通知


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

用户驳回通知。
用户单击通知,并setAutoCancel()在创建通知时调用 。
您需要cancel()特定的通知ID。此方法还会删除正在进行的通知。
您拨打电话cancelAll(),删除之前发出的所有通知。
如果在使用创建通知时设置超时 setTimeoutAfter(),系统会在指定的持续时间过后取消通知。如果需要,您可以在指定的超时持续时间过去之前取消通知。

消息传递应用的最佳做法


使用此处列出的最佳做法,快速参考为消息传递和聊天应用创建通知时应注意的事项。

使用MessagingStyle
从Android 7.0(API级别24)开始,Android提供专门用于消息传递内容的通知样式模板。使用 NotificationCompat.MessagingStyle 该类,您可以更改通知上显示的多个标签,包括会话标题,其他消息和通知的内容视图。

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

Notification notification = new Notification.Builder(this, CHANNEL_ID)
        .setStyle(new 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该类的通知 以折叠形式显示更多内容。您还可以使用该 addHistoricMessage()方法通过向消息传递相关通知添加历史消息来为对话提供上下文。

使用时NotificationCompat.MessagingStyle:

呼叫MessagingStyle.setConversationTitle()为超过两人的群聊进行设置标题。一个好的会话标题可能是群聊的名称,如果没有特定的名称,则可能是会话参与者的列表。如果没有这个,该消息可能被误认为属于与对话中最近消息的发送者的一对一对话。
使用此MessagingStyle.setData() 方法包括媒体消息,如图像。目前支持模式图像/ *的MIME类型。

使用直接回复
直接回复允许用户内联回复邮件。

用户回复内联回复操作后,使用 MessagingStyle.addMessage()更新 MessagingStyle通知,不要撤消或取消通知。不取消通知允许用户从通知中发送多个回复。
要使内联回复操作与Wear OS兼容,请致电。 Action.WearableExtender.setHintDisplayInlineAction(true)
使用该方法通过向通知添加历史消息来为直接回复对话提供上下文。 addHistoricMessage()

启用智能回复
要启用智能回复,请调用回复操作。当通知桥接到Wear OS设备时,这会导致用户可以使用智能回复响应。智能回复响应由使用 通知提供的上下文的完全监视机器学习模型生成,并且没有数据被上载到因特网以生成响应。 setAllowGeneratedResponses(true)NotificationCompat.MessagingStyle

添加通知元数据
分配通知元数据,以告知系统在设备处于“ 请勿打扰”模式时如何处理应用程序通知。例如,使用 或 方法覆盖“请勿打扰”模式。 addPerson() setCategory(Notification.CATEGORY_MESSAGE)

联系我

QQ:94297366
微信打赏:https://pan.baidu.com/s/1dSBXk3eFZu3mAMkw3xu9KQ

公众号推荐:

【Interface&navigation】创建一个通知(37)

转载于:https://blog.51cto.com/4789781/2153480

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值