Android7.0 Notification Show silently 阻止通知 定制

需求:控制Notification显示,让所有的通知都没有声音、震动、headsup(就是弹出来显示,类似短信)。但是在statusbar下拉时还有这个通知,这样玩游戏的时候就不会受到影响,通知也不会丢。

其实这个功能Android7.0默认就有了,在Settings中。

这里写图片描述

这里写图片描述

这里如果选择Block all就会阻止这个app相关的所有通知。不会有任何通知。如果选择Show silently,就和我们的需求是一致的。这里的实现代码已经找到了,但是我们不能用,因为用了的话就会产生冲突。比如我没有选Show silently,当我们这个需求的模式开启后,在进Settings这个选项看的话,肯定就会被勾选了,所以我们不能用它的方法实现。

这个Show silently的实现代码就是在frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java

    void setNotificationsEnabledForPackageImpl(String pkg, int uid, boolean enabled) {
        Slog.v(TAG, (enabled?"en":"dis") + "abling notifications for " + pkg);

        mAppOps.setMode(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg,
                enabled ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);

        // Now, cancel any outstanding notifications that are part of a just-disabled app
        if (ENABLE_BLOCKED_NOTIFICATIONS && !enabled) {
            cancelAllNotificationsInt(MY_UID, MY_PID, pkg, 0, 0, true, UserHandle.getUserId(uid),
                    REASON_PACKAGE_BANNED, null);
        }
    }

我们这里不用这个方法,我们要看这个方法设置了之后,哪里会用到,哪里会判断,来控制通知的显示,到时候就在那里加我们的判断来实现控制通知。就是多加一个我们的flag而已。


这边的通知是分2部分的,一部分是控制通知的声音、震动、led灯这些,还有一部分就是statusbar上的显示,比如是不是弹出显示通知Headsup。

1.NotificationManagerService控制通知声音、震动等,然后丢给StatusBar显示。
当应用程序发出通知,就一定会走这里


    private class EnqueueNotificationRunnable implements Runnable {
        private final NotificationRecord r;
        private final int userId;

        EnqueueNotificationRunnable(int userId, NotificationRecord r) {
            this.userId = userId;
            this.r = r;
        };

        @Override
        public void run() {

            synchronized (mNotificationList) {
                final StatusBarNotification n = r.sbn;
                if (DBG) Slog.d(TAG, "EnqueueNotificationRunnable.run for: " + n.getKey());
                NotificationRecord old = mNotificationsByKey.get(n.getKey());
                if (old != null) {
                    // Retain ranking information from previous record
                    r.copyRankingInformation(old);
                    Log.i("a", "NotificationManagerService: 2652");
                }

                final int callingUid = n.getUid();
                final int callingPid = n.getInitialPid();
                final Notification notification = n.getNotification();
                final String pkg = n.getPackageName();
                final int id = n.getId();
                final String tag = n.getTag();
                final boolean isSystemNotification = isUidSystem(callingUid) ||
                        ("android".equals(pkg));


                // Handle grouped notifications and bail out early if we
                // can to avoid extracting signals.
                handleGroupedNotificationLocked(r, old, callingUid, callingPid);

                // This conditional is a dirty hack to limit the logging done on
                //     behalf of the download manager without affecting other apps.
                if (!pkg.equals("com.android.providers.downloads")
                        || Log.isLoggable("DownloadManager", Log.VERBOSE)) {
                    int enqueueStatus = EVENTLOG_ENQUEUE_STATUS_NEW;
                    if (old != null) {
                        enqueueStatus = EVENTLOG_ENQUEUE_STATUS_UPDATE;
                        Log.i("a", "NotificationManagerService: 2676");
                    }
                    EventLogTags.writeNotificationEnqueue(callingUid, callingPid,
                            pkg, id, tag, userId, notification.toString(),
                            enqueueStatus);
                }

                mRankingHelper.extractSignals(r);

                final boolean isPackageSuspended = isPackageSuspendedForUser(pkg, callingUid);

                // blocked apps
                // 这里是blocked的apps,就是你在settings中选择Block all的app,这里就会帮通知都屏蔽了
                if (r.getImportance() == NotificationListenerService.Ranking.IMPORTANCE_NONE
                        || !noteNotificationOp(pkg, callingUid) || isPackageSuspended) {
                    if (!isSystemNotification) {
                        if (isPackageSuspended) {
                            Slog.e(TAG, "Suppressing notification from package due to package "
                                    + "suspended by administrator.");
                            mUsageStats.registerSuspendedByAdmin(r);
                            Log.i("a", "NotificationManagerService: 2695");
                        } else {
                            Slog.e(TAG, "Suppressing notification from package by user request.");
                            mUsageStats.registerBlocked(r);
                            Log.i("a", "NotificationManagerService: 2699");
                        }
                        return;
                    }
                }

                // tell the ranker service about the notification
                if (mRankerServices.isEnabled()) {
                    mRankerServices.onNotificationEnqueued(r);
                    Log.i("a", "NotificationManagerService: 2708");
                    // TODO delay the code below here for 100ms or until there is an answer
                }


                int index = indexOfNotificationLocked(n.getKey());
                if (index < 0) {
                    mNotificationList.add(r);
                    mUsageStats.registerPostedByApp(r);
                    Log.i("a", "NotificationManagerService: 2717");
                } else {
                    old = mNotificationList.get(index);
                    mNotificationList.set(index, r);
                    mUsageStats.registerUpdatedByApp(r, old);
                    // Make sure we don't lose the foreground service state.
                    notification.flags |=
                            old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;
                    r.isUpdate = true;
                    Log.i("a", "NotificationManagerService: 2726");
                }

                mNotificationsByKey.put(n.getKey(), r);

                // Ensure if this is a foreground service that the proper additional
                // flags are set.
                if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
                    notification.flags |= Notification.FLAG_ONGOING_EVENT
                            | Notification.FLAG_NO_CLEAR;
                    Log.i("a", "NotificationManagerService: 2736");
                }

                applyZenModeLocked(r);
                mRankingHelper.sort(mNotificationList);

                if (notification.getSmallIcon() != null) {
                    StatusBarNotification oldSbn = (old != null) ? old.sbn : null;
                    mListeners.notifyPostedLocked(n, oldSbn);
                    Log.i("a", "NotificationManagerService: 2745");
                } else {
                    Slog.e(TAG, "Not posting notification without small icon: " + notification);
                    if (old != null && !old.isCanceled) {
                        mListeners.notifyRemovedLocked(n);
                        Log.i("a", "NotificationManagerService: 2750");
                    }
                    // ATTENTION: in a future release we will bail out here
                    // so that we do not play sounds, show lights, etc. for invalid
                    // notifications
                    Slog.e(TAG, "WARNING: In a future release this will crash the app: "
                            + n.getPackageName());
                }

                buzzBeepBlinkLocked(r);
            }
        }
    }

