// 创建通知渠道(API 26+ 必需)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channelId = "chat_messages"
val channelName = "聊天消息"
val importance = NotificationManager.IMPORTANCE_HIGH
val channel = NotificationChannel(channelId, channelName, importance).apply {
description = "接收来自联系人的即时消息通知"
setShowBadge(true)
enableVibration(true)
vibrationPattern = longArrayOf(100, 200, 100, 300)
lockscreenVisibility = NotificationCompat.VISIBILITY_PRIVATE
}
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
#### 渠道重要性说明
| 重要性等级 | 常量值 | 行为表现 |
|---|---|---|
| 紧急 | `IMPORTANCE_HIGH` | 发出声音、浮动通知、显示在状态栏 |
| 高 | `IMPORTANCE_DEFAULT` | 发出声音、显示在通知栏顶部 |
| 中 | `IMPORTANCE_LOW` | 无声音、显示在通知列表中 |
| 低 | `IMPORTANCE_MIN` | 不显示图标、折叠在底部 |
⚠ 渠道ID一经发布并创建,不要轻易重命名或删除。 如果必须废弃旧渠道,应保留渠道ID并设置重要性为
### 1.4 NotificationManager:通知的发送与取消
`NotificationManager` 是提交和撤销通知的唯一入口。它充当应用进程到系统服务之间的桥梁。
#### 发送通知
IMPORTANCE_NONE,而非直接删除——否则用户之前对该渠道的个性化设置会丢失。
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notificationId = 1001
val notification = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle("新消息")
.setContentText("张三:下午三点会议室见")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.build()
notificationManager.notify(notificationId, notification)
#### 常用 API 速查
| 方法 | 说明 |
|---|---|
| `notify(int id, Notification notification)` | 发送/更新通知;相同id会覆盖 |
| `cancel(int id)` | 取消指定id的通知 |
| `cancelAll()` | 取消当前应用的所有通知 |
| `getActiveNotifications()` | 获取当前显示的通知列表 |
| `areNotificationsEnabled()` | 检查当前应用通知总开关 |
### 1.5 PendingIntent:延迟的交互回调
`PendingIntent` 封装一个 `Intent` 和触发动作,当用户点击通知或操作按钮时由系统代为执行。它允许通知在应用不运行时仍能触发目标组件。
#### 三种获取方式
- **`getActivity()`**:打开 Activity(最常用)
- **`getService()`**:启动 Service(后台任务场景)
- **`getBroadcast()`**:发送 Broadcast(轻量回调)
#### 点击跳转示例
val intent = Intent(this, ChatActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
putExtra("conversation_id", conversationId)
}
// FLAG_IMMUTABLE 是 Android 12+ 的推荐标志
val pendingIntent = PendingIntent.getActivity(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val notification = NotificationCompat.Builder(this, channelId)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.build()
💡 版本兼容要点:Android 12(API 31)开始,所有新建的
### 1.6 调试方法
通知调试主要依赖三种手段:
1. **logcat 过滤**:使用 `adb logcat -s NotificationService` 查看系统服务调度日志
2. **开发者选项**:开启“不保留活动”和“通知历史记录”观察通知存活情况
3. **Shell 注入**:直接通过 adb 发送测试通知,跳过应用 UI
PendingIntent 必须指定 FLAG_IMMUTABLE(除了少数特殊情况如 FLAG_MUTABLE 配合 NotificationCompat.MessagingStyle)。建议默认使用 FLAG_IMMUTABLE 并显式检查 API 级别。
# adb 发送一个即时通知(适用于测试)
adb shell cmd notification post \
--category chat \
--priority high \
--tag test \
--alert_once \
你的包名 1001 "测试标题" "测试内容"
常见错误排查清单
### 1.7 性能与稳定性建议
- **渠道注册位置**:在 `Application.onCreate()` 统一注册所有渠道,避免在 Activity 中重复创建
- **PendingIntent 复用**:相同 intent 应复用 `PendingIntent`,避免创建过多对象导致系统缓存膨胀
- **低耗电注意事项**:频繁更新通知(每秒超过1次)会引起系统背压,导致通知被延迟或丢弃
- **渠道数量限制**:单应用渠道数量建议控制在 5 个以内;超过 10 个会触发系统警告并降低用户体验
- 通知不显示 → 检查渠道是否已创建、通知总开关是否开启
- 点击无响应 → 检查
PendingIntent的FLAG_IMMUTABLE是否遗漏 - 渠道更新无效 → 确认渠道ID是否与已创建的相同;若相同,大部分属性在新安装时才会生效
- 通知图标异常 → 确认
setSmallIcon()使用的是纯透明背景的矢量/位图