美文网首页Android 源码
Android 8.0 Notification 源码分析(一)

Android 8.0 Notification 源码分析(一)

作者: 撸铁敲代码 | 来源:发表于2018-08-13 22:53 被阅读1次

    最近在搞SystemUI。这几天把Notification的流程整理了一遍。好记性不如烂博客。

    本编主要介绍的为Notification从App产生到System中的流程。

    另外一编讲诉的为SystemUI中怎样展示Notification

    《Android O 8.0 Notification 源码分析(二)》

    值得注意的是在AndroidO 8.0中,notification有了改变,使用NotificationChannel类。具体使用参加下面的demo.

    下面直接上流程图。


    App->System Notification流程

    上图为Apps产生Notification怎么发送到系统的中的流程图。

    下面看代码:

    步骤1,2,3,4 : MainActivity生产Notification准备工作。

        @RequiresApi(api = Build.VERSION_CODES.O)
        public void sendNotification(View view) {
            String id = "channel_0";
            String des = "111";
            NotificationChannel channel = new NotificationChannel(id, des, NotificationManager.IMPORTANCE_MIN);
            notificationManager.createNotificationChannel(channel);
            Notification notification = new Notification.Builder(MainActivity.this, id)
                    .setContentTitle("Base Notification View")
                    .setContentText("您有一条新通知")
                    .setSmallIcon(R.drawable.jd_icon)
                    .setStyle(new Notification.MediaStyle())
                    .setAutoCancel(false)
                    .build();
            notificationManager.notify(1, notification);
        }
    

    步骤5,6: NotificationManager发送notification。最后调用到notifyAsUser()方法:

        public void notifyAsUser(String tag, int id, Notification notification, UserHandle user)
        {
            // 获取NotificationManager的Service
            INotificationManager service = getService();
            String pkg = mContext.getPackageName();
            ...
            notification.reduceImageSizes(mContext);
            ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
            boolean isLowRam = am.isLowRamDevice();
            final Notification copy = Builder.maybeCloneStrippedForDelivery(notification, isLowRam);
            try {
                service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id, copy, user.getIdentifier());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    

    步骤7,8,9,10: 根据Android的规律,INotificationManager对应的service为NotificationManagerService.最后直接enqueueNotificationInternal()方法。

    void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid, final int callingPid, final String tag, final int id, final Notification notification, int incomingUserId) {
            if (DBG) {
                Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id
                        + " notification=" + notification);
            }
            checkCallerIsSystemOrSameApp(pkg);
     
            ...
     
            final StatusBarNotification n = new StatusBarNotification(
                    pkg, opPkg, id, tag, notificationUid, callingPid, notification,
                    user, null, System.currentTimeMillis());
            // 把notification的对象做了备份
            final NotificationRecord r = new NotificationRecord(getContext(), n, channel);
     
            if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0
                    && (channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0
                    && (r.getImportance() == IMPORTANCE_MIN || r.getImportance() == IMPORTANCE_NONE)) {
                // Increase the importance of foreground service notifications unless the user had an
                // opinion otherwise
                if (TextUtils.isEmpty(channelId)
                        || NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {
                    r.setImportance(IMPORTANCE_LOW, "Bumped for foreground service");
                } else {
                    channel.setImportance(IMPORTANCE_LOW);
                    mRankingHelper.updateNotificationChannel(pkg, notificationUid, channel, false);
                    r.updateNotificationChannel(channel);
                }
            }
     
            if (!checkDisqualifyingFeatures(userId, notificationUid, id, tag, r,
                    r.sbn.getOverrideGroupKey() != null)) {
                return;
            }
     
            // Whitelist pending intents.
            if (notification.allPendingIntents != null) {
                final int intentCount = notification.allPendingIntents.size();
                if (intentCount > 0) {
                    final ActivityManagerInternal am = LocalServices
                            .getService(ActivityManagerInternal.class);
                    final long duration = LocalServices.getService(
                            DeviceIdleController.LocalService.class).getNotificationWhitelistDuration();
                    for (int i = 0; i < intentCount; i++) {
                        PendingIntent pendingIntent = notification.allPendingIntents.valueAt(i);
                        if (pendingIntent != null) {
                            am.setPendingIntentWhitelistDuration(pendingIntent.getTarget(),
                                    WHITELIST_TOKEN, duration);
                        }
                    }
                }
            }
     
            mHandler.post(new EnqueueNotificationRunnable(userId, r));
        }
    

    步骤11:handler.post( EnqueueNotificationRunnable run):

    @Override
            public void run() {
                synchronized (mNotificationLock) {
                    mEnqueuedNotifications.add(r);
                    scheduleTimeoutLocked(r);
     
                    final StatusBarNotification n = r.sbn;
                    ...
     
                    // tell the assistant service about the notification
                    if (mAssistants.isEnabled()) {
                        mAssistants.onNotificationEnqueued(r);
                        mHandler.postDelayed(new PostNotificationRunnable(r.getKey()),
                                DELAY_FOR_ASSISTANT_TIME);
                    } else {
                        mHandler.post(new PostNotificationRunnable(r.getKey()));
                    }
                }
            }
    

    步骤12,13:handler.post( PostNotificationRunnable run):

    @Override
            public void run() {
                synchronized (mNotificationLock) {
                    try {
                        NotificationRecord r = null;
                        int N = mEnqueuedNotifications.size();
                        for (int i = 0; i < N; i++) {
                            final NotificationRecord enqueued = mEnqueuedNotifications.get(i);
                            if (Objects.equals(key, enqueued.getKey())) {
                                r = enqueued;
                                break;
                            }
                        }
                        ...
                        mNotificationsByKey.put(n.getKey(), r);
                        ...
                        //没有SmallIcon会失败
                        if (notification.getSmallIcon() != null) {
                            StatusBarNotification oldSbn = (old != null) ? old.sbn : null;
                            mListeners.notifyPostedLocked(n, oldSbn);
                            ...
                        } else {
                            Slog.e(TAG, "Not posting notification without small icon: " + notification);
                            ...
                        }
     
                        buzzBeepBlinkLocked(r);
                    } finally {
                        int N = mEnqueuedNotifications.size();
                        for (int i = 0; i < N; i++) {
                            final NotificationRecord enqueued = mEnqueuedNotifications.get(i);
                            if (Objects.equals(key, enqueued.getKey())) {
                                mEnqueuedNotifications.remove(i);
                                break;
                            }
                        }
                    }
                }
            }
    

    步骤14:调用NotificationManagerService.NotificationListeners --> notifyPostedLocked() --> notifyPosted() --> NotificationListenerService.onNotificationPosted();

    OK,上面描述了Notification从App应用,产生到系统的流程。

    另外一编讲诉的为SystemUI中怎样展示Notification

    《Android O 8.0 Notification 源码分析(二)》

    相关文章

      网友评论

        本文标题:Android 8.0 Notification 源码分析(一)

        本文链接:https://www.haomeiwen.com/subject/vempbftx.html