1.增量升级概述
在游戏开发中,为满足用户需求,产品运营需求,改动的特别多,升级是件极其频繁的事情(没办法,一切以用户为中心),如果一个游戏APP又同时是个集合类型的(内置多个游戏),做完这个游戏只有一个感觉:再也不会爱了。。。
我们的游戏是用Lua写的,所以Android客户端分为:
-
APK 升级(细分为 1.完整升级;2.增量升级;3.第三方升级);
-
Lua升级(细分为 1.大厅升级;2各个游戏升级),同时Lua的游戏采用的是热更新机制;
同时涉及 各个游戏->大厅->Apk的依赖关系,难度较大,代码逻辑实现相对复杂,前端,后端维护成本较大(不过既然集合都做过了,做单个类型游戏的升级功能那就不在话下)。。。
本篇主要讲 APK 升级中的 增量更新如何实现。
1.1 APK 增量升级过程
增量升级的原理很简单,即首先将应用的旧版本Apk与新版本Apk做差分,得到更新的部分的补丁,例如旧版本的APK有20M,新版的有21M,更新的部分则可能只有1M左右,这里需要说明的是,得到的差分包大小并不是简单的相减,因为需要包含一些上下文相关的东西,使用差分升级的好处显而易见,那么你不需要下载完整的21M文件,只需要下载更新部分就可以,而更新部分的差分包很小,可以很大程度上减少流量的损失。
- 在服务器上生成一个patch。
- 下载patch到手机中。
- 通过补丁获取一个已安装应用的新的安装apk。
- 安装应用的新版本并删掉旧的版本和patch。
1.2 如何生成差分包
通常使用bspatch
来制作差分包。
bsdiff oldfile newfile patchfile
差分包通常在服务器端生成,然后下发到客户端。源代码是C语言实现的。
bsdiff源码下载地址:
https://github.com/mendsley/bsdiff
http://www.daemonology.net/bsdiff/bsdiff-4.3.tar.gz
可以通过jni在java代码中调用bspatch
C代码,生成差分包
1.3 如何合成新的升级包
bspatch
的命令格式为:
bspatch oldfile newfile patchfile
android在data/app目录下会有原APK的备份,用原apk的备份和服务器的patch包可以合成新的apk。但是要注意版本控制,patch包一定是最终要合成的apk与原apk的差分包。原来的版本不同,升级后的版本不同,使用的差分包肯定也不是一个。
2. 代码实现
github上有个很好的开源项目,SmartAppUpdate
已经对bsdiff
和bspatch
做了很好的封装,可以直接使用。
GitHub地址:
android-xBuild
是一项集成了apk差分与合成,zip差分与合成,lua打包,apk打包,png/jpg图片压缩五大功能的开源项目
GitHub地址:
2.1 bsdiff
的改进
google chrome项目中对bsdiff进行了改进
代码实现地址:
https://chromium.googlesource.com/chromium/src/courgette/+/master
数据对比
Here are the sizes in bytes for the recent 190.1->190.4 update on the developer channel:
Full update 10,385,920
bsdiff update 704,512
Courgette update 78,848
3. 增量升级的不足
增量升级并非完美无缺的升级方式,至少存在以下两点不足:
- 增量升级是以两个应用版本之间的差异来生成补丁的,你无法保证用户每次的及时升级到最新,所以你必须对你所发布的每一个版本都和最新的版本作差分,以便使所有版本的用户都可以差分升级,这样操作相对于原来的整包升级较为繁琐,不过可以通过自动化的脚本批量生成。
- 增量升级成功的前提是,用户手机端必须有能够让你拷贝出来且与你服务器用于差分的版本一致的apk,这样就存在,例如,系统内置的apk无法获取到,无法进行增量升级;对于某些与你差分版本一致,但是内容有过修改的(比如破解版apk),这样也是无法进行增量升级的,为了防止合成补丁错误,最好在补丁合成前对旧版本的apk进行sha1sum校验,保证基础包的一致性。