APP 热修复都懂了,你会 SDK 热修复吗?最全方案在这里!
步骤
针对 jar 包体积大的情况,我们可以考虑对 sdk 项目进行拆包(拆 module),分成小的 jar 包和主包
主包负责反射加载,如果需要热修,下发子 jar 即可,比较轻量。
优缺点
优点:
只下发子包,轻量
缺点:
比较适合主包变动小的情况;
主包和子包耦合性强;
还是需要用到反射。
方案二:插件化
步骤
将 SDK 分包,宿主包仅提供 API 和加载核心实现的插件包,插件包就可以热更了。
优缺点
优点:
灵活
缺点:
对主项目工程的依赖太大,往往一些基本配置需要依赖于主工程的项目源码;
使用接入成本高,配置麻烦,而 SDK 的业务接入方需要的是快速接入;
插件化框架可能会对系统原生代码的运行造成不可预估的影响;
不得不依赖很多不需要的插件化框架功能。
方案三:业务方热更
走投无路之下,我想起,诶!很多 app 热更方案不是说支持 lib 热更吗!那先作为一个保底方案吧。
步骤
通过业务方 app 热更 lib 包。
优缺点
优点:
热更权把控在业务方手中,对业务方透明
缺点:
lib 包太大时,下载还是很耗流量的
diff 算法无法计算新旧 lib 的差异,只能整个替换掉
步骤相当繁琐,如下图:
业务方会杀了你的!
方案四:改造现有 APP 热修复方案
1. 那在选择热修复方案时考虑点有哪些?
1. 热更项目的需求
只需要简单的方法级别 Bug 修复?
需要资源及 so 库的修复?
需要 Native 的修复?
对平台兼容性要求及成功率要求?
是否需要对补丁包进行管理?
公司资源是否支持商业付费?
2. 学习及使用成本
集成难度和复杂度
代码侵入性
调试维护
3. 选择框架的关注点
尽量大厂
性能过关
有专人维护
热度高,开源社区活跃
2. 总结出需要热更的 SDK 特点
主要是代码热更,无 so 库、资源更新需求;
实时性要求高,因为一旦出问题,对业务方的影响极大;
兼容性要求高,你无法预料到业务方的活跃用户都有啥机型。
3. 那我们赶紧来看下,现有的 APP 热修复方案都有哪些?
3.1 综合优化的产物 —— Sophix(弃)
Sophix 功能完善、开发简单透明,可惜没开源,无法改造。
3.2 底层替换方案(弃)
底层替换方案不可避免地存在兼容问题,弃之。
3.3 类加载方案 —— Tinker
优点:
用户多
更新时间新,相比之下,其他有在 Github 上开源的框架,star 数都是 7000 以下,上次更新时间都在 1 年前,甚至 2 年前。
缺点:
dex 合成占用 ROM 较大
不够实时
需要改造 Application,业务方有感知。(也可以参考 InstantRun 做到不修改 Application 达到替换 Application 的效果,但该方案大量 hook 系统 api,不够稳定,大概有 1/1w 的概率会出现替换失败,所以 Tinker 最终还是没有使用 InstantRun 的方式)
还有两个问题,留给大家去思考:
会不会影响业务方加固?
和业务方是否冲突?
方案参考:
基于Tinker的SDK全局热更新方案(全网唯一)
扩展:
InstantRun 如何动态替换 Application,总结起来就两步:
打包时替换 Application 标签,插入 BootstrapApplication
运行时 hook 系统 api,将 BootstrapApplication 换回 MyApplication
3.4 插桩 —— 美团 Robust
Robust 的原理可以简单描述为:
打基础包时插桩,在每个方法前插入一段 if(changeQuickRedirect==null)-else 的逻辑;
加载补丁时,从补丁包中读取要替换的类及具体替换的方法实现,新建 ClassLoader 加载补丁 dex,当目标方法被执行时,此时 changeQuickRedirect != null,方法逻辑流程被改变,而替换掉之前的旧逻辑,达到 fix 的目的。
流程图
优点:
兼容性最优,兼容加固
实时生效
粒度细,支持方法级别的修复
高稳定性,修复成功率高达 99.9%
缺点:
在编译阶段插件侵入了产品代码,对运行效率、方法数、包体积还是产生了一些副作用。(支持指定某些 class 无需插入)
so 和资源的替换目前暂未实现
无法新增变量
没有补丁管理和安全校验,需要开发者自行实现
思考:
和其他的插桩插件混用是否有冲突?
评论