目录
增量更新
介绍
效果
步骤
总结
最近换了个新手机,号称2019年的android机皇一加7plus。面对这90z的屏幕,原本不玩游戏的我也入了王者农药的坑!不过很少玩,所以基本上每次玩都要下载补丁更新才能玩。今天我们就来讲一下Android应用的增量更新。
优点:
节省用户更新新版本的流量、时间、内存空间。
基本流程如下:
1、准备bsdiff和bzip2(生成补丁,合成新版本必须用到的工具)
mac/linux系统下:
下载bsdiff库:http://www.daemonology.net/bsdiff/
由上图可知,bsdiff库和bspatch依赖bzip库,所以我们还要下载一个bzip库:https://sourceforge.net/projects/bzip2/
下载下来的bsdiff压缩包解压出来,进入到解压后到目录,尝试执行命令“make”,发现无法执行,报错如下:
Makefile:13: *** missing separator. Stop.
解决:
vim命令编辑MakeFile
按下键盘的“i”进入编辑模式
如上图给这两行加上tab缩进,然后依次点击
键盘的“ESC”进入行末模式
输入“:wq”保存并退出vim
重新执行make命令,如果你出现了以下的错误,
error: unknown type name 'u_char'; did you mean 'char'?
成功生成了bsdiff可执行文件,但是在生成bspathc的时候,却出现错误提示,原因是:找不到u_char的声明,所以需要引入#include
出现以上结果表示执行成功,在原来基础下增加了以下两个文件
二、引入库
配置NDK环境,不懂的可以参考我之前写的博客:https://blog.csdn.net/u014736095/article/details/90201308
配好NDK环境后,下面引入bsdiff和bspatch
1、cmakefile
2、将前面准备好的资源复制进来,有bspatch.c和bzip压缩包的解压文件
编译后会出现问题找不到bzlib.h的问题,这是因为版本的问题
解决:把错误的#include
已经给大家编译好,包括bsdiff,bspatch,bzip2,大家直接下载就好
https://download.csdn.net/download/u014736095/11869005
2、配置Android项目ndk环境
这里不详细展开来说,提供一个比较便捷的方法,新创建一个ndk的项目,把一下重要文件复制进来即可!
module的build.gradle文件
//...
android {
//...
defaultConfig {
//...
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
3、引入项目bspatch.c和bzip2的库
如下图,引入bspatch.c库,用于将旧版本apk与补丁patch合成新版本apk文件。
bspatch.c所依赖的bzip2库也要复制进来。
4、c库代码(至关重要)
修改CMakeLists.txt配置文件
# 设置构建本机库所需的CMake最低版本。
cmake_minimum_required(VERSION 3.4.1)
# 声明一个文件夹所有的c文件
file(GLOB bzip2_resource bzip2-1.0.6/*.c)
add_library( # 设置库的名称。
native-lib
#将库设置为共享库。
SHARED
# 提供源文件的相对路径。
native-lib.cpp
bspatch.c
${bzip2_resource}
)
# 引入一个目录
include_directories(bzip2-1.0.6)
find_library(
log-lib
log )
target_link_libraries(
native-lib
${log-lib} )
重新编译可能无法通过,会有异常,作以下修改即可
重新编译即可。
Activity中声明一个native函数
/**
* 合成新的apk安装包
* @param oldApk 旧版本
* @param patch 补丁
* @param newApk 新版本
* @return
*/
public native String increaseUpdate(String oldApk,String patch,String newApk);
编辑native-lib.cpp,声明函数与之关联,注意这个函数的命名是有规律的,Java_{类名路径,分割用“_”}_{方法名}
5、编写更新的代码
涉及到文件读写,需要配置申请权限,并兼容高版本
AndroidManifest.xml
file_paths.xml
合成新版本apk,
new AsyncTask() {
@Override
protected File doInBackground(Void... voids) {
createNewFile(newApkPath);
increaseUpdate(oldApkPath, patchPath, newApkPath);
return new File(newApkPath);
}
@Override
protected void onPostExecute(File file) {
super.onPostExecute(file);
if(file == null) return;
installApk(file);
}
}.execute();
/**
* 创建一个文件
* @param path
* @return
*/
private File createNewFile(String path) {
File file = new File(path);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
/**
* 安装应用
* @param file
*/
private void installApk(File file) {
Intent intent = new Intent(Intent.ACTION_VIEW);
//兼容7.0
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
} else {
// 声明需要的临时权限
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// 第二个参数,即第一步中配置的authorities
String packageName = getApplication().getPackageName();
Uri contentUri = FileProvider.getUriForFile(MainActivity.this, packageName + ".fileprovider", file);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
}
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
6、制作差分包
制作两个版本,必须用相同的证书,否者不成功
unix下:bsdiff/. {旧版本} {新版本} {补丁名字}
win下命令:bsdiff {旧版本} {新版本} {补丁名字}
7、测试
标准情况下,补丁包的是在服务器上生成的,手机客户端从服务器上下载补丁patch,与手机上存在的旧版本,合成新的版本(通过调用bspatch.c中的main方法进行合成),然后安装!所以合成后,手机硬盘上会产生新的安装包。这个版本实际上与之前打包出来的新版本大小是一致的。
注意事项:
1、mac或者Linux系统中,需要在bsdff文件夹中进行make指令编译
2、bspatch.c文件记需要重新导入bzlib.h
3、正确编写CMakeList文件
4、记得调用bspatch.c中的main()方法所传进去的数组元素顺序
实际上增量更新的核心就是两部分,
- 会使用工具将新版本与旧版本进行差分,生成补丁包
- 会配置项目的NDK环境,调用bspatch.c库中的代码,将下载的补丁包+旧版本合并成新版本。
建议先下载完整的项目下来体验一下,然后看着源码一步一步学习!否则很多坑,最好能够下载这篇文章里的库,导入你的项目,这样可以省去折腾因为版本差异导致的问题!