Notice: 函数 WP_Scripts::localize 的调用方法不正确$l10n 参数必须是一个数组。若要将任意数据传递给脚本,请改用 wp_add_inline_script() 函数。 请查阅调试 WordPress来获取更多信息。 (这个消息是在 5.7.0 版本添加的。) in /data/www/appblog/wp-includes/functions.php on line 6131

Android增量更新 – 客户端使用bsdiff差分包与原包合并


Warning: Undefined array key "pay-ip" in /data/www/appblog/wp-content/plugins/wppay/include/wppay.functions.php on line 300

Warning: Undefined array key "pay-ip" in /data/www/appblog/wp-content/plugins/wppay/include/wppay.functions.php on line 300

bsdiff简介

Android增量更新需要用到二进制差分工具:bsdiff

bsdiff and bspatch are tools for building and applying patches to binary files.

官方网站:http://www.daemonology.net/bsdiff/
bsdiff for windows:http://www.pokorra.de/coding/bsdiff.html

Android版本区别设定

(1)旧版本

app.gradle

versionCode 1
versionName "1.0"

activity_main.xml

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="20dp"
    android:text="1.0版本"
    android:textSize="16sp"
    android:textColor="#3BC1FF"
    />

(2)新版本

添加资源文件:assets/cctv.mp4

app.gradle

versionCode 2
versionName "2.0"

activity_main.xml

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="20dp"
    android:text="2.0版本"
    android:textSize="16sp"
    android:textColor="#3BC1FF"
    />

NDK实现pacth

Java层声明native方法

public class BsPatch {

    /**
     * 合并
     * @param oldFilePath
     * @param newFilePath
     * @param patchFilePath
     */
    public static native void patch(String oldFilePath, String newFilePath, String patchFilePath);

    static {
        System.loadLibrary("BsPatch");
    }
}

C层合并算法实现:diffupdate.c

您需要先支付 1元 才能查看此处内容!

立即支付
已支付?点击这里查询

Java层调用bspatch实现bsdiff差分包与原包合并

class AppUpdateTask extends AsyncTask<Void, Void, Boolean> {
    @Override
    protected Boolean doInBackground(Void... params) {
        //1. 下载差分包
        Log.i(TAG, "开始下载");
        //File patchFile = DownloadUtil.download(PATCH_URL);
        //String patchFilePath = patchFile.getAbsolutePath();
        Log.i(TAG, "下载完成");
        //2. 获取旧版本已经安装的apk文件(/data/app/)
        String oldApk = ApkUtil.getSourceApkPath(MainActivity.this, getPackageName());
        Log.i(TAG, "Old Apk: " + oldApk);
        //3. 合并:oldFile+patchFile->newFile
        BsPatch.patch(oldApk, NEW_APK_PATH, PATCH_FILE_PATH);
        Log.i(TAG, "合并完成");
        try {
            Log.i(TAG, "New Apk MD5: " + MD5Util.getFileMD5String(NEW_APK_PATH));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        super.onPostExecute(result);
        if (!result) {
            Toast.makeText(MainActivity.this, "差分包合并失败", Toast.LENGTH_SHORT).show();
        }
        //1. 获取两个版本的签名进行对比
        //获取已经安装应用的签名
        String oldSign = SignUtil.getInstalledApkSignature(MainActivity.this, getPackageName());
        //获取未安装Apk文件的签名
        String newSign = SignUtil.getUnInstalledApkSignature(NEW_APK_PATH);
        if (TextUtils.equals(newSign, oldSign)) {
            //2. 安装
            ApkUtil.installApk(MainActivity.this, NEW_APK_PATH);
        } else {
            Toast.makeText(MainActivity.this, "签名不匹配", Toast.LENGTH_SHORT).show();
        }
        Toast.makeText(MainActivity.this, "差分包合并成功", Toast.LENGTH_SHORT).show();
    }
}

app.gradle 配置

defaultConfig {
    ...
    externalNativeBuild {
        cmake {
            cppFlags "-frtti -fexceptions"
            abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a'
        }
    }
}

externalNativeBuild {
    cmake {
        path "CMakeLists.txt"
    }
}

安装测试

> adb push diff.patch /sdcard/  //将差分包导入到SD卡中,模拟在线更新
[100%] /sdcard/diff.patch

> adb install DiffUpdate_v1.apk  //安装旧版Apk以待测试增量更新
[100%] /data/local/tmp/DiffUpdate_v1.apk
        pkg: /data/local/tmp/DiffUpdate_v1.apk
Success

>

运行日志输出,可以看到合并生成的 New Apk MD5 与服务器端合并生成的完全一致

cc.androidios.diffupdate I/yezhou: Old Apk: /data/app/cc.androidios.diffupdate-1/base.apk
cc.androidios.diffupdate I/yezhou: 合并完成
cc.androidios.diffupdate I/yezhou: New Apk MD5: 735a02764167048e738a7f6ea99f2b86

核心技术点

bspatch功能调用

bspatch的使用方法为

bspatch oldfile newfile patchfile

bspatch.c的main函数为其入口函数,这里将函数名改为bspatch_main,变为普通函数,即可实现被其它函数调用。

int bspatch_main(int argc, char * argv[])

CMakeLists.txt 配置

您需要先支付 1元 才能查看此处内容!

立即支付
已支付?点击这里查询

上一篇 使用Dockerfile为SpringBoot应用构建Docker镜像
下一篇 Android增量更新 - Apk差分合并算法服务端设计