Implementación en caliente y actualización en caliente de paquetes de recursos basados en el modo dividido bsDiff

Escenario del proyecto:

"Recientemente, hay un nuevo requisito en el proyecto. Originalmente, algunos recursos estáticos de la página web basados ​​en webview en la aplicación que desarrollé deben localizarse en el sistema para reducir el consumo de ancho de banda y el tráfico de la red. Basado en este escenario, el mecanismo de actualización del paquete de recursos ha llevado a la actualización de emmm La cosa es problemática, porque el paquete de recursos que tiene tiene una interfaz para devolver archivos json, imágenes, videos, etc. Entonces, ¿hay alguna manera de incluir todos los formatos de archivo y actualizarlos? Esa es la forma dividida bsdiff basada en algoritmos binarios.

principio

Creo que todo el mundo está familiarizado con el tema binario. Todos los formatos de archivo con los que entramos en contacto son en realidad códigos binarios dentro de la computadora. Por ejemplo, el ancho y el alto de la imagen se definen al principio. Si abre la imagen en el Bloc de notas y eliminar algunas de las partes anteriores de la imagen es No es que no se pueda abrir, es cierto, pero si elimina la segunda mitad, su imagen aún se puede abrir, pero solo se mostrará la mitad. tal vez no soy el único que ha hecho esto. Shrimp h(~ ̄▽ ̄)~ Estaba ocioso y aburrido tos tos Lian bastante viejo (*▽▽▀)

Preparar

archivos de código abierto necesarios

Aqui he organizado los codigos y herramientas que hay que usar y los junto: https://www.aliyundrive.com/s/ALCxbGeWY2o inserte la descripción de la imagen aquí
bzip2: Es una biblioteca de la que depende bsdiff, aqui solo guardo los archivos que necesito para ser utilizado, la dirección de descarga de la versión completa es: https://sourceforge.net/projects/bzip2/files/latest/download
bsdiff-win: Es un archivo ejecutable compilado bajo la plataforma Windows, que puede generar archivos de diferencia y merge en la plataforma Windows El archivo
bsdiff-source: es el código fuente de bsdiff, su sitio web oficial es: http://www.daemonology.net/bsdiff/

Cómo usar la herramienta

Simplemente abra la ventana de la línea de comando en el directorio donde se encuentra la herramienta
inserte la descripción de la imagen aquí

Luego ingrese el comando

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

Por ejemplo, creo dos archivos de texto old.txt y new.txt
old.txt
new.txt


inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Entonces puedo utilizar el comando bsdiff para generar archivos diff

inserte la descripción de la imagen aquí
Luego verá el paquete dividido que generamos
inserte la descripción de la imagen aquí

En este momento, usaré el comando bspatch para sintetizar los archivos old.txt y patch en new2.txt. Keke ignore mi error tipográfico
inserte la descripción de la imagen aquí
y luego este es el momento de ver si habrá dos archivos más recientes, uno new.txz/new2.txt.
inserte la descripción de la imagen aquí
Abrimos new2.txt y encontramos que es lo mismo que new.txt. Compruébalo. No es lo mismo
new2.txt

inserte la descripción de la imagen aquí

código:

Realmente creo que todos aquí entienden para qué es esto y cómo usarlo. En comparación con estos, ¡todos definitivamente quieren ver cómo usar el código para realizar estas operaciones!

integrado

1. Integre bspatch en el proyecto
Dado que el lado de Android solo necesita fusionar archivos, solo necesitamos integrar bspatch.Copiamos el archivo bspatch.c en la carpeta bsdiff-source/bsdiff-4.3 al directorio cpp, y luego lo colocamos en la carpeta bzip2 Copie el archivo en el directorio bzip (nuevo directorio) bajo cpp
inserte la descripción de la imagen aquí
Además, necesitamos modificar bspatch.c, agregamos la referencia de bzip2 en la parte superior del archivo

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

inserte la descripción de la imagen aquí

De lo contrario, puede informar el siguiente error cuando ejecuta el proyecto
inserte la descripción de la imagen aquí
, y luego debemos crear un nuevo bspatch.h y colocarlo en la carpeta bzip. El propósito de esto es usar el método principal en native-lib.cpp archivo (nota: principal aquí El método no es una función de entrada, sino una función ordinaria que ejecuta comandos)
inserte la descripción de la imagen aquí
El archivo bspatch.h es el siguiente

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

Luego introduzca el archivo de encabezado bspatch.h en bspatch.c
inserte la descripción de la imagen aquí
A continuación, debemos configurar el archivo CMakeLists.txt para vincular el archivo c y el archivo de encabezado .h bajo bzip al proyecto

2. Cree un método JNI
Cree una clase de herramienta PatchUtil y cree un método JNI para fusionar archivos

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++ implementa el método 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. Agregar llamada sintética en Actividad

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();
        });
    }
}

Bueno, aquí básicamente puedes seguir los pasos anteriores y puedes lograrlo.
Pero pero pero::: ¡Es más importante expresar lo que dije tres veces! ! ! Algunos estudiantes deberían haber descubierto el problema y no hay valor de retorno.Si cometo un error de paquete tm, entonces no es mi paquete de recursos, entonces GG. Por desgracia, aquí todavía tengo que ser muy responsable para decirles que es cierto que GG no tiene valor de retorno. Si hay un error en el abrazo, directamente hará que su aplicación se bloquee. Si la capa inferior informa un error, solo puedes pasar emmm. Parece que hay un valor de retorno y también causará un bloqueo. Oh, jajaja, olvídalo. Es mejor tener un valor de retorno que no tener ningún valor de retorno. Mira el código fuente y
inserte la descripción de la imagen aquí
verás sepa que el error devolverá 1. Si no hay ningún error, ¿puede personalizar uno? Esto es muy simple. Todo el
inserte la descripción de la imagen aquí
retorno vale la pena. El método es en realidad el anterior que no devuelve un método que valga la pena capy y luego agregue
inserte la descripción de la imagen aquí
estos tres ¡líneas de código y tres líneas de código para que el jefe me dé un salario de 500,000! ! ¡Te enseñaré hoy! ! Finalmente, puede hacer uno de los anteriores en forma de modelo y luego marcarlo como un aar para que el proyecto principal llame o cree directamente un modelo a través del proyecto principal para llamar al código. ! ! ! Bueno, la pequeña clase de hoy ha terminado. Actualice la tecnología práctica en el proyecto de vez en cuando. Realice la comprensión y el análisis más profundos en función del proyecto, para que cada programador pueda mantener su cabello en buen estado. ¡El hombre soy yo, soy simplemente estúpido! ! Nos vemos la próxima vez.

Supongo que te gusta

Origin blog.csdn.net/weixin_47143458/article/details/124171483
Recomendado
Clasificación