Android增量更新

来源:互联网 发布:男生用什么护肤品知乎 编辑:程序博客网 时间:2024/06/05 04:54

bspatch 官网:http://www.daemonology.net/bsdiff/

bzip2官网:http://www.bzip.org/downloads.html

下载工具包:https://github.com/zhaopingfu/DiffPatchToolsAndLinux/tree/master/tools

EclipseDemo地址:https://github.com/zhaopingfu/DnLsn11_update_server

VSDemo地址:https://github.com/zhaopingfu/DnPfDiff/tree/master/DnPfDiff

客户端Demo地址:https://github.com/zhaopingfu/DnPfLsn12Bspatch

为什么要用增量更新?

普通更新:假如一个旧包是10M,当发现有新版本之后(20M),就将20M下载下来,然后安装

增量更新:假如一个旧包是10M,当发现有新版本之后(20M),之后先生成一个差分包(以二进制的方式比较新包和旧包的差异,相同的地方记录索引,不同的地方记录索引并将内容压缩并记录) ,之后下载下来,然后和手机上已经安装的app进行合并,最后安装

比较之下发现增量更新会比普通更新更加省流量,那么有什么用呢?

如果不用360等其他app商店下载的话,一般都自己搭服务器,就按照阿里云服务器来算的话,1M流量差不多按照5毛钱来算,下载一个包节省10M,1000w的用户的话就是1000w * 10 * 0.5 ,这是一笔很大的生意啊

这里有个问题:假如我们安装完app之后就把安装包删除了,那么下载差分包之后还能合并吗?

答案当然是可以的,因为在我们第一次下载了,安装的时候,系统会帮助我们拷贝一份放在外置卡的data/app/路径下,每一个app按照自己的包名划分,一般没有root的话,这个路径下的文件是没有权限删除的,所以90%的情况下都是可以的,另外的10%是用户将手机root,获得了最高权限,然后将备份的安装包都删除了,这时候就要向服务器反馈了,将全量的包下载下来

生成差分包

步骤:
1、先生成一个windows下的差分工具

VS2013DEMO地址:https://github.com/zhaopingfu/DnPfDiff/tree/master/DnPfDiff首先下载一个bsdiff4.3-win32-src.zip解压:https://github.com/zhaopingfu/DiffPatchToolsAndLinux/tree/master/tools创建一个VS项目(这里用的是VS2013的),将平台设置为x64的在工程路径下创建两个文件夹:src  include,将头文件放入include,.c和.cpp放入src里这里在源文件里找不到头文件,需要一些设置vs 找头文件 设置:右键工程 --->  属性 ---> c++ -----> 附含包目录(头文件的目录)vs 解决 _CRT_SECURE_NO_WARNINGS:右键工程 --->  属性 ---> c++ -----> 命令行 添加 -D _CRT_SECURE_NO_WARNINGSvs 关闭sdl 安全检查:右键工程 --->  属性 ---> c++------>常规 ---->SDL检查 否vs 切换平台之后 需要重新配置上述依赖上面都好了之后运行项目,生成一个.exe文件在cmd中执行这个.exe    PfDiff.exe appOld.apk appNew.apk apk.patch    PFDiff.exe:刚才生成的.exe可执行文件    appOld.apk:旧的安装包    appNew.apk:新的安装包    apk.patch:生成的差分包执行完之后会看到在当前路径下生成了一个apk.patch差分文件 

2、Eclipse中生成差分文件

在Eclipse中创建一个web工程public class DnPfDiff {    public static native void diff(String oldPath, String newPath, String patchPath);    static {        System.loadLibrary("DnPfDiff");    }}之后进入项目的src路径下,生成头文件javah com.pf.updata.DnPfDiff

这里写图片描述

