Android 插件化

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 插件化相关的知识,希望对你有一定的参考价值。

参考技术A

原理:实现原理上都选择尽量少的hook,通过在manifest上预埋一些组件实现四大组件的插件化。其中Small更形成了一个跨平台、组件化的框架。

VirtulApp:
能够完全模拟app的运行环境,能够实现免安装应用和双开技术。
Atlas:
阿里出品,号称是一个容器化框架,结合了组件化和热更新技术。

android中有两种类加载器,DexClassLoader和PathClassLoader,它们都继承于BaseDexClassLoader。

两者的区别:DexClassLoader多了一个optimizedDirectory的路径参数,这个目录必须是内部存储路径,用于缓存系统创建的Dex文件。

所以我们可以使用DexClassLoader去加载外部Apk中的类。

ClassLoader调用loadClass方法加载类采用了双亲委托机制来避免重复加载类。
首先,ClassLoader会查看自身已经加载的类中是否已经存在此类,如不存在,然后,则会使用父类来加载此类,如不能成功加载,则会使用自身重载于BaseDexClassLoader的findClass()方法来加载此类。

DexClass的DexPathList在DexClass的构造器中生成,findClass()方法则是从DexPathList下面找出对应的DexFile,循环DexElements,通过dexElement.dexFile取出对应的DexFile,再通过DexFile.loadClassBinaryName()加载对应的类。

作用:使用插件DexClassLoader加载出需要的类。

通过每一个插件的DexClassLoader加载出自身所需要的类,当每一个插件需要加载相同的类库时,可采用该类库的不同版本来使用。

通过把每一个插件的pathList(DexFile)合并到主app的DexClassLoader上,来使各个插件和主app直接能够相互调用类和方法,并且各个插件中相同的功能可以抽取出来作为一个Common插件供其它插件使用。

插件调用主工程
在ClassLoader构造时指定主工程的DexClassLoader为父加载器即可直接调用主工程中的类和方法。
主工程调用插件
如果是多DexClassLoader的情况,则需要通过插件的DexClassLoader加载对应的类并反射调用其方法。此种情况,主工程一般会在一个统一的地方对访问插件中的类和方法做一些访问权限的管理及配置。

如果是单DexClassLoader的情况,则可以直接调用插件中的类和方法。但是当多个插件引用的库的版本不同时,会出现错误,因此,建议采用Gradle版本依赖管理统一处理主工程及各个插件的库依赖。

Android通过Resource来加载资源,只要有插件apk,就可以使用assertManager.addAssertPath(apkPath)的方式来生成assertManager,再使用其new出对应的Resource对象即可。

注意:由于AssertManager并不是Public,所以需要通过反射的方式去调用它。并且由于一些Rom对Resource的处理,所以,需要兼容处理。

有2种处理方式:

产生的原因:由于主工程和各个插件引用的Resource id重复产生的冲突。

解决思路:Android中的资源在系统中是以8位16进制0XPPTTRRRR的方式存在,其中PP即是资源区分的区域(Android系统只用它来区分系统资源和应用资源),只要让每一个插件的PP段取不同的值即可解决资源id冲突的问题。
具体解决方式:

1.修改aapt源码,编译期修改PP段。
2.修改Resource的arsc文件,其中的每一条都包含了资源id和映射路径。

Activity的处理最为复杂,有两种处理方式:
1.ProxyActivity的方式。
2.预埋StubActivity,hook系统启动Activity的过程。

原理:VirtualAPK通过替换了系统的Instrumentation,hook了Activity的启动和创建,省去了手动管理插件Activity生命周期的繁琐,让插件Activity像正常的Activity一样被系统管理,并且插件Activity在开发时和常规一样,即能独立运行又能作为插件被主工程调用。

Android插件化方向主要有2个方向:

Android 插件化

以上是关于Android 插件化的主要内容,如果未能解决你的问题,请参考以下文章

Android 插件化“ 插桩式 “ 插件化框架 ( 运行应用 | 代码整理 )

Android 插件化“ 插桩式 “ 插件化框架 ( 获取插件入口 Activity 组件 | 加载插件 Resources 资源 )

Android 插件化“ 插桩式 “ 插件化框架 ( 注入上下文的使用 )

Android 插件化Hook 插件化框架 ( 通过反射获取 “插件包“ 中的 Element[] dexElements )

Android 插件化Hook 插件化框架 ( 反射工具类 | 反射常用操作整理 )

Android 插件化Hook 插件化框架 ( Hook Activity 启动过程 | 静态代理 )