Node.js + Bsdiff 实现增量更新

随着一些功能的持续添加,软件变得有点大。这时候,需要增量更新避免用户消耗更多流量来进行更新。

实现原理

原理相对比较简单,通过对比客户端版本的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文件,其他的代码该开源项目都有提供。

你可能感兴趣的:(Node.js + Bsdiff 实现增量更新)