增量更新是由差量包和旧安装包合成新的安装包,再进行安装。
优点:
由于下载的是差量包,所以可以快速升级且节省用户流量。
缺点:
1. 增量升级是以两个应用版本之间的差异来生成补丁的,你无法保证用户每次的及时升级到最新,所以你必须对你所发布的每一个版本都和最新的版本作差分,以便使所有版本的用户都可以差分升级,这样操作相对于原来的整包升级较为繁琐,不过可以通过自动化的脚本批量生成。
2. 增量升级成功的前提是,用户手机端必须有能够让你拷贝出来且与你服务器用于差分的版本一致的apk,这样就存在,例如,系统内置的apk无法获取到,无法进行增量升级;对于某些与你差分版本一致,但是内容有过修改的(比如破解版apk),这样也是无法进行增量升级的,为了防止合成补丁错误,最好通过md5 或者其他方式对patch包进行完整性的校验。
摘自:https://www.jianshu.com/p/f0f2950dee74
一、bsdiff下载
bsdiff
下载地址:http://www.daemonology.net/bsdiff/,打开之后点击下图位置进行下载。
bsdiff下载后,解压bsdiff-4.3.tar.gz
,取出目录中的bspatch.c
文件,我们要用的就是这个文件中的bspatch_main
方法。
二、bzip2下载
bzip2
下载地址:https://sourceforge.net/projects/bzip2/或者在http://www.androidos.net.cn/android/9.0.0_r8/xref/external/bzip2取出文件blocksort.c
,bzip2.c
,bzlib.c
,bzlib.h
,bzlib_private.h
,compress.c
,crctable.c
,decompress.c
,huffman.c
,randtable.c
,因为bsdiff的编译需要依赖bzip2,所以需要这些c文件。
三、代码实现
1. 使用android studio创建JNI工程,可参考文章:https://blog.csdn.net/u010982507/article/details/85345985
2. 从bsdiff-4.3
包中拷贝bspatch.c
到cpp
目录下,如下图所示:
3. 需要会使用JNI技术,将bzip2中需要编译的文件拷贝到工程cpp目录下,如下图所示:
4. 在CMakeLists.txt
文件中添加编译文件
# camke编译版本
cmake_minimum_required(VERSION 3.4.1)
# 引入文件,使用bzip变量引用
file(GLOB bzip src/main/cpp/bzip/*)
# 添加动态编译文件
add_library( native-lib SHARED src/main/cpp/native-lib.cpp ${bzip} src/main/cpp/bspatch.c)
# 添加NDK中log库
find_library( log-lib log )
# 编译库
target_link_libraries( native-lib ${log-lib} )
注意:编译bspatch.c
文件时,要修改一些引入头文件,如下所示:
//#include <bzlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <err.h>
#include <unistd.h>
#include <fcntl.h>
#include "bzip/bzlib.h"
5. 在native-lib.cpp
中添加实现方法
#include <jni.h>
#include <string>
extern "C" {
extern int bspatch_main(int argc,char * argv[]);
}
extern "C"
JNIEXPORT jstring JNICALL
Java_com_learn_bsdiff_MainActivity_stringFromJNI(JNIEnv *env, jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C"
JNIEXPORT void JNICALL
Java_com_learn_bsdiff_MainActivity_bsPatch(JNIEnv *env, jobject instance, jstring oldApk_,
jstring patch_, jstring output_) {
const char *oldApk = env->GetStringUTFChars(oldApk_, 0);
const char *patch = env->GetStringUTFChars(patch_, 0);
const char *output = env->GetStringUTFChars(output_, 0);
// 调用合成方法
const char* argv[] = {"bsdiff",oldApk,output,patch};
bspatch_main(4, (char **) argv);
env->ReleaseStringUTFChars(oldApk_, oldApk);
env->ReleaseStringUTFChars(patch_, patch);
env->ReleaseStringUTFChars(output_, output);
}
6. 在MainActivity
中实现更新逻辑
步骤一:添加sd卡读写权限、6.0动态申请权限、7.0uri获取方式
步骤二:编写调用合成新apk安装包逻辑
步骤三:安装新的apk
详细步骤请参考MainActivity
代码:
@SuppressLint("StaticFieldLeak")
public void update() {
new AsyncTask<Void, Void, File>() {
@Override
protected File doInBackground(Void... voids) {
// 获取当前安装包路径 /data/app/com.learn.bsdiff-vkZp27c33gznzKVqB5pztg==/base.apk
// String path = getApplicationContext().getPackageResourcePath(); 或
String oldApk = getApplicationInfo().sourceDir;
Log.e("oldApk", "doInBackground: " + oldApk );
// 下载获取差分包路径
String patch = new File(Environment.getExternalStorageDirectory() + File.separator + "/download/patch").getAbsolutePath();
// 创建新版本的安装包
String output = createNewApk().getAbsolutePath();
// 调用native方法
bsPatch(oldApk, patch, output);
return new File(output);
}
@Override
protected void onPostExecute(File file) {
super.onPostExecute(file);
// 安装应用
AppUtil.install(MainActivity.this,file.getAbsolutePath());
}
}.execute();
}
7. 制作拆分patch
包
编写完更新逻辑,就要制作差量包,制作差量包可以使用工具,windows平台使用bsdiff.exe
工具,执行命令bsdiff.exe old.apk new.apk patch
,然后将生成的patch
差量包放到服务器上下载,这样每次在应用启动的时候,会去检测服务器上是否有更新的通知,如果有更新就下载差量包,再使用bsdiff技术将差量包合成新的apk进行安装。
代码放到了GitHub上,https://github.com/RenZhongrui/android-learn/tree/master/001-android-bsdiff
手机扫一扫
移动阅读更方便
你可能感兴趣的文章