前言
Linus Benedict Torvalds : RTFSC – Read The Funning Source Code
概括
本章通过跟踪registerReceiver(BroadcastReceiver receiver, IntentFilter filter)函数一路深入广播是如何被注册的。
动态注册过程
Step 1.ContextWrapper.registerReceiver()
|
|
Step 2.ContextImpl.registerReceiver()
|
|
通过几层的封装,最终会到ContextImpl.registerReceiverInternal这函数里,mPackageInfo变量是一个LoadedApk对象,LoadedApk是用来负责处理广播的接收。这里面首先会调用mMainThread.getHandler()来获取一个handler,先来看这个函数的过程再往下走。
Step 3.ActivityThread.getHandler()
|
|
我们看到最终是传回一个handler的对象,有这个对象就可以分发ActivityManagerService发送过来的广播消息给这个进程处理了。
接下来这个registerReceiverInternal函数通过LoadedApk.ReceiverDispatcher()获取一个IIntentReceiver接口对象rd,这是一个Binder对象。
Step 4.LoadedApk.getIIntentReceiver()
|
|
在这个函数里,创建了一个新的Receiver接口,并且将一个Activity和BroadcastReceiver绑定到LoadedApk,这样就可以在LoadedApk里查看是否存在相应的广播接收和发布器了。
在这里创建了一个InnerReceiver对象,这是一个Binder对象,实现了IIntentReceiver接口。最后通过getIIntentReceiver()返回给外部。
Step 5.ActivityManagerNative.registerReceiver()
|
|
这个函数最主要就是通过Binder驱动进入到ActivityManagerService中调用AMS的registerReceiver函数。
Step 6.ActivityManagerService.registerReceiver()
|
|
这个函数比较长,我们分成几个模块来解析。
Part 1
|
|
这里首先是获得调用registerReceiver函数的应用程序进程记录块,在这个Broadcast的进程记录块里就有MainActivity的启动代码。
Part 2
|
|
接下来是处理一个粘性的广播,将intents添加到stickyIntents里。代码虽多但功能简单。
Part 3
|
|
这里就是把广播接收器receiver保存一个ReceiverList列表中,这个列表的宿主进程是rl.app,这里就是MainActivity所在的进程了,在ActivityManagerService中,用一个进程记录块来表示这个应用程序进程,它里面有一个列表receivers,专门用来保存这个进程注册的广播接收器。接着,又把这个ReceiverList列表以receiver为Key值保存在ActivityManagerService的成员变量mRegisteredReceivers中,这些都是为了方便在收到广播时,快速找到对应的广播接收器的。
最后把广播接收器receiver和filter关联起来并保存到AMS的成员mReceiverResolver里。
静态注册过程
Step 1.AndroidManifest
|
|
在manifest添加receiver标签并且配上intentfilter。
Step 2.PackageManagerService.scanDirLI()
PMS管理类里面的scanDirLI()函数是安装流程的开吃,无论是开机安装APK、手动还是自动等安装方式,都会走到这个函数里。
scanDirLI()函数主要做的是对于后缀为APK的文件进行解析和安装。这里我们只看解析的函数。
scanDirLI()函数里解析的功能传递给scanPackageLI()函数执行。
Step 3.PackageManagerService.scanPackageLI()
scanPackageLI()函数对APK文件的解析过程是由PackageParser实例执行。该实例执行完解析后会保存在PMS中,其中就包括Receiver信息。
scanPackageLI()函数说调用的PackageParser实例函数是parsePackage()。
Step 4.PackageParser.parsePackage()
每一个Apk文件都是一个归档文件,里面包含了Android应用程序的配置文件AndroidManifest.xml,这里主要就是要对这个配置文件进行解析,解析完成后就会从Apk归档文件中得到这个配置文件,然后调用另外一个parsePackage()。
在第二个parsePackage()函数里就会对我们AndroidManifest.xml里的标签进行解析了。
接下来对Receiver的解析存在在”application”里,对”application”的解析是调用parseApplication函数。
Step 5.PackageParser.parseApplication()
|
|
这里上一点代码。我们看到这里有两个步骤。
第一:从parseActivity()函数里取得标签的内容。
第二:将它们保存到receivers里面。
我们首先来看parseActivity()函数是如何解析的。
Step 6.PackageParser.parseActivity()
parseActivity()这个函数,“
当解析完成后会一路沿着传递路线返回,一直返回到Step3。将数据保存在PackageParser.Package对象里。
接下来会调用另一个scanPackageLI()函数。
Step 7.PackageManagerService.scanPackageLI()
这函数其实就是封装了一层,实际的操作函数是scanPackageDirtyLI()。
Step 8.PackageManagerService.scanPackageDirtyLI()
|
|
然后我们可以看到这里,最后将receiver从package里面获取出来保存到PMS里面的一个全局变量mReceivers里,这样以后想查询就可以直接从PMS这里获取了。
总结
从两个注册的过程来看,我们可以知道receiver无论是从动态注册还是静态注册,最后都是AMS负责将其交互给用户,分别只在于一个字节保存到AMS另一个则要先保存到PMS然后AMS去获取。
过程都不复杂,重点是不要被太多枝叶给分散注意。