简单了解一下增量更新

1,461 阅读3分钟

什么是增量更新

简单的说, 就是用户本地有个文件X, 当前版本是A, 大小100M. 现在这个文件需要升级到版本B, 大小110m.

用户可以直接下载版本B, 覆盖本地的版本A, 完成升级. 这是普通升级. 使用流量110M.

用户还可以只下载版本B和版本A之间的差异包, 然后在本地将差异包和版本A结合, 生成版本B. 完成升级. 使用流量可能只有10M左右. 这就是"增量更新"了

Archiv-Patcher

实现增量更新的方案很多, 经过初步了解和比较, 我们选择google的 Archive-Pather

选择它的原因:

  1. 业务层逻辑是纯java的. 容易接入Android.
  2. 在开源的代码中, 核心部分也有java实现. 容易修改
  3. 压缩核心使用zlib. 虽然是native的, 在各个系统中都有稳定实现.
  4. 不需要重新签名, 用户侧可以使用

问题

因为是纯java的代码, 所以接入和应用都非常简单. 但是实际还是遇到了一些问题.

zlib版本更新.

实验发现安卓11上合并操作是必然失败的. 设备上合并的结果和实际目标大相径庭.

翻阅源码的issues, 发现已经有人提了这个问题, 但是google方面似乎并没想解决. 有人提到是因为zlib的版本不同导致.

回头再重新翻看源码的ReadMe. 确实提到了zlib版本等环境问题会导致合并结果异常, 并且提供了一个"适配窗口"来做环境检查. 能通过检测说明可以使用, 否则不能. 果然在Android 11以上的设备里, 检测没有通过.

定位到了问题, 那就解决它. 之前调研的时候也说了, 选择Archive-pather是因为它好改好移植, 与Android兼容性强. 我们找到一个可用的zlib版本. 将他内嵌到app中编译成so库. 另外因为zlib是通过java.util.zip包引入的, 所以java.util.zip的包也要移植到app内, 以保证使用的自家的zlib.

有专业的jni大佬支持, 整个移植过程还比较顺利. 因为使用的是自家移植的zlib. 所以不再有Android版本适配的问题, 都可以正常通过适配窗口的测试.

合并异常

解决了zlib版本问题, 发现还是有合并异常. 这些异常都发生在正常合并结束后, md5校验失败. 说明合并流程是正常执行完毕的, 但是合并的结果有问题.

这就需要分析Archive-patcher的合并流程了. 除了分析出流程外, 还需要在合并中插入关键日志, 以帮助我们分析用户合并失败的原因. 好在源码ReadMe中比较详细的介绍了patcher文件的格式. 结合源码, 慢慢啃到一些标记数据. 需要进一步分析过程, 试验验证.

题外

写文章的时候, 重新翻看issues, 发现有推荐sfpatcher. 当时遇到这个问题的时候还没有这个评论. 是一个比Archive-patcher更高效稳定的增量方案. 只发布了编译工具和文档. 需要商业授权. 从文档看, 确实提供了很多高效的思路:

  1. 以一种类似流的方式生成和使用补丁. 指定缓存的大小, 对比流内容, 并更新到目标文件
  2. archive-patcher非常消耗硬盘空间. 是可以重点优化的点.
  3. 核心算法可以替代. java/c/c++都可以
  4. 可以商业化, 属实意外.