Android 屏蔽锁屏界面上的通知显示

一. 前言

        [定制需求描述]:在插入SD后,  锁屏状态下, 去掉提示“SD卡可用于传输照片和媒体文件”

需求拆解:  要求正常显示在SystemUI下拉状态栏,  只需要屏蔽在锁屏状态下的通知.

二. 发送通知

首先来找找这个字符串"可用于传输照片和媒体文件"

是在/frameworks/base/core/res/res/values-zh-rCN.xml 中

在源码中搜索引用该字符串的文件为:StorageNotification.java     路径为:

 frameworks/base/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java

当插入SD后的逻辑代码为:

 private void onVolumeStateChangedInternal(VolumeInfo vol) {
        switch (vol.getType()) {
            case VolumeInfo.TYPE_PRIVATE:
                onPrivateVolumeStateChangedInternal(vol);
                break;
                //SD卡
            case VolumeInfo.TYPE_PUBLIC:
                onPublicVolumeStateChangedInternal(vol);
                break;
        }
    }

接下来, 待SD卡挂载成功后,就会走 onVolumeMounted(vol)方法

private Notification onVolumeMounted(VolumeInfo vol) {
....
Notification.Builder builder = buildNotificationBuilder(vol, title, text)
....
}

方法中,会创建通知builder对象

private Notification.Builder buildNotificationBuilder(VolumeInfo vol, CharSequence title,
            CharSequence text) {
        Notification.Builder builder =
                new Notification.Builder(mContext, NotificationChannels.STORAGE)
                        .setSmallIcon(getSmallIcon(vol.getDisk(), vol.getState()))
                        .setColor(mContext.getColor(R.color.system_notification_accent_color))
                        .setContentTitle(title)
                        .setContentText(text)
                        .setStyle(new Notification.BigTextStyle().bigText(text))
                        .setVisibility(Notification.VISIBILITY_PUBLIC)
                        .setLocalOnly(true)
                        .extend(new Notification.TvExtender());
        overrideNotificationAppName(mContext, builder, false);
        return builder;
    }

接下来回到 onPublicVolumeStateChangedInternal中, 当builder创建成功后,接下来就是发送通知

 private void onPublicVolumeStateChangedInternal(VolumeInfo vol) {
....
mNotificationManager.notifyAsUser(vol.getId(), SystemMessage.NOTE_STORAGE_PUBLIC,
                    notif, UserHandle.of(vol.getMountUserId()));
....
}

三. 显示通知

熟悉SystemUI模块的开发人员, 可以直接看管理锁屏状态下通知显示的文件:

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java  它是一个接口文件, 里面有这两个方法:

一个是通过userId 来过滤,  一个是字符串String key 来过滤隐藏通信

    boolean shouldHideNotifications(int userId);
    boolean shouldHideNotifications(String key);

具体的实现文件为NotificationLockscreenUserManagerImpl.java文件

我是通过用key这个方法来过滤的

public boolean shouldHideNotifications(String key) {
        if (getEntryManager() == null) {
            Log.wtf(TAG, "mEntryManager was null!", new Throwable());
            return true;
        }
        return isLockscreenPublicMode(mCurrentUserId)
                && getEntryManager().getNotificationData().getVisibilityOverride(key) ==
                        Notification.VISIBILITY_SECRET;
    }

通过全局搜索这个方法被调用的地方

Android 屏蔽锁屏界面上的通知显示_第1张图片 

 在NotificationFilter.java文件中的shouldFilterOut 方法中

  /**
     * @return true if the provided notification should NOT be shown right now.
     */
    public boolean shouldFilterOut(NotificationEntry entry) {
        final StatusBarNotification sbn = entry.notification;
        if (!(getEnvironment().isDeviceProvisioned()
                || showNotificationEvenIfUnprovisioned(sbn))) {
            return true;
        }

        if (!getEnvironment().isNotificationForCurrentProfiles(sbn)) {
            return true;
        }

        if (getUserManager().isLockscreenPublicMode(sbn.getUserId())
                && (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET
                        || getUserManager().shouldHideNotifications(sbn.getUserId())
                        || getUserManager().shouldHideNotifications(sbn.getKey()))) {
            return true;
        }
....

}

这个方法表达的意思就是 在特定条件下过滤掉通知, 所以这样子就有解决方法了, 我们在这个方法中根据特定的判断条件,返回true,表示需要在锁屏界面上过滤掉这个通知显示.

四. 解决方案

既然是通过key作为判断条件, 在发送通知的地方加上一个key相关的方法

 private Notification.Builder buildNotificationBuilder(VolumeInfo vol, CharSequence title,
            CharSequence text) {
        Notification.Builder builder =
                new Notification.Builder(mContext, NotificationChannels.STORAGE)
                        .setSmallIcon(getSmallIcon(vol.getDisk(), vol.getState()))
                        .setColor(mContext.getColor(R.color.system_notification_accent_color))
                        .setContentTitle(title)
                        .setContentText(text)
                        .setStyle(new Notification.BigTextStyle().bigText(text))
                        .setVisibility(Notification.VISIBILITY_PUBLIC)
                        .setLocalOnly(true)
                        //加上这个自定义的key  不需要显示在锁屏界面
                        .setGroup("not_show_on_lockscreen")
                        .extend(new Notification.TvExtender());
        overrideNotificationAppName(mContext, builder, false);
        return builder;
    }

然后在显示通知的过滤方法中,加入判断条件并返回true

    public boolean shouldFilterOut(NotificationEntry entry) {
        final StatusBarNotification sbn = entry.notification;
        if (!(getEnvironment().isDeviceProvisioned()
                || showNotificationEvenIfUnprovisioned(sbn))) {
            return true;
        }
        //在锁屏界面不显示SD卡的通知
        if ("not_show_on_lockscreen".equals(sbn.getGroupKey())) {
            return true;
        }
        //
   ....

   }

你可能感兴趣的:(Android,App,SystemUI通知,屏蔽锁屏通知)