文章来自:

                

Android系统中的广播(Broadcast)机制简要介绍和学习计划

        Android应用程序注册广播接收器(registerReceiver)的过程分析

                Android应用程序发送广播(sendBroadcast)的过程分析

Android 广播接收器注册与注销源码分析

  

 一、Android系统中的广播(Broadcast)机制简要介绍和学习计划

            

1. 广播的接收者需要通过调用registerReceiver函数告诉系统,它对什么样的广播有兴趣,即指定IntentFilter,并且向系统注册广播接收器,即指定BroadcastReceiver:

             

IntentFilter counterActionFilter = new IntentFilter(CounterService.BROADCAST_COUNTER_ACTION);registerReceiver(counterActionReceiver, counterActionFilter);

这里,指定感兴趣的广播就是CounterService.BROADCAST_COUNTER_ACTION了,而指定的广播接收器就是counterActonReceiver,它是一个BroadcastReceiver类型的实例。

2. 广播的发送者通过调用sendBroadcast函数来发送一个指定的广播,并且可以指定广播的相关参数:

Intent intent = new Intent(BROADCAST_COUNTER_ACTION);intent.putExtra(COUNTER_VALUE, counter);sendBroadcast(intent)

  

在第1步中,广播的接收者把广播接收器注册到ActivityManagerService中;在第2步中,广播的发送者同样是把广播发送到ActivityManagerService中,由ActivityManagerService去查找注册了这个广播的接收者,然后把广播分发给它们。

        在第2步的分发的过程,其实就是把这个广播转换成一个消息,然后放入到接收器所在的线程消息队列中去,最后就可以在消息循环中调用接收器的onReceive函数了。这里有一个要非常注意的地方是,由于ActivityManagerService把这个广播放进接收器所在的线程消息队列后,就返回了,它不关心这个消息什么时候会被处理,因此,对广播的处理是异步的,即调用sendBroadcast时,这个函数不会等待这个广播被处理完后才返回。

        下面,我们以一个序列图来总结一下,广播的注册和发送的过程:


虚线上面Step 1到Step 4步是注册广播接收器的过程,其中Step 2通过LoadedApk.getReceiverDispatcher在LoadedApk内部创建了一个IIntentReceiver接口,并且传递给ActivityManagerService;虚线下面的Step 5到Step 11是发送广播的过程,在Step 8中,ActivityManagerService利用上面得到的IIntentReceiver远程接口,调用LoadedApk.performReceiver接口,LoadedApk.performReceiver接口通过ActivityThread.H接口的post函数将这个广播消息放入到ActivityThread的消息队列中去,最后这个消息在LoadedApk的Args.run函数中处理,LoadedApk.Args.run函数接着调用MainActivity.BroadcastReceiver的onReceive函数来最终处理这个广播。


二、 Android应用程序注册广播接收器(registerReceiver)的过程分析


在Android的广播机制中,ActivityManagerService扮演着广播中心的角色,负责系统中所有广播的注册和发布操作,因此,Android应用程序注册广播接收器的过程就把是广播接收器注册到ActivityManagerService的过程。Android应用程序是通过调用ContextWrapper类的registerReceiver函数来把广播接收器BroadcastReceiver注册到ActivityManagerService中去的,而ContextWrapper类本身又借助ContextImpl类来注册广播接收器。

        在Android应用程序框架中,Activity和Service类都继承了ContextWrapper类,因此,我们可以在Activity或者Service的子类中调用registerReceiver函数来注册广播接收器。

Activity、Service、ContextWrapper和ContextImpl这四个类的关系:


注册广播接收器的操作是MainActivity发起的,我们先来看看注册过程的序列图:

1. 由于Activity继承于Context类,Context类是一个抽象类,定义了registerReceiver接口函数,因此在Activity的子类中,可以直接调用registerregisterReceiver函数,但是Activity及其父类都没有实现registerReceiver接口函数,在Activity调用registerReceiver来注册广播接收器时,根据Activity类继承关系,会依次调用一遍其父类的registerReceiver函数,就是父类ContextWrapper的registerReceiver函数。

2.ContextWrapper的registerReceiver函数会去调用ContextImpl.registerReceiver函数,从而调用ContextImpl.registerReceiverInternal函数。

3.获取应用程序主线程的消息器handle。ActivityThread.getHandler。有了这个Handler之后,就可以分发消息给应用程序处理了。

4.获取广播接收器中广播分发器。LoadedApk.getReceiverDispatcher函数实现。首先看一下参数r是不是已经有相应的ReceiverDispatcher存在了,如果有,就直接返回了,否则就新建一个ReceiverDispatcher,并且以r为Key值保在一个HashMap中,而这个HashMap以Context,这里即为MainActivity为Key值保存在LoadedApk的成员变量mReceivers中,这样,只要给定一个Activity和BroadcastReceiver,就可以查看LoadedApk里面是否已经存在相应的广播接收发布器ReceiverDispatcher了。广播接收器表保存在LoadedApk对象的成员变量mReceivers中

