天天看点

Android 应用增量升级方案之实践篇

作者:snowdream email:yanghui1986527#gmail.com qq 群: 529327615

每次下载完整的新安装包,进行覆盖安装。

将新安装包和已经安装的旧安装包进行比对,生成一个差分升级包(patch包)。用户下载patch包后,和已经安装的旧安装包进行合并,生成新安装包,再进行覆盖安装。

在早期的android应用开发中,由于android应用普遍比较小,因此,普遍采用了全量升级方案。简单粗暴,却行之有效。

但是,随着android的发展,android应用功能越来越多,体积越来越大,再综合以下几个因素考虑,全量升级方案逐渐无法满足我们的需求。

1.在国内,随着2g,3g,4g的逐步演进,手机网络越来越快,但有一点事实仍然没有改变:流量很贵,非常不够用。(这个因素不适合wifi用户和土豪用户)

Android 应用增量升级方案之实践篇

以北京移动为例,最基础套餐,5元30m流量。而最新的微信apk安装包35m。也就是说,如果你选了最基础套餐,你一个月内使用全量升级方案,升级一次微信,流量都不够用。

2.在敏捷开发大行其道的今天,开发者希望尽快将新开发的功能推送到用户面前,并及时得到用户的反馈。恨不能三天一小版,一周一大版。

综合以上因素,开发者必须为用户考虑:省流量,省流量,省流量。

显然,全量升级这种土豪做法已经不再适用,于是,增量升级应运而生。

首先,两句话简单概括增量升级原理:

1.服务端通过比对最新升级包,和当前应用包,生成差分升级包;

2.客户端将差分升级包和当前应用包合并,生成最新升级包。

接下来,简单介绍下增量升级的原理:

1.首先,客户端获取当前应用的version code和应用apk文件的md5值,发送给服务器;

2.服务器根据既定策略,给用户返回更新包信息。

通过md5值没有查询到旧有apk应用信息,返回全量升级包网址,全量升级包md5值;

需要返回patch包,但还没有生成patch包时,后台去生成patch包,并返回全量升级包网址,全量升级包md5值;

需要返回patch包,并且已经生成patch包时,返回patch包网址,patch包md5值,全量升级包网址,全量升级包md5值;

不需要返回patch包,则返回全量升级包网址,全量升级包md5值;

3.客户端根据返回信息进行更新操作。

如果只有全量升级包相关信息,则下载全量升级包,并在校验md5值后,安装更新包;

如果有差分升级包(patch包),则下载差分升级包。校验差分升级包的md5值。如果校验失败,走上面一个步骤。如果校验成功,则将差分升级包和当前版本的apk进行合并操作,生成新的应用包。校验新的应用包md5值。校验通过,这安装这个生成的新应用包。如果校验失败,则走上面一个步骤。

以上只是简单介绍了增量升级的原理,实际应用中还需要细化,考虑更多的场景。

注意: 下载过程中,必须支持断点续传策略。防止网络不畅时,不断重试,造成的流量浪费。

增量升级方案的核心就是使用diff/patch算法来对新旧apk进行diff/patch操作。

在封装hdiffpatch过程中遇到问题,得到作者@sisong的支持和帮助,在此表示感谢。

bsdiff/bspatch和hdiffpatch算法都是开源的,服务端可以根据源文件来进行编译集成。

这里我主要在android客户端的角度,介绍下bsdiff/bspatch和hdiffpatch怎么使用。

在build.gradle文件中自定义jnilib目录

将 <code>app/libs/armeabi-v7a/libbsdiffpatch.so</code> 拷贝到你的工程对应目录下。

将 <code>app/src/main/java/com/github/snowdream/bsdiffpatch</code> 和 <code>app/src/main/java/com/github/snowdream/diffpatch</code> 拷贝到你的工程对应目录下,包名和文件名都不能改变。

在java文件中参考以下代码进行调用。

将 <code>app/libs/armeabi-v7a/libhdiffpatch.so</code> 拷贝到你的工程对应目录下。

将<code>app/src/main/java/com/github/snowdream/hdiffpatch</code> 和 <code>app/src/main/java/com/github/snowdream/diffpatch</code> 拷贝到你的工程对应目录下,包名和文件名都不能改变。

这里我选择高德地图android客户端的两个版本来进行测试。

测试版本: amap_android_v7.7.4.2128_guanwang.apk 和 amap_android_v7.3.0.2036_guanwang.apk (注:版本跨度大,差异大)

对比算法: bsdiffpatch vs hdiffpatch

测试结果:(详见下图)

bsdiffpatch生成的patch包稍小。

两者的diff操作都非常耗资源,耗时间,无法忍受。(当然diff操作一般在服务端进行)

两者的patch操作都比较快。通过大概五次测试,bsdiffpatch的patch操作需要13s左右,而hdiffpatch的patch操作仅仅需要1s左右。

以上结果仅供参考。

测试结论:

bsdiffpatch应用更广泛

hdiffpatch看起来更高效

Android 应用增量升级方案之实践篇

以上算是比较成熟的增量升级方案了,但是仔细想想,可能还存在一些问题:

1.由于多渠道,多版本造成非常多patch包

2.bs diff/patch算法性能和内存开销太高

第一个问题可以通过服务器策略进行限制。比如,只有最新版5个版本内的升级采用增量升级,其他的仍然采用全量升级。

据说,还有一种更强大的算法,可以解决以上问题。大家有兴趣的话,可以自己去了解。

<a href="https://gist.github.com/9468305/fa8f1307ea4738225fca">crsync-基于rsync rolling算法的文件增量更新.md</a>

<a href="http://bbs.umeng.com/thread-19-1-1.html">友盟增量更新的原理是什么</a>

<a href="http://my.oschina.net/liucundong/blog/160436">android应用增量更新库(smart app updates)</a>

<a href="http://blog.csdn.net/yyh352091626/article/details/50579859">android实现应用的增量更新升级</a>

<a href="https://github.com/smuyyh/incrementallyupdate">https://github.com/smuyyh/incrementallyupdate</a>

<a href="http://blog.csdn.net/hmg25/article/details/8100896">浅析android应用增量升级</a>

<a href="https://github.com/cundong/smartappupdates">https://github.com/cundong/smartappupdates</a>

<a href="https://github.com/sisong/hdiffpatch">https://github.com/sisong/hdiffpatch</a>

<a href="http://www.daemonology.net/bsdiff/">http://www.daemonology.net/bsdiff/</a>

<a href="https://github.com/snowdream/android-diffpatch">https://github.com/snowdream/android-diffpatch</a>