diffpatch升级_android增量更新 - apk差分合并算法服务端设计 | APP开发技术博客

本文介绍了使用bsdiff和bspatch工具进行Android应用增量更新的方法,包括编译差分合并算法的SO库,以及Java层通过JNI调用C++实现的diff和patch方法,最后在主函数中演示了差分文件生成和合并的过程。
摘要由CSDN通过智能技术生成

bsdiff简介

Android增量更新需要用到二进制差分工具:bsdiff

bsdiff and bspatch are tools for building and applying patches to binary files.

编译bsdiff差分合并算法的so库

创建bsdiff差分与合并算法的so库文件,以便Java层通过JNI的方式调用。

bsdiff编译需要bzip库支持,需要引入bzip2的源文件

Makefile1

2

3

4

5

6

7

8

9

10export JAVA_HOME = /usr/lib/java/jdk1.8.0_112

CC := gcc

CFLAGS := -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/linux -I /usr/include

LDFLAGS := -fPIC -shared

SOURCE := $(wildcard *.c *.h)

libBsDiffAndPatch.so: $(SOURCE)

$(CC) $(LDFLAGS) $(CFLAGS) $^ -o libBsDiffAndPatch.so

clean:

rm libBsDiffAndPatch.so

cn_appblog_diffpatchserver_BsDiffAndPatch.c1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90#include "cn_appblog_diffpatchserver_BsDiffAndPatch.h"

#include "bsdiff.h"

#include

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: cn_appblog_diffpatchserver_BsDiffAndPatch

* Method: diff

* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I

*/

JNIEXPORT jint JNICALL Java_cn_appblog_diffpatchserver_BsDiffAndPatch_diff

(JNIEnv *env, jclass arg, jstring old, jstring new, jstring patch){

printf("-----BsDiffAndPatch_diff start-----\n");

clock_t start, finish;

double duration;

int argc = 4;

char * argv[argc];

argv[0] = "bsdiff";

argv[1] = (char*) ((*env)->GetStringUTFChars(env, old, 0));

argv[2] = (char*) ((*env)->GetStringUTFChars(env, new, 0));

argv[3] = (char*) ((*env)->GetStringUTFChars(env, patch, 0));

printf("old apk = %s \n", argv[1]);

printf("new apk = %s \n", argv[2]);

printf("patch = %s \n", argv[3]);

printf("start to generate patch file\n");

start = clock();

int ret = bsdiff_main(argc, argv);

finish = clock();

printf("finish to generate patch file\n");

duration = (double)(finish - start) / CLOCKS_PER_SEC;

printf("BsDiffAndPatch_diff result = %d \n", ret);

printf("time spended %f s \n",duration);

(*env)->ReleaseStringUTFChars(env, old, argv[1]);

(*env)->ReleaseStringUTFChars(env, new, argv[2]);

(*env)->ReleaseStringUTFChars(env, patch, argv[3]);

printf("-----BsDiffAndPatch_diff end-----\n");

return ret;

}

/*

* Class: cn_appblog_diffpatchserver_BsDiffAndPatch

* Method: patch

* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I

*/

JNIEXPORT jint JNICALL Java_cn_appblog_diffpatchserver_BsDiffAndPatch_patch

(JNIEnv *env, jclass arg, jstring old, jstring new, jstring patch){

printf("-----BsDiffAndPatch_patch start-----\n");

clock_t start, finish;

double duration;

int argc = 4;

char * argv[argc];

argv[0] = "bspatch";

argv[1] = (char*) ((*env)->GetStringUTFChars(env, old, 0));

argv[2] = (char*) ((*env)->GetStringUTFChars(env, new, 0));

argv[3] = (char*) ((*env)->GetStringUTFChars(env, patch, 0));

printf("old apk = %s \n", argv[1]);

printf("patch = %s \n", argv[3]);

printf("new apk = %s \n", argv[2]);

printf("start to apply patch file\n");

start = clock();

int ret = bspatch_main(argc, argv);

finish = clock();

printf("finish to apply patch file\n");

duration = (double)(finish - start) / CLOCKS_PER_SEC;

printf("BsDiffAndPatch_patch result = %d \n", ret);

printf("time spended %f s \n",duration);

(*env)->ReleaseStringUTFChars(env, old, argv[1]);

(*env)->ReleaseStringUTFChars(env, new, argv[2]);

(*env)->ReleaseStringUTFChars(env, patch, argv[3]);

printf("-----BsDiffAndPatch_patch end-----\n");

return ret;

}

#ifdef __cplusplus

}

#endif

Java层调用so库实现diff和patch

Java层采用JNI方式调用so库封装的diff和patch方法

native方法声明1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25public class BsDiffAndPatch{

/**

* 差分

* @param oldApkPath

* @param newApkPath

* @param patchPath

* @return

*/

public native static int diff(String oldApkPath, String newApkPath, String patchPath);

/**

* 合并

* @param oldApkPath

* @param newApkPath

* @param patchPath

* @return

*/

public static native int patch(String oldApkPath, String newApkPath, String patchPath);

static {

System.loadLibrary("BsDiffAndPatch");

}

}

主函数调用1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47public class DiffPatchServer {

// patch存储路径

public static final String PATCH_FILE_PATH = "diff.patch";

// 使用旧版本+patch包,合成的新版本

public static final String OLD_TO_NEW_APK_PATH = "generated.apk";

private static String oldApkPath = null;

private static String newApkPath = null;

public static void main(String[] args){

if (args.length != 2) {

System.out.println("抱歉,参数不正确!");

return;

}

System.out.println("\n\n------ Android Apk差分合并算法服务端演示 ------");

String os = System.getProperty("os.name");

System.out.println("操作系统:" + os);

oldApkPath = args[0];

newApkPath = args[1];

System.out.println("旧版Apk:" + oldApkPath);

System.out.println("新版Apk:" + newApkPath);

System.out.println();

generateDiff();

System.out.println();

applyPatch();

System.out.println();

}

public static void generateDiff(){

System.out.println("正在生成差分文件,请稍后...");

BsDiffAndPatch.diff(oldApkPath, newApkPath, PATCH_FILE_PATH);

}

public static void applyPatch(){

System.out.println("正在创建合并文件,请稍后...");

BsDiffAndPatch.patch(oldApkPath, OLD_TO_NEW_APK_PATH, PATCH_FILE_PATH);

try {

System.out.println("新版Apk MD5值:" + MD5Util.getFileMD5String(newApkPath));

System.out.println("合并Apk MD5值:" + MD5Util.getFileMD5String(OLD_TO_NEW_APK_PATH));

} catch (IOException e) {

e.printStackTrace();

}

}

}

生成jar包

注意指定 Main Class

执行差分合并算法

通过参数传入旧版Apk和新版Apk名称,生成差分包:diff.patch和合并Apk:generated.apk

比较新版Apk与合并Apk的MD5值是一致的,表明bsdiff差分合并成功!

1java -Djava.library.path=. -jar BsDiffAndPatch.jar DiffUpdate_v1.apk DiffUpdate_v2.apk

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值