下面来看看buzzBeepBlinkLocked这个函数


    @VisibleForTesting
    void buzzBeepBlinkLocked(NotificationRecord record) {
        boolean buzz = false;
        boolean beep = false;
        boolean blink = false;

        final Notification notification = record.sbn.getNotification();
        final String key = record.getKey();

        // Should this notification make noise, vibe, or use the LED?
        final boolean aboveThreshold = record.getImportance() >= IMPORTANCE_DEFAULT;
        final boolean canInterrupt = aboveThreshold && !record.isIntercepted();
        if (DBG || record.isIntercepted())
            Slog.v(TAG,
                    "pkg=" + record.sbn.getPackageName() + " canInterrupt=" + canInterrupt +
                            " intercept=" + record.isIntercepted()
            );

        final int currentUser;
        final long token = Binder.clearCallingIdentity();
        try {
            currentUser = ActivityManager.getCurrentUser();
        } finally {
            Binder.restoreCallingIdentity(token);
        }
        Log.i("a", "NotificationManagerService: 2837");

        // If we're not supposed to beep, vibrate, etc. then don't.
        final String disableEffects = disableNotificationEffects(record);
        if (disableEffects != null) {
            ZenLog.traceDisableEffects(record, disableEffects);
            Log.i("a", "NotificationManagerService: 2843");
        }

        // Remember if this notification already owns the notification channels.
        boolean wasBeep = key != null && key.equals(mSoundNotificationKey);
        boolean wasBuzz = key != null && key.equals(mVibrateNotificationKey);

        // These are set inside the conditional if the notification is allowed to make noise.
        boolean hasValidVibrate = false;
        boolean hasValidSound = false;

        boolean smsRingtone =  false;
        if (mCarrierConfig != null) {
            smsRingtone = mCarrierConfig.getBoolean(
                CarrierConfigManager.KEY_CONFIG_SMS_RINGTONE_INCALL);
            Log.i("a", "NotificationManagerService: 2858");
        }
        Log.i("a", "NotificationManagerService: 2860");
        // 这里就是我们要加flag判断的地方。如果要silent通知就不要进这个if判断,我们可以在这个if外面在多加一个我们的flag。
        if ((disableEffects == null || (smsRingtone && mInCall))
                && (record.getUserId() == UserHandle.USER_ALL ||
                    record.getUserId() == currentUser ||
                    mUserProfiles.isCurrentProfile(record.getUserId()))
                && canInterrupt
                && mSystemReady
                && mAudioManager != null) {
            if (DBG) Slog.v(TAG, "Interrupting!");
            Log.i("a", "NotificationManagerService: 2869");

            // should we use the default notification sound? (indicated either by
            // DEFAULT_SOUND or because notification.sound is pointing at
            // Settings.System.NOTIFICATION_SOUND)
            final boolean useDefaultSound =
                   (notification.defaults & Notification.DEFAULT_SOUND) != 0 ||
                           Settings.System.DEFAULT_NOTIFICATION_URI
                                   .equals(notification.sound);

            Uri soundUri = null;
            if (useDefaultSound) {
                soundUri = Settings.System.DEFAULT_NOTIFICATION_URI;

                // check to see if the default notification sound is silent
                hasValidSound = mSystemNotificationSound != null;
                Log.i("a", "NotificationManagerService: 2884");
            } else if (notification.sound != null) {
                soundUri = notification.sound;
                hasValidSound = (soundUri != null);
                Log.i("a", "NotificationManagerService: 2888");
            }

            // Does the notification want to specify its own vibration?
            final boolean hasCustomVibrate = notification.vibrate != null;

            // new in 4.2: if there was supposed to be a sound and we're in vibrate
            // mode, and no other vibration is specified, we fall back to vibration
            final boolean convertSoundToVibration =
                    !hasCustomVibrate
                            && hasValidSound
                            && (mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE);

            // The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback.
            final boolean useDefaultVibrate =
                    (notification.defaults & Notification.DEFAULT_VIBRATE) != 0;

            hasValidVibrate = useDefaultVibrate || convertSoundToVibration ||
                    hasCustomVibrate;

            Log.i("a", "useDefaultVibrate || convertSoundToVibration hasCustomVibrate  "+useDefaultVibrate+convertSoundToVibration+hasCustomVibrate);

            // We can alert, and we're allowed to alert, but if the developer asked us to only do
            // it once, and we already have, then don't.
            if (!(record.isUpdate
                    && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0)) {

                sendAccessibilityEvent(notification, record.sbn.getPackageName());

                if (hasValidSound) {
                    boolean looping =
                            (notification.flags & Notification.FLAG_INSISTENT) != 0;
                    AudioAttributes audioAttributes = audioAttributesForNotification(notification);
                    mSoundNotificationKey = key;
                    // do not play notifications if stream volume is 0 (typically because
                    // ringer mode is silent) or if there is a user of exclusive audio focus
                    if ((mAudioManager.getStreamVolume(
                            AudioAttributes.toLegacyStreamType(audioAttributes)) != 0)
                            && !mAudioManager.isAudioFocusExclusive()) {
                        final long identity = Binder.clearCallingIdentity();
                        try {
                            final IRingtonePlayer player =
                                    mAudioManager.getRingtonePlayer();
                            if (player != null) {
                                if (DBG) Slog.v(TAG, "Playing sound " + soundUri
                                        + " with attributes " + audioAttributes);
                                player.playAsync(soundUri, record.sbn.getUser(), looping,
                                        audioAttributes);
                                beep = true;
                            }
                        } catch (RemoteException e) {
                        } finally {
                            Binder.restoreCallingIdentity(identity);
                        }
                    }
                }

                if (hasValidVibrate && !(mAudioManager.getRingerModeInternal()
                        == AudioManager.RINGER_MODE_SILENT)) {
                    mVibrateNotificationKey = key;

                    if (useDefaultVibrate || convertSoundToVibration) {
                        // Escalate privileges so we can use the vibrator even if the
                        // notifying app does not have the VIBRATE permission.
                        long identity = Binder.clearCallingIdentity();
                        try {
                            mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
                                    useDefaultVibrate ? mDefaultVibrationPattern
                                            : mFallbackVibrationPattern,
                                    ((notification.flags & Notification.FLAG_INSISTENT) != 0)
                                            ? 0: -1, audioAttributesForNotification(notification));
                            buzz = true;
                        } finally {
                            Binder.restoreCallingIdentity(identity);
                        }
                    } else if (notification.vibrate.length > 1) {
                        // If you want your own vibration pattern, you need the VIBRATE
                        // permission
                        mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
                                notification.vibrate,
                                ((notification.flags & Notification.FLAG_INSISTENT) != 0)
                                        ? 0: -1, audioAttributesForNotification(notification));
                        buzz = true;
                    }
                }
            }

        }

        Log.i("a", "NotificationManagerService: 2977");
        // If a notification is updated to remove the actively playing sound or vibrate,
        // cancel that feedback now
        if (wasBeep && !hasValidSound) {
            clearSoundLocked();
            Log.i("a", "NotificationManagerService: 2982");
        }
        if (wasBuzz && !hasValidVibrate) {
            clearVibrateLocked();
            Log.i("a", "NotificationManagerService: 2986");
        }

        // light
        // release the light
        boolean wasShowLights = mLights.remove(key);
        if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 && aboveThreshold
                && ((record.getSuppressedVisualEffects()
                & NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF) == 0)) {
            Log.i("a", "NotificationManagerService: 2995");
            mLights.add(key);
            updateLightsLocked();
            if (mUseAttentionLight) {
                mAttentionLight.pulse();
            }
            blink = true;
        } else if (wasShowLights) {
            updateLightsLocked();
            Log.i("a", "NotificationManagerService: 3004");
        }


        if (buzz || beep || blink) {
            if (((record.getSuppressedVisualEffects()
                    & NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF) != 0)) {
                if (DBG) Slog.v(TAG, "Suppressed SystemUI from triggering screen on");
            } else {
                EventLogTags.writeNotificationAlert(key,
                        buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0);
                mHandler.post(mBuzzBeepBlinked);
            }
        }
    }

