通知流程,从框架到应用
我们都知道,Android应用想要发送通知,都需要先用Notification.Builder来构建一个通知,然后NotificationManager.notify()来将这个通知发送出来。发送出来的通知Notification将通过Binder通信,在框架中被处理后,封装成StatusBarNotification,传递到systemUI系统应用中,在通知栏中呈现出ExpandableNotificationRow。下面的图表示了这一流程
讲解流程之前,我们可以先来看下,Notification和StatusBarNotifacation之间的关系。PS:这里具体讲后者,对于前者的介绍,大家可以网上了解。Notifiaction类里面包含了很多信息,主要包括应用信息,布局信息等。
StatusBarNotification
先上图
先看最上面的两行介绍:StatusBarNotification封装了Notifiaction。由NotificationManagerService发送给客户端,客户端包括状态栏(也就是我们的systemUI)以及注册了NotificationListenerService的应用。事实上,这不是通过广播的形式进行的跨进程通信,而是Binder通信机制,状态栏中也注册了NLService服务。
机制大概如下
然后再看看StatusBarNotification中的属性
- pkg
- id
- tag
- uid
- notification
从notify()开始
NotificationManager.notify() –> NotificationManager.notifyAsUser()–> service.enqueNotificationWithTag()–>NMS.enqueueNotificationInternal()
然后在enqueueNotificationInternal中将通知Notification封装成StatusBarNotifitio,如图所示:
最后会执行Runnable中任务。在该任务里面,会根据是否有SmallIcon来执行不同的方法
最后会执行到notifyPosted()方法中
在04266行代码可以看出,这样,我们的框架就可以和systemUI进程联系起来了。通知经过APP发送后,经过framework层进行包装,最后通过onNotificationPosted方法在SystemUI中被获取到,继而执行一系列通知的显示处理操作。注意,这里的listener.onNotificationPosted方法并不是会直接走到SystemUI中BaseStatusBar中的onNotificationPosted,而是通过NotificationWrapListener以及消息官发管道的方式最终和SystemUI取得联系。这样做的目的在于避免NotificationManagerService可以有序地处理不同的通知监听器。前面框架中一条线执行到NMS.notifyPostedLocked。这里面会有个for()循环,这个是用来处理不同客户端的NotificationListenerService的。我们的SystemUI只占用了其中一个service。也就是说NotificationManagerService中会有多个Stub,他们来自于不同的客户端请求。 下面打印一份来一条通知的具体流程:
从上面可以看出来,NotificationManagerService中有4个NotificationLisenterService服务,其中一个来自SystemUI。简单排列一下,如下图
①NotifyAsUser()–>②enqueueNotificationWithTag()–>③enqueueNotificationInternal()–>
④enqueueNotificationRunnable.run()–>⑤notifyPostedLocked()–>⑥for(mServices){
notifyPosted()–>
NLW.onNotificationPosted()–>
sendMessage(POSTED)–>obtainMessage(POSTED)–>
NotificationListenerService.onNotificationPosted()//SystemUI中有复写该方法
}
其中,①–>②步骤是APP侧和框架层通信的地方,service.enqueueNotificationWithTag()这一句执行在NotificationManager.java中,service为
这个sService其实就是NotificationManagerService中的mService
所以。我们上面执行的enqueueNotificationWithTag来自这儿。
以上