0%

第8章:最简单的插件化解决方案

本章介绍一种最简单的插件化方案,适用于四大组件,技术涉及以下3个方面:

  • 合并所有的插件dex,用以解决插件类的加载问题
  • 在宿主AndroidManifest中预先声明插件中的四大组件(插件中的Activity如果很多就很麻烦)
  • 把插件中的所有资源一次性合并到宿主资源中(可能会导致资源id冲突)

在AndroidManifest 中声明插件中的组件

在插件中有啥,在宿主中声明啥就行

宿主App加载插件中的类

把插件dex都合并到宿主的dex中,那么宿主App对应的ClassLoader 就可以加载插件中任意类:

1
2
3
4
5
6
7
8
9
10
11
12
13
//代码参考: https://github.com/BaoBaoJianqiang/ZeusStudy1.0

public final class BaseDexClassLoaderHookHelper {
public static void patchClassLoder(ClassLoader cl,File apkFile,File optDexFile){
//获取BaseDexClassLoder: pathList
Object pathListObj = RefInvoke.getFiledObject(DexClassLoader.class.getSuperclass(), cl, "pathList");

//获取PathList: Element[] dexElements
Object[] dexElements = (Object[])RefInvoke.getFieldObject(pathListObj.getClass(), pathListObj, "dexElements");

...//手敲太难了,到时候复制下
}
}

启动插件Service

根据前面两章,素组App就能启动一个插件中的Service了,代码如下:

1
2
3
4
Intent intent = new Intent();
String serviceName = "jianqiang.com.plugin1.TestService1";
intent.setClassName(this, serviceName);
startService(intent);

加载插件中的资源

四大组件都可以这样实现插件化方案,Service 、ContentProvider 和 Receiver 都只要合并dex就够了,他们没有资源的概念。Activity严重依赖资源,所以必须解决插件中的资源问题。前面章节介绍了AssetManager 和 Resources ,AssetManager 有个 addAssetPath 方法,可以一次性把插件的路径都“灌进去”,然后根据这个“超级” AssetManager 生成一个“超级” Resources ,以后无论是查找插件还是宿主的资源,都能通过这个“超级”Resources 找到了。上述实现如下:

1
//代码参考:  https://github.com/BaoBaoJianqiang/ZeusStudy1.1

至此,Activity 的“傻瓜式”插件化解决方案就完成了,我们甚至可以从插件Activity跳转到宿主中的Activity,但是这个方案有以下两个问题:

  • 插件的四大组件都必需先在宿主中声明,不能新增
  • 插件和宿主的资源都合并到一起,资源id可能会有冲突
谢谢你的鼓励