关于声音、震动、灯光就在上面这处理的。

2.StatusBar部分,控制通知的显示,Headsup就在这控制。
BaseStatusBar.java
当有通知从NotificationManagerService过来后,就会走onNotificationPosted。onNotificationPosted会根据通知是新增还是更新做不同的处理,所以我们要在2个地方去阻止通知显示。


        @Override
        public void onNotificationPosted(final StatusBarNotification sbn,
                final RankingMap rankingMap) {
            if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);
            Log.i("a", "StatusBarNotification "+sbn);
            Log.i("a", "Notification "+sbn.getNotification());
            if (sbn != null) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        processForRemoteInput(sbn.getNotification());
                        String key = sbn.getKey();
                        mKeysKeptForRemoteInput.remove(key);
                        boolean isUpdate = mNotificationData.get(key) != null;
                        // In case we don't allow child notifications, we ignore children of
                        // notifications that have a summary, since we're not going to show them
                        // anyway. This is true also when the summary is canceled,
                        // because children are automatically canceled by NoMan in that case.
                        if (!ENABLE_CHILD_NOTIFICATIONS
                            && mGroupManager.isChildInGroupWithSummary(sbn)) {
                            if (DEBUG) {
                                Log.d(TAG, "Ignoring group child due to existing summary: " + sbn);
                            }

                            // Remove existing notification to avoid stale data.
                            if (isUpdate) {
                                removeNotification(key, rankingMap);
                            } else {
                                mNotificationData.updateRanking(rankingMap);
                            }
                            return;
                        }
                        if (isUpdate) {
                            updateNotification(sbn, rankingMap);
                            Log.i("a", "StatusBar:  "+653);
                        } else {
                            addNotification(sbn, rankingMap, null /* oldEntry */);
                            Log.i("a", "StatusBar:  "+656);
                        }
                    }
                });
            }
        }

