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 提交给系统通知管理器,让系统尝试展示。
但是它能不能真正弹出来,需要满足:
Android 8+
✅ 已创建对应 NotificationChannel
✅ Builder 使用同一个 channelIdAndroid 13+
✅ 有 POST_NOTIFICATIONS 权限用户没有关闭该 App 通知权限
对应渠道没有被用户关闭
你前面提到的:
老用户升级后继续沿用旧 DEFAULT 渠道
其实就是 NotificationChannel 一旦创建,用户可以修改它的级别,代码无法再提升。
例如:
第一次:
NotificationChannel(
"default",
"默认",
IMPORTANCE_LOW
)
用户使用后把它保持为低重要性。
后来版本升级:
NotificationChannel(
"default",
"默认",
IMPORTANCE_HIGH
)
不会生效。
所以只能:
NotificationChannel(
"new_channel",
"任务提醒",
IMPORTANCE_HIGH
)
换一个新的 channelId,让系统重新创建渠道。你之前看到的注释就是这个意思。