准备工作:
增量更新开源库:http://www.daemonology.net/bsdiff/
bsdiff还依赖bzip: https://sourceforge.net/projects/bzip2
使用步骤
- 查看bsdiff.c 找到main方法,阅读main函数会发现
if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
- 新建JAVA服务器程序,并编写native代码。
- 编辑c的实现代码。
开始撸码
- 编写JAVA native代码如下:
public class BsDiff {
static {
// 这个文件是后面生成的so文件
System.load("/Users/apple/Desktop/bsdiff/bsdiff.so");
}
public static native int diff(String oldPath,
String newPath, String patchPath);
}
- 通过javap命令生成头文件
cd src/main/java/ //进入java目录
javah top.andnux.update.BsDiff //生成头文件
- 在桌面上新建文件夹bsdiff,拷贝blocksort.c crctable.c bsdiff.c
decompress.c huffman.c bzlib.c jni.h bzlib.h jni_md.h
bzlib_private.h randtable.c compress.c top_andnux_update_BsDiff.h
到bsdiff目录下,注意:jni.h和jni_md.h是在你电脑的jdk安装目录下,。 - 修改bsdiff.c得main方法为bsdiff_main。
修改bsdiff.c得#include <bzlib.h>为#include "bzlib.h"。
修改top_andnux_update_BsDiff.h的#include <jni.h> 为#include "jni.h"
修改bsdiff.c 顶部加入 #include "top_andnux_update_BsDiff.h"
在bsdiff.c 底部加入
JNIEXPORT jint JNICALL Java_top_andnux_update_BsDiff_diff
(JNIEnv *env, jclass clazz, jstring oldPath_, jstring newPath_, jstring patchPath_){
const char* argv[4];
argv[1] = (*env)->GetStringUTFChars(env,oldPath_, 0);
argv[2] = (*env)->GetStringUTFChars(env,newPath_, 0);
argv[3] = (*env)->GetStringUTFChars(env, patchPath_, 0);
bsdiff_main(4,argv);
(*env)->ReleaseStringUTFChars(env,oldPath_, argv[1]);
(*env)->ReleaseStringUTFChars(env,newPath_, argv[2]);
(*env)->ReleaseStringUTFChars(env,patchPath_,argv[3]);
return 0;
}
- 编译
cd 到你桌面上文件夹bsdiff下
bsdiff gcc -shared -fPIC -o bsdiff.so *.c
即可得到bsdiff.so文件
- 调试与测试
public class MainTest {
public static void main(String args[]) {
BsDiff.diff("/Users/apple/Desktop/压缩解压.png",
"/Users/apple/Desktop/压缩解压.png",
"/Users/apple/Desktop/aa.patch");
}
}
//在/Users/apple/Desktop/就会生成aa.patch的差分文件。
- 优化
将生成的so文件拷贝到resources目录下。
public class BsDiff {
static {
BsDiff.init();
// System.load("/Users/apple/Desktop/bsdiff/bsdiff.so");
}
private static final String SO_NAME = "bsdiff.so";
public static void init() {
try {
InputStream inputStream = Thread.currentThread().getContextClassLoader()
.getResourceAsStream(SO_NAME);
String property = System.getProperty("java.library.path");
String[] split = property.split(":");
String s = split[0];
File file = new File(s, SO_NAME);
System.out.println(file.getAbsolutePath());
if (file.exists()) {
System.load(file.getAbsolutePath());
} else {
try {
file.getParentFile().mkdirs();
file.createNewFile();
FileUtils.copyInputStreamToFile(inputStream, file);
System.load(file.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static native int diff(String oldPath, String newPath, String patchPath);
}
结束语
- 做增量更新不难,难得是要后台维护多个版本的差分包,具体的细节还需要服务器工程师细条。
- APP端的的增量更新下次讲。
- 有兴趣的可以看看Android客服端增量更新:https://www.jianshu.com/p/33c1a80d1b0f
网友评论