Android热修复实战

一、背景

调研了一下目前主流的热修复架构主要是两种,

底层替换方案 底层替换方案限制颇多,但时效性最好,加载轻快,立即见效 阿里系的AndFix、Sophix 类加载方案 类加载方案时效性差,需要重新冷启动才能见效,但修复范围广,限制少 QZone超级补丁、微信Tinker

其一是类和资源整体替换方案,QZone超级补丁、微信Tinker就是这种。

利用DexClassLoader在应用启动阶段替换需要替换的Class文件、资源达到修复的目的

优点:方便,直接替换简单干脆,开发新的替换补丁Patch.Apk即可 缺点:只能替换修改后的整个类文件不能局部修改代码,必须重启App,而且有dex分包造成的找不类问题。

其二是底层替换方案,阿里系的AndFix、Sophix是这种。

直接在已经加载的类中native层替换掉原有的方法。

优点:效果立竿见影,不需要重启App 缺点:兼容性差,准备工作复杂,需要对应改动native C++层方法。

我建议使用第三方SDK的,优先使用微信Tinker方案,目前有免费可用,其次是阿里的Andfix开源版本,最新的Sophix更好(对比发现应该是目前最好的)但是需要收费。

如果我们自己开发我尝试研究了一下第一套方案,也就是类替换的方案,生成Patch.apk或者Pacth.jar。

PS:目前的方案只是解决了类文件的替换,后续解决了资源文件替换后会再次更新!!本方案暂时没有解决dex拆包造成的加载class失败问题,后续补充。

二、具体方案

下边是根据第一套方案具体实施的方案和逻辑代码

  • 宿主App流程图

  • 补丁App流程图

  • 热修复类逻辑图

  • 首先是生成补丁包

      一共就两步: 

      1、利用jar命令 jar cvf F:/output.jar F:/com/a/b/c/d.class 打包class到jar文件,支持多个class空格拼接,也可以用build.gradle建立task自动打包指定目录下的class为指定目录结构的jar。注意jar包一定要包含自身package包结构的目录结构。

      2、使用dex命令 dx --dex --output F:\patch.jar F:\output.jar 打包成dex文件,最后我要用的就是这个patch.jar,最终用于升级的包可以是dex、jar(dex的jar)、apk文件的任何一种。

  • 热更新实现代码

      更新核心类

      HotfixHelper.java

      这里我用app-debug.apk直接用改动了代码的工程生成的apk来作为patch包,简单粗暴。

      loadPatch()模拟下载过程,我放到了assets里,复制一下可以相当于下载过程,创建给patch文件生成的dex们用的缓存文件夹和存放apk文件的路径,同时提供加载完成和失败的监听。

      mDexPath为复制的patch文件所在地址,Android10开始不支持放在sdCard,只能放在data下的默认缓存目录(文件、图片、下载等)。

      mCacheDir为解析后dex文件的存放位置。

      因为我是把app-debug.apk这个补丁包放到宿主App的assets中测试的,忽略了下载过程,DexPathUtil只是处理复制assets到App的data目录,所以没有贴代码,正式流程是直接下载到data/app/cache/自己目录下。

applyPath()负责加载补丁dex,利用java的反射原理。

combineArray()负责将补丁dex放到App的最前边。

      ReflectUtl.java(反射操作类)

最精简版本的单dexApp热更方案核心代码完结    

-------------------------------------------------------------------------------------------------------------------

       最后是宿主App代码应用

       Application的attachBaseContext方法中loadPatch即可。

       这里使用SharedPreference缓存来标记是否需要热更的。

       前文说的下载准备好apk放到指定目录后直接loadPatch即可。

三、问题梳理

1、dex分包,android新加入的odex方案,会导致替换报错,下一期会尝试解决这个问题。

这里我找了一个QZone空间的解决方案https://mp.weixin.qq.com/s?__biz=MzI1MTA1MzM2Nw==&mid=400118620&idx=1&sn=b4fdd5055731290eef12ad0d17f39d4a

目前我也是依靠这个方法解决这个问题,生成了一个所有类都要引用的类,单独打hack.dex包。

2、生成Patch.dex过程比较繁琐,需要简化加入gradle自动化插件,以后会具体讲解生成patch的自动化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值