原理:增量更新使用的是bsdiff对新老apk包进行区分, 生成一个增量包,然后在手机上使用bspatch对老包进行增量,重新安装;
下载资源到本地,在Android工程中添加NDK,并把c文件导入到cpp文件夹中;
在项目中配置,并且引入:
cutil.cpp
#include <jni.h>
#include <string>
extern "C" {
extern int bspatch_main(int argc, char *argv[]);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_zp_c_update_NativeUtil_doPatchNative(JNIEnv *env, jclass type, jstring oldFile_, jstring newFile_,
jstring patchFile_) {
const char *oldFile = env->GetStringUTFChars(oldFile_, 0);
const char *newFile = env->GetStringUTFChars(newFile_, 0);
const char *patchFile = env->GetStringUTFChars(patchFile_, 0);
char *argv[4] = {
"bspatch",//可以随意填
const_cast<char *>(oldFile),
const_cast<char *>(newFile),
const_cast<char *>(patchFile)
};
bspatch_main(4, argv);
env->ReleaseStringUTFChars(oldFile_, oldFile);
env->ReleaseStringUTFChars(newFile_, newFile);
env->ReleaseStringUTFChars(patchFile_, patchFile);
}
build.gradle
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
...
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
NativeUtil
public class NativeUtil {
static {
System.loadLibrary("cutil");
}
public static native void doPatchNative(String oldFile, String newFile, String patchFile);
}
主工程里边引入
object : AsyncTask<Void, Void, File>() {
override fun doInBackground(vararg voids: Void): File {
//bspatch做合成 得到新版本的apk文件
val oldApk = applicationInfo.sourceDir
val patch = File(Environment.getExternalStorageDirectory(), "/" + packageName +"patch.diff").absolutePath
val newApk = File(Environment.getExternalStorageDirectory(), "/" + packageName +"new.apk")
if (!newApk.exists()) {
try {
newApk.createNewFile()
} catch (e: IOException) {
e.printStackTrace()
}
}
NativeUtil.doPatchNative(oldApk, newApk.absolutePath, patch)
return newApk
}
override fun onPostExecute(file: File) {
super.onPostExecute(file)
if (file.exists()) {
//安装
val intent = Intent(Intent.ACTION_VIEW)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val fileUri = FileProvider.getUriForFile(
this@Main,
this@Main.applicationInfo.packageName + ".provider",
file
)
intent.setDataAndType(fileUri, "application/vnd.android.package-archive")
} else {
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive")
}
this@Main.startActivity(intent)
} else {
}
}
}.execute()