首先需要知道静态广播是在什么时候注册的?带着这个疑问就不得不分析apk的解析原理。
一、apk解析原理
1、静态广播注册
首先,手机在启动的时候,会把所有的apk的都安装一遍,然后立马就会解析所有apk的配置文件信息,如果配置文件中有广播,就会把它注册。
2、apk安装过程会产生3个目录
- data/app : apk的放置目录
- data/data/包名/ :应用所属目录,也就是数据库、sp等保存的目录
- data/dalvik-cache :虚拟机去加载执行指令
针对这三个目录,我们应该去分析那个目录呢?由于安装以后会全盘扫描apk,所以应该分析data/app目录。也就是说,当apk安装完成以后,立马就回去全盘扫描data/app 目录,解析xml配置文件。
3、如何解析
离不开PMS!!! PMS服务是什么时候启动的呢?
(1)PMS启动流程
大致流程如下:
当手机启动的时候,首先Linux内核启动,然后启动init进程,init进程启动以后,又会启动一个很重要的进程zygote进程,然后孵化SystemServer服务,SystemServer服务便会启动PMS服务、AMS服务等。
(2)PMS解析apk流程
9.0源码跟踪流程如下:
最终进入submit()方法
最后调用parsePackage()方法,将解析的结果保存在PackageParser.Package,在去看一下这个对象到底存了那些信息?
(3)PackageParser.Package
该类源码太长,只截取部分有用的代码,伪代码如下:
public final static class Package implements Parcelable {
......
public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
public final ArrayList<Service> services = new ArrayList<Service>(0);
public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
......
}
看到这里,应该注意到系统会将解析到权限信息,activity信息,广播信息等等保存到集合中,我们这里只关注广播信息receivers 。它的类型是Activity,注意这里的Activity并不是四大组件中的Activity,而是一个内部类,主要代码如下:
public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
public final ActivityInfo info;
....
}
类里面有个局部变量ActivityInfo ,它其实里面存放了类的名称,比如com.xxx.xxx.MyReCeiver,这点很重要。
既然拿到广播的类名称,那么intentFilter从哪里来呢?注意Activity是继承Component的,Component代码如下:
public static abstract class Component<II extends IntentInfo> {
public final ArrayList<II> intents;
.....
}
public static abstract class IntentInfo extends IntentFilter {
.....
}
没错Component的局部变量intents就存放了所有的intentFilter信息。
(4)实现
拿到了静态广播的类名和intentFilter信息,就可以进行在宿主中注册了。
二、代码实现
1、拿到Package对象
2、拿到receivers对象
3、遍历receivers,过程中拿到每一个receiver的广播名称
通过ActivityInfo来拿
4、遍历receivers,过程中拿到每一个receiver的intentFilter![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/08cb007df22d72a96935c7da7b9ced62.png)
5、遍历receivers,注册每一个receiver
完成以上代码,就实现了插件中静态广播的注册。