服务端生成差分文件(Windows环境下)
首先,差分算法是用C语言实现的,而服务端应用程序是用Java语言编写的。要想让Java语言能够调用C语言,就必须用到JNI技术。
1. 编写Java本地方法
Java本地方法应该如何编写呢?该方法应该有几个参数呢?需不需要有返回值呢?首先,要确定Java本地方法的形参个数和是否需要有返回值,我们就要先查看差分算法的实现需要传入多少个参数,实现差分算法的函数是否有返回值。也就是说,我们要去查看差分算法的具体实现源码。
-
进入bsdiff官网,可以看到:
-
因为我们要在Windows环境下生成dll动态链接库文件供Java调用,所以我们点击”Windows平台“,去下载作者在WIndows平台下编译的源码。
-
下载完成后,将bsdiff4.3-win32-src.zip文件解压出来,用Visual Studio打开bsdiff.dsp文件,可以看到生成差分文件的程序源码。然而我们需要生成dll动态链接库文件,因此需要对其进行修改。
-
打开bsdiff.cpp文件,查看main函数源码,可以发现该程序要生成差分文件需要4个参数,其中第一个参数(程序名称)是没用的,也就是说Java本地方法要调用bsdiff库需要传入3个参数,分别是:旧版本apk文件的路径、新版本apk文件的路径和生成差分文件的路径。
- 编写Java代码,并使用javah命令生成头文件。
package com.skyward;
public class Main {
public static void main(String[] args) {
}
public static native void bsdiff(String oldfile, String newfile, String patchfile);
}
6.使用Visual Studio新建一个空项目,将生成的头文件拷贝至项目中,同时拷贝jdk目录下的jni.h、jni_md.h文件和bsdiff项目中所有的源文件和头文件。
7.打开bsdiff.cpp文件,将main函数修改为bsdiff_main,并导入com_skyward_Main.h、jni.h头文件,用C++语言实现Java本地方法调用bsdiff_main方法。
#include "jni.h"
#include "com_skyward_Main.h"
JNIEXPORT void JNICALL Java_com_skyward_Main_bsdiff
(JNIEnv *env, jclass cls, jstring oldfile_str, jstring newfile_str, jstring patchfile_str) {
char* oldfile = (char*)env->GetStringUTFChars(oldfile_str, JNI_FALSE);
char* newfile = (char*)env->GetStringUTFChars(newfile_str, JNI_FALSE);
char* patchfile = (char*)env->GetStringUTFChars(patchfile_str, JNI_FALSE);
char* argv[4];
argv[0] = "bsdiff";
argv[1] = oldfile;
argv[2] = newfile;
argv[3] = patchfile;
int argc = 4;
bsdiff_main(4, argv);
env->ReleaseStringUTFChars(oldfile_str, oldfile);
env->ReleaseStringUTFChars(newfile_str, newfile);
env->ReleaseStringUTFChars(patchfile_str, patchfile);
}
8.配置Visual Studio生成64位的动态链接库文件
9.点击”生成解决方案“,可以看到Visual Studio报错,如下图:
这个错误可以通过在bzlib.c首行添加一行#define _CRT_SECURE_NO_WARNINGS
,然后继续重新生成解决方案,Visual Studio又报了另一个错误,如下图:
这个错误可以通过配置项目属性解决,将sdl检查改为”否“,即可解决这个错误
重新生成解决方案,将生成的dll动态链接库文件拷贝至Java项目的根目录。
10.编写JAVA代码
package com.skyward;
import java.io.File;
public class Main {
public static final String OLDFILE_PATH = "";
public static final String NEWFILE_PATH = "";
public static final String PATCHFILE_PATH = "";
static {
System.loadLibrary("bsdiff");
}
public static void main(String[] args) {
bsdiff(OLDFILE_PATH, NEWFILE_PATH, PATCHFILE_PATH);
}
public static native void bsdiff(String oldfile, String newfile, String patchfile);
}
至此,Windows服务器端基本完成。