为了解决 Native 模块上线后的问题,mPaaS 提供了热修复功能,实现不发布客户端 apk 场景下的热修复。目前 Android 端热修复主要包括 andfix 和 dexpatch,考虑到 andfix 的版本兼容性,目前主要推荐使用 DexPatch。android
DexPatch 修复原理比较简单,就是在启动后经过 RPC 拉取当前须要下发的 jar 包地址,而后经过独立进程去下载 jar 包文件,下载完成后保存。在二次启动的时候 hook 系统的 classLoader,修改 DexPathList,在其数组的最前面加入一个有修改过的 class 的 dex 文件,使其拦截住数组后面的 dex 文件中同名的 class 的加载。apache
以下图所示,classloader 就会优先加载 Patch.dex 中的 Ding.class,而忽略 Classes.dex 中的 Ding.class,达到了替换的效果。数组
基于这样的原理,DexPatch 具备如下特征:markdown
支持范围上:是基于类级别的替换,因此只支持 Java 模块的 patch,不支持非 Java 模块的 patch,好比 so 模块;框架
兼容性上:因为是代理了系统的 ClassLoader,使用的黑科技较少,因此总体方案兼容性较好;less
生效时效性上:只能在下载 patch 后重启后才能生效,不支持实时生效;工具
成功率上:因为下载是使用的独立进程,减小了启动阶段主进程闪退对 patch 下载的影响,提高了下载的成功比例。组件化
如下是关于在 mPaaS 下使用 DexPatch 模块的主要步骤以及问题排查思路,方便开发者平常开发。gradle
启动阶段调用 MPHotpatch.init(),主要触发 Patch 信息的 RPC 请求,若是命中发布 Patch 发布规则,RPC 会返回 Patch 的 jar 包下载地址,客户端去触发下载,下载后保存在客户端私有目录/data/user/0/
包名/dexpatch/patch/
下。ui
以组件化模式接入为例,介绍下 Patch 发布的主要流程。
须要保存改动前的构建产物,方便后续作 Patch 生成,地址在:build/intermediates/bundle/xxxx-raw.jar
从新编译,保存构建产物,产物地址:build/intermediates/bundle/xxxx-raw.jar
主要用于热修复包时用于指定修复的类,配置文件为 .txt 格式,该配置文件应包含并按顺序包含如下信息:
须要 Patch 的类。以 L 开头,后跟以混淆后真实类名。若是多个类,每行只可写一个。示例:Lxxx.xxx.clazzX
设置 Patch 类型为 dexpatch。示例:PatchType: dexpatch
设置是不是静态 Bundle。默认为 false,若是是静态连接的 Bundle,须要显式设置为 true。示例:HostDex: true
(*目前 mPaaS 客户端的模块通常都在静态连接里,通常写 true)
生成 patch 须要用到项目的打包秘钥,须要提早准备好,能够在打包脚步下找到对应的配置
① 经过 mPaaS 自带的 IDE 工具,点击热修复,进入修复页面。
② 按照页面提示,填入以前准备的修复前和修复后的 jar 包地址,还有白名单配置文件,勾选 dexPatch,进入到下一步
③ 下一步主要选择打包的配置文件,最近点击完成生成 patch 文件
生成 patch 产物以下:
查看产物,可使用 dex2jar 工具反解 diff.dex 文件,用 jd-gui 文件查看反解产物是否符合预期
反解后能够看到修改的模块:
① 选择上一步的产物 jar 包进行上传
② 上传后能够经过白名单进行发布,验证 patch 的稳定性
白名单发布后,启动客户端,搜索关键字:DynamicRelease,能够看到在 tool 进程有触发下载的日志打出。
这里须要说明的是,这里触发 patch 的下载是在 tool 进程,不在主进程的主要缘由是怕因为主进程因为启动致使重复闪退,致使 patch 不能下载成功,单独在 tool 进程实现下载,尽可能提升 patch 的下载成功比例。
而后去下载目录查看,是否下载保存成功,下载目录在:/data/user/0/
包名/dexpatch/patch/20201023110012@20201023110012.jar
确认下载保存成功后,杀掉 App,重启查看是否生效,重启能够搜索关键字
DexPatchManager,查看 patch 生效的日志,日志会打印当前是否存在 patch 以及 patch 是否加载的日志。
同时咱们也能够就实际业务场景进行验证,查看是否生效。
aar 模式集成的时候,须要继承框架的 QuinoxlessApplication,指定 Application 为框架的实现类才能实现 dexpatch 的加载。QuinoxlessApplication 内主要封装了 dexpatch 模块的初始化和加载。
须要使用加固前的 apk 生成 patch,不能用加固后的包生成 patch。而后还须要验证在不一样加固厂商下的兼容表现。
请使用 Android 官网上的方式引入 apache http client,禁止使用导入 jar 包或者 gradle implementation/compile 的方式导入 http client。不然会引发 classloader 加载类混乱。
建议方式:
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
复制代码
E · N · D