随着android应用体积的不断增大,以及应用版本发布的不断更迭,用户的升级成了一个问题,google也意识到不断更新应用对用户流量的损耗,在Google I/O 上提及的 Smart App update,即应用增量升级,或者叫做差分升级的做法,并在新版本的Google Play中得到支持。现在在主流的应用商店中都会看见这种新兴的更新,讲的通俗易懂点就是——省流量跟新,哈哈,是不是很耳熟呢,接下来就看看怎么实现吧。
其实增量升级的原理很简单,即首先将应用的旧版本Apk与新版本Apk做差分,得到更新的部分的补丁,例如旧版本的APK有5M,新版的有8M,更新的部分则可能只有3M左右(这里需要说明的是,得到的差分包大小并不是简单的相减,因为其实需要包含一些上下文相关的东西),使用差分升级的好处显而易见,那么你不需要下载完整的8M文件,只需要下载更新部分就可以,而更新部分可能只有3、4M,可以很大程度上减少流量的损失。在用户下载了差分包之后,需要在手机端将他们组合起来。可以参考的做法是先将手机端的旧版本软件(多半在/data/下),复制到SD卡或者cache中,将它们和之前的差分patch进行组合,得到一个新版本的apk应用,如果不出意外的话,这个生成的apk和你之前做差分的apk是一致的。
首先咱们认识一下一个程序:http://sites.inka.de/tesla/others.html#bsdiff
不需要看懂,咱们只要下载这个玩意:bsdiff(win下的操作文件)
看看咱们下载的是啥玩意
├── bsdiff-4.3 //bsdiff的源码路径,官网获取
│ ├── bsdiff.1
│ ├── bsdiff.c
│ ├── bspatch.1
│ ├── bspatch.c
│ └── Makefile
├── bsdiff4.3-win32 //windows PC端的测试工具
│ ├── Binary diff.txt
│ ├── bsdiff.exe
│ ├── bspatch.exe
│ └── LICENSE
├── bspatch //手机端的测试工具
bsdiff是二进制差分工具,其对应的bspatch是相应的补丁合成工具,需要注意的是增量升级的补丁包,是需要在服务器端,即PC端完成,大致流程如,制作补丁时调用bsdiff函数,根据两个不同版本的二进制文件,生成补丁文件。
操作:在下载的文件目录中的bsdiff4.3-win32文件夹下,按住shift键同时右击鼠标,选择再选择从此打开命令窗口,打开cmd
命令:bsdiff oldfile newfile patchfile
例如: bsdiff xx_v1.0.apk xx_v2.0.apk xx.patch
将生成的补丁包 xx.patch放置在升级服务器上,供用户下载升级,对应多版本需要对不同的版本进行差分,对于版本跨度较大的,建议整包升级。
用户在下载了 xx.patch补丁包后,需要用到补丁所对应的apk,即原来系统安装的旧版本apk和补丁合成的bspatch工具。系统旧版本的apk可以通过copy系统data/app目录下的apk文件获取,而补丁合成的bspatch可以通过将bspatch源码稍作修改,封装成一个so库,供手机端调用。
在PC端可以使用指令重新合成apk文件:
bspatch的命令格式为:
bspatch oldfile newfile patchfile
验证差分包是否正确。
好了,接下来说说手机端该干的事吧,我记着之前写过用android studio进行ndk开发的博客,当时的环境是android studio1.5+ndk-build-r10e;现在是android studio2.2.2+ndk-build-r13b,现在和之前的开发过程有点小不同,下面也将提到。
首先新建一个类,写个native方法,把三个参数写进去
/**
* 类说明: APK Patch工具类
*/
public class ApkPatchUtils {
static {
System.loadLibrary("apkpatch");
}
/**
* native方法 使用路径为oldApkPath的apk与路径为patchPath的补丁包,合成新的apk,并存储于newApkPath
* <p>
* 返回:0,说明操作成功
*
* @param oldApkPath 示例:/sdcard/old.apk
* @param newApkPath 示例:/sdcard/new.apk
* @param patchPath 示例:/sdcard/xx.patch
* @return
*/
public static native int patch(String oldApkPath, String newApkPath, String patchPath);
}
剩下的操作和之前我写的文章步骤相同:
点击打开链接
就是新的studio更好的集成了NDK,使用之前的方法还是有
#include <jni.h>报找不到的异常,这是因为没有关联源码,需要在工程的gradle里面配置如下:
android {
...
externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
sourceSets.main {
jni.srcDirs = []
// jniLibs.srcDirs = ['libs']
jniLibs.srcDirs = ['src/main/jniLibs']//设置目标的so存放路径
}
}
这是你还需要在jni里面建一个.mk文件来配置编译你的c代码
然后编译,结果会存放在:app\build\intermediates\ndkBuild