16、权限与通知:通知权限、POST_NOTIFICATIONS、通知渠道权限
通知权限,说实话,是 Android 13(API 33)之后变化最大的一个运行时权限。以前我们发通知,只要建个 NotificationManager 就能弹,用户根本拦不住。现在不行了——你得先问用户「我能不能给你发通知」。
我个人习惯把通知权限看作「用户对 App 骚扰程度的容忍阈值」。你想想看,如果一个天气 App 天天弹广告通知,用户大概率会关掉它。所以,处理好通知权限,不仅是合规问题,更是用户体验问题。
16.1 通知权限的演进史
先简单回顾一下历史。Android 12 及之前,通知权限是隐式的——只要 App 有前台服务或者用户主动交互,就能发通知。但 Google 发现,很多 App 滥用这个能力,导致用户被大量垃圾通知轰炸。
所以 Android 13 引入了 POST_NOTIFICATIONS 权限。这是一个 Normal 级别的运行时权限,需要用户在运行时授权。
关键点:
- Android 13+:必须声明
POST_NOTIFICATIONS权限 - Android 12 及以下:不需要此权限,但建议适配
- 如果用户拒绝,App 将无法发送任何通知(包括前台服务通知)
我记得第一次适配这个权限时,踩了个坑——我的 App 有个前台服务,用户拒绝通知权限后,前台服务的持续通知直接消失了。嗯,这里要注意:前台服务的通知也受此权限管控。
16.2 声明与请求通知权限
首先,在 AndroidManifest.xml 中声明权限:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
然后,在代码中请求权限。和普通运行时权限一样:
// 检查权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
!= PackageManager.PERMISSION_GRANTED) {
// 请求权限
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.POST_NOTIFICATIONS},
NOTIFICATION_PERMISSION_REQUEST_CODE);
}
但这里有个坑——用户拒绝后,系统不会再次弹窗。我曾经遇到一个用户反馈:「我点了拒绝,然后 App 再也不问我要通知权限了。」这就是 Android 的权限机制:用户拒绝一次后,再次请求会直接回调 onRequestPermissionsResult 返回拒绝。
避坑指南:
我曾经在项目中遇到一个 Bug:用户拒绝通知权限后,App 的前台服务崩溃了。原因是前台服务需要显示一个持续通知,但权限被拒导致通知无法创建。解决方案是:在权限被拒时,降级处理——比如不启动前台服务,或者使用其他方式提示用户。
16.3 通知渠道权限
通知渠道(Notification Channel)是 Android 8.0(API 26)引入的。它允许用户对不同类型的通知进行精细控制。比如,一个社交 App 可以有「私信通知」「点赞通知」「系统通知」三个渠道,用户可以单独关闭某个渠道。
但注意:通知渠道的权限和 POST_NOTIFICATIONS 权限是两回事。
POST_NOTIFICATIONS:控制 App 能否发通知(全局开关)- 通知渠道:控制某个类型的通知是否显示(局部开关)
用户可以在系统设置中,对每个渠道单独设置:
- 允许通知
- 静默通知(无声音、无震动)
- 完全关闭
我个人建议:不要创建太多渠道。我见过一个 App 创建了 20 多个渠道,用户根本分不清。一般来说,3-5 个渠道就足够了。
16.4 创建通知渠道的最佳实践
创建通知渠道的代码很简单:
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID,
"渠道名称",
NotificationManager.IMPORTANCE_HIGH
);
channel.setDescription("渠道描述");
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
这里有个细节:渠道的重要性级别。
| 重要性级别 | 行为表现 | 使用场景 |
|---|---|---|
IMPORTANCE_HIGH |
弹出横幅、有声音、有震动 | 私信、紧急通知 |
IMPORTANCE_DEFAULT |
有声音、无横幅 | 一般通知 |
IMPORTANCE_LOW |
无声音、无横幅 | 静默通知 |
IMPORTANCE_MIN |
不显示在状态栏 | 后台任务通知 |
嗯,这里要注意:渠道一旦创建,重要性级别就不能修改了。用户可以在设置中手动调整,但代码层面无法覆盖。所以,创建渠道时一定要想清楚。
小技巧:
如果你需要修改渠道的重要性,可以删除旧渠道重新创建。但删除渠道会导致该渠道的所有通知被移除,用户可能会困惑。我一般建议:创建时就用 IMPORTANCE_DEFAULT,后续通过更新渠道描述来引导用户调整。
16.5 权限与通知渠道的交互逻辑
说白了,整个流程是这样的:
- 用户安装 App,系统弹出通知权限请求
- 用户同意 → App 可以发通知
- 用户拒绝 → App 无法发任何通知
- 即使同意了,用户还可以在设置中关闭某个渠道
所以,你的代码需要处理两种状态:
- 全局权限被拒:不要尝试发通知,直接降级处理
- 渠道被关闭:发通知不会报错,但用户看不到
我曾经在项目中遇到一个场景:用户关闭了「促销通知」渠道,但 App 仍然在后台发促销通知。虽然不会崩溃,但浪费了系统资源。后来我加了一个检查:
NotificationManager manager = getSystemService(NotificationManager.class);
if (manager.getNotificationChannel(CHANNEL_ID).getImportance() == NotificationManager.IMPORTANCE_NONE) {
// 渠道被关闭,不要发通知
return;
}
16.6 知识体系总览
下面这张图,是我梳理的通知权限与渠道的核心逻辑:
从图中可以看出,POST_NOTIFICATIONS 是总开关,通知渠道是分开关。总开关关了,分开关再精细也没用。反过来,总开关开了,用户还可以通过分开关来过滤不想要的通知。
16.7 总结
通知权限这块,说白了就是「尊重用户的选择」。我见过太多 App 在用户拒绝通知权限后,反复弹窗请求,甚至用「不授权就无法使用」来要挟用户。这种做法,用户体验极差,而且 Google Play 也会下架这类 App。
我个人建议的做法是:
- 第一次请求时,解释清楚为什么需要通知权限
- 用户拒绝后,不要反复弹窗,而是提供手动开启的引导
- 通知渠道不要太多,3-5 个足矣
- 渠道的重要性级别要合理,别把垃圾通知设成 HIGH
嗯,最后说一句:通知权限的适配其实不难,难的是想清楚「用户到底需不需要我的通知」。想明白这一点,代码怎么写都顺。