增量更新主要通过新旧包生成差分包,客户端通过下载差分包就能与旧包合成新包。因为差分包一般比较小,所以能大大节省流量和加快下载速度。
在Android中的主要使用场景是APK的升级、或者在线资源的升级等。
增量更新主要通过开源库BsDiff,来实现拆分和合并的功能。首先需要下载BsDiff的源码。由于BsDiff依赖于Bzip2,所以需要把Bzip2的源码也下载下来。
bsdiff网站:http://www.daemonology.net/bsdiff/
下载解压后把bspatch.c 文件拷贝到项目中,如果你需要差分功能,也可以将bsdiff.c同时拷贝到项目中。
bzip2官网:https://www.sourceware.org/bzip2/downloads.html
下载解压后发现很多无用的文件,我们看下Makefile文件中有这么的一段,这才是编译的核心源码:
OBJS= blocksort.o \
huffman.o \
crctable.o \
randtable.o \
compress.o \
decompress.o \
bzlib.o
我们将这七个文件的.h和.c文件拷贝到项目中,发现报错,还少了一个bzlib_private.h文件,我们拷贝进去,最终是这样子的:
到了这一步可能bspatch.c文件的#include
生成差分包或合成新包的命令
通过bsdiff 生成patch包的命令:
bsdiff oldfile newfile patchfile
例如: bsdiff xx_v1.0.apk xx_v2.0.apk xx.patch
bspatch生成新包命令:
bspatch oldfile newfile patchfile
例如: bsdiff xx_v1.0.apk xx_v2.0.apk xx.patch
编写ndk代码
我们新建一个java类,并在类中声明一个native方法,按Alt加Enter键生成jni代码
/**
*
* @param oldPath 旧文件的路径
* @param bsPatchPath 差分包的路径
* @param outPath 差分合成后的输出路径
*/
private native static void bsPatch(String oldPath,String bsPatchPath,String outPath);
我们看看jni的具体实现,其实就是调用了bspatch.c的main方法,主要就是调用了bsdiff oldfile newfile patchfile这句命令:
//这个主要是为了导入其中的方法
extern "C" {
extern int bs_patch_main(int argc, char *argv[]);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_flyer_bspatchupdate_jni_BsPatchJni_bsPatch(JNIEnv *env, jclass clazz, jstring old_path,
jstring bs_patch_path, jstring out_path) {
//将java字符串转换成char指针
const char *oldPath = env->GetStringUTFChars(old_path, 0);
const char *patch = env->GetStringUTFChars(bs_patch_path, 0);
const char *output = env->GetStringUTFChars(out_path, 0);
int argc = 4;
char *argv[argc];
argv[0] = "bspatch";
argv[1] = const_cast(oldPath);
argv[2] = const_cast(output);
argv[3] = const_cast(patch);
bs_patch_main(argc,argv);
// 释放相应的指针gc
env->ReleaseStringUTFChars(old_path, oldPath);
env->ReleaseStringUTFChars(bs_patch_path, patch);
env->ReleaseStringUTFChars(out_path, output);
}
运行过程中报错:java.lang.UnsatisfiedLinkError大多是因为没有找到对应的so库。
实际开发中可以解压相应的apk,看看lib下是否存在相应的so库,如果不存在可能就是项目配置有问题,导致没有将so打包进去。
在app下的build.gradle下配置下ndk即可
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "........"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
//这里配置需要打包的ABI架构so,如果不配置可能会导致找不到so
ndk {
abiFilters 'armeabi-v7a'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
更多Android进阶技术请扫码关注公众号