首先看updateNotification,这个函数在BaseStatusBar.java中


    public void updateNotification(StatusBarNotification notification, RankingMap ranking) {
        if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");

        final String key = notification.getKey();
        Entry entry = mNotificationData.get(key);
        if (entry == null) {
            return;
        } else {
            mHeadsUpEntriesToRemoveOnSwitch.remove(entry);
            mRemoteInputEntriesToRemoveOnCollapse.remove(entry);
        }

        Notification n = notification.getNotification();
        mNotificationData.updateRanking(ranking);

        boolean applyInPlace;
        try {
            applyInPlace = entry.cacheContentViews(mContext, notification.getNotification());
        } catch (RuntimeException e) {
            Log.e(TAG, "Unable to get notification remote views", e);
            applyInPlace = false;
        }
        boolean shouldPeek = shouldPeek(entry, notification);
        //这里会根据shouldPeek的值,来处理是否显示headsup通知,所以把shouldPeek该成false就可以阻止了。
        Log.i("a", "StatusBar: set shouldPeek updateNotification  "+shouldPeek);
        Log.i("a", "StatusBar:  "+2407);
        boolean alertAgain = alertAgain(entry, n);
        if (DEBUG) {
            Log.d(TAG, "applyInPlace=" + applyInPlace
                    + " shouldPeek=" + shouldPeek
                    + " alertAgain=" + alertAgain);
        }

        final StatusBarNotification oldNotification = entry.notification;
        entry.notification = notification;
        mGroupManager.onEntryUpdated(entry, oldNotification);

        boolean updateSuccessful = false;
        if (applyInPlace) {
            Log.i("a", "StatusBar:  "+2421);
            if (DEBUG) Log.d(TAG, "reusing notification for key: " + key);
            try {
                if (entry.icon != null) {
                    Log.i("a", "StatusBar:  "+2425);
                    // Update the icon
                    final StatusBarIcon ic = new StatusBarIcon(
                            notification.getUser(),
                            notification.getPackageName(),
                            n.getSmallIcon(),
                            n.iconLevel,
                            n.number,
                            StatusBarIconView.contentDescForNotification(mContext, n));
                    entry.icon.setNotification(n);
                    if (!entry.icon.set(ic)) {
                        Log.i("a", "StatusBar:  "+2436);
                        handleNotificationError(notification, "Couldn't update icon: " + ic);
                        return;
                    }
                }
                Log.i("a", "StatusBar:  "+2441);
                updateNotificationViews(entry, notification);
                updateSuccessful = true;
            }
            catch (RuntimeException e) {
                // It failed to apply cleanly.
                Log.w(TAG, "Couldn't reapply views for package " +
                        notification.getPackageName(), e);
            }
        }
        if (!updateSuccessful) {
            Log.i("a", "StatusBar:  "+2452);
            if (DEBUG) Log.d(TAG, "not reusing notification for key: " + key);
            final StatusBarIcon ic = new StatusBarIcon(
                    notification.getUser(),
                    notification.getPackageName(),
                    n.getSmallIcon(),
                    n.iconLevel,
                    n.number,
                    StatusBarIconView.contentDescForNotification(mContext, n));
            entry.icon.setNotification(n);
            entry.icon.set(ic);
            if (!inflateViews(entry, mStackScroller)) {
                Log.i("a", "StatusBar:  "+2464);
                handleNotificationError(notification, "Couldn't update remote views for: "
                        + notification);
            }
        }
        updateHeadsUp(key, entry, shouldPeek, alertAgain);
        updateNotifications();

        if (!notification.isClearable()) {
            Log.i("a", "StatusBar:  "+2473);
            // The user may have performed a dismiss action on the notification, since it's
            // not clearable we should snap it back.
            mStackScroller.snapViewIfNeeded(entry.row);
        }

        if (DEBUG) {
            // Is this for you?
            boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
            Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
        }

        setAreThereNotifications();
    }

