Android开发学习Android开发

Android 增量更新的实现

2017-11-21  本文已影响0人  kakarottol

扯淡

最近闲来无事,学习了一下增量更新。

增量更新的概念就不扯了,有兴趣的看一下鸿洋大神的文章Android 增量更新完全解析 是增量不是热修复

测试设备(Android 5.0系统)

Talk is cheap!废话不多说,接下来开始踩坑之路。

准备工具

生成增量文件

    static {
        System.loadLibrary("bsdiff");
    }

    /**
     * native 方法 比较路径为 oldPath 的 apk 与 newPath 的 apk 之间差异,并生成 patch 包,存储于 patchPath
     */
    public static native int genDiff(String oldApkPath, String newApkPath, String patchPath);
 在 Terminal 中进入到项目 ..app\src\main\java> 下输入 javah -d ../jni  包名.方法名

如: javah -d ../jni sj.updateplus_utils.DiffUtil
JNIEXPORT jint JNICALL Java_sj_updateplus_utils_DiffUtil_genDiff
                 (JNIEnv *env, jclass cls, jstring old, jstring new, jstring patch) {
    int argc = 4;
    char * argv[argc];
    argv[0] = "bsdiff";
    argv[1] = (char*) ((*env)->GetStringUTFChars(env, old, 0));
    argv[2] = (char*) ((*env)->GetStringUTFChars(env, new, 0));
    argv[3] = (char*) ((*env)->GetStringUTFChars(env, patch, 0));

    printf("old apk = %s \n", argv[1]);
    printf("new apk = %s \n", argv[2]);
    printf("patch = %s \n", argv[3]);

    int ret = diffMain(argc, argv);

    printf("genDiff result = %d ", ret);

    (*env)->ReleaseStringUTFChars(env, old, argv[1]);
    (*env)->ReleaseStringUTFChars(env, new, argv[2]);
    (*env)->ReleaseStringUTFChars(env, patch, argv[3]);

    return ret;
}
//原代码:
int main(int argc, char *argv[]) {
    ...
}
//修改为:
int diffMain(int argc, char *argv[]) {
    ...
}
//原代码
#include <bzlib.h>
//修改为,可自定义
#include "bzip2/bzlib.h"

最后再进行编译运行,这期间可能遇到各种报错,哈哈,没关系,反正我也不知道怎么解决。(。‿。开玩笑,后面有踩坑经历)

增量文件和 oldApk 的合并

这个和增量文件的生成类似

    static {
        System.loadLibrary("bsdiff");
    }

    /**
     * native 方法 合并旧 apk 和补丁 patch,生成新的 apk
     * @param oldApkPath 旧apk文件路径
     * @param newApkPath 合并生成的新 apk 保存路径
     * @param patchPath  增量文件路径
     * @return 合并结果: 0-成功 -其他失败
     */
    public static native int mypatch(String oldApkPath, String newApkPath, String patchPath);`
在 Terminal 中进入到项目 ..app\src\main\java> 下输入 javah -d ../jni  包名.方法名

如:javah -d ../jni sj.updateplus_utils.PatchUtil
JNIEXPORT jint JNICALL Java_sj_updateplus_utils_PatchUtil_mypatch
        (JNIEnv *env, jclass cls,
         jstring old, jstring new, jstring patch) {
    int argc = 4;
    char *argv[argc];
    argv[0] = "bspatch";
    argv[1] = (char *) ((*env)->GetStringUTFChars(env, old, 0));
    argv[2] = (char *) ((*env)->GetStringUTFChars(env, new, 0));
    argv[3] = (char *) ((*env)->GetStringUTFChars(env, patch, 0));

    int ret = patchMain(argc, argv);

    (*env)->ReleaseStringUTFChars(env, old, argv[1]);
    (*env)->ReleaseStringUTFChars(env, new, argv[2]);
    (*env)->ReleaseStringUTFChars(env, patch, argv[3]);
    return ret;
}
//原代码
int main(int argc, char *argv[]) {
    ...
}
//修改为,可自定义
int patchMain(int argc, char *argv[]) {
    ...
}
//原代码:
#include <bzlib.h>
//修改为:
#include "bzip2/bzlib.h"

踩过的坑

add_library( # Sets the name of the library.
             bsdiff

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/jni/bzip2/blocksort.c
             src/main/jni/bzip2/bzip2.c
             src/main/jni/bzip2/bzip2recover.c
             src/main/jni/bzip2/bzlib.c
             src/main/jni/bzip2/compress.c
             src/main/jni/bzip2/crctable.c
             src/main/jni/bzip2/decompress.c
             src/main/jni/bzip2/dlltest.c
             src/main/jni/bzip2/huffman.c
             src/main/jni/bzip2/mk251.c
             src/main/jni/bzip2/randtable.c
             src/main/jni/bzip2/spewG.c
             src/main/jni/bzip2/unzcrash.c
             src/main/jni/bsdiff.c
             src/main/jni/bspatch.c )

CMakeLists.txt 中这两处地方要一致,可自定义

add_library( # Sets the name of the library.
             bsdiff
             ... )

target_link_libraries( # Specifies the target library.
                       bsdiff
                      ...)
android.useDeprecatedNdk=true

进行 MD5 验证

这个步骤是为了检验合并生成的 apk 文件和我们要升级更新的 apk 文件是否一样
在 apk 文件目录下打开 cmd
输入命令行

//***.apk 为需要验证的 apk 文件名
certutil -hashfile ***.apk MD5
image.png

写在最后

到这边增量更新操作基本就完成了。还有一些考虑不足之处。
当然这只是进行了增量文件的生成和新 apk 的合并,而且也只是在本地进行。其实呢,增量文件的生成最好在服务端进行,而且需要生成多个版本与最新版本的增量文件,才能保证各个版本的用户可以正常更新;更新完后还要安装等。
笔者这里是对其他 apk 的增量更新,如果是对本身 apk 的更新的话,还需要提取自身 apk 之类的,其他步骤可参照以上所写。

第一次写文章,还望各位指点

上一篇 下一篇

猜你喜欢

热点阅读