发布网友 发布时间:2023-04-21 19:08
共1个回答
热心网友 时间:2023-10-16 12:33
Android应用除了组件和窗口管理,还有通知显示也是非常重要的,通知是应用界面之外向用户显示的界面。 NotificationListenerService继承于Service,该服务是为了给app提供获取通知的新增和删除事件,通知的数量和内容等相关信息的途径,该类的主要方法:
常见的Flags:
关于前台服务是用户可感知的,前台服务需要显示一个通知,比如后台播放音乐。
创建通知过程,此处的PendingIntent是当通知被点击后的跳转动作,可以是启动Activity、Service,或者发送Broadcast。 对于更新通知只需要发送notifyID相同的通知即可。
除了调用NotificationManager的cancel()或者cancelAll(),也可
点击查看大图
点击查看大图
可见,通知发送与通知取消流程的步骤一直对齐,这里就只介绍通知发送流程,通知取消流程就不再介绍。
[-> NotificationManager.java]
在App端调用NotificationManager类的notify()方法,最终通过binder调用,会进入system_server进程的 NotificationManagerService(简称NMS),执行enqueueNotificationWithTag()方法。
[-> NotificationManagerService.java]
这个过程主要功能:
接下来看看WorkerHandler到底运行在哪个线程,这需要从NMS服务初始化过程来说起:
[-> SystemServer.java]
该过程运行在system_server进程的主线程。
[-> SystemServiceManager.java]
该过程先创建NotificationManagerService(简称NMS),然后再调用其onStart方法。
[-> NMS.java]
到此,我们可以得知onStart()过程创建的mHandler运行在system_server的主线程。那么上面的执行流便进入了 system_server主线程。
[-> NMS.java]
这里的mListeners是指NotificationListeners对象
[-> NMS.java]
这里是在system_server进程中第二次采用异步方式来处理。
此处的listener来自于ManagedServiceInfo的service成员变量,listener数据类型是NotificationListenerWrapper的代理对象,详见第三大节。 此处sbnHolder的数据类型为StatusBarNotificationHolder,继承于IStatusBarNotificationHolder.Stub对象,经过binder调用进入到systemui进程的 便是IStatusBarNotificationHolder.Stub.Proxy对象。
[-> NotificationListenerService.java]
此时运行在systemui进程,sbnHolder是IStatusBarNotificationHolder的代理端。 此处mHandler = new MyHandler(getMainLooper()),也就是运行在systemui主线程的handler
[-> NotificationListenerService.java]
此处调用NotificationListenerService实例对象的onNotificationPosted()
[-> BaseStatusBar.java]
此处的mHandler便是systemui的主线程
[-> PhoneStatusBar.java]
如果创建的通知视图为空则会直接返回。
[-> BaseStatusBar.java]
[-> SystemServer.java]
[-> SystemServer.java]
启动服务SystemUIService,运行在进程com.android.systemui,接下来进入systemui进程
[-> SystemUIService.java]
服务启动后,先执行其onCreate()方法
[-> SystemUIApplication.java]
此处以SystemBars为例来展开
[-> SystemUIApplication.java]
[-> SystemBars.java]
[-> SystemBars.java]
config_statusBarComponent的定义位于文件config.xml中,其值为PhoneStatusBar。
[-> PhoneStatusBar.java]
[-> BaseStatusBar.java]
[-> NotificationListenerService.java]
经过binder调用,向system_server中的NMS注册*
[-> NMS.java]
mListeners的对象类型为ManagedServices。此处的INotificationListener便是NotificationListenerWrapper的代理对象
[-> ManagedServices.java]
[-> ManagedServices.java]
[-> ManagedServices.java]
可见,前面的listener的对端便是运行在systemui中的NotificationListenerWrapper的代理对象。
整个过程涉及到3个Handler都是运行在system_server的主线程:NMS的mHandler,NLS的mHandler以及BaseStatusBar的mHandler。
一次通知发送的过程,在system_server进程里面经过了步骤[2.3],[2.4]的两次异步调用,进入systemui进程,也经历[2.6],[2.8]共两次异步调用。 本身是异步调用,再进过一次异步意义并不大。
另外,这里需要注意的是前台服务也会显示通知,该通知是为了提升服务的优先级,并且让用户可感知该服务的存在,以防止进程被杀,比如音乐播放。 对于常规的通知可通过点击通知(允许清除的通知)或者点击通知栏的清除按钮来清除。