前言
Android增量更新的功能,网上只有原生态环境下的教程,没有Qt For Android的,所以我先是根据网上教程在Android Studio平台上进行学习和实践,后面根据原理,将其移植到了Qt平台上。
资源链接
教程
因为Android Studio环境下的增量更新教程有很多,比如:
Android增量更新(bsdiff使用)_bsdiff 使用文档-CSDN博客(详细、细节)
Android使用bsdiff和bspatch实现增量更新 - 简书 (jianshu.com)(这个里面有例子和资源,立马见效)
bsdiff
教程中提供的bsdiff官网中没找到源码的下载位置,但是github下有:
附指令:
#生成差异文件命令
bsdiff [旧文件] [新文件] [差异文件]
#合并文件命令
bspatch [旧文件] [新文件] [差异文件]
ninja
在Android Studio环境下编译,报错(Could not find Ninja on PATH or in SDK CMake bin folders.),因为缺少ninja。下载ninja.exe文件后,将其放到Cmake.exe同目录下。
Releases · ninja-build/ninja (github.com)
思路
主体是通过使用bsdiff和bzip配合来实现增量更新的,两者都是使用C语言开发的,所以Android Studio环境下是通过JNI调用的,Cmake工具编译的,整体就复杂些。
而我通过Qt 跨平台主体使用C++进行开发的,增量更新这部分代码直接添加到工程下,直接使用,不需要JNI和CMake的配合。
增量更新流程
可参考教程
Android增量更新方案_android 增量更新-CSDN博客
代码说明
由于安卓端只需要合成,所以只将bsdiff中的bspatch.c添加到工程中,而bspatch依赖bzip,故将其源码也添加到工程中,涉及的部分pro文件如下:
android:{
SOURCES += \
update/bspatch.c \
update/bzip/blocksort.c \
update/bzip/bzlib.c \
update/bzip/compress.c \
update/bzip/crctable.c \
update/bzip/decompress.c \
update/bzip/huffman.c \
update/bzip/randtable.c
HEADERS += \
update/bspatch.h \
update/bzip/bzlib.h \
update/bzip/bzlib_private.h
}
多出来的bspatch.h是为了方便在其他地方引用合成函数,即:bspatch.c中的main函数,由于main这个名字比较冲突、敏感,所以我将其改为“spatchMain”。
//bspatch.h
#ifndef INCREMENTUPDATEDEMO_BSPATCH_H
#define INCREMENTUPDATEDEMO_BSPATCH_H
#ifdef __cplusplus
extern "C" {
int spatchMain(int argc,char * argv[]);
}
#endif
#endif //INCREMENTUPDATEDEMO_BSPATCH_H
旧apk+补丁=新apk,其中旧apk即本应用的apk,通过Context.getApplicationInfo().sourceDir来获取。
调用合成代码如下:
bool SystemHelper::patchApk(QString patch, QString &newApk, QString &err)
{
#ifdef Q_OS_ANDROID
QAndroidJniObject appInfoJniObj =QtAndroid::androidContext().callObjectMethod("getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;");
QAndroidJniObject field = appInfoJniObj.getObjectField("sourceDir", "Ljava/lang/String;");
QString oldApk = field .toString();
if(QFile::exists(patch))
{
newApk = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)+"/new.apk";
char oldStr[256] = {0};
char newStr[256] = {0};
char patchStr[256] = {0};
strlcpy(oldStr,oldApk.toStdString().c_str(),oldApk.length()+1);
strlcpy(newStr,newApk.toStdString().c_str(),newApk.length()+1);
strlcpy(patchStr,patch.toStdString().c_str(),patch.length()+1);
int argc = 4;
char * argv[argc];
argv[0] = "bspatch";
argv[1] = oldStr;
argv[2] = newStr;
argv[3] = patchStr;
//调用合并的方法
int ret = spatchMain(argc, argv);
if(ret !=0)
{
err = QStringLiteral("合成新apk失败。");
return false;
}
}
else
{
err = QStringLiteral("补丁文件不存在。");
return false;
}
return true;
#else
return true;
#endif
}
结束语
增量更新比想象中容易实现,但是可以预想到,在后续实践中会比想象中麻烦些。