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
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
Luego ingrese el comando
#生成差异文件命令
bsdiff [旧文件] [新文件] [差异文件]
#合并文件命令
bspatch [旧文件] [新文件] [差异文件]
#生成差异文件命令
bsdiff [旧文件] [新文件] [差异文件]
#合并文件命令
bspatch [旧文件] [新文件] [差异文件]
Por ejemplo, creo dos archivos de texto old.txt y new.txt
old.txt
new.txt
Entonces puedo utilizar el comando bsdiff para generar archivos diff
Luego verá el paquete dividido que generamos
En este momento, usaré el comando bspatch para sintetizar los archivos old.txt y patch en new2.txt. Keke ignore mi error tipográfico
y luego este es el momento de ver si habrá dos archivos más recientes, uno new.txz/new2.txt.
Abrimos new2.txt y encontramos que es lo mismo que new.txt. Compruébalo. No es lo mismo
new2.txt
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
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"
De lo contrario, puede informar el siguiente error cuando ejecuta el proyecto
, 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)
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
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
verás sepa que el error devolverá 1. Si no hay ningún error, ¿puede personalizar uno? Esto es muy simple. Todo el
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
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.