android升级优化之增量更新

2022-04-24  本文已影响0人  夏木友人

一、 什么是增量更新?

我们一般版本升级,都需要先下载一个新包,下载完之后再安装覆盖旧包。下载一个完整的apk正常都是几十M,甚至几百M,这样既浪费时间又浪费流量。

这时候有人就会想,我们不是有旧的安装包,只要知道新安装包更新哪些内容,是不是只要下载这些需要更新的内容,而不用下载整个完整安装包。

这时就出现了增量更新,增量更新只需要下载差分包,即可完成更新。

二、增量更新原理

增量更新的原理,简单的说就是通过算法找出新版本和旧版本不一样的地方(这个过程也叫做差分),然后将不一样的地方抽取出来形成所谓的更新补丁(patch),也称之为差分包。客户端在检测到更新的时候,只需要下载差分包到本地,然后将差分包合并至本地的安装包,形成新版本的安装包,文件校验通过后再执行安装即可。

自从 Android 4.1 开始, Google Play 引入了应用程序的增量更新功能,App使用该升级方式,可节省约2/3的流量。

三、实现方案

3.1如何生成path差分包
macOS操作验证
  1. 安装
    brew install bsdiff

  2. Mac 安装brew环境,命令终端

    /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"

  3. 生成差量文件
    bsdiff 1.0.apk 2.0.apk out.patch

window操作验证
  1. bsdiff 下载地址
    链接: https://pan.baidu.com/s/1whjZccBKwcWjiXGxd9LzdQ?pwd=c5pw 提取码: c5pw

  2. 然后打开Windows命令行工具,切换到该目录,打入命令bsdiff v1.0.0.apk v1.0.1.apk patch.patch生成差量文件,
    bsdiff 1.0.apk 2.0.apk out.patch

3.2Android客户端的实现

1.得到out.path文件,只需要与旧包对比,合成出新包。

2.客户端要自行编译bspatch.c来实现合并差分包,也就是所谓的ndk开发,项目中导入bsdiff相关文件bspath.c, bzip包等(下载gitlub demo自取)


image.png

3.新建update-lib.cpp文件,执行out.path与旧包合成新包方法


image.png
image.png

4.增量更新代码实例
private void updateAPK() {
new AsyncTask<Void, Void, File>() {
@Override
protected File doInBackground(Void... voids) {
File oldFile = new File(Environment.getExternalStorageDirectory(), "1.0.apk");
Log.e(MainActivity.class.getSimpleName(), "oldFile是否存在:"+oldFile.exists());
String oldFilePath = oldFile.getAbsolutePath();

            File patchFile = new File(Environment.getExternalStorageDirectory(), "out.patch");
            Log.e(MainActivity.class.getSimpleName(), "patchFile是否存在:"+patchFile.exists());
            String patchFilePath = patchFile.getAbsolutePath();
            String outPath = createNewFile().getAbsolutePath();
            PatchUtils.bsPatch(oldFilePath, patchFilePath, outPath);
            return new File(outPath);
        }

        @Override
        protected void onPostExecute(File file) {
            super.onPostExecute(file);

            if (file != null) {
                if (!file.exists()) return;
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    Uri fileUri = FileProvider.getUriForFile(MainActivity.this, MainActivity.this.getApplicationInfo().packageName + ".fileprovider", file);
                    intent.setDataAndType(fileUri, "application/vnd.android.package-archive");
                } else {
                    intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
                }
                MainActivity.this.startActivity(intent);
            } else {
                Toast.makeText(MainActivity.this, "差分包不存在!", Toast.LENGTH_LONG).show();
            }

        }
    }.execute();
}
demo下载地址

https://github.com/liyuyitong/basdiff

上一篇下一篇

猜你喜欢

热点阅读