之后,将头文件放入VS项目中这里会发现在头文件中找不到jni.h,这里要找jni.h,注意是window下的JDK下面的是window下的,SDK下的是linux下的这里要在JDK里复制jni.h和jni_md.h在bsdiff.cpp中引入刚才生成的头文件,然后把main方法改个名字,改为bsdiff_main/** Class:     com_pf_update_DnPfDiff* Method:    diff* Signature: ()V*/JNIEXPORT void JNICALL Java_com_pf_update_DnPfDiff_diff(JNIEnv *env, jclass jcls, jstring old_path_jstr, jstring new_path_jstr, jstring patch_path_jstr){    int argc = 4;    char *argv[4];    char *old_path_cstr = (char*)env->GetStringUTFChars(old_path_jstr, NULL);    char *new_path_cstr = (char*)env->GetStringUTFChars(new_path_jstr, NULL);    char *patch_path_cstr = (char*)env->GetStringUTFChars(patch_path_jstr, NULL);    argv[0] = "bsdiff_Pf";    argv[1] = old_path_cstr;    argv[2] = new_path_cstr;    argv[3] = patch_path_cstr;    bsdiff_main(argc, argv);    env->ReleaseStringUTFChars(old_path_jstr, old_path_cstr);    env->ReleaseStringUTFChars(new_path_jstr, new_path_cstr);    env->ReleaseStringUTFChars(patch_path_jstr, patch_path_cstr);}之后生成一个.dll动态库,注意不是exe文件然后放入eclipse工程的根目录中eclipse里写个main方法即可执行,生成差分包public class ContantsWin {    // 路径不能包含中文    public static final String BASE_PATH = "E:\\software\\Eclipse\\eclipse-jee-oxygen-R-win32-x86_64\\projects\\DnLsn11_update_server\\WebContent\\download\\";    public static final String OLD_APK_PATH = BASE_PATH + "apkOld.apk";    public static final String NEW_APK_PATH = BASE_PATH + "apkNew.apk";    public static final String PATCH_PATH = BASE_PATH + "apk.patch";    public static final String URL_PATCH_PATH = "/download/apk.patch";}public class MainTest {    public static void main(String[] args) {        DnPfDiff.diff(ContantsWin.OLD_APK_PATH, ContantsWin.NEW_APK_PATH, ContantsWin.PATCH_PATH);    }}随便写个servlet,就可以将差分包进行下载了Eclipse下Demo地址:https://github.com/zhaopingfu/DnLsn11_update_serverVS2013DEMO地址:https://github.com/zhaopingfu/DnPfDiff/tree/master/DnPfDiff

3、Linux下生成差分文件

首先下载一个bsdiff4.3-win32-src.zip解压(最上面有链接):https://github.com/zhaopingfu/DiffPatchToolsAndLinux/tree/master/toolsbsdiff.c中的<bzlib.h>修改为"bzlib.h"除了bsdiff.c中的main方法外,其他的main方法都改成其他的名字修改权限 chmod 777 ./*生成一个可执行文件gcc -fPIC blocksort.c decompress.c bsdiff.c  randtable.c  bzip2.c huffman.c compress.c bzlib.c crctable.c -o PfBsDiff执行可执行文件./PfBsDiff apkOld.apk apkNew.apk apk.patch生成一个.so动态库(在服务器的后台可以直接使用,安卓客户端不能直接用,需要用NDK进行交叉编译)gcc -fPIC -shared blocksort.c decompress.c bsdiff.c  randtable.c  bzip2.c huffman.c compress.c bzlib.c crctable.c -o PfBsDiff.so

合并差分包(客户端完成)

客户端Demo地址:https://github.com/zhaopingfu/DnPfLsn12Bspatch

创建一个Android项目(NDK项目)首先将bzip下的头文件和源文件和bsdiff中的bspatch.c复制到cpp下(源文件里面的main方法都改名)配置CMakeLists.txt写native方法public class BsPatch {    public native static int patch(String oldfile, String newfile, String patchfile);    static{        System.loadLibrary("PfBisPatch");    }}生成头文件,也是上面的javah命令,cmd进入java目录,执行javah com.pf.bspatch.BsPatchbspatch中引入头文件,并实现头文件中的方法/* * Class:     com_pf_bspatch_BsPatch * Method:    patch * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I */JNIEXPORT jint JNICALL Java_com_pf_bspatch_BsPatch_patch        (JNIEnv *env, jclass jcls, jstring old_path_jstr, jstring new_path_jstr,         jstring patch_path_jstr) {    int ret = -1;    LOGI("jni patch begin");    char *old_path_cstr = (*env)->GetStringUTFChars(env, old_path_jstr, JNI_FALSE);    char *new_path_cstr = (*env)->GetStringUTFChars(env, new_path_jstr, JNI_FALSE);    char *patch_path_cstr = (*env)->GetStringUTFChars(env, patch_path_jstr, JNI_FALSE);    int argc = 4;    char *argv[4];    argv[0] = "PfBsPatch";    argv[1] = old_path_cstr;    argv[2] = new_path_cstr;    argv[3] = patch_path_cstr;    //如果成功ret等于0    ret = bspatch_main(argc, argv);    LOGI("jni patch end");    (*env)->ReleaseStringUTFChars(env, old_path_jstr, old_path_cstr);    (*env)->ReleaseStringUTFChars(env, new_path_jstr, new_path_cstr);    (*env)->ReleaseStringUTFChars(env, patch_path_jstr, patch_path_cstr);    return ret;}cmd里查看下打包生成的包的MD5值和合并生成的包的MD5的值是一样的查看md5 值certutil -hashfile apkNew.apk MD53a68cc74cf9b0a3841419a54922233d1certutil -hashfile apk_new_merger.apk MD53a68cc74cf9b0a3841419a54922233d1

总结下命令

进入DnPfDiff所在路径下DnPfDiff.exe apkOld.apk apkNew.apk apk.patch    DnPfDiff.exe:要执行的文件    apkOld.apk:旧的apk    apkNew.apk:新的apk    apk.patch:生成的差分包///////////////////////////////进入bspatch所在路径下bspatch.exe apkOld.apk apkNewMerger.apk apk.patch    bspatch.exe:要执行的文件    apkOld.apk:旧的apk包    apkNewMerger.apk:合并后的文件    apk.patch:差分包//////////////////////////////////////linux下生成一个可执行文件    gcc -fPIC blocksort.c decompress.c bsdiff.c  randtable.c  bzip2.c huffman.c compress.c bzlib.c crctable.c -o PfBsDiff执行可执行文件    ./PfBsDiff apkOld.apk apkNew.apk apk.patch生成一个.so动态库(在服务器的后台可以直接使用,安卓客户端不能直接用,需要用NDK进行交叉编译)    gcc -fPIC -shared blocksort.c decompress.c bsdiff.c  randtable.c  bzip2.c huffman.c compress.c bzlib.c crctable.c -o PfBsDiff.so/////////////////////////////////////////java中native方法生成头文件进入java文件所在的根目录假如是/app/src/main/java/com/pf/bspatch/BsPatch.java的话就进入到java目录下就可以了在cmd里进入java目录下,执行javah命令(配好JDK之后就可以执行)    javah com.pf.bspatch.BsPatch这样就会生成一个头文件///////////////////////////////////查看md5 值    certutil -hashfile apkNew.apk MD53a68cc74cf9b0a3841419a54922233d1
原创粉丝点击