bsDiff 分割モードに基づくリソース パッケージのホット デプロイメントとホット アップデート

プロジェクトのシナリオ:

「最近、プロジェクトに新しい要件があります。もともと、私が開発したアプリの Web ビューに基づく一部の Web ページの静的リソースは、ネットワーク帯域幅とトラフィックの消費を削減するためにシステムにローカライズする必要がありました。このシナリオに基づいて、リソース パッケージの更新メカニズムが原因で emmm update が発生しましたが、保持しているリソース パックには json ファイル、画像、ビデオなどを返すインターフェイスがあるため、これが厄介です。では、すべてのファイル形式を含めて更新する方法はあるのでしょうか? それは、バイナリ アルゴリズムに基づく bsdiff 分割形式です。

原理

バイナリについては誰もがよく知っていると思います。私たちが触れるすべてのファイル形式は、実際にはコンピュータ内部のバイナリ コードです。たとえば、画像の幅と高さは最初に定義されています。画像をメモ帳で開くと、画像の前の部分の一部を削除すると、開けなくなるわけではありませんが、後半を削除しても画像は開くことはできますが、半分しか表示されなくなります。こんなことをしたのは私だけではないかもしれません エビh(~ ̄▽ ̄)~ 暇で暇でした 咳咳リアン 結構老けましたね(*▽▽▀)

準備

オープンソースファイルが必要

ここでは、使用する必要があるコードとツールを整理してまとめています: https://www.aliyundrive.com/s/ALCxbGeWY2o ここに画像の説明を挿入
bzip2: bsdiff が依存するライブラリです。ここでは、必要なファイルのみを保存します。使用する場合、完全版のダウンロード アドレスは次のとおりです: https://sourceforge.net/projects/bzip2/files/latest/download
bsdiff-win: Windows プラットフォームでコンパイルされた実行可能ファイルであり、差分ファイルを生成できます。ファイル
bsdiff-source: は bsdiff のソース コードであり、その公式 Web サイトは http://www.daemonology.net/bsdiff/ です。

ツールの使用方法

ツールが配置されているディレクトリでコマンド ライン ウィンドウを開くだけです。
ここに画像の説明を挿入

次にコマンドを入力します

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

たとえば、old.txt と new.txt という 2 つのテキスト ファイルを作成します
old.txt
new.txt


ここに画像の説明を挿入
ここに画像の説明を挿入

次に、bsdiff コマンドを利用して diff ファイルを生成します。

ここに画像の説明を挿入
すると、生成した分割パッケージが表示されます。
ここに画像の説明を挿入

このとき、bspatchコマンドを使用してold.txtとpatchファイルをnew2.txtに合成します。私のタイプミスは無視してください
ここに画像の説明を挿入
。それでは、new.txz/new2.txt の 2 つの最新ファイルがあるかどうかを確認してください
ここに画像の説明を挿入
。new2.txt を開くと、それが new.txt と同じであることがわかります。確認してください。同じ
new2.txtではありません

ここに画像の説明を挿入

コード:

ここにいる皆さんは、これが何のためにあるのか、どのように使用するのかを理解していると本当に信じています。これらと比較して、皆さんは間違いなくコードを使用してこれらの操作を実行する方法を知りたいと思っています。

統合された

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 ヘッダー ファイルを導入します。
ここに画像の説明を挿入
次に、c ファイルと bzip の下の .h ヘッダー ファイルをプロジェクトにリンクするように CMakeLists.txt ファイルを構成する必要があります。

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. アクティビティに合成呼び出しを追加する

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

さて、ここでは基本的に上記の手順に従って完了できますが、
しかししかし::: 言ったことを 3 回表現することの方が重要です。一部の学生は問題を発見したはずですが、戻り値がありません。tm パッケージでエラーが発生した場合、それは私のリソース パッケージではなく、GG になります。残念ながら、ここでも、GG には戻り値がないということは本当であると、非常に責任を持ってお伝えしなければなりません。抱擁にエラーがある場合、アプリが直接クラッシュする原因になります。最下層がエラーを報告した場合、 emmm だけを渡すことができます。戻り値があるようですが、それはクラッシュの原因にもなります。ああ、ははは忘れてください。戻り値がないよりも戻り値がある方が良いです。ソースコードを見ると
ここに画像の説明を挿入
、失敗すると 1 が返されることを知っています。失敗がない場合は、カスタマイズするだけで済みますか? これは非常に簡単で、
ここに画像の説明を挿入
戻り値全体が価値があります。実際には、メソッドは価値のあるメソッド capy を返さない上記のメソッドであり、これらを追加し
ここに画像の説明を挿入
ます3 行のコードと 3 行のコードで、上司から 500,000 の給料をもらえます。今日は私が教えます!最後に、上記のいずれかをモデルの形式で作成し、それをメイン プロジェクトが呼び出すための aar としてマークするか、メイン プロジェクトを通じてモデルを直接作成してコードを呼び出すことができます。さて、今日の小さな授業は終わりました。プロジェクト内の実用的​​な技術を随時更新し、プロジェクトに基づいて深く理解して分析し、すべてのプログラマーが髪を美しく保つことができるようにします。次回お会いしましょう。

おすすめ

転載: blog.csdn.net/weixin_47143458/article/details/124171483