android增量更新
2016-08-27 14:49
429 查看
今天学习了一下增量更新,这个技术已经出现很长时间了,但是现实中,估计只有大厂才利用了这一技术在做产品!
国内有些第三方服务平台,像友盟提供自动更新的服务,也是用的增量方式!
其他的像QQ,Sina微博,陌陌,蘑菇街等都用到了,解压一下它们的apk,看一下lib目录:
QQ:libbspatch.so
微博:libbsdiffjni.so
陌陌:libbsdiff.so
蘑菇街:libpatcher.so
这些只不过so的名字不一样而已,但都用到了增量更新.
其它的一些主流app解包后,都看到了libandfix.so这个库,这个是阿里推出的一个支持ART和Dalvik的热修复的框架,在线修复bug.
今天学习增量更新而非热更新
主角:http://www.daemonology.net/bsdiff
官方说明:
(1)bsdiff 和 bspatch是编译,安装补丁到二进制文件的一个工具,
(2)这个工具用到了bzip2的压缩功能,所以补丁的大小小于新旧版本的一个差值
(3)bsdiff非常吃内存
解压,可以看到一共5个文件
然后编译make,报错
查看一下Makefile
无奈,在网上找了一下,找到了解决方法.
http://kinggoo.com/bsdiffupdate.htm#respond
原因是:目标体下一行的,命令要用TAB键开头,且不能隔一行。
也就是说在.ifndef的前面要有TAB开头才可以~因为他是安装的下一个子集命令。
接着编译,结果报错,找不到头文件
先前说过bsdiff依赖bzip2,有图
好,下载bzip2,解压
http://www.bzip.org/downloads.html
make
sudo make install
安装的时候,会创建一些文件,所以给权限
然后编译
第一个反应还是,连接bzip2库除了问题,其实不用makefile脚本也可以得到2个二进制工具
仔细看下这个Makefile, bsdiff和bspatch分别是2个模块,互不依赖,用make仅仅是多了可以指定目标到/usr/local目录,然后提供了一键安装功能,就是部署二进制工具和帮助(man)命令到/usr/local, Makefile仅仅是大项目管理的利器,还好这个文件不多,可以2次手动编译就完成了!
好可以生成,bzip2库之前已经安装在系统标准目录
2个工具都可以正常生成!
linux下链接库通常会去3个文件下找
/lib是内核级的,/usr/lib是系统级的,/usr/local/lib是用户级的
想了下,Makefile估计还是有点问题,然后自己改了下
这样make就可以成功生成2个工具了
分别是3个参数,老版本,新版本,补丁
还没有apk,首要任务先生成2个版本的apk
这里要把补丁合成功能移植到手机客户端上,那么就要用到NDK了
bsdiff是二进制差分工具,其对应的bspatch是相应的补丁合成工具
镜头切换到androidstudio上
主要是先编译一下模块,然后进入到debug目录,用javah命令
好了,如果没有问题,会看见一个.h文件
<2>因为补丁合成用到bzip2解压,所以要把zip2的包拷贝过来
<3>然后将bspatch.c拷贝到jni下面
bspatch.c实际上只有2个函数,一个offtin和main(),增加一个native函数
懂jni的都知道,这个函数名是不能乱写的,必须把.h头文件的那个声明函数拷贝过来,然后参数修改和增加主体,java调native会传值到这个函数里来!
然后这里会调用main()方法,这里我把main方法名字改成了domain,因为main是C程序的入口,这里不需要这个入口
下面是我自己的测试案例:
native代码写好了,那么java需要传入3个参数的值
这里需要三个路径,定义常量
oldVersionPath为app在手机上的安装包路径,从ApplicationInfo这个类获得,newVersionPath为新版本apk包合成地址,downPatchPath为补丁地址
为了测试,这里把补丁文件apk.patch会先放到sd卡/PatchCache/这个目录下,等app合成完成后,新的apk会输出到sd卡/PatchCache/下
然后有了合成后的,就可以安装更新了
服务端差分补丁
我下了几张高清图片放到了2.0版本的assets下面,这样2.0版本的apk大小会比较大,1.0版本大小是1.7M,2.0版本是16.9M,差分后apk.patch有14M!
好了,分析到这了
下面是我的测试项目,可以自己测测
https://github.com/shonegg/PatchUpdate
国内有些第三方服务平台,像友盟提供自动更新的服务,也是用的增量方式!
其他的像QQ,Sina微博,陌陌,蘑菇街等都用到了,解压一下它们的apk,看一下lib目录:
QQ:libbspatch.so
微博:libbsdiffjni.so
陌陌:libbsdiff.so
蘑菇街:libpatcher.so
这些只不过so的名字不一样而已,但都用到了增量更新.
其它的一些主流app解包后,都看到了libandfix.so这个库,这个是阿里推出的一个支持ART和Dalvik的热修复的框架,在线修复bug.
今天学习增量更新而非热更新
主角:http://www.daemonology.net/bsdiff
官方说明:
(1)bsdiff 和 bspatch是编译,安装补丁到二进制文件的一个工具,
(2)这个工具用到了bzip2的压缩功能,所以补丁的大小小于新旧版本的一个差值
(3)bsdiff非常吃内存
1.编译生成工具
开干,我用的是ubuntu,点击here下源代码,编译解压,可以看到一共5个文件
shone@Dell:~/Soft/bsdiff-4.3$ ls bsdiff.1 bsdiff.c bspatch.1 bspatch.c Makefile
然后编译make,报错
Makefile:13: *** missing separator. Stop.
查看一下Makefile
无奈,在网上找了一下,找到了解决方法.
http://kinggoo.com/bsdiffupdate.htm#respond
原因是:目标体下一行的,命令要用TAB键开头,且不能隔一行。
也就是说在.ifndef的前面要有TAB开头才可以~因为他是安装的下一个子集命令。
接着编译,结果报错,找不到头文件
bsdiff.c:33:19: fatal error: bzlib.h: No such file or directory #include <bzlib.h> ^ compilation terminated.
先前说过bsdiff依赖bzip2,有图
好,下载bzip2,解压
http://www.bzip.org/downloads.html
make
sudo make install
安装的时候,会创建一些文件,所以给权限
然后编译
cc -O3 -lbz2 bsdiff.c -o bsdiff /tmp/cctTxPKV.o: In function `main': bsdiff.c:(.text.startup+0x2aa): undefined reference to `BZ2_bzWriteOpen' bsdiff.c:(.text.startup+0x9e9): undefined reference to `BZ2_bzWrite' bsdiff.c:(.text.startup+0xb2c): undefined reference to `BZ2_bzWrite' bsdiff.c:(.text.startup+0xc7b): undefined reference to `BZ2_bzWrite' bsdiff.c:(.text.startup+0xccf): undefined reference to `BZ2_bzWriteClose' bsdiff.c:(.text.startup+0xd22): undefined reference to `BZ2_bzWriteOpen' bsdiff.c:(.text.startup+0xd4d): undefined reference to `BZ2_bzWrite' bsdiff.c:(.text.startup+0xd73): undefined reference to `BZ2_bzWriteClose' bsdiff.c:(.text.startup+0xdc6): undefined reference to `BZ2_bzWriteOpen' bsdiff.c:(.text.startup+0xdf1): undefined reference to `BZ2_bzWrite' bsdiff.c:(.text.startup+0xe17): undefined reference to `BZ2_bzWriteClose' collect2: error: ld returned 1 exit status make: *** [bsdiff] Error 1
第一个反应还是,连接bzip2库除了问题,其实不用makefile脚本也可以得到2个二进制工具
CFLAGS += -O3 -lbz2 PREFIX ?= /usr/local INSTALL_PROGRAM ?= ${INSTALL} -c -s -m 555 INSTALL_MAN ?= ${INSTALL} -c -m 444 all: bsdiff bspatch bsdiff: bsdiff.c bspatch: bspatch.c install: ${INSTALL_PROGRAM} bsdiff bspatch ${PREFIX}/bin .ifndef WITHOUT_MAN ${INSTALL_MAN} bsdiff.1 bspatch.1 ${PREFIX}/man/man1 .endif
仔细看下这个Makefile, bsdiff和bspatch分别是2个模块,互不依赖,用make仅仅是多了可以指定目标到/usr/local目录,然后提供了一键安装功能,就是部署二进制工具和帮助(man)命令到/usr/local, Makefile仅仅是大项目管理的利器,还好这个文件不多,可以2次手动编译就完成了!
gcc bsdiff.c -lbz2 -o bsdiff
好可以生成,bzip2库之前已经安装在系统标准目录
gcc bspatch.c -lbz2 -o bspatch
2个工具都可以正常生成!
linux下链接库通常会去3个文件下找
/lib是内核级的,/usr/lib是系统级的,/usr/local/lib是用户级的
想了下,Makefile估计还是有点问题,然后自己改了下
CC=gcc LDFLAGS= CFLAGS=-Wall -O3 -g -lbz2 PREFIX ?= /usr/local INSTALL_PROGRAM ?= ${INSTALL} -c -s -m 555 INSTALL_MAN ?= ${INSTALL} -c -m 444 all: bsdiff bspatch bsdiff: bsdiff.c $(CC) bsdiff.c $(CFLAGS) $(LDFLAGS) -o bsdiff bspatch: bspatch.c $(CC) bspatch.c $(CFLAGS) $(LDFLAGS) -o bspatch install: ${INSTALL_PROGRAM} bsdiff bspatch ${PREFIX}/bin .ifndef WITHOUT_MAN ${INSTALL_MAN} bsdiff.1 bspatch.1 ${PREFIX}/man/man1 .endif
这样make就可以成功生成2个工具了
Makefile的规则 目标 : 需要的条件 (注意冒号两边有空格) 命令 (注意前面用tab键开头) 解释一下: 1 目标可以是一个或多个,可以是Object File,也可以是执行文件,甚至可以是一个标签。 2 需要的条件就是生成目标所需要的文件或目标 3 命令就是生成目标所需要执行的脚本
2.生成补丁文件
差分生成补丁方式bsdiff old_version.apk new_version.apk diff.patch
分别是3个参数,老版本,新版本,补丁
还没有apk,首要任务先生成2个版本的apk
这里要把补丁合成功能移植到手机客户端上,那么就要用到NDK了
bsdiff是二进制差分工具,其对应的bspatch是相应的补丁合成工具
镜头切换到androidstudio上
2.1 先定义一个调度native层的类
public class Updater { public static native void applyPatch(String oldPath, String newPath, String patchPath); }
2.2 生成.h头文件
因为as的版本原因,生成.h的方式也不一样,我用的androidstudio版本是2.1.1v,网上方法大多不可行,正确的姿势是shone@Dell:~/Public/work_androidstudio/PatchUpdate/app/build/intermediates/classes/debug$ javah com.sugar.patch.Updater
主要是先编译一下模块,然后进入到debug目录,用javah命令
好了,如果没有问题,会看见一个.h文件
2.3 编写补丁合成代码
<1>首先建立一个jni的文件夹,将.h头文件移动过来<2>因为补丁合成用到bzip2解压,所以要把zip2的包拷贝过来
<3>然后将bspatch.c拷贝到jni下面
bspatch.c实际上只有2个函数,一个offtin和main(),增加一个native函数
JNIEXPORT void JNICALL Java_com_sugar_patch_Updater_applyPatch (JNIEnv *env, jclass clazz, jstring old_path, jstring new_path, jstring patch){ int argc=4; char * argv[argc]; argv[0]="bspatch"; argv[1]=(*env)->GetStringUTFChars(env, old_path, 0); argv[2]=(*env)->GetStringUTFChars(env, new_path, 0); argv[3]=(*env)->GetStringUTFChars(env, patch, 0); int ret = domain(argc, argv); (*env)->ReleaseStringUTFChars(env,old_path, argv[1]); (*env)->ReleaseStringUTFChars(env,new_path, argv[2]); (*env)->ReleaseStringUTFChars(env,patch, argv[3]); return ret; }
懂jni的都知道,这个函数名是不能乱写的,必须把.h头文件的那个声明函数拷贝过来,然后参数修改和增加主体,java调native会传值到这个函数里来!
然后这里会调用main()方法,这里我把main方法名字改成了domain,因为main是C程序的入口,这里不需要这个入口
下面是我自己的测试案例:
native代码写好了,那么java需要传入3个参数的值
java核心代码 String oldVersionPath = AppUtils.getOldVersionPath(context.get()); Updater.applyPatch(oldVersionPath, newVersionPath, downPatchPath);
这里需要三个路径,定义常量
public interface Contants { String rootDir = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "PatchCache" + File.separator; String downPatchPath = rootDir + "apk.patch"; String newVersionPath = rootDir + "PatchUpdate_v_2_0.apk"; }
oldVersionPath为app在手机上的安装包路径,从ApplicationInfo这个类获得,newVersionPath为新版本apk包合成地址,downPatchPath为补丁地址
为了测试,这里把补丁文件apk.patch会先放到sd卡/PatchCache/这个目录下,等app合成完成后,新的apk会输出到sd卡/PatchCache/下
然后有了合成后的,就可以安装更新了
AppUtils.install(context.get(), newVersionPath);
服务端差分补丁
shone@Dell:~/Soft/bsdiff-4.3$ ls app_v_1_0.apk bsdiff bsdiff.c bspatch.1 Makefile app_v_2_0.apk bsdiff.1 bspatch bspatch.c
app_v_1_0.apk和
app_v_2_0.apk分别是1.0和2.0版本,测试的话
我下了几张高清图片放到了2.0版本的assets下面,这样2.0版本的apk大小会比较大,1.0版本大小是1.7M,2.0版本是16.9M,差分后apk.patch有14M!
shone@Dell:~/Soft/bsdiff-4.3$ ./bsdiff app_v_1_0.apk app_v_2_0.apk apk.patch shone@Dell:~/Soft/bsdiff-4.3$ ls apk.patch app_v_1_0.apk app_v_2_0.apk bsdiff bsdiff.1 bsdiff.c bspatch bspatch.1 bspatch.c Makefile
好了,分析到这了
下面是我的测试项目,可以自己测测
https://github.com/shonegg/PatchUpdate
相关文章推荐
- Android 增量更新(一)
- android增量更新(打补丁方式)
- android增量更新中差分包生成以及合成
- Android增量更新和签名校验
- Android增量更新(四)-客户端合并差分包生成新的apk安装包
- android游戏的增量更新(资源及代码的热更新)
- Android增量更新
- android增量更新中增量文件的生成和合并
- Android增量更新和签名校验
- android增量更新中增量文件的生成和合并
- Android增量更新
- android差异化更新(增量更新)
- Android增量更新(二)-差分文件(Windows-part2)-dll动态库和jar包
- Android增量更新
- Android增量更新(三)-差分文件(Linux)-生成jar和.so库
- Android app智能升级(增量更新)
- Android增量更新(1)
- Android增量更新
- android增量更新(差分法)