Notification是系统的通知类,所有的系统通知以及应用通知都会调用该API来进行内容的填充,完成具体的通知编辑,并通过NotificationManager的notify方法来发送出来。
Notification.java路径一般如下:frameworks/base/core/java/android/app/Notification.java
Notification在6.0的源码中是如此实现的:
Notification.java有一个public的内部类,叫Builder;这个类会有我们常用的各个属性的set方法,如下图:
我们在使用Notification对象的时候,要求new一个Notification.Builder就是因为如此。Notification本身并不会有set和get方法来处理,而交给Builder来处理,这样可以保证内容的匿名性,防止被外部的类截获内容,一种安全的考虑吧。
而这些参数,比如ContentText、ContentTitle等,他的类型都是private
这样就外部根本无法访问,所以真的太安全了,以至于我想get都没法get。
而在Notification new的时候呢,Builder就已经完成了他的工作,如图是Notification的构造函数:
这是一个hide的方法,但是系统级的应用可以调用。
我们用的是另一个:
做完这一切,我们会调用一个build()方法来完成,如图:
这里是Builder的build()方法,我们发现它最后return了一个UnreadConversation对象(之后的不讨论了,主要是检测和执行序列化的作用)
NotificationManager.java的路径:frameworks/base/core/java/android/app/NotificationManager.java
NotificationManager是Notification的一个管理类,他的启动是通过binder机制,获得一个Notification的binder来启动对应的系统服务,如图:
启动了NotificationManager之后,调用notify方法就显示出来了,如图:
下面的notify方法是最后调用的。(全过程)
我们的目的是根据特性的contentText来屏蔽特定的notification;屏蔽的方式就是当判断他现实的是我们要屏蔽的notification的时候,我们不让他执行notify方法。所以,关键点就是在执行notify方法之前来确认我们的notification是特定的。
之前尝试了很多方法都不行,最后考虑了一下static的特性,如此才好。
static在java的内存中会分配一块区域,用来存放所有的全局类的变量;又因为notification本身设计的问题,无法通过get的方法拿到特性的contentText字段,notification解析也无法获得,因为他是内部类Builder来实现的,而Builder本身并不支持get操作。
所以,我们通过控制一个static标志位的方法来确定是否屏蔽当前notification;而标志位的判断在Builder内部完成,如此解决了问题。
对策如下: