阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680
本文将继续通过Service调用原理来解读Replugin插件化技术
一、开启插件内Service
第1步
在《Replugin插件化技术解读之框架初始化、插件安装与加载(二)》中我们知道插件在加载的时候会自动生成PluginContext来作为插件内上下文使用,而插件中startService其实调用的就是已经被重写的startService方法了。
PluginContext.java
第2步
PluginServiceClient.startService中会首先获取ComponentName对象,得到插件包名和对应Service Class类型对象,然后获得开启的Service所属的进程号,如UI进程或者常驻进程。接着会通过进程号获得对应的IPluginServiceService pss对象,进行pss.startService操作。
第3步
重点看下如果根据不同进程去生成相应的PSS对象,也就是方法sServerFetcher.fetchByProcess方法
- 显然,针对不同进程号,使用了一个ArrayMap来缓存对应pss对象,如果是常驻进程,也就是进程号
会直接获得PluginServiceServer.mStub的IPluginServiceService对象来进行相关Service操作。
- 如果Service所处的是非常驻进程,这里会采用一个比较巧妙的方法去首先拉起该进程,跟踪下面方法:
MP.java
显然,会调用常驻进程服务的PmHostSvc.startPluginProcess方法去拉起对应进程,PmHostSvc常驻进程服务再整个Replugin确实起到了对各插件管理的作用,包括拉起插件Service进程。继续往下看,调用了PmBase.startPluginProcessLocked方法:
这里是个对数据库Provider的插入操作,那么究竟是对哪个Provider进行了数据库操作呢?
关键在这里:
最终生成的Uri是这样的:
这个玩意对应的啥呢?貌似宿主Manifest中并没有配置这个,如果分析过gradle插件应该可以想到,估计又是动态编译自动生成的,反编译宿主apk可以在Manifest中发现:
这样就全部串起来啦,想要开启分配在自定义进程中的Service首先就需要通过启动动态编译自动生成的对应进程Provider来拉起进程。
最终返回的IPluginClient的IBinder实现体其实就是PluginProcessPer,生成的PSS也就是PluginServiceServer.mStub了。跟上述常驻进程生成的PSS方式是一样的。
第4步
PSS中startService最终调用的是PluginServiceServer.this.startServiceLocked(intent,client)方法,其内部首先通过retrieveServiceLocked方法生成ServiceRecord对象,接着利用installServiceIfNeededLocked方法去加载Service对象,利用发射将PluginContext通过attachBaseContextLocked方法赋值到上下文内部,接着执行Service的onCreate方法,然后记录以及被加载,同时startPitService开启一个坑位Service,提高进程优先级防止被杀,后面继续调用onStartCommand方法。
二、总结
针对插件中startService的Service对象,其实Replugin框架仅仅将此Service当做一个普通的类进行代码强制执行其对应的生命周期各回调方法,当然Android FWK启动Service证明周期也是类似的方式做的,只是原始启动Service的各生命周期是在进程对应的ActivityThread中,而Replugin则是在PSS内部代码执行。这一点跟启动插件Activity是不太一样的。同时还有一个就是启动自定义进程的Service会利用动态编译自动生成的对应该进程的Provider,首先调用该Provider的insert数据库操作去吊起此进程,然后再获得IPluginClient中的PSS,显然,Replugin框架的使用动态编译的地方无处不在。
原文链接:https://blog.csdn.net/hellogmm/article/details/79188334
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680