通知可在应用未使用时及时提供有关应用中事件的简短信息。本文档介绍了如何创建具有各种功能的通知。有关通知如何在 Android 上显示的说明,请参阅通知概览。如需查看使用通知的示例代码,请参阅 GitHub 上的 People 示例。
本页中的代码使用 AndroidX 库中的 NotificationCompat
API。通过这些 API,您可以添加仅在较新版本 Android 上可用的功能,同时仍能向后兼容 Android 9(API 级别 28)。但是,某些功能(例如内嵌回复操作)在早期版本中会导致空操作。
添加 AndroidX Core 库
虽然使用 Android Studio 创建的大多数项目都包含使用 NotificationCompat
所必需的依赖项,但请验证您的模块级 build.gradle
文件是否包含以下依赖项:
Groovy
dependencies { implementation "androidx.core:core:2.2.0" }
Kotlin
dependencies { implementation("androidx.core:core-ktx:2.2.0") }
创建基本通知
最基本、最紧凑的形式(也称为“折叠形式”)的通知会显示一个图标、标题和少量文本内容。本部分介绍了如何创建一条通知,让用户可以点按该通知以启动应用中的 activity。
如需详细了解通知的各个部分,请参阅通知剖析。
声明运行时权限
Android 13(API 级别 33)及更高版本支持通过应用发布非豁免(包括前台服务 [FGS])通知的运行时权限。
您需要在应用的清单文件中声明的权限位于以下代码段中:
<manifest ...> <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <application ...> ... </application> </manifest>
如需详细了解运行时权限,请参阅通知运行时权限。
设置通知内容
首先,请使用 NotificationCompat.Builder
对象设置通知的内容和渠道。以下示例展示了如何创建包含以下信息的通知:
小图标,通过
setSmallIcon()
设置。这是所必需的唯一用户可见内容。标题,通过
setContentTitle()
设置。正文文本,通过
setContentText()
设置。通知优先级,通过
setPriority()
设置。优先级决定了 Android 7.1 及更低版本上的通知的干扰程度。对于 Android 8.0 及更高版本,请改为设置渠道重要性,如下一部分所示。
Kotlin
var builder = NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(R.drawable.notification_icon) .setContentTitle(textTitle) .setContentText(textContent) .setPriority(NotificationCompat.PRIORITY_DEFAULT)
Java
NotificationCompat.Builder builder = 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()
添加样式模板来启用可展开的通知。例如,以下代码会创建一个更大的文本区域:
Kotlin
var builder = NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(R.drawable.notification_icon) .setContentTitle("My notification") .setContentText("Much longer text that cannot fit one line...") .setStyle(NotificationCompat.BigTextStyle() .bigText("Much longer text that cannot fit one line...")) .setPriority(NotificationCompat.PRIORITY_DEFAULT)
Java
NotificationCompat.Builder builder = 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);
如需详细了解其他大型通知样式,包括如何添加图片和媒体播放控件,请参阅创建展开式通知。
创建渠道并设置重要性
您需要先将 NotificationChannel
的实例传递给 createNotificationChannel()
,在系统中注册应用的通知渠道,然后才能在 Android 8.0 及更高版本上发送通知。以下代码被 SDK_INT
版本中的条件阻止:
Kotlin
private fun createNotificationChannel() { // Create the NotificationChannel, but only on API 26+ because // the NotificationChannel class is 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) } }
Java
private void createNotificationChannel() { // Create the NotificationChannel, but only on API 26+ because // the NotificationChannel class is 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 及更低版本,如上例所示。
虽然您必须设置通知的重要性或优先级,如以下示例所示,但系统不保证您会获得提醒行为。在某些情况下,系统可能会根据其他因素更改重要性级别,并且用户可以随时重新定义给定渠道的重要性级别。
如需详细了解不同级别的含义,请参阅通知重要性级别。
设置通知的点按操作
每个通知都必须响应点按操作,通常是为了打开应用中与通知对应的 activity。为此,请指定使用 PendingIntent
对象定义的内容 intent,并将其传递给 setContentIntent()
。
以下代码段展示了如何创建基本 intent,以在用户点按通知时打开 activity:
Kotlin
// 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, PendingIntent.FLAG_IMMUTABLE) 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 fires when the user taps the notification. .setContentIntent(pendingIntent) .setAutoCancel(true)
Java
// 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, PendingIntent.FLAG_IMMUTABLE); NotificationCompat.Builder builder = 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 fires when the user taps the notification. .setContentIntent(pendingIntent) .setAutoCancel(true);
此代码会调用 setAutoCancel()
,它会在用户点按通知时自动移除通知。
上例中显示的 setFlags()
方法在用户使用通知打开您的应用后保留了预期的导航体验。您可能需要根据要启动的 activity 类型(可以是以下类型之一)来使用它:
专门用于响应通知的 activity。用户在正常使用应用期间不会无缘无故地导航到此 activity,因此该 activity 会启动新任务,而不是添加到应用的现有任务和返回堆栈。这是在上述示例中创建的 intent 类型。
应用的常规应用流程中存在的 Activity。在这种情况下,启动 activity 会创建一个返回堆栈,以便保留用户对返回和向上按钮的预期。
如需详细了解配置通知 intent 的不同方法,请参阅从通知启动 activity。
显示通知
如需显示通知,请调用 NotificationManagerCompat.notify()
,并向其传递通知的唯一 ID 和 NotificationCompat.Builder.build()
的结果。具体可见以下示例:
Kotlin
with(NotificationManagerCompat.from(this)) { if (ActivityCompat.checkSelfPermission( this@MainActivity, Manifest.permission.POST_NOTIFICATIONS ) != PackageManager.PERMISSION_GRANTED ) { // TODO: Consider calling // ActivityCompat#requestPermissions // here to request the missing permissions, and then overriding // public fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, // grantResults: IntArray) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. return@with } // notificationId is a unique int for each notification that you must define. notify(NOTIFICATION_ID, builder.build()) }
Java
with(NotificationManagerCompat.from(this)) { if (ActivityCompat.checkSelfPermission( this@MainActivity, Manifest.permission.POST_NOTIFICATIONS ) != PackageManager.PERMISSION_GRANTED ) { // TODO: Consider calling // ActivityCompat#requestPermissions // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. return } // notificationId is a unique int for each notification that you must define. notify(NOTIFICATION_ID, builder.build()) }
保存您传递给 NotificationManagerCompat.notify()
的通知 ID,因为当您想要更新或移除通知时需要用到。
此外,如需在搭载 Android 13 及更高版本的设备上测试基本通知,请手动开启通知或创建请求通知的对话框。
添加操作按钮
通知最多可以提供三个操作按钮,以便用户快速响应,例如暂停提醒或回复短信。但这些操作按钮不得重复用户点按通知时执行的操作。
如需添加操作按钮,请将 PendingIntent
传递给 addAction()
方法。这就像是设置通知的默认点按操作,除了启动 activity 之外,您可以执行其他操作,例如启动在后台执行作业的 BroadcastReceiver
,这样该操作就不会中断已经打开的应用。
例如,以下代码展示了如何将广播发送到特定接收器:
Kotlin
val ACTION_SNOOZE = "snooze" 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)
Java
String ACTION_SNOOZE = "snooze" 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 builder = 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)中引入的直接回复操作可让用户直接在通知中输入文本。然后,文本会在不打开 activity 的情况下传递给您的应用。例如,您可以使用直接回复操作,让用户能够在通知中回复短信或更新任务列表。
直接回复操作在通知中显示为用于打开文本输入的附加按钮。用户完成输入后,系统会将文本响应附加到您为通知操作指定的 intent,并将该 intent 发送到您的应用。
添加回复按钮
如需创建支持直接回复的通知操作,请按以下步骤操作:
- 创建可添加到通知操作的
RemoteInput.Builder
实例。此类的构造函数接受系统用作文本输入键的字符串。您的应用稍后使用该键来检索输入的文本。Kotlin
// 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() }
Java
// 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
。Kotlin
// Build a PendingIntent for the reply action to trigger. var replyPendingIntent: PendingIntent = PendingIntent.getBroadcast(applicationContext, conversation.getConversationId(), getMessageReplyIntent(conversation.getConversationId()), PendingIntent.FLAG_UPDATE_CURRENT)
Java
// Build a PendingIntent for the reply action to trigger. PendingIntent replyPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), conversation.getConversationId(), getMessageReplyIntent(conversation.getConversationId()), PendingIntent.FLAG_UPDATE_CURRENT);
- 使用
addRemoteInput()
将RemoteInput
对象附加到操作。Kotlin
// 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()
Java
// 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();
- 对通知应用操作并发出通知。
Kotlin
// 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) }
Java
// Build the notification and add the action. Notification newMessageNotification = new 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. NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); notificationManager.notify(notificationId, newMessageNotification);
当用户触发通知操作时,系统会提示用户输入回复,如图 4 所示。
从回复中检索用户输入
如需从通知的回复界面接收用户输入,请调用 RemoteInput.getResultsFromIntent()
,并向其传递 BroadcastReceiver
收到的 Intent
:
Kotlin
private fun getMessageText(intent: Intent): CharSequence? { return RemoteInput.getResultsFromIntent(intent)?.getCharSequence(KEY_TEXT_REPLY) }
Java
private CharSequence getMessageText(Intent intent) { Bundle remoteInput = RemoteInput.getResultsFromIntent(intent); if (remoteInput != null) { return remoteInput.getCharSequence(KEY_TEXT_REPLY); } return null; }
处理文本后,通过调用 NotificationManagerCompat.notify()
并使用相同的 ID 和标记(如果使用的话)更新通知。如需隐藏直接回复界面,并向用户确认他们的回复已正确接收和处理,您必须这样做。
Kotlin
// 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) }
Java
// 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()
将回复附加到通知底部。不过,如果您要构建即时通讯应用,请创建消息式通知,并将新消息附加到对话中。
如需了解有关即时通讯应用通知的更多建议,请参阅即时通讯应用最佳实践部分。
添加进度条
通知可以包含动画形式的进度指示器,向用户显示正在进行的操作状态。
如果您可以估算操作在任何时间的完成进度,请调用 setProgress(max, progress,
false)
以使用指示符的“确定性”形式(如图 5 所示)。第一个参数是“complete”值,例如 100。第二个因素是完成程度。最后一个表示这是一个确定性进度条。
随着操作的继续,持续使用更新后的 progress
值调用 setProgress(max, progress,
false)
并重新发出通知,如以下示例所示。
Kotlin
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 that tracks the progress here. // Usually, this is 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 once more to remove the progress bar. builder.setContentText("Download complete") .setProgress(0, 0, false) notify(notificationId, builder.build()) }
Java
... NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID); builder.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; builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false); notificationManager.notify(notificationId, builder.build()); // Do the job that tracks the progress here. // Usually, this is 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 once more to remove the progress bar. builder.setContentText("Download complete") .setProgress(0,0,false); notificationManager.notify(notificationId, builder.build());
操作结束时,progress
必须等于 max
。您可以离开进度条以显示操作已完成,也可以将其移除。无论是哪种情况,都请更新通知文本以显示操作已完成。如需移除进度条,请调用 setProgress(0, 0, false)
。
如需显示不确定的进度条(不指示完成百分比的进度条),请调用 setProgress(0, 0, true)
。结果是,指示器的样式与前面的进度条相同,只不过它是一个不指示完成的连续动画。在您调用 setProgress(0, 0, false)
之前,进度动画会一直运行,然后更新通知以移除 activity 指示器。
请记得更改通知文本,以表明操作已完成。
设置系统范围的类别
Android 使用预定义的系统范围类别来确定当用户启用勿扰模式时,是否发出给定通知干扰用户。
如果您的通知属于 NotificationCompat
中定义的通知类别之一(例如 CATEGORY_ALARM
、CATEGORY_REMINDER
、CATEGORY_EVENT
或 CATEGORY_CALL
),请通过将相应类别传递给 setCategory()
进行声明:
Kotlin
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)
Java
NotificationCompat.Builder builder = 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);
系统会根据这些有关通知类别的信息来决定是否在设备处于“勿扰”模式时显示通知。但是,您无需设置系统范围的类别。只有当您的通知与 NotificationCompat
中定义的某个类别匹配时,您才应执行此操作。
显示紧急消息
您的应用可能需要显示紧急的时效性消息,例如来电或响铃的闹钟。在这些情况下,您可以将全屏 intent 与通知相关联。
调用通知后,用户会看到以下某种内容,具体取决于设备的锁定状态:
- 如果用户的设备处于锁定状态,系统会显示全屏 activity,并覆盖锁定屏幕。
- 如果用户的设备处于解锁状态,通知会以展开形式显示,其中包含用于处理或关闭通知的选项。
以下代码段演示了如何将通知与全屏 intent 相关联:
Kotlin
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)
Java
Intent fullScreenIntent = new Intent(this, ImportantActivity.class); PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(this, 0, fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(R.drawable.notification_icon) .setContentTitle("My notification") .setContentText("Hello World!") .setPriority(NotificationCompat.PRIORITY_DEFAULT) .setFullScreenIntent(fullScreenPendingIntent, true);
设置锁定屏幕公开范围
如需控制锁定屏幕中通知的详细可见信息,请调用 setVisibility()
并指定以下值之一:
VISIBILITY_PUBLIC
:在锁定屏幕上显示通知的完整内容。VISIBILITY_SECRET
:锁定屏幕上不会显示通知的任何部分。VISIBILITY_PRIVATE
:锁定屏幕上仅显示基本信息,如通知图标和内容标题。未显示通知的完整内容。
设置 VISIBILITY_PRIVATE
时,您还可以提供隐藏某些详细信息的备用版本通知内容。例如,短信应用可能会显示一条通知,指出“您有 3 条新短信”,但隐藏了短信内容和发送者。如需提供此备用通知,请先照常使用 NotificationCompat.Builder
创建备用通知。然后,使用 setPublicVersion()
将备用通知附加到普通通知中。
请注意,用户始终可以最终控制其通知是否显示在锁定屏幕上,并且可以根据应用的通知渠道控制通知。
更新通知
如需在发出通知后对其进行更新,请再次调用 NotificationManagerCompat.notify()
,并向其传递您之前使用的相同 ID。如果之前的通知已关闭,系统会改为创建新通知。
您可以选择调用 setOnlyAlertOnce()
,这样您的通知只会在用户首次出现时通过声音、振动或视觉提示来打断用户,而不适用于后续更新。
移除通知
除非发生以下情况之一,否则通知仍然可见:
- 用户关闭通知。
- 如果您在创建通知时调用了
setAutoCancel()
,用户便会点按该通知。 - 您可以针对特定通知 ID 调用
cancel()
。此方法还会删除持续性通知。 - 您调用了
cancelAll()
方法,该方法将移除之前发出的所有通知。 - 如果您在创建通知时使用
setTimeoutAfter()
设置了超时,则会经过指定的时长。如果需要,您可以在指定的超时时长过去之前取消通知。
有关即时通讯应用的最佳做法
为即时通讯和聊天应用创建通知时,请考虑此处列出的最佳实践。
使用 MessagingStyle
从 Android 7.0(API 级别 24)开始,Android 提供了专用于消息内容的通知样式模板。使用 NotificationCompat.MessagingStyle
类,您可以更改在通知中显示的多个标签,包括会话标题、其他消息和通知的内容视图。
以下代码段演示了如何使用 MessagingStyle
类自定义通知的样式。
Kotlin
val user = Person.Builder() .setIcon(userIcon) .setName(userName) .build() val notification = NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("2 new messages with $sender") .setContentText(subject) .setSmallIcon(R.drawable.new_message) .setStyle(NotificationCompat.MessagingStyle(user) .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getPerson()) .addMessage(messages[2].getText(), messages[2].getTime(), messages[2].getPerson()) ) .build()
Java
Person user = new Person.Builder() .setIcon(userIcon) .setName(userName) .build(); Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("2 new messages with " + sender) .setContentText(subject) .setSmallIcon(R.drawable.new_message) .setStyle(new NotificationCompat.MessagingStyle(user) .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getPerson()) .addMessage(messages[2].getText(), messages[2].getTime(), messages[2].getPerson()) ) .build();
从 Android 9.0(API 级别 28)开始,还需要使用 Person
类才能优化通知及其头像的呈现方式。
使用 NotificationCompat.MessagingStyle
时,请执行以下操作:
- 调用
MessagingStyle.setConversationTitle()
,为超过两个人的群聊设置标题。一个好的会话标题可以是群聊的名称,如果没有名称,可以是会话的参与者列表。否则,消息可能会被误认为属于与会话中最新消息的发送者的一对一对话。 - 使用
MessagingStyle.setData()
方法包含图片等媒体消息。支持模式 image/* 的 MIME 类型。
使用直接回复
直接回复可让用户以内嵌方式回复消息。
- 当用户使用内嵌回复操作回复后,请使用
MessagingStyle.addMessage()
更新MessagingStyle
通知,并且不要撤消或取消通知。不取消通知可让用户通过通知发送多次回复。 - 如需使内嵌回复操作与 Wear OS 兼容,请调用
Action.WearableExtender.setHintDisplayInlineAction(true)
。 - 通过向通知添加历史消息,使用
addHistoricMessage()
方法为直接回复对话提供上下文。
启用智能回复
- 如需启用智能回复,请对回复操作调用
setAllowGeneratedResponses(true)
。这样,当通知桥接到 Wear OS 设备时,用户就可以使用智能回复响应。智能回复响应由完全在手表上的机器学习模型使用NotificationCompat.MessagingStyle
通知提供的上下文生成,不会将数据上传到互联网来生成响应。
添加通知元数据
- 分配通知元数据,以告知系统当设备处于
Do Not Disturb mode
状态时如何处理应用通知。例如,使用addPerson()
或setCategory(Notification.CATEGORY_MESSAGE)
方法替换“勿扰”模式。