利用bsdiff完成app的增量更新

当手机app应用需要更新时,如果需要重新下载一个完成的应用apk文件,十分消耗流量。这时候就可以使用增量更新技术。

增量更新可以使用bsdiff工具来完成,简单的说就是通过工具将旧的apk和新的apk进行比较,然后生成一个差异包,这个差异包的体积大小会远远地小于整个完整apk的大小。然后用户通过网络请求只需要下载这个差异包就可以完成应用的升级。

首先通过网络下载bsdiff工具

下载链接

下载完成后进入文件夹,直接make编译是不行的,使用vim或编辑器打开MakeFile文件,发现格式有问题,定位到.ifndef WITHOUT_MAN和.endif前面,然后按tab键进行缩进。

然后保存.

发现直接make又报错。

第二个问题解决方法:打开bspatc,添加#include <sys/types.h>后解决

重新make后获得bsdiff和bspatch可执行文件。

使用Android Studio新建一个ndk项目,将bspatch.c文件和依赖的文件导入cpp文件夹下:

然后编辑CMakeLists.txt文件:

cmake_minimum_required(VERSION 3.4.1)

include_directories(bzip)   #引入头文件
file(GLOB bzip_source_file bzip/*.c)   #引入bzip中所有的c文件
add_library(
        native-lib
        SHARED
        native-lib.cpp
        bspatch.c
        ${bzip_source_file})

find_library(
        log-lib
        log)

target_link_libraries(
        native-lib
        ${log-lib})

思路:用户手动点击更新按钮,然后从网络上下载差分包(patch又叫补丁),下载完成后发送Intent安装apk,覆盖本地的旧apk即可完成。

编辑native-lib.cpp:

#include <jni.h>
#include <string>

extern "C" {
    extern int main(int argc, const char * argv[]);   //导入bspatch文件的main函数
}

extern "C"
JNIEXPORT void JNICALL
Java_com_example_bsdiffdemo_MainActivity_getNewApk(JNIEnv *env, jobject thiz, jstring old_path,
                                                   jstring new_path, jstring patch) {
    const char *charOldPath = env->GetStringUTFChars(old_path, 0);
    const char *charNewPath = env->GetStringUTFChars(new_path, 0);
    const char *charPatch = env->GetStringUTFChars(patch, 0);

    const char *argv[] = {"",charOldPath, charNewPath, charPatch};
    main(4, argv); //通过函数将旧的APK和差分包处理得到新的apk,并通过第2个参数输出出来

    env->ReleaseStringUTFChars(old_path, charOldPath);
    env->ReleaseStringUTFChars(new_path, charNewPath);
    env->ReleaseStringUTFChars(patch, charPatch);
}

将旧的apk路径,下载完成的差分包路径和新apk的路径作为参数传给bspatch.c的main函数,main函数就会将旧apk和差分包通过处理得到新的apk,然后发送安装APK的Intent。

服务端(开发者):

将旧的apk和最新版本的apk,通过bsdiff工具得到差分包

命令./bsdiff old.apk new.apk patch

用户端

这个查分包被上传到网上,用户通过点击更新按钮:

public void update(View view) {
        //模拟网络下载差分包
        new AsyncTask<Void, Void, File>() {
            @Override
            protected File doInBackground(Void... voids) {
                String oldApk = getApplicationInfo().sourceDir;   //获取当前app(旧版)的apk的路径

                //这里是模拟下载patch的网络请求过程
                String patch = new File(Environment.getExternalStorageDirectory(), "patch").getAbsolutePath();
                String newApk = createApk();
                getNewApk(oldApk, newApk, patch);
                return new File(newApk);
            }

            @Override
            protected void onPostExecute(File file) {
                if(file != null && file.exists()){
                    //发送安装apk的intent
                    Intent intent = new Intent(Intent.ACTION_VIEW);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    Uri fileUri;
                    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
                        fileUri = FileProvider.getUriForFile(MainActivity.this,
                                getApplicationInfo().packageName + ".fileprovider", file);
                    }else{
                        fileUri = Uri.fromFile(file);
                    }
                    intent.setDataAndType(fileUri, TYPE);
                    startActivity(intent);
                }else{
                    Log.d(TAG, "onPostExecute: " + "文件不存在!");
                }
            }
        }.execute();
    }

下载得到差分包patch后,调用bspatch.c的main函数获得新版的apk后,发送安装APk的Intent,完成版本的更新。

如图:

在这里插入图片描述

demo地址:https://github.com/lyx19970504/bsdiffDemo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哒哒呵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值