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不能完全依赖系统设置。我建议你这样做:

  1. 默认使用PRIVATE:除非你的通知内容完全不涉及隐私(比如天气、音乐播放器),否则默认用PRIVATE
  2. 敏感场景用SECRET:验证码、支付结果、私密聊天——这些必须用SECRET
  3. 提供用户选项:在App设置里让用户自己选择「锁屏时是否显示详情」

注意:从Android 8.0(API 26)开始,通知渠道(NotificationChannel)也支持设置setLockscreenVisibility。如果你在渠道级别设置了可见性,它会覆盖单条通知的设置。我曾经踩过这个坑——渠道设了PRIVATE,单条通知设了PUBLIC,结果锁屏上死活不显示内容。排查了半天才发现是渠道配置的问题。

10.4 知识体系图

下面这张图,帮你理清锁屏通知的完整决策流程:

锁屏通知可见性决策流程 通知到达 系统锁屏通知开关? 完全不显示 显示全部内容 按可见性处理 PUBLIC → 显示完整内容 PRIVATE → 显示隐藏文案 SECRET → 完全不显示 忽略可见性设置

小技巧:如果你想让通知在锁屏时显示自定义内容,但又不想暴露敏感信息,可以用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