APP 热修复都懂了,你会 SDK 热修复吗?最全方案在这里!

前言

刚开始要作 SDK 热修复,我是拒绝的 ~面试

某日,解决完一个线上 bug 后,我冒出了一个念头:让咱们的 SDK 也具备热修复的能力呗!算法

可是查了查,网上资料少、不少热修复方案只针对app……api

但是我都拍胸脯向老大夸口了,焉有退缩的道理?!安全

加上万一之后手抖,出了个什么大 bug 或者兼容问题,个人职业生涯不就要终结了!?架构

我滴乖乖,保命要紧!仍是赶忙作个保底方案吧。app

1、背景和目的

咱们想实现的效果很简单,以下场景三:框架

2、技术方案

先说明下,方案没有最好,只有最合适。虽然我最终选定了方案四,但若是各位小伙伴的团队有资源、有其余方案的经验、SDK的热更需求更丰富,能够自行选择其余方案。性能

方案一:JAR 替换

步骤

从服务端下载 jar -> 经过反射,加载jar -> 建立相关对象而且操做之。学习

方案参考:
Android SDK热修复机制简析以实现
优缺点

优势:优化

无兼容问题

缺点:

一、反射消耗性能;

二、jar 包若是体积大,整个下载就很不友好;

三、肯定改动的代码范围繁琐,维护麻烦。

方案一改进:子 JAR 替换

步骤

一、针对 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 特色

  1. 主要是代码热更,无so库、资源更新需求;
  2. 实时性要求高,由于一旦出问题,对业务方的影响极大;
  3. 兼容性要求高,你没法预料到业务方的活跃用户都有啥机型。

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,总结起来就两步:
  1. 打包时替换 Application 标签,插入BootstrapApplication
  2. 运行时 hook 系统api,将 BootstrapApplication 换回 MyApplication
3.4 插桩 —— 美团 Robust

Robust 的原理能够简单描述为:

一、打基础包时插桩,在每一个方法前插入一段 if(changeQuickRedirect==null)-else 的逻辑;

二、加载补丁时,从补丁包中读取要替换的类及具体替换的方法实现,新建 ClassLoader 加载补丁 dex,当目标方法被执行时,此时 changeQuickRedirect != null,方法逻辑流程被改变,而替换掉以前的旧逻辑,达到 fix 的目的。

优势:

  1. 兼容性最优,兼容加固
  2. 实时生效
  3. 粒度细,支持方法级别的修复
  4. 高稳定性,修复成功率高达99.9%

缺点:

  1. 在编译阶段插件侵入了产品代码,对运行效率、方法数、包体积仍是产生了一些反作用。(支持指定某些class无需插入)
  2. so和资源的替换目前暂未实现
  3. 没法新增变量
  4. 没有补丁管理和安全校验,须要开发者自行实现

思考:

1. 和其余的插桩插件混用是否有冲突?

3、实现

就在我美滋滋地接入 Robust 时,问题来了!

Robust 须要是 Application 才能插桩和打补丁,要用在 SDK 上,仍是须要一轮改造的。

如何改造?我将在下篇博文中详解,同时将推出封装好的库,让 SDK 开发者只需 5 分钟便可让本身的 SDK 拥有热修复的能力,敬请期待。

4、除了热更技术自己,咱们还应该关心的

固然,咱们的焦点并不局限在技术实现上,还有不少值得咱们去考虑的:

咱们怎么对分发进行控制?对监控数据进行统计?若是补丁引发了崩溃,咱们怎么第一时间补救?

1. 精准分发

结合外部维度系统,根据用户维度,好比渠道、系统版本等等作有差异的下发。

2. 数据分析

上线后咱们最关心的就是补丁的兼容性和成功率。

  1. 补丁拉取成功率 = 请求补丁成功的用户 / 发起请求补丁的用户
  2. 补丁下载成功率 = 下载补丁成功的用户 / 尝试下载补丁的用户
  3. patch应用成功率 = patch成功的用户 - 回滚的用户 / 补丁下载成功的用户

3. 补丁回滚机制

咱们须要支持自动监控崩溃,若是是下发的补丁引发的,则下次启动补丁自动失效,避免扩大影响范围。

Android开发资料+面试架构资料 免费分享 点击连接 便可领取

《Android架构师必备学习资源免费领取(架构视频+面试专题文档+学习笔记)》

相关文章
相关标签/搜索