一 代理方式
1 在宿主的 Manifest 中注册,通过代理组件,当启动插件组件时首先启动一个代理组件,然后通过这个代理组件来构建、启动插件组件。
2 利用DexClassLoader
加载插件
3 创建 AssetManager,加载插件资源。
在 Android 中,资源是通过 R.java 中的 id 来调用访问的。但是实现插件化之后,宿主是无法通过 R 文件访问插件的资源,所以这里使用反射来生成属于插件的AssetManager
,并利用addAssetPath
函数加载插件资源。
二 hook方式
通过对安装,启动等系统api做hook。模拟及控制其安装启动流程,完成插件化实现
三 multidex
1.aapt的改造
分别对不同的插件项目分配不同的packageId,然后对各个插件的资源进行编译,生成R文件,然后与宿主项目的R文件进行id的合并。要求:由于最终会将所有的资源文件id进行合并,因此,所有的资源名称均不能相同。
2.运行ClassLoader加载各Bundle
和MultiDex的思路是一样的,所有的插件都被加载到同一个ClassLoader当中,因此,不同插件中的Class必须保持包名和类名的唯一。否则,加载过的类不会再次被加载。加载dex
都是从dexElements数组的顺序入手,修改expandFieldArray方法的实现,将修复的类放到dexElements的前方。
3.运行时资源的加载
通过调用AssetManager的addAssetPath方法,加载到assetManager对象中,然后再用assetManager对象,创建delegateResources对象,并保存在RuntimeArgs.delegateResources当中,然后调用AndroidHack.injectResources方法,对Application和LoadedApk中的mResources成员变量进行注入
4.运行时动态替换Resource对象
通过反射替换ActivityThread的mInstrumentation对象,替换成InstrumentationHook.class,然后就可以在执行startActivity时,拦截其newActivity和callActivityOnCreate方法,在newActivity方法中,动态的替换newActivity的mResources对象。在callActivityOnCreate方法中将ContextImplHook注入到新创建的Activity中。