Android bsdiff 实现增量更新

首先了解一下什么是增量更新,引用百度百科

增量更新是指在进行更新操作时,只更新需要改变的地方,不需要更新或者已经更新过的地方则不会重复更新,增量更新与完全更新相对。

Android 增量更新可以使用bsdiff

首先下载bsdiff之后解压,进入文件夹执行make,如果报以下错误需要下载bzip2然后解压进入bzip2目录执行make编译

    cc -O3 -lbz2    bspatch.c   -o bspatch
/tmp/ccUIgKAP.o:在函数‘main’中:
bspatch.c:(.text.startup+0x142):对‘BZ2_bzReadOpen’未定义的引用
bspatch.c:(.text.startup+0x1ac):对‘BZ2_bzReadOpen’未定义的引用
bspatch.c:(.text.startup+0x216):对‘BZ2_bzReadOpen’未定义的引用
bspatch.c:(.text.startup+0x2ff):对‘BZ2_bzRead’未定义的引用
bspatch.c:(.text.startup+0x3eb):对‘BZ2_bzRead’未定义的引用
bspatch.c:(.text.startup+0x474):对‘BZ2_bzRead’未定义的引用
bspatch.c:(.text.startup+0x4b4):对‘BZ2_bzReadClose’未定义的引用
bspatch.c:(.text.startup+0x4c3):对‘BZ2_bzReadClose’未定义的引用
bspatch.c:(.text.startup+0x4d2):对‘BZ2_bzReadClose’未定义的引用
collect2: error: ld returned 1 exit status
<内置>: recipe for target 'bspatch' failed
make: *** [bspatch] Error 1

编译之后在bsdiff.c 和 bspatch.c 中加入以下代码

#include "bzip2/bzlib.c"
#include "bzip2/crctable.c"
#include "bzip2/compress.c"
#include "bzip2/decompress.c"
#include "bzip2/randtable.c"
#include "bzip2/blocksort.c"
#include "bzip2/huffman.c"

之后再执行make 不出意外就会生产bsdiff 和 bspatch 文件,这两个文件用于命令行执行。

Android端使用bsdiff

由于Android端只需要将生成的增量包和旧的apk合成新的apk所以只需要引入bspatch.c就可以了

环境: ndk20 + android studio

  • bsdiff 生成差分包
    ./bsdiff old.apk new.apk patch.patch

  • bspatch 生成新的apk,所以我们导入bspatch.c 文件到我们Android 项目目录.
Android项目集成bspatch:
  • 首先新建ndk项目,把bspatch.c文件拷贝到cpp目录下,由于 bspatch.c中使用了bzip2,所以我们导入bzip2 中如下这些文件拷贝到cpp/bzip2目录下
    Android bsdiff 实现增量更新_第1张图片
    然后配置CMakeLists文件
    file(GLOB bzip2 bzip2/*.c)

    add_library( 
             native-lib
             SHARED
             ${bzip2}
             bspatch.c
             native-lib.cpp )

find_library(
              log-lib
              log )

include_directories(bzip2)

target_link_libraries(native-lib
                       ${log-lib} )

修改bspatch.c文件中的main方法名字改成bspatch.这样库已经导入成功了.

  • 编写JNI函数
    extern "C"
JNIEXPORT jint JNICALL
Java_com_example_bsdiff_MainActivity_generateNewApk(JNIEnv *env, jobject instance, jstring oldPath_,
                                                    jstring newPath_, jstring patchPath_) {
    const char *oldPath = env->GetStringUTFChars(oldPath_, 0);
    const char *newPath = env->GetStringUTFChars(newPath_, 0);
    const char *patchPath = env->GetStringUTFChars(patchPath_, 0);
    char * args[4];
    args[0]="bsdiff";
    args[1] = (char *)oldPath;
    args[2] = (char *)newPath;
    args[3] = (char *)patchPath;

    int res = bspatch(4,args);


    env->ReleaseStringUTFChars(oldPath_, oldPath);
    env->ReleaseStringUTFChars(newPath_, newPath);
    env->ReleaseStringUTFChars(patchPath_, patchPath);

    return res;
}

在Java层调用次方法就可以成功生成新的apk了.

你可能感兴趣的:(Android)