10、通知可见性与锁屏:VISIBILITY_PUBLIC、VISIBILITY_PRIVATE、VISIBILITY_SECRET
锁屏通知,说白了就是你的App在手机锁屏状态下,能「露」多少信息给用户看。
我刚开始做通知开发时,觉得这功能很简单——不就是显示或不显示吗?直到有一次,一个金融类App的用户反馈说:「为什么我的银行转账金额在锁屏上所有人都能看到?」我才意识到,这个「可见性」设计,其实藏着不少隐私保护的学问。
Android从5.0开始,就提供了三个级别的锁屏通知可见性。嗯,咱们一个一个来看。
10.1 三个可见性级别
Android定义了三个常量,都在NotificationCompat里:
| 常量 | 值 | 含义 |
|---|---|---|
VISIBILITY_PUBLIC |
1 | 锁屏时显示完整通知内容 |
VISIBILITY_PRIVATE |
0 | 锁屏时隐藏敏感内容,显示「图标+应用名」 |
VISIBILITY_SECRET |
-1 | 锁屏时不显示任何通知信息 |
你可能会问:这三个级别到底怎么用?我举个例子你就明白了。
假设你做了一个即时通讯App:
- PUBLIC:锁屏上直接显示「张三:今晚吃饭吗?」——适合不重要或用户主动期望看到的通知
- PRIVATE:锁屏上只显示「1条新消息」,点开才看到具体内容——适合聊天、邮件等含隐私的场景
- SECRET:锁屏上连「1条新消息」都不显示,解锁后才看到——适合银行验证码、支付通知等极度敏感的场景
核心原则:通知的可见性,应该和内容的敏感度成反比。越敏感,可见性越低。
10.2 代码怎么写?
设置可见性其实就一行代码:
// 公开可见
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setContentTitle("快递通知")
.setContentText("您的包裹已到达驿站");
// 私密可见
NotificationCompat.Builder builderPrivate = new NotificationCompat.Builder(context, CHANNEL_ID)
.setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
.setContentTitle("新消息")
.setContentText("您有一条新消息"); // 锁屏时这个text会被隐藏
// 完全隐藏
NotificationCompat.Builder builderSecret = new NotificationCompat.Builder(context, CHANNEL_ID)
.setVisibility(NotificationCompat.VISIBILITY_SECRET)
.setContentTitle("验证码")
.setContentText("您的验证码是:123456"); // 锁屏时完全不显示
等等,这里有个坑。你设置了VISIBILITY_PRIVATE,锁屏时系统会把setContentText的内容替换成默认的「隐藏文案」。但如果你想要自定义这个隐藏文案呢?
嗯,Android提供了setPublicVersion方法:
// 创建一个「公开版本」的通知,用于锁屏时显示
Notification publicNotification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setContentTitle("新消息")
.setContentText("您有1条新消息") // 锁屏时显示这个
.setSmallIcon(R.drawable.ic_message)
.build();
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
.setContentTitle("新消息")
.setContentText("张三:今晚吃饭吗?") // 解锁后显示这个
.setPublicVersion(publicNotification); // 锁屏时显示这个
我在项目中遇到过这样一个场景:用户锁屏时,我们希望显示「您有1条新消息」,但解锁后要显示具体内容。用setPublicVersion就完美解决了。
10.3 锁屏通知的隐私保护策略
光设置可见性还不够。你想想看,用户可以在系统设置里,全局控制锁屏通知的行为:
- 显示所有通知内容:相当于所有通知都变成PUBLIC
- 隐藏敏感通知内容:PRIVATE级别的通知会被隐藏
- 完全不显示通知:所有通知在锁屏上消失
所以,你的App不能完全依赖系统设置。我建议你这样做:
- 默认使用PRIVATE:除非你的通知内容完全不涉及隐私(比如天气、音乐播放器),否则默认用PRIVATE
- 敏感场景用SECRET:验证码、支付结果、私密聊天——这些必须用SECRET
- 提供用户选项:在App设置里让用户自己选择「锁屏时是否显示详情」
注意:从Android 8.0(API 26)开始,通知渠道(NotificationChannel)也支持设置setLockscreenVisibility。如果你在渠道级别设置了可见性,它会覆盖单条通知的设置。我曾经踩过这个坑——渠道设了PRIVATE,单条通知设了PUBLIC,结果锁屏上死活不显示内容。排查了半天才发现是渠道配置的问题。
10.4 知识体系图
下面这张图,帮你理清锁屏通知的完整决策流程:
小技巧:如果你想让通知在锁屏时显示自定义内容,但又不想暴露敏感信息,可以用setPublicVersion创建一个「阉割版」通知。比如聊天App,锁屏时显示「您有3条新消息」,解锁后显示具体内容。这样既保护了隐私,又给了用户足够的信息。
10.5 避坑指南
我曾经在做一个企业IM项目时,遇到过这样一个问题:用户反馈说「为什么我设置了锁屏不显示内容,但通知还是能看到一部分?」
排查后发现,问题出在通知渠道上。Android 8.0之后,通知渠道的setLockscreenVisibility优先级高于单条通知的setVisibility。如果你在渠道里设了VISIBILITY_PUBLIC,那单条通知设PRIVATE也没用。
所以,我的建议是:
- 在渠道创建时,统一设置一个合理的默认可见性
- 特殊通知再通过
setVisibility单独覆盖 - 测试时,一定要在锁屏状态下验证
另外,别忘了Android 11(API 30)之后,系统对通知的权限管理更严格了。如果你的App targetSdkVersion >= 30,需要动态申请POST_NOTIFICATIONS权限。这个权限和锁屏可见性没有直接关系,但用户如果拒绝了通知权限,那锁屏可见性也就无从谈起了。
嗯,锁屏通知的隐私保护,说白了就是一句话:不该看的,别让它在锁屏上出现。把握好PUBLIC、PRIVATE、SECRET这三个级别,再配合系统设置和用户偏好,你的App在隐私保护上就不会出大问题。
公众号:蓝海资料掘金营,微信deep3321