addNotification是在PhoneStatusBar.java中实现的。


    @Override
    public void addNotification(StatusBarNotification notification, RankingMap ranking,
            Entry oldEntry) {
        if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey());

        mNotificationData.updateRanking(ranking);
        Entry shadeEntry = createNotificationViews(notification);
        if (shadeEntry == null) {
            return;
        }
        boolean isHeadsUped = shouldPeek(shadeEntry);
        // 和updateNotification那一样,把isHeadsUped设置成false就可以阻止了。
        Log.i("a", "PhoneStatusBar: set is headsuped false");
        Log.i("a", "PhoneStatusBar:  "+isHeadsUped+1575);
        if (isHeadsUped) {
            mHeadsUpManager.showNotification(shadeEntry);
            // Mark as seen immediately
            setNotificationShown(notification);
            Log.i("a", "PhoneStatusBar:  "+1582);
        }

        if (!isHeadsUped && notification.getNotification().fullScreenIntent != null) {
            if (shouldSuppressFullScreenIntent(notification.getKey())) {
                if (DEBUG) {
                    Log.i("a", "PhoneStatusBar:  "+1586);
                    Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + notification.getKey());
                }
            } else if (mNotificationData.getImportance(notification.getKey())
                    < NotificationListenerService.Ranking.IMPORTANCE_MAX) {
                if (DEBUG) {
                    Log.i("a", "PhoneStatusBar:  "+1592);
                    Log.d(TAG, "No Fullscreen intent: not important enough: "
                            + notification.getKey());
                }
            }else if(!isHeadsUped) {
                Log.i("a", "PhoneStatusBar:  "+1599);
            }
            else {
                Log.i("a", "PhoneStatusBar:  "+1597);
                // Stop screensaver if the notification has a full-screen intent.
                // (like an incoming phone call)
                awakenDreams();

                // not immersive & a full-screen alert should be shown
                if (DEBUG)
                    Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
                try {
                    EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
                            notification.getKey());
                    notification.getNotification().fullScreenIntent.send();
                    shadeEntry.notifyFullScreenIntentLaunched();
                    MetricsLogger.count(mContext, "note_fullscreen", 1);
                } catch (PendingIntent.CanceledException e) {
                }
            }
        }
        addNotificationViews(shadeEntry, ranking);
        // Recalculate the position of the sliding windows and the titles.
        setAreThereNotifications();
    }

