当前位置:网站首页>systemui屏蔽通知栏
systemui屏蔽通知栏
2022-08-10 14:29:00 【纵容_伊人倩影】
背景描述
客户说要屏蔽掉某个应用里的通知,但是不全部屏蔽,只屏蔽指定应用的部分通知。
很奇怪,这个东西要系统来做,应用不发通知不就好了嘛?
但是没办法,甲方爸爸的需求,唉(:
需求实现
方案1 ------ systemui中屏蔽通知
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java的shouldFilterOut方法中添加过滤
/** * "packageName/channelId" * 表示 包名中此channelID的通知可以显示,其它全部屏蔽,判断逻辑见{@link notificationHide} * */
private static void initNotificationFilterList(){
notificationFilterList.add("com.aaa.bbb/background_download");
notificationFilterList.add("com.aaaa.ccc/background__upgrade");
}
/** * @return true/false 标时指定同时是否需要隐藏 * @param key 指定应用的包名 * @param channelId 显示指定的通知,其它通知全部过滤 * */
public static boolean notificationHide(String key,String channelId){
if (notificationFilterList.size() == 0){
initNotificationFilterList();
}
if (key != null && key.length() > 0 && channelId != null && channelId.length() > 0){
for (int i=0;i < notificationFilterList.size();i++){
String index = notificationFilterList.get(i);
String packageName ;
String cId ;
if (index != null && index.length() > 0){
String[] dex = index.split("/");
if (dex !=null && dex.length == 2){
packageName = dex[0];
cId = dex[1];
if (key.contains(packageName)
&& !channelId.equals(cId)) {
return true;
}
}
}
}
}
return false;
}
/** * @return true if the provided notification should NOT be shown right now. */
public boolean shouldFilterOut(NotificationEntry entry) {
final StatusBarNotification sbn = entry.getSbn();
...
if (sbn != null){
if (notificationHide(sbn.getKey(),sbn.getNotification().getChannelId())){
//屏蔽应用通知
return true;
}
}
...
return false;
}
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java的onNotificationPosted中
@Override
public void onNotificationPosted(final StatusBarNotification sbn,
final RankingMap rankingMap) {
if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);
if (sbn != null){
//屏蔽应用通知
if (NotificationFilter.notificationHide(sbn.getKey(),sbn.getNotification().getChannelId())){
return ;
}
}
if (sbn != null && !onPluginNotificationPosted(sbn, rankingMap)) {
mMainHandler.post(() -> {
processForRemoteInput(sbn.getNotification(), mContext);
for (NotificationHandler handler : mNotificationHandlers) {
handler.onNotificationPosted(sbn, rankingMap);
}
});
}
}
上述方法可以屏蔽systemui下面的通知,实现指定应用只显示指定通知,其它通知全部隐藏的需求。
but
这个效果只是不显示通知,通知本身还是在的。
1、比如launcher的通知小圆点,长按桌面图标的通知显示等问题。
frameworks/base/core/java/android/service/notification/NotificationListenerService.java
的getActiveNotifications方法获取通知。
2、其它应用可以通过
frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java的getNotificationRecord、getActiveNotificationsFromListener或者其他方法获取通知内容。
换个思路重新触发
我们应该从根本上删除那些要屏蔽的通知,或者从一开始就不让它add到NotificationManagerService中去。
方案2 ------ framework中屏蔽
frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java中
通知的获取主要在
@GuardedBy("mNotificationLock")
final ArrayList<NotificationRecord> mNotificationList = new ArrayList<>();
@GuardedBy("mNotificationLock")
final ArrayMap<String, NotificationRecord> mNotificationsByKey = new ArrayMap<>();
这两个列表和map中存储。我们要实现阻断添加,实现屏蔽特定通知。
1、跟踪上面2个add和put数据的地方
2、PostNotificationRunnable的run方法中进行add和put通知数据
3、EnqueueNotificationRunnable中启动的PostNotificationRunnable
4、enqueueNotificationInternal方法中启动EnqueueNotificationRunnable,但是后续发现还有其他地方也启用了EnqueueNotificationRunnable。
所以我们在enqueueNotificationInternal和EnqueueNotificationRunnable 2个地方都加了一些屏蔽处理。
void enqueueNotificationInternal(...){
...
if (notificationHide(pkg,channelId)){
//过滤通知
return;
}
if (channel == null) {
final String noChannelStr = "No Channel found for "
}
...
}
内部类EnqueueNotificationRunnable的run方法中
public void run() {
...
if (contextId != null) {
(new SnoozeNotificationRunnable(r.getSbn().getKey(),
0, contextId)).snoozeLocked(r);
return;
}
//屏蔽通知
if(r != null && r.getSbn() !=null && r.getSbn().getNotification() !=null){
String key = r.getSbn().getKey();
String channelId = r.getSbn().getNotification().getChannelId();
if (notificationHide(key,channelId)){
return;
}
}
mEnqueuedNotifications.add(r);
...
}
这样修改之后,就可以完全屏蔽,通知不会添加到列表中了。
结尾
上述流程只是notification通知流程中的一小部分
完整的通知发送----framework添加通知----systemui显示通知。等流程没有完全跟踪。
如果有理解不到位的地方,欢迎留言~
补充
通知的使用:https://blog.csdn.net/jppipai/article/details/122864465
1、应用发送通知------framework中service管理通知数据
NotificationManager.notify------NotificationManagerService.enqueueNotificationWithTag------NotificationManagerService.enqueueNotificationInternal
这里就和上面service屏蔽通知的地方呼应上了。
//manager作为给上层的接口,最终还是会掉到service管理通知数据
frameworks/base/core/java/android/app/NotificationManager.java
public void notify(int id, Notification notification)
{
notify(null, id, notification);
}
public void notify(String tag, int id, Notification notification)
{
notifyAsUser(tag, id, notification, mContext.getUser());
}
public void notifyAsUser(String tag, int id, Notification notification, UserHandle user)
{
INotificationManager service = getService();
String pkg = mContext.getPackageName();
try {
if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
fixNotification(notification), user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
//service管理通知数据
frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
@Override
public void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
Notification notification, int userId) throws RemoteException {
enqueueNotificationInternal(pkg, opPkg, Binder.getCallingUid(),
Binder.getCallingPid(), tag, id, notification, userId);
}
边栏推荐
猜你喜欢

How does IT Xiaobai learn PHP systematically

WSL 提示音关闭

领域驱动模型设计与微服务架构落地-从项目去剖析领域驱动
![[Gazebo Introductory Tutorial] Lecture 3 Static/Dynamic Programming Modeling of SDF Files](/img/ec/87566763daf7faa3769ee186f93ee0.jpg)
[Gazebo Introductory Tutorial] Lecture 3 Static/Dynamic Programming Modeling of SDF Files

基于ArcGIS水文分析、HEC-RAS模拟技术在洪水危险性及风险评估

MySQL interview questions

实现一个深克隆

Classifying irises using decision trees

这一次,话筒给你:向自由软件之父斯托曼 提问啦!

借数据智能,亚马逊云科技助力企业打造品牌内生增长力
随机推荐
普林斯顿微积分读本05第四章--求解多项式的极限问题
【MindSpore易点通机器人-02】设计与技术选型
雨水中存在的PFAS化学物质对饮用水安全构成了威胁
波士顿房价预测
EVE模拟器的使用-带图超详细(学网络用)「建议收藏」
强意识 压责任 安全培训筑牢生产屏障
记录几道整型提升的题目
电脑重装系统提示activex部件不能创建对象如何解决
产品使用说明书小程序开发制作说明
Unfinished mathematics test paper ----- test paper generator (Qt includes source code)
laravel throws the error to Dingding
【219】慕课三千多的那个go工程师的培训课笔记 02 go语言的编程思想
池化技术有多牛?来,告诉你阿里的Druid为啥如此牛逼!
每个月工资表在数据库如何存储?求一个设计思路
Alibaba的秒杀系统—千亿级并发设计手册上线了
data product manager
How is the monthly salary table stored in the database?Ask for a design idea
CSP-J1 CSP-S1 初赛 第1轮(2022.08.09)
文件系统设计
开源SPL消灭数以万计的数据库中间表