一,增量更新的原理,主要是根据新旧包生成差分包,这个差分包由服务器端生成,客户端下载,下载完成后,进行合并,合并成功后通知用户进行安装。
二,如何生成差分包:
一般来说,这个不需要客户端关心,这个由后台开发人员去实现,现在比较流行的开源项目,bsdiff。 里面有两个核心的文件,一个Bsdiff.c和Bspatch.c,Bsdiff.c给后台生成差分包,Bspatch.c给客户端合并这个差分包。
三,具体实现(只实现Bspatch部分,Bsdiff主要是服务器端使用,感兴趣的同学可以自己研究,本文不作解释)
第一步:从http://www.daemonology.net/bsdiff/下载后解压文件,到文件目录中.其中依赖的bzip2也要copy到Jni目录中,如图:
第二步:编写mk文件:LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := bspatch
LOCAL_SRC_FILES := bspatch.c
include $(BUILD_SHARED_LIBRARY)
第三步:定义java层本地方法:
public classBsPatch {
/**
* 合并
*
*@paramoldfile
*@paramnewfile
*@parampatchfile
*/
public native static voidpatch(String oldfile,String newfile,String patchfile);
static{
System.loadLibrary("bspatch");
}
}
第四步:生成头文件,并实现这个方法:
//合并
JNIEXPORTvoidJNICALLJava_xm_bsdiff_BsPatch_patch
(JNIEnv*env,jclassjcls,jstringoldfile_jstr,jstringnewfile_jstr,jstringpatchfile_jstr){
intargc =4;
char* oldfile = (char*)(*env)->GetStringUTFChars(env,oldfile_jstr,NULL);
char* newfile = (char*)(*env)->GetStringUTFChars(env,newfile_jstr,NULL);
char* patchfile = (char*)(*env)->GetStringUTFChars(env,patchfile_jstr,NULL);
__android_log_print(ANDROID_LOG_ERROR,"HelloJni","oldfile*%s",oldfile);
__android_log_print(ANDROID_LOG_ERROR,"HelloJni","newfile*%s",newfile);
__android_log_print(ANDROID_LOG_ERROR,"HelloJni","patchfile*%s",patchfile);
//参数(第一个参数无效)
char*argv[4];
argv[0] ="bspatch";
argv[1] = oldfile;
argv[2] = newfile;
argv[3] = patchfile;
//特别注意,bspatch.c文件没有bspatch_main方法,把main方法改成bspatch_main即可
bspatch_main(argc,argv);
__android_log_print(ANDROID_LOG_ERROR,"HelloJni","bspatch_main*%s","bspatch_main");
(*env)->ReleaseStringUTFChars(env,oldfile_jstr,oldfile);
(*env)->ReleaseStringUTFChars(env,newfile_jstr,newfile);
(*env)->ReleaseStringUTFChars(env,patchfile_jstr,patchfile);
}
第五步,编译,生成so动态库。然后可以直接调用这个动态库的方法。
//1.下载差分包
Log.d("jason","开始合并");
//获取当前应用的apk文件/data/app/app
String oldfile = ApkUtils.getSourceApkPath(MainActivity.this,getPackageName());
//2.合并得到最新版本的APK文件
String newfile = Constants.NEW_APK_PATH;
String patchfile = Constants.PATCH_FILE;
BsPatch.patch(oldfile,newfile,patchfile);
Log.d("jason","oldfile:"+oldfile);
Log.d("jason","newfile:"+newfile);
Log.d("jason","patchfile:"+patchfile);
Toast.makeText(MainActivity.this,"您正在进行无流量更新",Toast.LENGTH_SHORT).show();
//合并完成后安装。
ApkUtils.installApk(MainActivity.this,Constants.NEW_APK_PATH);