第1章 Material Design 通知系统架构

1.1 通知系统架构概述

Material Design 通知系统自 Android 8.0(API 26)引入通知渠道(Notification Channel)后,从原本的全局通知模型演变为“渠道–样式–重要性–分组–摘要”的多层架构。应用通过 NotificationManager 将通知发送至指定渠道,系统根据渠道的重要级别决定是否弹出、声音、震动等行为;通知样式定义内容布局;分组与摘要用于折叠多条通知,提升信息浏览效率。下图展示了核心组件及其交互关系。

Android Material Design 通知系统架构 应用(App) NotificationManager 通知渠道 通知样式 重要级别 分组与摘要 系统 UI 显示 说明:通知渠道是核心配置入口,决定了通知的行为、样式和聚合方式。 应用必须先创建渠道,再通过 NotificationManager 发送通知。

1.2 通知渠道(Notification Channel)

通知渠道是 Android 8.0 引入的强制机制。每个渠道定义了一组通知行为:重要级别、声音、灯光、震动模式、是否显示角标等。用户可在系统设置中独立调整每个渠道的权限。

API 元素说明
NotificationChannel(String id, CharSequence name, int importance)创建渠道对象,id 必须唯一,name 为用户可见的名称,importance 决定通知的打断能力
NotificationManager.createNotificationChannel(…)将渠道注册到系统。多次调用相同 id 会更新已有渠道(部分字段不能降级)
setSound(Uri uri, AudioAttributes attrs)自定义通知提示音
setVibrationPattern(long[] pattern)设置震动模式
setShowBadge(boolean show)是否显示桌面角标

实现流程:在 Application.onCreate() 或启动 Activity 中统一创建所有渠道,保证通知发送前渠道已就绪。

// Kotlin 示例:创建两个通知渠道
val channel1 = NotificationChannel(
    "chat_messages",
    "聊天消息",
    NotificationManager.IMPORTANCE_HIGH
).apply {
    description = "接收即时聊天通知"
    enableVibration(true)
    setShowBadge(true)
}

val channel2 = NotificationChannel(
    "update_notice",
    "更新提醒",
    NotificationManager.IMPORTANCE_DEFAULT
).apply {
    description = "应用更新与维护通知"
    setSound(null, null) // 静音
}

val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel1)
notificationManager.createNotificationChannel(channel2)

1.3 通知样式(Notification Style)

Material Design 提供多种内置样式,适用于不同内容类型。样式通过 NotificationCompat.Builder.setStyle() 设置。

样式类适用场景关键特性
NotificationCompat.BigTextStyle长文本内容展开后显示最多 256 个字符
NotificationCompat.BigPictureStyle图片分享展开后展示大图
NotificationCompat.InboxStyle邮件/消息列表可添加多行摘要
NotificationCompat.MessagingStyle聊天对话支持回复、标记已读等交互
NotificationCompat.MediaStyle媒体播放控制显示播放/暂停、上一首等按钮

1.4 通知重要级别(Importance)

重要级别控制通知的视觉和听觉打断方式。Android 系统将渠道重要性映射为用户可感知的打断级别。

常量值系统行为
IMPORTANCE_NONE0不显示通知,完全静默
IMPORTANCE_MIN1折叠在通知栏底部,无声音/震动
IMPORTANCE_LOW2显示但不发出声音
IMPORTANCE_DEFAULT3显示并发出声音(无震动)
IMPORTANCE_HIGH4弹出 Heads-up 通知,有声音和震动
IMPORTANCE_MAX5(Android 10+)类似 HIGH,但优先级更高

1.5 通知分组与摘要(Group & Summary)

将多条相关通知按组折叠,并提供一条摘要通知展示聚合信息。

  • 分组通知:调用 Builder.setGroup(String groupKey) 为每条通知指定同一 groupKey。
  • 摘要通知:使用 Builder.setGroupSummary(true) 创建,系统会用它代表整组通知。
  • 自动分组:Android 7.0 起系统会自动对来自同一应用的通知分组(基于主题相似性),但建议开发者显式控制。
// 创建两条分组消息
val builder1 = NotificationCompat.Builder(this, "chat_messages")
    .setSmallIcon(R.drawable.ic_message)
    .setContentTitle("张三")
    .setContentText("你好,下午3点开会")
    .setGroup("group_chat")

val builder2 = NotificationCompat.Builder(this, "chat_messages")
    .setSmallIcon(R.drawable.ic_message)
    .setContentTitle("李四")
    .setContentText("收到,会准时参加")
    .setGroup("group_chat")

// 创建摘要通知
val summary = NotificationCompat.Builder(this, "chat_messages")
    .setSmallIcon(R.drawable.ic_group)
    .setContentTitle("聊天消息")
    .setContentText("2条未读消息")
    .setGroup("group_chat")
    .setGroupSummary(true)
    .build()

notificationManager.notify(1, builder1.build())
notificationManager.notify(2, builder2.build())
notificationManager.notify(0, summary)

1.6 调试与验证

开发阶段可使用 adb 命令检查渠道状态和发送测试通知:

# 列出所有通知渠道(指定包名)
adb shell dumpsys notification --package com.example.myapp | grep "Channel"

# 发送一条测试通知(需要 root 或使用 Android 9+ 的 NotificationManager API)
adb shell am broadcast -a android.intent.action.NOTIFY --es channel_id chat_messages --es title "调试" --es text "测试内容"

# 在模拟器中手动设置渠道重要性
Settings → Apps & notifications → [应用名] → App notifications → 选择渠道 → 调整

1.7 常见错误与避坑

错误场景原因解决方案
通知不显示、无声音未创建渠道或重要性设为 MIN/NONE检查 createNotificationChannel 调用是否在通知发送前完成
升级应用后渠道设置被重置渠道 id 改变或使用旧 id 更新时部分属性不可降级保持渠道 id 稳定;如需修改重要性,使用 setImportance 并重新创建
分组通知未折叠未设置 setGroup 或摘要通知缺失确保所有组内通知使用相同 groupKey,并发送一条摘要通知
Heads-up 通知不弹出渠道重要性低于 IMPORTANCE_HIGH 或用户手动关闭设置为 IMPORTANCE_HIGH,且当前不在“请勿打扰”模式

1.8 性能与稳定性优化

  • 渠道数量控制:每个应用通常不超过 10 个渠道,过多会导致系统 UI 和设置页面混乱。
  • 延迟创建:只在首次需要发送通知时才创建渠道,避免冷启动性能开销。
  • 避免频繁删除/重建:渠道删除后,历史通知将丢失;重建渠道应优先使用更新接口。
  • 合理使用样式:大图样式加载时应使用压缩过的位图,防止 OOM。
  • 分组记忆:使用 NotificationCompat.Builder.setSortKey 和 setGroupAlertBehavior 精细控制组内通知的排序和提醒方式。
💡 最佳实践:在应用启动时同步创建所有渠道,并在设置界面提供渠道跳转链接(Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)),提升用户可控性。