增量更新 也叫差分升级,通过某种算法,找出旧包和新包不一样的地方,然后生成差分包,这样用户下载的时候不需要下载完整大小的包到手机,只需要下载差分包,然后将差分包和本地的安装包合并成新的安装包,文件校验后安装。
bsdiff old.apk new.apk patch.apk
bspatch old.apk new.apk patch.patch
CMakeLists.txt
调动JNI的差分包合成的工具类
public class BsPatchUtils {
static {
System.
loadLibrary(
"bspatch")
;
}
public static native int
patch(String oldApk
,String newApk
,String patch_)
;
}
native-lib.cpp
#include
<jni.h>
#include
<string>
//告诉我们的程序在某个地方有实现patch方法
extern
"C"{
//C++ C调用,包裹一下
extern int
patch(
int argc
,char * argv[])
;
}
extern
"C"
JNIEXPORT
jint
JNICALL
Java_com_example_ndk_BsPatchUtils_patch(
JNIEnv *env
,
jclass clazz
,
jstring old_apk
,
jstring new_apk
,
jstring patch_) {
//
TODO: implement patch()
// bspatch oldfile newfile patchfile
int argc=
4
;
char * argv[argc]
;
argv[
0]=
"bspatch"
;
argv[
1]=
const_cast<
char *>(env->GetStringUTFChars(old_apk
,
0))
;
argv[
2]=
const_cast<
char *>(env->GetStringUTFChars(new_apk
,
0))
;
argv[
3]=
const_cast<
char *>(env->GetStringUTFChars(patch_
,
0))
;
//0表示成功
int result=patch(argc
,argv)
;
//释放资源
env->ReleaseStringUTFChars(old_apk
,argv[
1])
;
env->ReleaseStringUTFChars(new_apk
,argv[
2])
;
env->ReleaseStringUTFChars(patch_
,argv[
3])
;
return result
;
}
java代码
File newFile =
new File(getExternalFilesDir(
"apk")
,
"app.apk")
;//合成后的地址
File patchFile =
new File(getExternalFilesDir(
"apk")
,
"patch.apk")
;//差分包下载保存地址获取
int result = BsPatchUtils.
patch(getApplicationInfo().
sourceDir
, newFile.getAbsolutePath()
,
patchFile.getAbsolutePath())
;
if (result ==
0) {
install(newFile)
;
}
private void
install(File file) {
Intent intent =
new Intent(Intent.
ACTION_VIEW)
;
intent.addFlags(Intent.
FLAG_ACTIVITY_NEW_TASK)
;
if (Build.VERSION.
SDK_INT >= Build.VERSION_CODES.
N) {
// 7.0+以上版本
Uri apkUri = FileProvider.
getUriForFile(
this, getPackageName() +
".fileprovider"
, file)
;
intent.addFlags(Intent.
FLAG_GRANT_READ_URI_PERMISSION)
;
intent.setDataAndType(apkUri
,
"application/vnd.android.package-archive")
;
}
else {
intent.setDataAndType(Uri.
fromFile(file)
,
"application/vnd.android.package-archive")
;
}
startActivity(intent)
;
}
合并的地方建议放在外置存储(SDcard)当中
合并的过程比较耗时,需要放到子线程中进行。