notification源码分析_Android O 8.0 Notification 源码分析(一)

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

本编主要介绍生成过程:App create Notification –> System’s  NotificationManagerService。

另外一编介绍展示过程:System Notification –> SystemUI –> Display Notifications,

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

下面直接上流程图。

上图为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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值