最近在优化公司的SDK项目,其中有个优化点是让合作伙伴(CP)减少重新打包的次数,也就是运行时动态更新SDK。
在目前的项目中,SDK更新一般在两种情况下发生,一是新增功能(可能伴随接入其他三方SDK),这种情况一般需要CP配合修改业务逻辑。二是Bug修复。
针对这个需求,我思考了几种动态更新的可能性:
- 反编译Apk,替换SDK后重新打包签名。
- SDK功能插件化,动态加载。
- 使用JS引擎。
反编译Apk
这种方式,是在SDK更新后,对CP已经生成的Apk反编译并进行修改。
入门级的工具组合:Apktool+dex2jar+jd-gui,一般流程为
- 使用
apktool
反编译apk。 - 使用
dex2jar
将dex文件转换为jar文件。 - 然后通过
jd-gui
来操作jar文件。(如果apk做了混淆,则代码可读性很低,需要另外想办法解决混淆的问题) - 修改后通过
apktool
重新打包。
这种方式成本略高,针对需求的适用性也不高。
SDK插件化,动态加载。
这种方式,需要将SDK的功能进行详细的解构拆分,封装为一个个独立的功能模块。需要使用或更新时,再下载对应的模块到本地,在运行时通过DexClassLoader加载下载的功能模块。
这种方式其实是针对我们的需求最好的解决方案。然而,这种方式在上架Google Play商店时大概率会被判定为热更新,导致无法过审。
使用JS引擎
通过在Android中集成JS引擎,脱离WebView来使用JS代码。常见的库有j2v8、Hermes、QuickJs等。
目前的想法是整理SDK,拆分基础功能和业务逻辑,基础功能使用原生实现(Java或者Kotlin),业务逻辑使用JS引擎+JS代码来实现,便于动态更新。
这种方式是目前可行性较高的一种方式,后续也会进行一些尝试,过程中对JS引擎的使用也会通过博客记录。