美文网首页JNI基础积累
Android使用bsdiff和bspatch实现增量更新

Android使用bsdiff和bspatch实现增量更新

作者: itfitness | 来源:发表于2021-09-08 08:03 被阅读0次

    目录

    前期准备

    1.工具下载

    这里我把需要用到的代码和工具都整理了一下放到了一起:https://www.aliyundrive.com/s/ALCxbGeWY2o


    bzip2:是bsdiff依赖的一个库,这里我只存放了需要用到的文件,完整版的下载地址为:https://sourceforge.net/projects/bzip2/files/latest/download
    bsdiff-win:是编译好的Windows平台下的可执行文件,可以在Windows平台生成差异文件和合并文件
    bsdiff-source:是bsdiff的源码,它的官网为:http://www.daemonology.net/bsdiff/
    2.工具的使用方法

    只需要在工具所在的目录打开命令行窗口



    然后输入命令即可

    #生成差异文件命令
    bsdiff [旧文件] [新文件] [差异文件]
    #合并文件命令
    bspatch [旧文件] [新文件] [差异文件]
    

    例如我这创建两个文本文件old.txt和new.txt


    old.txt new.txt

    然后我可以利用bsdiff命令生成差异文件




    这个时候我再利用bspatch命令,将old.txt和patch文件合成new2.txt




    我们打开new2.txt发现与new.txt是一样的
    new2.txt

    原理讲解

    实现原理其实就是将新APK文件与旧APK文件进行对比,得出一个差异文件,然后用户端下载这个差异文件与手机上的那个旧APK文件进行合并即可得到与新的APK文件一样的文件,然后再安装这个新APK即可实现增量更新,如下图所示


    具体实现

    1.集成bspatch到项目

    由于Android端只需要合并文件所以我们只需要集成bspatch即可,我们将bsdiff-source/bsdiff-4.3文件夹中的bspatch.c文件拷贝到cpp目录,然后将bzip2文件夹下的文件拷贝到cpp下的bzip(新建的目录)目录下



    此外我们还要对bspatch.c进行修改,我们在文件顶部加入bzip2的引用

    /** 导入bzip2的引用*/
    #include "bzip/bzlib.c"
    #include "bzip/crctable.c"
    #include "bzip/compress.c"
    #include "bzip/decompress.c"
    #include "bzip/randtable.c"
    #include "bzip/blocksort.c"
    #include "bzip/huffman.c"
    

    否则的话你运行项目的时候可能会报如下错误



    然后我们还需要新建bspatch.h放到bzip文件夹下,这样做目的是为了可以在native-lib.cpp文件中使用main方法(注意:这里的main方法并不是入口函数,就是一个执行命令的普通函数)



    bspatch.h文件如下
    #ifndef INCREMENTUPDATEDEMO_BSPATCH_H
    #define INCREMENTUPDATEDEMO_BSPATCH_H
    int main(int argc,char * argv[]);
    #endif //INCREMENTUPDATEDEMO_BSPATCH_H
    

    然后在bspatch.c中引入bspatch.h头文件



    接下来我们需要配置下CMakeLists.txt文件将bzip下的c文件和.h头文件链接到项目

    cmake_minimum_required(VERSION 3.10.2)
    
    project("incrementupdatedemo")
    #定义一个全局变量包含了所有要编译的C文件
    file(GLOB BZIP bzip/*.c)
    #导入头文件
    include_directories(bzip)
    add_library( # Sets the name of the library.
                 native-lib
                 SHARED
                 native-lib.cpp
                 #将bzip下的.c文件添加到library
                 BZIP)
    find_library( # Sets the name of the path variable.
                  log-lib
                  log )
    target_link_libraries( # Specifies the target library.
                           native-lib
                           ${log-lib} )
    
    2.创建JNI方法

    创建PatchUtil工具类,创建合并文件的JNI方法

    public class PatchUtil {
        static {
            System.loadLibrary("native-lib");
        }
        /**
         * 合并APK文件
         * @param oldApkFile 旧APK文件路径
         * @param newApkFile 新APK文件路径(存储生成的APK的路径)
         * @param patchFile 差异文件
         */
        public native static void patchAPK(String oldApkFile,String newApkFile,String patchFile);
    }
    

    C++实现JNI方法

    #include <jni.h>
    #include <string>
    #include "bspatch.h"
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_itfitness_incrementupdatedemo_PatchUtil_patchAPK(JNIEnv *env, jclass clazz,
                                                              jstring old_apk_file,
                                                              jstring new_apk_file,
                                                              jstring patch_file) {
        int argc = 4;
        char * argv[argc];
        argv[0] = "bspatch";
        argv[1] = (char*) (env->GetStringUTFChars(old_apk_file, 0));
        argv[2] = (char*) (env->GetStringUTFChars(new_apk_file, 0));
        argv[3] = (char*) (env->GetStringUTFChars(patch_file, 0));
    
        //调用合并的方法
        main(argc, argv);
    
        env->ReleaseStringUTFChars(old_apk_file, argv[1]);
        env->ReleaseStringUTFChars(new_apk_file, argv[2]);
        env->ReleaseStringUTFChars(patch_file, argv[3]);
    }
    
    3.Activity中增加合成的调用
    public class MainActivity extends AppCompatActivity {
        private TextView tv_version;
        private Button bt_update;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            tv_version = findViewById(R.id.tv_version);
            bt_update = findViewById(R.id.bt_update);
            tv_version.setText("1.0");
            bt_update.setOnClickListener(v->{
                new Thread(() -> {
                    File oldApkFile = new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "old.apk");
                    File newApkFile = new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "new.apk");
                    File patchFile = new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "patch");
                    PatchUtil.patchAPK(oldApkFile.getAbsolutePath(),newApkFile.getAbsolutePath(),patchFile.getAbsolutePath());
                    //安装APK
                    AppUtils.installApp(newApkFile);
                }).start();
            });
        }
    }
    
    4.编译生成旧APK

    这里我们在1.0版本(旧版本)中展示当前应用的版本号,如下所示



    然后我们取出编译生成的APK命名为old.apk


    5.编译生成新APK

    然后我们将版本号改为2.0并且在按钮下增加一张图片



    我们将其命名为new.apk


    6.使用bsdiff生成差异文件

    使用bsdiff生成差异文件



    7.使用bspatch合并文件

    接下来我们装回旧版然后将old.apk和patch放到SD卡中,当然真实环境的patch文件是通过网络下载得到的,这里我们模拟已经下载完毕了



    点击按钮,会发现Download文件夹下出现了一个new.apk文件



    然后我们通过代码将new.apk安装到手机上

    案例源码

    https://gitee.com/itfitness/increment-update

    相关文章

      网友评论

        本文标题:Android使用bsdiff和bspatch实现增量更新

        本文链接:https://www.haomeiwen.com/subject/glvpwltx.html