创建和管理通知渠道

从 Android 8.0(API 级别 26)开始,必须为所有通知分配渠道。对于每个渠道,您都可以设置应用于该渠道中所有通知的视觉和听觉行为。用户可以更改这些设置,并决定应用中的哪些通知渠道可以具有侵扰性或可见。

请观看以下视频,简要了解 Android 8.0 中的渠道和其他通知功能。

系统设置中会针对每个应用提供通知渠道的用户设置,如图 1 所示。

图 1:时钟应用及该应用的某个渠道的通知设置。

创建通知渠道后,您便无法更改通知行为。此时,用户拥有完全控制权。不过,您仍然可以更改频道的名称和说明。

为需要发送的每种通知类型创建一个渠道。您还可以创建通知渠道来反映用户做出的选择。例如,您可以为用户在即时通讯应用中创建的每个会话组设置单独的通知渠道。

当您以 Android 8.0(API 级别 26)或更高版本为目标平台时,必须实现一个或多个通知渠道。如果您的 targetSdkVersion 设置为 25 或更低,当您的应用在 Android 8.0(API 级别 26)或更高版本上运行时,其行为与在搭载 Android 7.1(API 级别 25)或更低版本的设备上运行时相同。

创建通知渠道

如需创建通知渠道,请按以下步骤操作:

  1. 使用唯一的频道 ID、用户可见的名称和重要性级别构建 NotificationChannel 对象。

  2. (可选)使用 setDescription() 指定用户在系统设置中看到的说明。

  3. 通过将通知渠道传递给 createNotificationChannel() 来注册通知渠道。

以下示例展示了如何创建和注册通知渠道:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    // Create the NotificationChannel.
    val importance = NotificationManager.IMPORTANCE_DEFAULT
    val mChannel = NotificationChannel(CHANNEL_ID, name, importance)
    mChannel.description = descriptionText
    // Register the channel with the system. You can't change the importance
    // or other notification behaviors after this.
    val notificationManager =
        context.getSystemService(NotificationManager::class.java)
    notificationManager?.createNotificationChannel(mChannel)
}

使用原始值重新创建现有通知渠道不会执行任何操作,因此在启动应用时可以安全地调用此代码。

默认情况下,发布到给定渠道的所有通知都使用 NotificationManagerCompat 类中的重要性级别(例如 IMPORTANCE_DEFAULT 或 IMPORTANCE_HIGH)定义的视觉和听觉行为。如需详细了解重要程度级别,请参阅下一部分。

如果您想进一步自定义渠道的默认通知行为,可以对 NotificationChannel 调用 enableLights()、setLightColor() 和 setVibrationPattern() 等方法。请注意,创建渠道后,您便无法更改这些设置,并且用户对这些行为是否处于活跃状态拥有最终控制权。

您还可以通过调用 createNotificationChannels() 在单个操作中创建多个通知渠道。

设置重要性级别

渠道重要性会影响在渠道中发布的所有通知的中断级别。在 NotificationChannel 构造函数中指定重要性级别,使用五个重要性级别之一,范围从 IMPORTANCE_NONE(0) 到 IMPORTANCE_HIGH(4)。

如需支持搭载 Android 7.1(API 级别 25)或更低版本的设备,您还必须使用 NotificationCompat 类中的优先级常量,为每条通知调用 setPriority()。

重要性 (NotificationManager.IMPORTANCE_*) 和优先级 (NotificationCompat.PRIORITY_*) 常量会映射到用户可见的重要性选项,如下表所示。

用户可见的重要性级别 重要性(Android 8.0 及更高版本) 优先级(Android 7.1 及更低版本)
紧急
发出提示音,并以浮动通知的形式显示。
IMPORTANCE_HIGH PRIORITY_HIGH 或 PRIORITY_MAX
高
发出提示音。
IMPORTANCE_DEFAULT PRIORITY_DEFAULT
中
不发出提示音。
IMPORTANCE_LOW PRIORITY_LOW
低
无提示音,且不会在状态栏中显示。
IMPORTANCE_MIN PRIORITY_MIN
无
不发出提示音,也不会在状态栏或通知栏中显示。
IMPORTANCE_NONE N/A

无论重要程度如何,所有通知都会在非干扰性的系统界面位置显示,例如,显示在抽屉式通知栏中,以及在启动器图标上作为标志显示(但您可以修改通知标志的外观)。

将渠道提交到 NotificationManager 后,您将无法更改重要性级别。不过,用户可以随时更改您的应用渠道的偏好设置。

如需了解如何选择适当的优先级,请参阅通知设计指南中的“优先级”。

读取通知渠道设置

用户可以修改通知渠道的设置,包括振动和提醒声音等行为。如果您想了解用户对通知渠道应用的设置,请按以下步骤操作:

  1. 通过调用 getNotificationChannel() 或 getNotificationChannels() 获取 NotificationChannel 对象。

  2. 查询特定渠道设置,例如 getVibrationPattern()、getSound() 和 getImportance()。

如果您检测到某个渠道设置会阻止应用的预期行为,可以建议用户更改该设置,并提供一个用于打开渠道设置的操作,如下一部分所示。

打开通知渠道设置

创建通知渠道后,您无法以编程方式更改通知渠道的视觉和听觉行为。只有用户可以从系统设置中更改渠道行为。为了让用户能够快速访问这些通知设置,请在应用的设置界面中添加一个用于打开这些系统设置的项。

您可以使用采用 ACTION_CHANNEL_NOTIFICATION_SETTINGS 操作的 Intent 打开通知渠道的系统设置。

例如,以下示例代码展示了如何将用户重定向到通知渠道的设置:

val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS).apply {
    putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
    putExtra(Settings.EXTRA_CHANNEL_ID, CHANNEL_ID)
}
Button(onClick = {
    context.startActivity(intent)
}) {
    Text("Open Channel Settings")
}

请注意,该 intent 需要两个 extra,分别用于指定应用的软件包名称(也称为应用 ID)和要修改的渠道。

删除通知渠道

您可以通过调用 deleteNotificationChannel() 删除通知渠道。以下示例代码演示了如何完成此过程:

val notificationManager =
    ContextCompat.getSystemService<NotificationManager>(context, NotificationManager::class.java)
notificationManager?.deleteNotificationChannel(channelId)

创建通知渠道分组

如果您想进一步整理频道在设置界面中的显示方式,可以创建频道组。如果您的应用支持多个用户账号,则建议您使用此功能,因为这样您就可以为每个账号创建一个通知渠道分组。渠道组可帮助用户区分和控制多个名称相同的通知渠道。

图 2. 包含个人账号和工作账号分组的通知渠道设置。

例如,社交网络应用可能支持个人账号和工作账号。在这种情况下,每个账号可能需要多个具有相同功能和名称的通知渠道,例如:

  • 拥有两个频道的个人账号:

    • 新评论

    • 帖子推荐

  • 拥有两个频道的商家账号:

    • 新评论

    • 帖子推荐

将通知渠道按账号分组,可让用户区分这些渠道。

每个通知渠道组都需要一个 ID(该 ID 在您的软件包中必须是唯一的)以及一个用户可见的名称。以下代码段演示了如何创建通知渠道分组。

fun createNotificationChannelGroup(context: Context, groupId: String, groupName: String) {
    val notificationManager =
        ContextCompat.getSystemService(context, NotificationManager::class.java)
    notificationManager?.createNotificationChannelGroup(NotificationChannelGroup(groupId, groupName))
}

创建新群组后,您可以调用 setGroup() 将新的 NotificationChannel 对象与该群组相关联。

将渠道提交到通知管理器后,您便无法更改通知渠道与群组之间的关联。