美文网首页
使用 bsdiff 进行增量更新

使用 bsdiff 进行增量更新

作者: 石器时代小古董 | 来源:发表于2020-03-05 15:35 被阅读0次

    增量更新的原理

    1. 生成差异文件
    2. 下发差异文件到手机
    3. 客户端拿到差异包后和旧 APK 进行合成,生成新的 APK
    4. 客户端主动安装新的 APK

    使用 bsdiff 生成差异包

    使用 bsdiff 提供的工具生成差异包

    ./bsdiff oldfile newfile patchfile
    

    客户端引用 bsdiff 的库

    CMakeLists

    include_directories(${CMAKE_SOURCE_DIR}/bzip2)
    
    aux_source_directory(${CMAKE_SOURCE_DIR}/bzip2/ bzip2_src)
    
    add_library(
            native-lib
            SHARED
            native-lib.cpp
            bspatch.c
            ${bzip2_src}
    )
    
    target_link_libraries( 
            native-lib
            log)
    

    native cpp 根据传入的旧 apk 路径,新 apk 路径,以及 patch 路径合成一个新的 apk

    这里会将旧apk和patch合成,合成后存放的路径就是传入的 新 apk 地址

    #include <jni.h>
    #include <string>
    
    // 声明一个函数
    extern "C" {
        // 声明一个函数 加上 extern 表示是在外部实现的
    extern int bspatch_main(int argc, char *argv[]);
    }
    
    extern "C" JNIEXPORT jstring JNICALL
    Java_com_netease_bsdiff_MainActivity_stringFromJNI(
            JNIEnv *env,
            jobject /* this */) {
        std::string hello = "Hello from C++";
        return env->NewStringUTF(hello.c_str());
    }
    
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_netease_bsdiff_MainActivity_doPatchNative(JNIEnv *env, jobject instance, jstring oldApk_,
                                                       jstring newApk_, jstring patch_) {
        const char *oldApk = env->GetStringUTFChars(oldApk_, 0);
        const char *newApk = env->GetStringUTFChars(newApk_, 0);
        const char *patch = env->GetStringUTFChars(patch_, 0);
    
        //1 声明 , 实现
        //2 声明&实现
        char *argv[4] = {
                "bspatch",//可以随意填""
                const_cast<char *>(oldApk),
                const_cast<char *>(newApk),
                const_cast<char *>(patch)
        };
        bspatch_main(4, argv);
    
        env->ReleaseStringUTFChars(oldApk_, oldApk);
        env->ReleaseStringUTFChars(newApk_, newApk);
        env->ReleaseStringUTFChars(patch_, patch);
    }
    

    Android 端拿到合成后的新 apk 就可以安装了

     public void onUpdate(View view) {
            //网络请求下载查分包(省略。直接拷贝查分包到sd卡)
    
            new AsyncTask<Void, Void, File>() {
    
                @Override
                protected File doInBackground(Void... voids) {
                    //bspatch 做合成 得到新版本的apk文件
                    //sz: linux>windows
                    //rz: windows>linux
                    String patch = new File(Environment.getExternalStorageDirectory(),
                            "patch.diff").getAbsolutePath();
                    File newApk = new File(Environment.getExternalStorageDirectory(), "new.apk");
                    if (!newApk.exists()) {
                        try {
                            newApk.createNewFile();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    // 获取当前 apk 的安装路径
                    String oldApk = getApplicationInfo().sourceDir;
                    doPatchNative(oldApk, newApk.getAbsolutePath(), patch);
                    return newApk;
                }
    
                @Override
                protected void onPostExecute(File apkFile) {
                    //安装
                    if (!apkFile.exists()) {
                        return;
                    }
                    Intent intent = new Intent(Intent.ACTION_VIEW);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    if (Build.VERSION.SDK_INT >= 24) { //Android 7.0及以上
                        // 参数2 清单文件中provider节点里面的authorities ; 参数3  共享的文件,即apk包的file类
                        Uri apkUri = FileProvider.getUriForFile(MainActivity.this,
                                getApplicationInfo().packageName + ".provider", apkFile);
                        //对目标应用临时授权该Uri所代表的文件
                        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                        intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
                    } else {
                        intent.setDataAndType(Uri.fromFile(apkFile),
                                "application/vnd.android.package-archive");
                    }
                    startActivity(intent);
                }
            }.execute();
    
        }
    
        private native void doPatchNative(String oldApk, String newApk, String patch);
    

    相关文章

      网友评论

          本文标题:使用 bsdiff 进行增量更新

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