Android 12.0 应用中监听系统收到的通知

Android 12.0 通知简介icon-default.png?t=N7T8https://blog.csdn.net/Smile_729day/article/details/135502031?spm=1001.2014.3001.5502 

1. 需求

在系统内置应用中或者在第三方应用中,获取Android系统收到的通知的内容.

2. NotificationListenerService 接口

Android 系统预留了专门的API, 即 NotificationListenerService 接口,它的源码路径为:

源码路径 : /frameworks/base/core/java/android/service/notification/NotificationListenerService.javapublic abstract class NotificationListenerService extends Service {......

3. 实现 NotificationListenerService

NotificationListenerService 是抽象类,通过在 Service 中实现该抽象类,并实现需要的接口,代码如下:

public class MyNotificationListenerService extends NotificationListenerService {//当系统收到新的通知时,会触发该接口@Overridepublic void onNotificationPosted(StatusBarNotification sbn) {addAlienNotificationInfo(sbn); //获取通知的内容}//当系统移除通知时,即在通知列表中清除通知时,或者卸载应用时,该应用包名下的通知都会被清除,也同样会会触发该接口@Overridepublic void onNotificationRemoved(StatusBarNotification sbn) {super.onNotificationRemoved(sbn);}
}

上面两个接口,第一个是监听系统新通知,第二个是监听系统通知清除,如果看过Android Systemui 中有关通知的内容,就会发现,System UI 对通知的显示和通知的清除,同样也是继承该API.

下面,分析当系统收到新通知时,如何解析出通知里的内容.

4. 获取通知内容

   private void addAlienNotificationInfo(StatusBarNotification sbn) {String packageName = sbn.getPackageName();//获取发送通知的包名Notification notification = sbn.getNotification(); //获得一个Notification对象Bundle extras = notification.extras;RemoteViews contentView = notification.contentView;//ApplicationInfo appInfo = extras.getParcelable(NotificationCompat.EXTRA_BUILDER_APPLICATION_INFO);//如果是系统内置应用,可以获取到ApplicationInfo ,后面会有解释//String appName = appInfo.loadLabel(mPm).toString(); //如果是系统内置的应用,可以通过ApplicationInfo对象获取通知发送这条通知的应用名String category = notification.category;String channelId = notification.getChannelId();//String className = getNotificationClassName(notification);//如果是系统内置应用,可以获取到通知中设置的Intent,后面会有解释int color = notification.color;//通知setColor()设置的颜色boolean defaultVibrate = (notification.vibrate == null) ? true : false;String notificationVibrationString = Arrays.toString(notification.vibrate);int importance = notification.priority; //通知的重要性String key = sbn.getKey();//通知的Key,删除通知时,需要通过Key来确定删除哪条通知Icon myLargeIconToIcon = extras.getParcelable(Notification.EXTRA_LARGE_ICON);//获取通知设置的大图片,即setLargeIcon() ,int ledColor = notification.ledARGB;//通知led灯颜色String sound = (notification.sound != null) ? notification.sound.toString() : null;int progress = extras.getInt(Notification.EXTRA_PROGRESS);//当前进度值int progressMax = extras.getInt(Notification.EXTRA_PROGRESS_MAX);//设定的最大进度值boolean progressIndeterminate = extras.getBoolean(Notification.EXTRA_PROGRESS_INDETERMINATE);//是否在通知中显示进度值int flagsToCheck = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;boolean resident = (notification.flags & flagsToCheck) != 0;//是否是常驻通知(前台&onging),类似于音乐应用,String smallIcon = notification.getSmallIcon().toString();//通知设置的smallIcon()String title = (String) extras.get(Notification.EXTRA_TITLE);//通知标题String subText = (String) extras.get(Notification.EXTRA_SUB_TEXT);//通知附加内容String text = (String) extras.get(Notification.EXTRA_TEXT);//通知内容boolean userRemovable = (notification.flags & Notification.FLAG_AUTO_CANCEL) != 0; //是否可移除通知,即 setAutoCancel(boolean autoCancel) 中设定的值long when = notification.when;//通知的时间String template = getNotificationTemplate(notification);//获取通知的类型,下面会详细介绍//BigTextStyle通知中,bigText的内容String bigText = (String) extras.getCharSequence(Notification.EXTRA_BIG_TEXT);    //BigPictureStyle通知中设置的大图片Bitmap picture_extraBitmap = extras.getParcelable(Notification.EXTRA_PICTURE);//状态栏通知列表中,折叠时是否显示图片,注意:该属性在Android12上有,Android11上没有,boolean mShowBigPictureWhenCollapsed = extras.getBoolean(Notification.EXTRA_SHOW_BIG_PICTURE_WHEN_COLLASED);//通过下面的方法也可以查看通知中的设置的全部参数for(String mykey : notification.extras.keySet()){String ex = " " + mykey +" => " + notification.extras.get(mykey)+ ";";Log.d(TAG,"ex="+ex);}
}

(1) 获取ApplicationInfo

      上面在获取通知的ApplicationInfo时,使用了 Notification.EXTRA_BUILDER_APPLICATION_INFO,该值不对系统外开放,如下源码所示:

源码路径:/frameworks/base/core/java/android/app/Notification.java/*** @hide*/public static final String EXTRA_BUILDER_APPLICATION_INFO = "android.appInfo";

(2) getNotificationClassName(notification)

        上面还涉及到了getNotificationClassName(notification) 获取这条通知中通过PendingIntent中设置的 Intent ,方法中用到了不对外使用的方法,代码如下:

 private String getNotificationClassName(Notification notification) {if (notification.contentIntent != null) {Intent intent = notification.contentIntent.getIntent();if (intent != null && intent.getComponent() != null) {return intent.getComponent().getClassName();}}return null;}

(3) 获取 PendingIntent 对象

         其中的 notification.contentIntent 是获取 通知中的 PendingIntent 对象,源码如下:

源码路径:/frameworks/base/core/java/android/app/Notification.java /*** 单击展开的状态条目时要执行的意图。*/public PendingIntent contentIntent;
(4) PendingIntent.getIntent()

         接着再通过调用 PendingIntent 对象中的 getIntent() 来获取通知中设定的 Intent, 源码如下:

源码路径: /frameworks/base/core/java/android/app/PendingIntent.java/*** @hide (该方法不对外公开)* 返回 PendingIntent 中的 Intent .*/@UnsupportedAppUsagepublic Intent getIntent() {try {return ActivityManager.getService().getIntentForIntentSender(mTarget);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}

 由于源码中有@hide,表明该方法不对第三方应用开放,所以如果是系统内置的应用,则可以使用.

(5) getNotificationTemplate(Notification notification) 

         Android中定义了一些通知模板,常用的如: BigPictureStyle , BigTextStyle 等,代码如下:

/*** 返回通知的类型,如果没有使用,则返回null.* 返回的类型,如: "android.app.Notification$BigTextStyle",* 因此需要对字符串进行截取,如最后返回: "BigTextStyle"
*/private String getNotificationTemplate(Notification notification) {String template = notification.extras.getString(Notification.EXTRA_TEMPLATE);if (template != null) {int indexOf = template.indexOf('$');return template.substring(indexOf + 1);}return null;}

5. 通知的清除 

当通知被清除时,会调用 onNotificationRemoved(StatusBarNotification sbn) 方法,其中的参数 sbn 代表被删除的通知.可以在该方法里做一些删除后的工作.

6 . NotificationListenerService 中其他有用的方法

(1) 获取有效的通知 : getActiveNotifications() 

源码路径: /frameworks/base/core/java/android/service/notification/NotificationListenerService.java/*** 请求未完成通知的列表(即那些对当前用户)。** @return 活动通知数组,按自然顺序排序。*/public StatusBarNotification[] getActiveNotifications() {StatusBarNotification[] activeNotifications = getActiveNotifications(null, TRIM_FULL);return activeNotifications != null ? activeNotifications : new StatusBarNotification[0];}

(2) 删除指定单条通知 : cancelNotification(String key)   

源码路径: /frameworks/base/core/java/android/service/notification/NotificationListenerService.java /*** 删除指定的一条通知**/public final void cancelNotification(String key) {if (!isBound()) return;//是否绑定了NotificationListenerService服务try {getNotificationInterface().cancelNotificationsFromListener(mWrapper,new String[] { key });} catch (android.os.RemoteException ex) {Log.v(TAG, "Unable to contact notification manager", ex);}}

 (3) 删除指定的多条通知: cancelNotifications(String[] keys)

源码路径: /frameworks/base/core/java/android/service/notification/NotificationListenerService.java /*** 删除 数组 keys 中指定key的通知*/public final void cancelNotifications(String[] keys) {if (!isBound()) return;try {getNotificationInterface().cancelNotificationsFromListener(mWrapper, keys);} catch (android.os.RemoteException ex) {Log.v(TAG, "Unable to contact notification manager", ex);}}

(4) 清除所有通知,对应于通知列表下的 清除所有通知的按钮功能: cancelAllNotifications()

  /*** 通知通知管理器清除所有通知* 类似于Android状态栏和通知面板调用 UI 的“全部关闭”功能* 收到通知后,通知管理器实际上会删除所有活动通知* 并且收到多个 {@link #onNotificationRemoved(StatusBarNotification)} 回调。*/public final void cancelAllNotifications() {cancelNotifications(null /*all*/);}

至此,关于监听系统通知介绍完毕,谢谢观看!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/663394.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Github 2F2【解决】经验帖-PPHub登入

最近在做项目时,Github总是出问题,这是一经验贴 Github 2F2登入问题【无法登入】PPhub 2F2是为了安全,更好的生态 启用 2FA 二十八 (28) 天后,要在使用 GitHub.com 时 2FA 检查 物理安全密钥、Windows Hello 或面容 ID/触控 ID、SMS、GitHub Mobile 都可以作为 2F2 的工…

jenkins 下载插件sentry-cli失败 证书过期

现状 npm set ENTRYCLI_CDNURLhttps://cdn.npm.taobao.org/dist/sentry-cli npm set sentrycli_cdnurlhttps://cdn.npm.taobao.org/dist/sentry-cli 原因是npm原域名停止解析,在访问上面sentry-cli的cdn资源的时候 证书过期无法下载。 解决: 替换证书过期…

【C语言】通讯录实现(下)

目录 1.进阶通讯录特点(下) 2.实现步骤 (1)保存增加的联系人数据到文件中 (2)加载保存的联系人数据 3.完整C语言通讯录代码 (1)contact.h (2)test.c (3)contact.c 4.结语 1.…

MongoDB从入门到实战之MongoDB简介

前言 相信很多同学对MongoDB这个非关系型数据库都应该挺熟悉的,在一些高性能、动态扩缩容、高可用、海量数据存储、数据价值较低、高扩展的业务场景下MongoDB可能是我们的首选,因为MongoDB通常能让我们以更低的成本解决问题(包括学习、开发、…

嵌入式中Qt5.7.1添加支持openssl方法

1、openssl编译 版本:openssl-1.0.2g 一定要选对Qt版本对应的openssl版本,由于开始选的openssl版本不对,导致编译Qt时出现很多错误。 交叉编译 ./config no-asm shared --prefix/opt/Xilinx2018_zynq/zynq_openssl_1.0.2/ --cross-compile…

vivo发布2023 年度科技创新;阿里全新AI代理,可模拟人类操作手机

vivo 发布 2023 年度十大产品技术创新 近日,vivo 发布了「2023 年度科技创新」十大产品技术创新榜单,并将这些技术分为了 4 个板块。 「四大蓝科技」为 vivo 在去年推出的全新技术品牌,涵盖蓝晶芯片技术栈、蓝海续航系统、蓝心大模型、蓝河操…

2023年算法SAO-CNN-BiLSTM-ATTENTION回归预测(matlab)

2023年算法SAO-CNN-BiLSTM-ATTENTION回归预测(matlab) SAO-CNN-BiLSTM-Attention雪消融优化器优化卷积-长短期记忆神经网络结合注意力机制的数据回归预测 Matlab语言。 雪消融优化器( SAO) 是受自然界中雪的升华和融化行为的启发,开发了一种…

LeetCode 834. 树中距离之和

简单换根DP 其实就是看好变化量&#xff0c;然后让父亲更新儿子就好了&#xff5e; 上图2当根节点的时候&#xff0c;ans[2] ans[0] -sz[2]n-sz[2]; class Solution { public:vector<int> sumOfDistancesInTree(int n, vector<vector<int>>& edges) {v…

Java学习day26:和线程相关的Object类的方法、等待线程和唤醒线程(知识点详解)

声明&#xff1a;该专栏本人重新过一遍java知识点时候的笔记汇总&#xff0c;主要是每天的知识点题解&#xff0c;算是让自己巩固复习&#xff0c;也希望能给初学的朋友们一点帮助&#xff0c;大佬们不喜勿喷(抱拳了老铁&#xff01;) 往期回顾 Java学习day25&#xff1a;守护线…

假期刷题打卡--Day20

1、MT1173魔数 一个数字&#xff0c;把他乘以二&#xff0c;会得到一个新的数字&#xff0c;如果这个新数字依然由原数中那些数字组成&#xff0c;就称原数为一个魔数。输入正整数N&#xff0c;检查它是否是一个魔数&#xff0c;输出YES或者NO。 格式 输入格式&#xff1a; …

MySQL之SQL的查询语句如何执行

文章目录 前言一、一条查询的SQL是如何执行的二、MySQL的“零件”们1.连接器2.查询缓存3.分析器4.优化器5.执行器 总结 前言 做了多年技术之后&#xff0c;技术更新换代太快&#xff0c;从我入行时候从单体架构到后面分布式SOA&#xff0c;再到微服务&#xff0c;从后端再到全…

Docker搭建MySQL8主从复制

之前文章我们了解了面试官&#xff1a;说一说Binlog是怎么实现的&#xff0c;这里我们用Docker搭建主从复制环境。 docker安装主从MySQL 这里我们使用MySQL8.0.32版本&#xff1a; 主库配置 master.cnf //基础配置 [client] port3306 socket/var/run/mysqld/mysql.sock [m…

Java项目:基于SSM框架实现的教务管理系统(ssm+B/S架构+源码+数据库+毕业论文)

一、项目简介 本项目是一套ssm813基于SSM框架实现的教务管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#x…

Docker进阶篇-DockerFile

一、简介 Dockerfile是用来构建Docker镜像的文本文件&#xff0c;是由一条条构建镜像所需的指令和参数构成的脚 本。 构建步骤&#xff1a; 1、编写Dockerfile文件 2、docker build命令构建镜像 3、docker run依镜像运行容器实例 二、Docker构建过程解析 1、Dockerfile…

2024美国大学生数学建模C题网球运动中的势头详解思路+具体代码

2024美国大学生数学建模C题网球运动中的势头详解思路具体代码 E题数据已更新&#xff0c;做E题的小伙伴推荐看看博主的E题解析文章。那么废话不多说我们继续来做C题。 赛题分析 我们先阅题&#xff1a; 在2023年温布尔登男单决赛中&#xff0c;20岁的西班牙新星卡洛斯阿尔卡…

数据结构—动态查找

动态查找介绍 1. 动态查找的引入&#xff1a;当查找表以线性表的形式组织时&#xff0c;若对查找表进行插入、删除或排序操作&#xff0c;就必须移动大量的记录&#xff0c;当记录数很多时&#xff0c;这种移动的代价很大。 2. 动态查找表的设计思想&#xff1a;表结构本身是…

【论文速览_01】Awesome Few Shot Segmentation论文

Awesome Few Shot Segmentation Awesome Few Shot Segmentation论文CVPR 2023Hierarchical Dense Correlation Distillation for Few-Shot Segmentation文章内容 MIANet: Aggregating Unbiased Instance and General Information for Few-Shot Semantic Segmentation文章内容 I…

探讨深浅拷贝在js加密中的运用

深浅拷贝是JavaScript中常用的概念&#xff0c;用于复制对象或数组。它们在处理数据时有不同的用途&#xff0c;适用于不同的场景。在本文中&#xff0c;我们将详细介绍深浅拷贝的概念&#xff0c;提供案例代码&#xff0c;并探讨它们在JavaScript中的应用场景&#xff0c;以及…

MySQL原理(一)架构组成之逻辑模块(1)组成

总的来说&#xff0c;MySQL可以看成是二层架构&#xff0c;第一层我们通常叫做SQL Layer&#xff0c;在MySQL数据库系统处理底层数据之前的所有工作都是在这一层完成的&#xff0c;包括权限判断&#xff0c;sql解析&#xff0c;执行计划优化&#xff0c;query cache的处理等等&…

中二少年工具箱(PC端)简介

同学们可以私信我加入学习群&#xff01; 正文开始 简介一、功能模块1.node版本管理工具 总结 简介 中二少年开发的中二少年工具箱&#xff0c;相信博主&#xff0c;功能不孬。 辅助自己开发工作&#xff0c;帮助新人快速入门&#xff0c;提供交互式文档辅助学习……如果还不…