在新建广播接收发布器ReceiverDispatcher时,会在构造函数里面创建一个InnerReceiver实例,这是一个Binder对象,实现了IIntentReceiver接口,可以通过ReceiverDispatcher.getIIntentReceiver函数来获得,获得后就会把它传给ActivityManagerService,以便接收广播。在ReceiverDispatcher类的构造函数中,还会把传进来的Handle类型的参数activityThread保存下来,以便后面在分发广播的时候使用。

LoadedApk.mReceivers:

        

5. ActivityManagerProxy.注册registerReceiver,这个函数通过Binder驱动程序就进入到ActivityManagerService中的registerReceiver函数中去了。

6. ActivityManagerService.registerReceiver函数注册广播,首先是获得调用registerReceiver函数的应用程序进程记录块,它里面有一个列表receivers,专门用来保存这个进程注册的广播接收器即ReceiverList,ReceiverList列表用于保存BroadcastFilter。接着,又把这个ReceiverList列表以receiver为Key值保存在ActivityManagerService的成员变量mRegisteredReceivers HashMap表中。创建BroadcastFilter来把广播接收器列表rl和filter关联起来,然后保存在ActivityManagerService中的成员变量mReceiverResolver中去。


注销广播


1.还是从activity.unregisterReceiver() ——> contextWrapper.unregisterReceiver() ——> ContextImpl

.unregisterReceiver() ——>forgetReceiverDispatcher();

2.forgetReceiverDispatcher函数首先从表中查找指定广播接收器的IIntentReceiver,该函数中从mReceivers表中取出对应的广播接收器表,从广播接收器表中取出指定的广播接收器的分发器,     3.通过ActivityManagerProxy代理向ActivityManagerService发送注销广播接收器的请求。 4.ActivityManagerService负责广播接收器的注销工作:首先从mRegisteredReceivers表中查找到receiver对应的ReceiverList,从应用进程的receivers表中移除当前广播接收器对应的ReceiverList,从mRegisteredReceivers表中移除ReceiverList,同时从mReceiverResolver的过滤Action 
至此广播接收器的注册与注销就介绍完了,注册的本质其实就是将广播接收器添加到ActivityManagerService的相应成员变量中存储,从而在分发广播的时候,可以根据表中注册的接收器来分发;而广播接收器的注销工作就是从相应的存储表中移除。


三、Android应用程序发送广播(sendBroadcast)的过程分析


  广播的发送过程比广播接收器的注册过程要复杂得多了,不过这个过程仍然是以ActivityManagerService为中心。广播的发送者将广播发送到ActivityManagerService,ActivityManagerService接收到这个广播以后,就会在自己的注册中心查看有哪些广播接收器订阅了该广播,然后把这个广播逐一发送到这些广播接收器中,但是ActivityManagerService并不等待广播接收器处理这些广播就返回了,因此,广播的发送和处理是异步的。概括来说,广播的发送路径就是从发送者到ActivityManagerService,再从ActivityManagerService到接收者,这中间的两个过程都是通过Binder进程间通信机制来完成的。


序列图:


  最后,我们总结一下这个Android应用程序发送广播的过程:

        1. Step 1 - Step 7,计数器服务CounterService通过sendBroadcast把一个广播通过Binder进程间通信机制发送给ActivityManagerService,ActivityManagerService根据这个广播的Action类型找到相应的广播接收器,然后把这个广播放进自己的消息队列中去,就完成第一阶段对这个广播的异步分发了;

        2. Step 8 - Step 15,ActivityManagerService在消息循环中处理这个广播,并通过Binder进程间通信机制把这个广播分发给注册的广播接收分发器ReceiverDispatcher,ReceiverDispatcher把这个广播放进MainActivity所在的线程的消息队列中去,就完成第二阶段对这个广播的异步分发了;

        3. Step 16 - Step 17, ReceiverDispatcher的内部类Args在MainActivity所在的线程消息循环中处理这个广播,最终是将这个广播分发给所注册的BroadcastReceiver实例的onReceive函数进行处理。

                  

更多相关文章

  1. Android输入子系统之InputReader读取键盘消息过程分析
  2. 浅谈Android系统启动过程

随机推荐

  1. Android App性能信息获取方法
  2. 物流货运移动APP解决方案
  3. Android开发重要参考资料
  4. Android调用百度地图Web端接口,实现百度定
  5. 解决Android Studio运行编译时间久的最有
  6. 直接拿来用!十大Material Design开源项目
  7. Android Studio获取数字签名(SHA1)的方法
  8. Android Volley:使用方法总结及实例解析
  9. Android之用Handler实现主线程和子线程互
  10. Android 歌词Lrc显示 自定义View