最后看看shouldPeek,在BaseStatusBar.java中实现


    protected boolean shouldPeek(Entry entry, StatusBarNotification sbn) {
        Log.i("a", "StatusBar:  "+2548);
        if (!mUseHeadsUp || isDeviceInVrMode()) {
            Log.i("a", "StatusBar:  "+2550);
            return false;
        }

        if (mNotificationData.shouldFilterOut(sbn)) {
            if (DEBUG) Log.d(TAG, "No peeking: filtered notification: " + sbn.getKey());
            Log.i("a", "StatusBar:  "+2556);
            return false;
        }

        boolean inUse = mPowerManager.isScreenOn();
        try {
            inUse = inUse && !mDreamManager.isDreaming();
            Log.i("a", "StatusBar:  "+2563);
        } catch (RemoteException e) {
            Log.d(TAG, "failed to query dream manager", e);
        }

        if (!inUse) {
            if (DEBUG) {
                Log.d(TAG, "No peeking: not in use: " + sbn.getKey());
            }
            Log.i("a", "StatusBar:  "+2572);
            return false;
        }

        if (mNotificationData.shouldSuppressScreenOn(sbn.getKey())) {
            if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
            Log.i("a", "StatusBar:  "+2578);
            return false;
        }

        if (entry.hasJustLaunchedFullScreenIntent()) {
            if (DEBUG) Log.d(TAG, "No peeking: recent fullscreen: " + sbn.getKey());
            Log.i("a", "StatusBar:  "+2584);
            return false;
        }

        if (isSnoozedPackage(sbn)) {
            if (DEBUG) Log.d(TAG, "No peeking: snoozed package: " + sbn.getKey());
            Log.i("a", "StatusBar:  "+2590);
            return false;
        }

        // 在settings中设置了show silently后,就会走这里。只要这个shouldPeek函数返回false,就不会显示headsup这样的通知。
        if (mNotificationData.getImportance(sbn.getKey()) < IMPORTANCE_HIGH) {
            if (DEBUG) Log.d(TAG, "No peeking: unimportant notification: " + sbn.getKey());
            Log.i("a", "StatusBar:  "+2596);
            return false;
        }

        if (sbn.getNotification().fullScreenIntent != null) {
            if (mAccessibilityManager.isTouchExplorationEnabled()) {
                if (DEBUG) Log.d(TAG, "No peeking: accessible fullscreen: " + sbn.getKey());
                Log.i("a", "StatusBar:  "+2603);
                return false;
            } else {
                Log.i("a", "StatusBar:  "+2606);
                // we only allow head-up on the lockscreen if it doesn't have a fullscreen intent
                return !mStatusBarKeyguardViewManager.isShowing()
                        || mStatusBarKeyguardViewManager.isOccluded();
            }
        }

        return true;
    }

最后在settings数据库中加入自己的字段做flag,在上面的地方来判断,是否开启这个模式。开启后就可以实现和系统自带的Settings->Notifications中Show silently一样的效果了,也不会和系统这个功能有冲突。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值