Android Notification

Channel(通知渠道)

理解 Android Notification 的 Channel(通知渠道),可以把它理解成:

Channel 是系统给通知分类管理的一个“通道/类别”,用户可以针对这个类别单独控制通知行为。
它不是消息本身,也不是发送通道,而是通知规则的集合
举个现实例子:
一个 App 可能有:

微信
 |
 |-- 聊天消息通知 Channel
 |
 |-- 服务通知 Channel
 |
 |-- 视频号通知 Channel
 |
 |-- 文件下载通知 Channel

用户可以:

  • 关闭「视频号通知」
  • 保留「聊天消息通知」
  • 把「重要消息」设置成响铃
  • 把「营销通知」设置成静音

这就是 Channel 的意义。


以前 Android 7.0 以前

通知只有一个总开关:

App
 |
 |-- Notification
 |-- Notification
 |-- Notification

系统只能:

允许这个App通知
关闭这个App通知

粒度比较粗。


Android 8.0以后

变成:

App
 |
 |-- Channel A
 |      |
 |      |-- Notification 1
 |      |-- Notification 2
 |
 |-- Channel B
        |
        |-- Notification 3
        |-- Notification 4

系统管理的是 Channel。

比如:

val channel = NotificationChannel(
    "download",
    "下载通知",
    NotificationManager.IMPORTANCE_LOW
)

表示:

创建一个叫:

id: download
名字: 下载通知
重要级别: 低

的通知类别。

然后:

NotificationCompat.Builder(
    context,
    "download"
)

意思是:

我要发送一条属于 download 这个类别的通知。


Channel 里面保存什么?

比如:

NotificationChannel(
    "task",
    "任务提醒",
    IMPORTANCE_HIGH
)

里面包含:

属性 作用
channelId 唯一标识
name 给用户看的名字
importance 重要程度
声音 响铃方式
震动 是否震动
灯光 LED
是否显示角标 badge

例如:

任务提醒 Channel

重要程度: 高
声音: 微信提示音
震动: 开启

所有属于这个 Channel 的通知都继承这个规则。


为什么代码不能修改 Channel?

因为 Channel 是给用户控制的。

比如:

你的 App 创建:

新闻通知 Channel
重要级别 HIGH

用户觉得烦:

设置
  ↓
App通知
  ↓
新闻通知
  ↓
关闭声音

此时:

App升级:

channel.importance = HIGH

系统不会允许你强制改回来。

否则 App 可以偷偷把用户关闭的通知重新打开。

所以:

Channel 创建后,部分属性由用户接管。


结合你之前看的代码

比如:

private const val CHANNEL_ID = "cron_job_channel"

然后:

createNotificationChannel(
    NotificationChannel(
        CHANNEL_ID,
        "定时任务提醒",
        IMPORTANCE_HIGH
    )
)

相当于:

告诉系统:

我这个App有一个通知分类:

cron_job_channel

名字:
定时任务提醒

级别:
重要

之后:

NotificationCompat.Builder(
    context,
    "cron_job_channel"
)

表示:

我要发一个定时任务提醒通知
请按照这个Channel的规则展示

所以一句话总结:

Notification 是一条消息,Channel 是这类消息的展示规则。Android 8.0以后,所有通知必须归属于某个 Channel,系统和用户通过 Channel 管理通知行为。

你前面看到的“新增 channelId 避免老用户沿用 DEFAULT 渠道”,本质就是:

旧 Channel 的配置已经被系统和用户保存了,换新的 Channel 相当于创建一个新的通知分类,让新的通知规则重新生效。

如何编码

要看 Android 版本

1. Android 8.0(API 26)及以上:必须创建 NotificationChannel

从 Android 8.0 开始,通知必须绑定一个 NotificationChannel(通知渠道),否则通知不会显示。

流程:

val channel = NotificationChannel(
    "default_channel_id",
    "默认通知",
    NotificationManager.IMPORTANCE_DEFAULT
)

notificationManager.createNotificationChannel(channel)

然后创建通知时指定渠道:

val notification = NotificationCompat.Builder(context, "default_channel_id")
    .setSmallIcon(R.drawable.ic_notify)
    .setContentTitle("标题")
    .setContentText("内容")
    .build()

notificationManager.notify(1, notification)

这里:

NotificationCompat.Builder(context, "default_channel_id")

第二个参数就是 channelId

如果这个 channelId 没有提前创建:

  • Android 8.0+:通知不会正常显示
  • Android 7.1 及以下:忽略 channel,不影响

2. Android 7.1(API 25)及以下:没有渠道概念

直接:

NotificationCompat.Builder(context)

即可。

所以一般兼容写法:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    val channel = NotificationChannel(
        CHANNEL_ID,
        "通知",
        NotificationManager.IMPORTANCE_DEFAULT
    )
    notificationManager.createNotificationChannel(channel)
}

val notification = NotificationCompat.Builder(context, CHANNEL_ID)
    .setSmallIcon(R.drawable.ic_notify)
    .build()

3. Android 13(API 33)新增通知权限

即使渠道创建了,Android 13+ 还需要:

<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

并且用户授权:

requestPermissions(
    arrayOf(Manifest.permission.POST_NOTIFICATIONS),
    100
)

否则:

NotificationManager.notify()

执行了,也可能不展示。


结合你前面看的代码:

notificationManager.notify(
    NOTIFICATION_TAG,
    notificationId,
    notification
)

这行的作用就是:

把已经构建好的 Notification 提交给系统通知管理器,让系统尝试展示。

但是它能不能真正弹出来,需要满足:

  1. Android 8+
    ✅ 已创建对应 NotificationChannel
    ✅ Builder 使用同一个 channelId

  2. Android 13+
    ✅ 有 POST_NOTIFICATIONS 权限

  3. 用户没有关闭该 App 通知权限

  4. 对应渠道没有被用户关闭

你前面提到的:

老用户升级后继续沿用旧 DEFAULT 渠道

其实就是 NotificationChannel 一旦创建,用户可以修改它的级别,代码无法再提升

例如:

第一次:

NotificationChannel(
    "default",
    "默认",
    IMPORTANCE_LOW
)

用户使用后把它保持为低重要性。

后来版本升级:

NotificationChannel(
    "default",
    "默认",
    IMPORTANCE_HIGH
)

不会生效。

所以只能:

NotificationChannel(
    "new_channel",
    "任务提醒",
    IMPORTANCE_HIGH
)

换一个新的 channelId,让系统重新创建渠道。你之前看到的注释就是这个意思。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容