25 NotificationListenerService通知机制

Python042

25 NotificationListenerService通知机制,第1张

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]共两次异步调用。 本身是异步调用,再进过一次异步意义并不大。

另外,这里需要注意的是前台服务也会显示通知,该通知是为了提升服务的优先级,并且让用户可感知该服务的存在,以防止进程被杀,比如音乐播放。 对于常规的通知可通过点击通知(允许清除的通知)或者点击通知栏的清除按钮来清除。

java中的事件监听不是通过线程实现的,它是通过一种注册--通知机制实现的。在java的设计模式中,有一种模式叫:观察者模式,和这个类似。

举个例子,本例子是一个简单的监听当数据发生变化时要做的操作:

1,我们先定义一个接口,可以让多个监听者实现

2、实现一监听者

3、被监听者

4、main方法里面是监听的应用。这样就可以监听DataManager中的updateData行为了,当有数据发生变化时,就可以即时被监听者收到。

java消息通知有两种方案:

1.如果是平台级别的系统,可使用第三方消息推送服务,例如极光,用这个来做消息订阅与分发。

2.如果只是简简单单的需要提示到web页面,可以用js 定时ajax访问后台,后台来确定是否有数据更新,无论这个数据是哪来的。

消息通知可以了解一下极光推送