Skip to content

一步一步教你从0开始实现安卓增量更新,包括前端和后台的全部教程。

License

Notifications You must be signed in to change notification settings

djzhao627/android_app_update

 
 

Repository files navigation

android_app_update

安卓客户端和服务端实现增量更新全解

1.下载bsdiff库

首先增量更新用到了开源的bsdiff库,先到官网下载,地址是http://www.daemonology.net/bsdiff/ 。但是目前官网上的window port连接失效了,不知道原因,我只能百度去下载 bsdiff4.3-win32-src.zip。 bsdiff这个库是依赖于bzip的,所以还要去bzip的官网下载。 www.bzip.org

2.新建一个vs2017的空项目,名字叫bsdiff,拆分安装包的工程。把工程里的.h和.c文件分别导入进去。

导入后有很多编译错误

原因是用了一些不安全的函数,如fopen,需要声明一些宏定义,在每个报错的c文件最前端加入这样的声明 #define _CRT_SECURE_NO_WARNINGS,还有将setmode改成_setmode,fileno改成_fileno,将isatty改成_isatty,将lseek改成_lseek,将read改成_read。至此工程编译全部通过。

最后设置打包成dll动态库。

3.新建java工程,作为服务端的拆分的程序

编写native函数,

private native static int diff(String oldFile, String newFile, String patchFile);

参数设置有三个:旧的apk路径,新的apk路径,以及新旧apk拆分出来的拆分包路径。

然后用javah命令来生成头文件,可以一键配置,具体参考这篇文章。https://blog.csdn.net/wisevenus/article/details/53046076

把生成的头文件放在vs的工程目录下,由于需要jni.h,和jni_md.h 这两个头文件,需要去C:\Program Files\Java\jdk1.8.0_181\include里面复制出来放在工程目录下,然后添加现有项把他加进来。至此头文件都找到了,如图

找到bsdiff.cpp的文件,由于里面有main函数,我们不需要,把他改名成bsdiff_main,然后我们自己写一个动态库的对外接口函数去调用bsdiff_main生成拆分包,代码如下:

JNIEXPORT jint JNICALL Java_app_1update_1service_ServiceDiff_diff(JNIEnv *env, jclass cls, jstring oldFile_jstr, jstring newFile_jstr, jstring patchFile_jstr) {
	const char* oldFile = (char*)env->GetStringUTFChars(oldFile_jstr, NULL);
	const char* newFile = (char*)env->GetStringUTFChars(newFile_jstr, NULL);
	const char* patchFile = (char*)env->GetStringUTFChars(patchFile_jstr, NULL);

	int argc = 4;
	char *argv[4];
	argv[0] = "bsdiff";
	argv[1] = (char*)oldFile;
	argv[2] = (char*)newFile;
	argv[3] = (char*)patchFile;

	int result = bsdiff_main(argc, argv);

	env->ReleaseStringUTFChars(oldFile_jstr, oldFile);
	env->ReleaseStringUTFChars(newFile_jstr, newFile);
	env->ReleaseStringUTFChars(patchFile_jstr, patchFile);

	return result;
}

4.eclpise调用dll动态库

把生成的dll动态库复制到src文件夹下,然后配置一下dll的搜索路径。

右击项目,从弹出的右键菜单中选择“Properties”,或者按Alt+Enter键。

弹出properties设置窗口,从左侧列表中找到“Java Build Path”,然后选择右侧的“libraries”选项卡,点击“JRE System Library”。

选择“Native library location”,在没有设置的情况下可以看见后面写的是“(None)”,点击“Edit”按钮。

弹设置对话框,把dll文件夹所在的目录复制粘贴到location path框中,点击OK按钮即可。返回properties窗口,点击OK按钮。

这样用System.loadLibrary("bsdiff");就可以调用动态库了。

5.测试拆分是否成功

网上下载了微信的6.0版本和6.6版本的apk包,进行拆分,拆分后生成weixin.patch,拆分是异步的,比较慢,等待一段时间,发现生成了weixin.patch,拆分成功。如图,大概节省了7M的流量

public class ServiceDiff {
	
	private native static int diff(String oldFile, String newFile, String patchFile);
	
	public static void main(String[] args) {
		int result = diff("F:\\java-project\\app_update_service\\src\\weixin_v6.0.apk", 
				"F:\\java-project\\app_update_service\\src\\weixin_1080.apk", 
				"F:\\java-project\\app_update_service\\src\\weixin.patch");
		System.out.print(result);
	}
	
	static {
		System.loadLibrary("bsdiff");
	}
}

由于微信的apk过大,就不放在github上了,需要的朋友自己百度去下载吧。

6.客户端部分:android studio 3.1.3 新建一个工程

随便取名,叫app_update_client,然后要勾选include c/c++ support,在MainActivity里面加入函数 public native static int patch(String oldFile, String newFile, String patchFile);

在左侧cpp中引入zip2的文件夹,放进去后编译有大量的错误,都是一些类型需要强转什么的,我已经全部修改好了。

然后在native-lib.cpp中加入patch函数的实现,同理就是调用了bspatch.c里面写好的东西,具体可以看我上传的源代码。

接下来就是模拟下载更新包,然后与旧的apk包合并生成新的apk包,生成后直接安装即可。

在此遇到的问题有:

1. github上的bspatch是不能用的,必须到官网上去下载

2. 用android studio在native-lib上自动生成的native函数,第二个参数是jclass, 会导致识别不到,改成jobject就可以了。

3. 我测试是直接将.patch文件和.apk的文件拷贝到手机里面进行合成的,合成的文件必须生成在自己的包里面,其他地方不能生成。

About

一步一步教你从0开始实现安卓增量更新,包括前端和后台的全部教程。

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C 79.3%
  • C++ 19.2%
  • Java 1.2%
  • CMake 0.3%