[关闭]
@cxm-2016 2017-02-18T08:30:47.000000Z 字数 2281 阅读 2569

Android:增量更新实现

Android

版本:2
作者:陈小默

参考自:张鸿洋- Android 增量更新完全解析 是增量不是热修复


一、下载工具

下载地址-bsdiff 4.3

注意:这里下载的是源码,需要对其执行编译操作。

解压到相应的文件夹,然后在此文件夹执行make(或其他编译指令)操作。

如果此时编译失败,我们需要修改 Makefile 文件,将其中 install 块下的 . 开头的命令添加一个缩进,结果就是下面这个样子:

  1. CFLAGS += -O3 -lbz2
  2. PREFIX ?= /usr/local
  3. INSTALL_PROGRAM ?= ${INSTALL} -c -s -m 555
  4. INSTALL_MAN ?= ${INSTALL} -c -m 444
  5. all: bsdiff bspatch
  6. bsdiff: bsdiff.c
  7. bspatch: bspatch.c
  8. install:
  9. ${INSTALL_PROGRAM} bsdiff bspatch ${PREFIX}/bin
  10. .ifndef WITHOUT_MAN
  11. ${INSTALL_MAN} bsdiff.1 bspatch.1 ${PREFIX}/man/man1
  12. .endif

然后,重新执行编译指令,如果执行成功,将会生成一个 bsdiff 文件。这个文件就是用来生成增量文件的工具。

如果以上过程失败,可以去下面的下载地址下载并编译工具:

GitHub下载地址 bsdiff-4.3

该工具编译完成之后会生成两个工具文件,一个是用于计算差异并生成增量文件的bsdiff,另一个是用来合并文件的bspacth

二、生成和合并增量文件

在这里我们使用命令来生成一个增量包,并使用命令合并增量包。

假设我们原来的文件是 qq-1.0.apk ,新版本安装包是qq-2.0.apk,那么我们可以执行下面的命令:

./bsdiff qq-1.0.apk qq-2.0.apk qq-1.0-to-2.0.patch

这样就生成了一个 qq-1.0-to-2.0.patch增量包。

那么合并的过程类似,仅仅是使用的工具不同而已:

./bspatch qq-1.0.apk qq-2.0.apk qq-1.0-to-2.0.patch

三、在客户端执行增量更新

上面的示例在PC上使用命令将旧的安装包和增量包进行了合并。但是在实际应用场景上,我们需要在客户终端上执行最终的合并操作。

3.1 提取当前应用的apk文件路径

  1. fun extract(ctx: Context): String {
  2. val context = ctx.applicationContext
  3. val applicationInfo = context.applicationInfo
  4. val apkPath = applicationInfo.sourceDir
  5. return apkPath
  6. }

3.2 制作bspatch.so

该过程需要先配置NDK环境,请参考NDK开发OpenGL ES 3.0(一)——OpenGL-ES 3.0介绍以及NDK环境搭建

声明一个native方法:

  1. class BsPatch{
  2. // 其中的三个参数为三个文件的路径
  3. external fun bspatch(oldApk: String, newApk :String, patch :String): Int
  4. companion object {
  5. init {
  6. System.loadLibrary("bsdiff")
  7. }
  8. }
  9. }

首先,把之前下载的bsdiff中的 bspatch.c 拷贝到 jni 文件夹下,然后在其中实现本地方法:

  1. JNIEXPORT jint JNICALL Java_***_bspatch
  2. (JNIEnv *env, jclass cls,
  3. jstring old, jstring new, jstring patch){
  4. int argc = 4;
  5. char * argv[argc];
  6. argv[0] = "bspatch";
  7. argv[1] = (char*) ((*env)->GetStringUTFChars(env, old, 0));
  8. argv[2] = (char*) ((*env)->GetStringUTFChars(env, new, 0));
  9. argv[3] = (char*) ((*env)->GetStringUTFChars(env, patch, 0));
  10. int ret = patchMethod(argc, argv);
  11. (*env)->ReleaseStringUTFChars(env, old, argv[1]);
  12. (*env)->ReleaseStringUTFChars(env, new, argv[2]);
  13. (*env)->ReleaseStringUTFChars(env, patch, argv[3]);
  14. return ret;
  15. }
注:patchMethod为 bspatch.c 文件中的 main 方法

此时 bspatch 依赖于另一个库 bzlib,所以我们需要先下载另一个库文件,并导入到我们的工程中。

下载地址:

我们将解压后的文件添加进 jni 文件夹,然后将 完善 CMakeList.txt 文件即可。注意编译时可能会报错,main函数重复定义:

Error:(70) multiple definition of `main'

我们只需要定位到这些main函数,然后直接删除即可。这样一来,一个增量更新的应用就完成了。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注