概述
上一次我们在window下通过bsdiff的win版实现了在window下的差分,但是一般我们差分都是放在服务器上进行的。所以这次我们要做的就是在服务器上生成.so库,并让项目运行在linux服务器上来实现差分。
需要准备:linux服务器一台,eclipse,bsdiff,bzip2
生成相应的.so库
1.在window的eclipse下新建web项目
编写native方法
public class PatchDiffUtil {
/**
* 拆分
* @param oldApkPath 老apk的路径
* @param newApkPath 新apk的路径
* @param diffPath 差分后的文件路径
*/
public native static void diff(String oldApkPath,String newApkPath,String diffPath);
}
2.生成相应的.h文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_gxl_util_PatchDiffUtil */
#ifndef _Included_com_gxl_util_PatchDiffUtil
#define _Included_com_gxl_util_PatchDiffUtil
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_gxl_util_PatchDiffUtil
* Method: diff
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_gxl_util_PatchDiffUtil_diff
(JNIEnv *, jclass, jstring, jstring, jstring);
#ifdef __cplusplus
}
#endif
#endif
3.下载bsdiff和bzip2
4.将相应的文件放到同一个文件夹
新建一个文件夹bsdiff_linux。
将bsdiff下的bsdiff.c赋值到bsdiff_linux下,然后将下载的bzip2下的所有.c和.h文件都复制到文件夹下。
将生成的com_gxl_util_PatchDiffUtil.h文件复制到文件夹下。
将jni.h赋值到文件夹下。需要注意:由于我们要在linux下编译生成.so文件,com_gxl_util_PatchDiffUtil.h依赖于jni.h,所以需要将找android源码下的jni.h,而不是找jdk下的jni.h文件。如我的jni.h在D:\android-ndk-r13b\platforms\android-12\arch-x86\usr\include下。
5.修改文件
修改com_gxl_util_PatchDiffUtil.h中的jni.h的引用为
#include "jni.h"
修改bsdiff.c中的,bzlib.h的引用为#include "bzlib.h"
,然后添加com_gxl_util_PatchDiffUtil.h头文件的引用,并实现
//1.引入头文件
#include "com_gxl_util_PatchDiffUtil.h"
#include <sys/types.h>
//2.引入bzlib.h
#include "bzlib.h"
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
//3.将main方法修改为bsdiff_main
int bsdiff_main(int argc,char *argv[]){
}
//4.实现头文件中的函数
JNIEXPORT void JNICALL Java_com_gxl_util_PatchDiffUtil_diff
(JNIEnv * env, jclass cls, jstring old_apk_path_str, jstring new_apk_path_str, jstring patch_path_str){
//将jstring转成char*
char* old_apk_path=(char*)(*env)->GetStringUTFChars(env,old_apk_path_str,NULL);
char* new_apk_path=(char*)(*env)->GetStringUTFChars(env,new_apk_path_str,NULL);
char* patch_path=(char*)(*env)->GetStringUTFChars(env,patch_path_str,NULL);
//bspatch_main的参数
int argc=4;
char * argv[4];
argv[0]="bsdiff";
argv[1]=old_apk_path;
argv[2]=new_apk_path;
argv[3]=patch_path;
//调用bspatch的函数进行合并
bsdiff_main(argc,argv);
//释放
(*env)->ReleaseStringUTFChars(env,old_apk_path_str,old_apk_path);
(*env)->ReleaseStringUTFChars(env,new_apk_path_str,new_apk_path);
(*env)->ReleaseStringUTFChars(env,patch_path_str,patch_path);
}
将bzip2.c中的main方法修改为bzip2_main
IntNative bzip2_main ( IntNative argc, Char *argv[] ){
}
5.编译生成.so库
将bsdiff_linux这个文件夹上传至服务器
使用cd命令切换到bsdiff_linux目录下,执行如下命令生成bsdiff.so库
gcc -fPIC -shared blocksort.c decompress.c bsdiff.c randtable.c bzip2.c huffman.c compress.c bzlib.c crctable.c -o bsdiff.so
我试过了,不会发生错误,而且在服务器上生成的速度很快,有了如下文件则代表成功了。
将代码运行在服务器进行差分
1.将old.apk和new.apk上传至linux上
修改这两个文件的路径为linux上的路径
public class ContantLinux {
public static final String old_apk_path = "/home/ubuntu/bsdiff_linux/ndk_03_update_old.apk";
public static final String new_apk_path = "/home/ubuntu/bsdiff_linux/ndk_03_update_new.apk";
public static final String patch_path = "/home/ubuntu/bsdiff_linux/apk.patch";
}
2.修改加载.so文件的路径为linux下的路径
要注意是load,不是loadLibrary,
static {
//System.loadLibrary("ndk_patch_update");
System.load("//home/ubuntu/bsdiff_linux/bsdiff.so");
}
3.调用
public static void main(String[] args) {
PatchDiffUtil.diff(ContantLinux.old_apk_path, ContantLinux.new_apk_path, ContantLinux.patch_path);
System.out.println("拆分完毕!");
}
项目如下
很容易
4.打包项目生成.jar包文件
项目–>右键Export–>
选中runnable jar file
选中第二个
4.将jar文件上传至linux
将bsdiff.jar上传至linux服务器
执行 java -jar bsdiff.jar
就可以生成相应的patch包
5.原理
如果面试时被问到是否研究过其中的源码,则根据下面的进行吹水