Android 插件化原理解析(7):广播的管理

684 查看

Activity生命周期管理 以及 插件加载机制 中我们详细讲述了插件化过程中对于Activity组件的处理方式,为了实现Activity的插件化我们付出了相当多的努力;那么Android系统的其他组件,比如BroadcastReceiver,Service还有ContentProvider,它们又该如何处理呢?

相比Activity,BroadcastReceiver要简单很多——广播的生命周期相当简单;如果希望插件能够支持广播,这意味着什么?

回想一下我们日常开发的时候是如何使用BroadcastReceiver的:注册, 发送接收;因此,要实现BroadcastReceiver的插件化就这三种操作提供支持;接下来我们将一步步完成这个过程。

阅读本文之前,可以先clone一份 understand-plugin-framework,参考此项目的receiver-management 模块。另外,插件框架原理解析系列文章见索引

如果连BroadcastReceiver的工作原理都不清楚,又怎么能让插件支持它?老规矩,知己知彼。

源码分析

我们可以注册一个BroadcastReceiver然后接收我们感兴趣的广播,也可以给某有缘人发出某个广播;因此,我们对源码的分析按照两条路线展开:

注册过程

不论是静态广播还是动态广播,在使用之前都是需要注册的;动态广播的注册需要借助Context类的registerReceiver方法,而静态广播的注册直接在AndroidManifest.xml中声明即可;我们首先分析一下动态广播的注册过程。

Context类的registerReceiver的真正实现在ContextImpl里面,而这个方法间接调用了registerReceiverInternal,源码如下:

可以看到,BroadcastReceiver的注册也是通过AMS完成的;在进入AMS跟踪它的registerReceiver方法之前,我们先弄清楚这个IIntentReceiver类型的变量rd是什么。首先查阅API文档,很遗憾SDK里面没有导出这个类,我们直接去 grepcode 上看,文档如下:

System private API for dispatching intent broadcasts. This is given to the activity manager as part of registering for an intent broadcasts, and is called when it receives intents.

这个类是通过AIDL工具生成的,它是一个Binder对象,因此可以用来跨进程传输;文档说的很清楚,它是用来进行广播分发的。什么意思呢?

由于广播的分发过程是在AMS中进行的,而AMS所在的进程和BroadcastReceiver所在的进程不一样,因此要把广播分发到BroadcastReceiver具体的进程需要进行跨进程通信,这个通信的载体就是IIntentReceiver类。其实这个类的作用跟 Activity生命周期管理 中提到的 IApplicationThread相同,都是App进程给AMS进程用来进行通信的对象。另外,IIntentReceiver是一个接口,从上述代码中可以看出,它的实现类为LoadedApk.ReceiverDispatcher。

OK,我们继续跟踪源码,AMS类的registerReceiver方法代码有点多,这里不一一解释了,感兴趣的话可以自行查阅;这个方法主要做了以下两件事:

  1. 对发送者的身份和权限做出一定的校检
  2. 把这个BroadcastReceiver以BroadcastFilter的形式存储在AMS的mReceiverResolver变量中,供后续使用。

就这样,被传递过来的BroadcastReceiver已经成功地注册在系统之中,能够接收特定类型的广播了;那么注册在AndroidManifest.xml中的静态广播是如何被系统感知的呢?

插件加载机制 中我们知道系统会通过PackageParser解析Apk中的AndroidManifest.xml文件,因此我们有理由认为,系统会在解析AndroidMafest.xml的标签(也即静态注册的广播)的时候保存相应的信息;而Apk的解析过程是在PMS中进行的,因此静态注册广播的信息存储在PMS中。接下来的分析会证实这一结论。

发送和接收过程

发送过程

发送广播很简单,就是一句context.sendBroadcast(),我们顺藤摸瓜,跟踪这个方法。前文也提到过,Context中方法的调用都会委托到ContextImpl这个类,我们直接看ContextImpl对这个方法的实现:

嗯,发送广播也是通过AMS进行的,我们直接查看ActivityManagerService类的broadcastIntent方法,这个方法仅仅是调用了broadcastIntentLocked方法,我们继续跟踪;broadcastIntentLocked这个方法相当长,处理了诸如粘性广播,顺序广播,各种Flag以及动态广播静态广播的接收过程,这些我们暂时不关心;值得注意的是,在这个方法中我们发现,其实广播的发送和接收是融为一体的。某个广播被发送之后,AMS会找出所有注册过的BroadcastReceiver中与这个广播匹配的接收者,然后将这个广播分发给相应的接收者处理。

匹配过程

某一条广播被发出之后,并不是阿猫阿狗都能接收它并处理的;BroadcastReceiver可能只对某些类型的广播感兴趣,因此它也只能接收和处理这种特定类型的广播;在broadcastIntentLocked方法内部有如下代码: