前言
在上篇文章中,我们已经大概了解了SystemUI的启动流程及结构框架,本文将从Android 15源码层面研究通知相关的发送和显示逻辑。
通知整体交互
一条通知发出要经过三个进程:APP进程、SystemServer进程和SystemUI进程,APP进程发出通知、SystemServer进程统一存储并通知注册的NotificationListenerService,SystemUI显示通知并处理通知事件。
一、通知的发送逻辑
一般来说,如果 app 想发送一条新的通知,都会使用到以下代码
val skipIntent = Intent(context, ResultActivity::class.java)
val clickPendingIntent = PendingIntent.getActivity(context, 0, skipIntent, PendingIntent.FLAG_MUTABLE)
val action = NotificationCompat.Action.Builder(null, "动作", clickPendingIntent).build()
val notificationCompat = NotificationCompat.Builder(context, PUSH_CHANNEL)
.setSmallIcon(R.drawable.small_icon)
.setContentTitle("标题")
.setContentText("内容")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setWhen(System.currentTimeMillis())
.addAction(action)
NotificationManagerCompat.from(context).notify(123, notificationCompat.build())
可以看到我们通过 NotificationCompat.Builder 新建了一个 Notification 对象,最后通过 NotificationManagerCompat#notify() 方法将 Notification 发送出去。
具体在内部是怎么实现的?
大概流程如下:
大体上经历下面几个步骤:
- 当一个APP要发出通知,会调用NotificationManagerCompat.notify(),并带上APP进程的信息。
- APP要把通知发送到SystemServer进程,需要跨进程,首先获取NotificationManagerService的代理,跨进程调用NotificationManagerService的方法。
- 进入NotificationManagerService,先把通知加入到通知队列,然后遍历注册到NotificationManagerService中的NotificationListenerService,把通知分发给NotificationListenerService。
- SystemUI收到通知后对通知进行后续处理,比如数据过滤筛选。
- SystemUI在数据处理完成后,通过调用SystemServer进程创建RemoteViews然后回调给SystemUI对视图进行加载。
二、通知的显示逻辑
SystemUI在启动的时候会注册NotificationListener,后续监听到通知后,经过一系列中转和数据筛选把通知显示出来。
主要时序图如下:
主要流程包括以下几步:
- SystemUI在启动CentralSurfacesImpl服务的时候通过Dagger进行注册NotificationListenerService,所以收到通知消息后会直接回调到NotificationListener。
- NotificationListener获取到通知后,会将通知分发给NotificationHandler,再经过NotifCollection的一系列中转并封装成NotificationEntry,最后通过onBuildList回调给ShadeListBuilder。
- ShadeListBuilder在收到回调后,对通知进行筛选、过滤、排序、分组等操作最后生成一个新的通知列表。
- 新的通知列表通过NotifViewRenderer接口分发给ShadeViewDiffer对View进行操作,如add、remove等。
三、小结
本文从总体上介绍了通知的发送和显示逻辑,旨在对整体框架有一个理解。
如果对某个流程感兴趣也可在评论区留言,后续将针对进行文章分析。