Android 15 将禁止NotificationListenerService 读取 OTP

今天介绍一个在国内没什么用的 Android 15 更新,主要是看到了,就顺带介绍一下 NotificationListenerService

相信大家对于 NotificationListenerService 应该不会陌生吧,例如在「微信红包通知」、「消息防撤回」、「短信增强通知」、「通知栏管理」等插件都可能会看到过它的身影,而 NotificationListenerService 是在 Android 4.3 的时候被引入,可以说是一个长期存在的 API。

简单介绍一下,首先你可以通过继承 NotificationListenerService 实现一个监听服务,通过 onListenerConnected 你可以快速判断服务是否成功启用,通过 onNotificationPosted 可以读取系统通知栏的消息。

java 复制代码
public class NotificationListener extends NotificationListenerService {
  @Override
  public void onNotificationPosted(StatusBarNotification nf) {
    super.onNotificationPosted(nf);

      Notification notification = nf.getNotification();
      Bundle extras = notification.extras;
      if (extras != null) {
          String title = extras.getString(Notification.EXTRA_TITLE, "");
          String content = extras.getString(Notification.EXTRA_TEXT, "");
          Log.e("notification", "title: " + title + " content: " + content);
      }
  }
  @Override
  public void onNotificationRemoved(StatusBarNotification nf) {
    super.onNotificationRemoved(nf);
  }

    @Override
    public void onListenerConnected() {
        super.onListenerConnected();
    }
}

之后通过在 AndroidManifest 声明服务,就可以使用对应的通知栏内容监听能力。

xml 复制代码
     <service
            android:name=".view.NotificationListener"
            android:exported="true"
            android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
            <intent-filter>
                <action android:name="android.service.notification.NotificationListenerService" />
            </intent-filter>
        </service>

当然, 由于通知内容可能包含某些敏感数据,所以一般情况下应用除非获得用户手动允许,否则 App 无法直接使用该 API。

而在原生系统下,开启权限的路径在一般在 "Settings-> Notifications -> Notification read, reply & control " ,开启时也会有对应的提示:

不过这个位置在很多第三方 OS 上面可能不一致,而且不好找,所以一般推荐可以通过 ACTION_NOTIFICATION_LISTENER_SETTINGS 来实现调整打开:

java 复制代码
      Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      context.startActivity(intent);

事实上根据 NotificationListenerService 的能力,它在国产系统里都会被定义为高危权限,正常情况下系统都不会建议用户开启它:

甚至有时候你还会看到下面这样的情况,例如左侧小米上出现受限的场景,另外右侧在我的华为上看到「平安好车主」也有对应权限描述在,也是有趣:

而且这个支持有时候很诡异,例如有时候在小米上无法触发,需要重启手机才可以正常 connected ,一般情况下可以通过 adb shell dumpsys notification 来确认 Live notification listeners 里是否包含了你定义的监听:

而在成功加入监听之后,通过这个 API App 就可以获取到各种通知的数据,例如包名、title、content 等内容,剋看到此时 App 已经拥有了极高的权限,也可以监听到你微信的通知:

可以看到当拥有 NotificationListenerService 权限之后, App 其实可以很方便地获取到需求用户的隐私内容,其中就包括 OTP 推送:

所以在 Android 15 之前,具有通知访问权限的应用能够读取所有传入的通知,甚至是带有 OTP 代码的通知,而Android 15 之后,系统会阻止不受信任的应用读取敏感通知,即使它们有权读取所有通知也是如此,gif 展示了 14 和 15 上收到 OTP 推送时系统的不同反应:

但是这个支持主要是通过 Android System Intelligence(ASI) 来完成 ,ASI 会在将所有通知发送到 NotificationListenerService 之前对通知进行处理,如果 ASI 检测到通知中包含如身份验证代码,它会告诉系统将其标记为"敏感内容",并停止将通知发送到不受信任的 NotificationListenerService

不受信任的 NotificationListenerService 属于在 Android 15 中没有 RECEIVE_SENSITIVE_NOTIFICATIONS 权限的应用。

这个权限只会赋予使用系统证书签名的应用或拥有特定角色的应用,大多数情况下,赋予RECEIVE_SENSITIVE_NOTIFICATIONS 权限的角色只能由系统应用持有,另外一些特定角色可以由第三方应用持有,例如 COMPANION_DEVICE_WATCHCOMPANION_DEVICE_GLASSES 等。

这些特定角色分别被赋予手表配套应用、智能眼镜配套应用和默认启动器等,换句话说,在 Android 15 上唯一可以读取带有身份验证代码的通知的第三方应用:连接到智能手表的应用、连接到智能眼镜的应用或默认主屏幕启动器应用。

另外,在调试时可以通过 adb 命令来做授权处理,这个调整可以保证用户在使用 NotificationListenerService 带来的便捷时能更好保护自己的深度隐私,避免 OTP 代码泄漏,当然这个调整在国内又显得不是很有用。

sh 复制代码
adb shell cmd appops set --user 0 <PACKAGE> RECEIVE_SENSITIVE_NOTIFICATIONS allow

因为这个功能依赖于 Android System Intelligence(ASI) 来完成,Android System Intelligence 作为 Private Compute Core 中的一个系统组件,它主要是在保持数据私密性的同时为 Android 中的智能功能提供支持。

曾经在 Android 12 上还出现过 Android System Intelligence 反复崩溃的问题。

而 ASI 主要依赖于安装了 Google 服务,甚至一些深度功能是 Pixel 独有,所以大多数情况下,你的手机里一般是没有 ASI 的,在没有 ASI 的情况下,就会 API 35 的模拟器场景一样, NotificationListenerService 依然拥有很高的读取能力,所以国内 ROM 厂商是否最终会同样支持 NotificationListenerService 的 OTP 隐私过滤能力还不好说,这也是为什么说这个更新有点鸡肋的原因。

后续只能坐等国内的 android 15 版更新来测试最终效果了。

相关推荐
N***73851 小时前
Vue网络编程详解
前端·javascript·vue.js
e***71671 小时前
Spring Boot项目接收前端参数的11种方式
前端·spring boot·后端
程序猿小蒜1 小时前
基于springboot的的学生干部管理系统开发与设计
java·前端·spring boot·后端·spring
银空飞羽1 小时前
让Trae CN SOLO自主发挥,看看能做出一个什么样的项目
前端·人工智能·trae
Eshine、2 小时前
解决前端项目中,浏览器无法正常加载带.gz名称的文件
前端·vue3·.gz·.gz名称的js文件无法被加载
alexhilton2 小时前
深入理解withContext和launch的真正区别
android·kotlin·android jetpack
用户47949283569152 小时前
别再当 AI 的"人肉定位器"了:一个工具让 React 组件秒定位
前端·aigc·ai编程
WYiQIU3 小时前
面了一次字节前端岗,我才知道何为“造火箭”的极致!
前端·javascript·vue.js·react.js·面试
qq_316837753 小时前
uniapp 观察列表每个元素的曝光时间
前端·javascript·uni-app
小夏同学呀3 小时前
在 Vue 2 中实现 “点击下载条码 → 打开新窗口预览 → 自动唤起浏览器打印” 的功能
前端·javascript·vue.js