随着一些功能的持续添加,软件变得有点大。这时候,需要增量更新避免用户消耗更多流量来进行更新。
实现原理
原理相对比较简单,通过对比客户端版本的apk和最新版本的apk的二进制差异,生成的作为补丁。然后下载只需下载这个补丁,然后在客户端进行合成,即可实现增量更新。
由于后台使用到LeanCloud以及Node.js,所以自动生成差异包就选择用Node.js来完成。
客户端只需要添加一个合成apk的so文件即可。
Node.js 实现方案
生成差异包
var path = require('path'),
child_process = require('child_process');
module.exports = function(originalFile, targetFile, patchFile, cb) {
var bsdiffPath = path.join(__dirname, 'bin', process.platform, 'bsdiff');
if (process.platform === 'win32') {
bsdiffPath += '.exe';
}
var options = {
timeout: 60 * 1000
};
var args = [originalFile, targetFile, patchFile];
return child_process.execFile(bsdiffPath, args, options, cb);
};
处理上传
var genPatch = require('./cloud/genPatch')
var md5 = require('./cloud/md5')
var fs = require('fs');
var async = require('async');
// 版本差的限制
var LIMIT = 5;
if (!request || !request.params.versionCode) {
response.error("need versionCode")
}
var versionCode = request.params.versionCode;
console.log(versionCode)
var versions = [];
for (var index = 1; index < LIMIT; index++) {
versions.push(versionCode - index);
}
console.info(versions)
md5("./apk/" + versionCode + ".apk", function(md5Code) {
async.each(versions, function(oldVersion, callback) {
fs.exists("./apk/" + oldVersion + ".apk", function (exists) {
if (!exists) {
callback(null);
return;
}
console.log("生成差异包 old : " + oldVersion + " new : " + versionCode)
genPatch(oldVersion, versionCode, function (error, path) {
if (error) {
console.error(error);
callback(error);
return;
}
upload(path, oldVersion, versionCode, md5Code)
callback(null);
console.log(path + " 生成完毕.")
})
})
}, function(err) {
if (err) {
console.error(err)
}
});
})
function upload(path, oldVersion, newVersion, md5Code) {
if (newVersion <= oldVersion) {
console.error("你他妈在逗我吗")
return;
}
var SmartUpdatePatch = AV.Object.extend("SmartUpdatePatch");
fs.readFile(path, function(err, buffer) {
if (err) {
console.error(err);
return;
}
console.log("开始上传" + path)
var file = new AV.File(oldVersion + "" + newVersion + ".patch", buffer);
file.save().then(function() {
var patch = new SmartUpdatePatch();
patch.set("oldVersion", oldVersion);
patch.set("newVersion", newVersion);
patch.set("file", file);
patch.set("md5", md5Code);
patch.save().then(function() {
console.log(path + " 上传成功");
}, function(err) {
console.error(path + " 上传失败,错误" + err);
})
}, function(error) {
console.error("文件上传失败,错误" + error);
});
})
}
客户端实现方案
客户端实现比较简单,根据 SmartAppUpdates 开源项目提供的jni,自行编译生成自己所需架构的so文件,其他的代码该开源项目都有提供。