APP升级—BsDiff增量更新

时间:2021-7-20 作者:qvyue

BsDiff算法介绍:

bsdiff是由Conlin Percival开源的一个优秀的差分算法,而且是跨平台的。在目前很多大厂的app中都包含一个bspatch.so的库,其实主要是用于组装差分包的。感兴趣的同学可以看一下。增量更新使用的好处主要有两点:1、对用户来说,下载速度快,省流量,提高用户体验 2,对服务器来说,减少服务器的带宽压力。

源码下载:

https://github.com/cnSchwarzer/bsdiff-win/releases

算法原理:

https://www.cnblogs.com/startkey/p/10678173.html

android使用:

1、 native工程

   android studio新建native c++工程,新建好功能后,打开main目录,可以看到入下图所示:
APP升级---BsDiff增量更新
图 1 工程目录

在cpp文件夹中拷贝bsdiff源码中的bzip2文件夹,并且将bsdiff.c 和bspatch.c文件也拷贝到cpp目录中,然后再CMakeLists.text中进行配置:

cmake_minimum_required(VERSION 3.4.1)

//bzip2文件夹下的文件较多是,使用目录来进行引入
aux_source_directory(bzip2  SOURCES)

add_library(
        DiffUtils   //此处是可以为您所需的library的名字
        SHARED
        native-lib.cpp
        bspatch.c     //新引入的文件
        bsdiff.c     //新引入的文件
        ${SOURCES})
include_directories(bzip2)

target_link_libraries(
        DiffUtils    //此处是可以为您所需的library的名字
        log)

2、Java ,JNI,C++结构搭建

在java目录中添加BsPatchUtils工具供java代码调用:

public class BsPatchUtils {
    static{
        System.loadLibrary("DiffUtils");   //此处的library的名字未您在CMakeLists.text中指定的名称
    }

//组装差分包
    public static native int patch(String oldApk,String newApk,String patchFile);

//获取差分包
   public static native int diff(String oldApk ,String newApk,String dissFile);
}

3、功能实现

在 BsPatchUtils工具中对应的patch ,diff静态nativie方法上使用alt+enter快捷键,生成对应的jni代码,如:cpp/native-lib.cpp所示:

注意:
1. 下载好bsdiff源码后,自己可以编译生成对应的exe文件,在命令行执行bsdiff命令可知,需要的参数说明:

命令行:

 bsdiff oldfile newfile patchfile   

 bspatch oldfile newfile patchfile

oldfile -------原文件的名称
newfile  ------新文件的名称
patchfile --------差分文件名

上述差分和组包指令需要四个参数:指令,oldfile ,newfile ,patchfile  ,那么我们在下面的使用中就需要传递四个参数。
extern "C" {

//特别说明:此处的executePatch 方法是将bspatch.c中的main方法修改了一下名字,方便区分的,    executeDiff方法类似。
extern int executePatch(int argc, char *argv[]);
extern int executeDiff(int argc, char *argv[]);
}

/*
 * TODO  组装新包
 */
extern "C"
JNIEXPORT jint JNICALL
Java_com_leon_bsdiffupdatedemo_BsPatchUtils_patch(JNIEnv *env, jclass clazz, jstring old_apk,
                                                  jstring new_apk, jstring patch_file) {
    // TODO: implement patch()
    int args = 4;
    char *argv[args];
    argv[0] = "DiffUtils";

    argv[1] = (char *) (env->GetStringUTFChars(old_apk, 0));
    argv[2] = (char *) (env->GetStringUTFChars(new_apk, 0));
    argv[3] = (char *) (env->GetStringUTFChars(patch_file, 0));

    //此处executePathch()就是上面我们修改出的
    int result = executePatch(args, argv);

    env->ReleaseStringUTFChars(old_apk, argv[1]);
    env->ReleaseStringUTFChars(new_apk, argv[2]);
    env->ReleaseStringUTFChars(patch_file, argv[3]);
    return result;
}

4、java使用

 public void patch() {
        File newFile = new File(getExternalFilesDir("apk"), "app.apk");
        File patchFile = new File(getExternalFilesDir("apk"), "patch.apk");
        int result = BsPatchUtils.patch(getApplicationInfo().sourceDir, newFile.getAbsolutePath(),
                patchFile.getAbsolutePath());
        if (result == 0) {
            install(newFile);
        }
    }



  private void install(File file) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 7.0+以上版本
            Uri apkUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", file);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
        } else {
            intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
        }
        startActivity(intent);
    }

总之,使用差分算法对安装包进行差分包处理,这样在服务器端只提供差分包共用户下载更新,虽然更新下载速度比较快,但是每次都需要安装,这个问题作一记录。

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。