Hot deployment and hot update of resource packages based on bsDiff split mode

Project scenario:

`Recently, there is a new requirement in the project. Originally, some webpage static resources based on webview in the app I developed need to be localized into the system so as to reduce the consumption of network bandwidth and traffic. Based on this scenario, the update mechanism of the resource package has led to emmm update. The thing is troublesome, because the resource packs you hold have interfaces to return json files, pictures, videos, and so on. So is there a way to include all file formats and update them? That is the bsdiff split form based on binary algorithms.

principle

I believe everyone is familiar with the binary thing. All the file formats we come into contact with are actually binary codes inside the computer. For example, the width and height of the picture are defined at the beginning. If you open the picture in Notepad and delete some of the previous parts of the picture is It’s not that it can’t be opened, it’s true, but if you delete the second half, then your picture can still be opened, but only half of it will be displayed. Maybe maybe I’m not the only one who has done this. Shrimp h(~ ̄▽ ̄)~ I was idle and bored cough cough Lian quite old (*▽▽▀)

Prepare

open source files needed

Here I have organized the codes and tools that need to be used and put them together: https://www.aliyundrive.com/s/ALCxbGeWY2o insert image description here
bzip2: It is a library that bsdiff depends on. Here I only store the files that need to be used , the download address of the full version is: https://sourceforge.net/projects/bzip2/files/latest/download
bsdiff-win: It is a compiled executable file under the Windows platform, which can generate difference files and merge on the Windows platform The file
bsdiff-source: is the source code of bsdiff, its official website is: http://www.daemonology.net/bsdiff/

How to use the tool

Just open the command line window in the directory where the tool is located
insert image description here

Then enter the command

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

For example, I create two text files old.txt and new.txt
old.txt
new.txt


insert image description here
insert image description here

Then I can utilize the bsdiff command to generate diff files

insert image description here
Then you will see the split package we generated
insert image description here

At this time, I will use the bspatch command to synthesize the old.txt and patch files into new2.txt. Keke ignore my typo
insert image description here
and then this is the time to see if there will be two latest files, one new.txz/new2.txt.
insert image description here
We open new2.txt and find that it is the same as new.txt. Check it out. Not the same
new2.txt

insert image description here

code:

I really believe that everyone here understands what this thing is for and how to use it. Compared with these, everyone definitely wants to see how to use code to perform these operations!

integrated

1. Integrate bspatch into the project
Since the Android side only needs to merge files, we only need to integrate bspatch. We copy the bspatch.c file in the bsdiff-source/bsdiff-4.3 folder to the cpp directory, and then put it in the bzip2 folder Copy the file to the bzip (new directory) directory under cpp
insert image description here
In addition, we need to modify bspatch.c, we add the reference of bzip2 at the top of the file

/** 导入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"

insert image description here

Otherwise, you may report the following error when you run the project
insert image description here
, and then we need to create a new bspatch.h and put it in the bzip folder. The purpose of this is to use the main method in the native-lib.cpp file (note: main here The method is not an entry function, but an ordinary function that executes commands)
insert image description here
The bspatch.h file is as follows

#ifndef INCREMENTUPDATEDEMO_BSPATCH_H
#define INCREMENTUPDATEDEMO_BSPATCH_H
int main(int argc,char * argv[]);
#endif //INCREMENTUPDATEDEMO_BSPATCH_H

Then introduce the bspatch.h header file in bspatch.c
insert image description here
Next we need to configure the CMakeLists.txt file to link the c file and the .h header file under bzip to the project

2. Create a JNI method
Create a PatchUtil tool class and create a JNI method for merging files

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++ implements JNI method

#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. Add synthetic call in 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();
        });
    }
}

Well, here you can basically follow the above steps and you can get it done.
But but but::: It is more important to express what I said three times! ! ! Some students should have discovered the problem and there is no return value. If I make a tm package error, then it is not my resource package, then GG. Alas, here I still have to be very responsible to tell you that it is true that GG has no return value. If there is an error in the embrace, it will directly cause your app to crash. If the bottom layer reports an error, you can only pass emmm. It seems that there is a return value and it will also cause a crash. Oh hahaha forget it. It is better to have a return value than to have no return value.
insert image description here
Look at the source code and you will know that failure will return 1. If there is no failure, can you just customize one? This is very simple, and the whole
insert image description here
return is worthwhile. The method is actually the one above that does not return a worthwhile method capy and then add
insert image description here
these three lines of code and three lines of code to let the boss give me a salary of 500,000! ! I will teach you today! ! Finally, you can make one of the above in the form of a model and then mark it as an aar for the main project to call or directly create a model through the main project to call the code! ! ! ! Well, today's little class is over. Update the practical technology in the project from time to time. Do the deepest understanding and analysis based on the project, so that every programmer can keep his hair good. The man is me, I am just stupid! ! See you next time.

Guess you like

Origin blog.csdn.net/weixin_47143458/article/details/124171483