最近在开发xposed模块中想要实现一个清除所有通知的功能,但是发现cancelAll只能清除单个应用的所有通知。
查看NotificationManager源码可知
http://androidxref.com/5.1.0_r1/xref/frameworks/base/core/java/android/app/NotificationManager.java

28    /**229     * Cancel all previously shown notifications. See {@link #cancel} for the230     * detailed behavior.231     */232    public void cancelAll()233    {234        INotificationManager service = getService();              //此处获取了包名,导致只能关闭该包下的消息235        String pkg = mContext.getPackageName();236        if (localLOGV) Log.v(TAG, pkg + ": cancelAll()");237        try {238            service.cancelAllNotifications(pkg, UserHandle.myUserId());239        } catch (RemoteException e) {240        }241    }

再次查看UserHandle.myUserId的源码

/**233     * Returns the user id of the current process234     * @return user id of the current process235     * @hide  这个方法是隐藏的236     */237    @SystemApi238    public static final int myUserId() {          //获取进程对应的UID239        return getUserId(Process.myUid());240    }

cancelAll中关闭通知使用了uid和包名,可以看出来其实是只关闭一个应用里所有的通知

但是通知栏上面明明是有一个清除所有通知的按钮,通过源码来看一下它的实现
在源码中找到一个这样的布局
http://androidxref.com/5.1.0_r1/xref/frameworks/base/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml
该布局里面只有一个DismissViewButton控件,通过调用它的ID,找到了这样一个类:
http://androidxref.com/5.1.0_r1/xref/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java
通过里面的setOnButtonClickListener,在源码中查找调用类这个方法的类
http://androidxref.com/5.1.0_r1/xref/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
在PhoneStatusBar中,有这样一段代码:

744        mDismissView.setOnButtonClickListener(new View.OnClickListener() {745            @Override746            public void onClick(View v) {747                clearAllNotifications();748            }749        });

clearAllNotifications() 这个方法应该就是我们想要的那个清除所有通知的方法
我们来看一下它的具体实现

943    private void clearAllNotifications() {944945        // animate-swipe all dismissable notifications, then animate the shade closed946        int numChildren = mStackScroller.getChildCount();947948        final ArrayList viewsToHide = new ArrayList(numChildren);949        for (int i = 0; i < numChildren; i++) {950            final View child = mStackScroller.getChildAt(i);951            if (mStackScroller.canChildBeDismissed(child)) {952                if (child.getVisibility() == View.VISIBLE) {953                    viewsToHide.add(child);954                }955            }956        }957        if (viewsToHide.isEmpty()) {958            animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);959            return;960        }961962        addPostCollapseAction(new Runnable() {963            @Override964            public void run() {965                try {966                    mBarService.onClearAllNotifications(mCurrentUserId);967                } catch (Exception ex) { }968            }969        });970971        performDismissAllAnimations(viewsToHide);972973    }

通过Xposed Hook后调用该方法,成功实现清除所有通知栏的内容,但是仍然有一改问题:在通知栏收起的情况下,清除通知后,状态栏仍然有图标存在,而在下拉状态栏后才清除。
这个问题应该是由于该方法中

952                if (child.getVisibility() == View.VISIBLE) {953                    viewsToHide.add(child);954                }

这一段代码造成的。
解决方法:
1.使用xposed hook替换整个清除通知栏的方法,去掉这一部分。比较麻烦,而且可能会造成某些问题,但是效果好。
2.在调用hook出来的clearAllNotificatons的时候,执行一下拉通知栏和收起通知栏的方法。效果稍微差一些,但是不至于出现太大问题。

更多相关文章

  1. android 使用InstanceState保存和恢复数据
  2. android 系统定制之编译方法总结
  3. Android(安卓)4.0 ICS SystemUI浅析——StatusBar加载流程分析
  4. Android(安卓)限制显示小数点位数
  5. Android与H5页面的互调
  6. android OpenGLES开发第三课 绘制一个可以翻转的Polygon
  7. java化改造--xml布局文件转成java——学习整理
  8. Android(安卓)上网流量监控方法
  9. [安卓开发Android] RecyclerView 类型与点击事件的用法

随机推荐

  1. Android(安卓)layout属性
  2. TextView跑马灯效果
  3. 针对于Button的OnClickListener
  4. [android]控件Button常用属性
  5. Android中RelativeLayout相对布局
  6. Android出错问题:AndroidManifest.xml:2:
  7. Android(安卓)网站资源收集大全
  8. Android(安卓)网站资源收集大全
  9. Android(安卓)之Tab
  10. Android内核学习笔记