Android使用bsdiff做差分包增量更新

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/wb_001/article/details/102766706

一、 很久没有写博客了,一年了,最近辞职了,一直没有时间来提升自己,现在有时间来学习一下了。最近了解到一个技术叫做增量更新,自己学了一下,所以做个记录同时分享给大家。
二、 增量更新意思就是,两个版本的apk包做差分,提取出新包中增加的东西,作为一个差分包,从而使用户下载的更新包比新包更小,比如,你现在的版本是1.0,大小是20M,而你现在要发一个包大小是30M,如果要下载30M的包会使用更多的流量,耗时更多,这时,使用bsdiff做两者的差分包,此时该差分包的大小在10M左右,用户只需要下载该10M的包进行更新。这时客户端会使用bspatch进行合成一个新的完整包。使用的技术就是c/c++进行合成,在Android中要使用NDK技术。
三、 现在开始:

  1. 首先打开bsdiff的网站,下载bsdiff压缩包bsdiff下载,找到网站中的“here”,将安装包下载下来,解压后你将会看到下面图片的东西:
    在这里插入图片描述
    先解释bsdiff.c是用来做差分包的,bspatch是做合成的。
  2. 合成差分包需要配置命令,第一种是使用Linux环境做合成,第二种是使用windows环境合成,
    第一种:使用Linux服务器
    首先你得有一台Linux服务器
    使用wget命令下载bsdiff包,如果没有wget命令的话,先百度安装一下
    a、下载bsdiff:wget http://www.daemonology.net/bsdiff/bsdiff-4.3.tar.gz
    b、解压bsdiff:tar -xvf bsdiff-4.3.tar.gz
    c、cd到bsdiff下然后ls,跟刚才解压看到的一样:bsdiff.1 bsdiff.c bspatch.1 bspatch.c Makefile这些文件
    d、修改Makefile:vim Makefile,因为该文件中的13行和15行缩进格式有问题,但是make的时候会失败,所以用vim打开编辑,首先按insert键,进入编辑,然后就上下左右键到相应行数将其缩进,然后输入w进行编辑保存,具体vim使用命令自行百度,大概就是这样子。缩进后的格式是这样的:
CFLAGS          +=      -O3 -lbz2                                                               
                                                                                                
PREFIX          ?=      /usr/local                                            
INSTALL_PROGRAM ?=      ${INSTALL} -c -s -m 555                               
INSTALL_MAN     ?=      ${INSTALL} -c -m 444                                  
                                                                              
all:            bsdiff bspatch                                                
bsdiff:         bsdiff.c                                                      
bspatch:        bspatch.c                                                     
                                                                               
install:                                                                       
        ${INSTALL_PROGRAM} bsdiff bspatch ${PREFIX}/bin                        
        .ifndef WITHOUT_MAN                                                                     
        ${INSTALL_MAN} bsdiff.1 bspatch.1 ${PREFIX}/man/man1                     
        .endif 

e、下载bzip2,因为bsdiff是依赖于bzip2的,所以下载方式为使用以下命令:
Centos: yum -y install bzip2-devel.x86_64
Mac: brew install bzip2
d、最后,make一下,完之后 ls一下:bsdiff bsdiff.1 bsdiff.c bspatch bspatch.1 bspatch.c Makefile
多了两个工具:bsdiff、bspatch,没错,就只要这两个,
f、做差分包是使用:./bsdiff oldapk newapk patch,这个命令中,oldapk是原来版本apk,newapk是更新的新版本apk,patch是使用该命令的生成的差分包。ok大功告成。至于怎么把文件导入导出Linux系统,可以使用Xftp工具。
第二种:在windows环境
去网上找bsdiff差分包生成工具,我这里有,后面附件给出来,
a、下载加压,解压后你会看到:
在这里插入图片描述
红色框里面的东西,没错哦,然后用cmd命令进入到该文件下,把,oldapk,newapk复制到该文件下,
使用命令:bsdiff oldapk newapk patch
完了之后会看到patch文件,没错,这就是差分包,ok,完事具备,只欠代码。
3、如果是新工程,只需要在new工程的时候选择native c++工程即可,如果是老项目没有使用到ndk的环境的,你先new一个native c++工程,把里面的cpp目录全部拷贝到工程对应位置,并且在app.gradle配置下面图片中的红框里面的代码即可:
在这里插入图片描述
4、把第一步我们下载bsdiff解压后的bspatch.c文件复制到cpp目录下,因为bspatch依赖bzip2里面的文件,然后下载bzip2下载地址:bzip2下载,解压,将里面的相关文件复制到项目中,建一个文件夹叫bzip,放在下面,相关文件为下图中红色框内所有文件:
在这里插入图片描述
此时同步一下,咦,发现patch一堆错误,不要慌,找到CMakeLists.txt文件,加入下面图中红色框里面的东西:
在这里插入图片描述
ok,你以为好了吗?别急,同步后发现还有错(新版本AndroidStudio),莫慌
因为新版本的studio原来代码的头文件引入格式找不到bzlib.h文件,所有把

#include <bzlib.h>

改成

#include "bzip/bzlib.h"

ok,最后环境配置好了,那么怎么用呢?
5、因为我们是用Java代码调用的,所以要写一个native方法来调用c/c++方法合成新的apk:

  /**
     * 合成差分包
     * @param oldApk    旧版本的apk
     * @param patch     拆分包,patch文件
     * @param outPut    合成后新版本apk的输出路径
     */
    private native void bsPatch(String oldApk,String patch,String outPut);

6、然后会在native-lib.cpp文件中生成对应的c++方法:

extern "C"
JNIEXPORT void JNICALL
Java_com_example_bsdiff_MainActivity_bsPatch(JNIEnv *env, jobject instance, jstring oldApk_,
                                             jstring patch_, jstring outPut_) {

    //将Java字符串转化成c/c++字符串(转化成UTF-8格式的char指针)
    const char *oldApk = env->GetStringUTFChars(oldApk_, 0);
    const char *patch = env->GetStringUTFChars(patch_, 0);
    const char *outPut = env->GetStringUTFChars(outPut_, 0);


    //释放指针
    env->ReleaseStringUTFChars(oldApk_, oldApk);
    env->ReleaseStringUTFChars(patch_, patch);
    env->ReleaseStringUTFChars(outPut_, outPut);
}

那么,此时我们在这里去调用bspatch.c中的main方法,可以自己去看看这个源码,反正我是看不懂,调用该方法的时候还要引用该方法,具体如下图红色框内:
在这里插入图片描述
至于为什么main方法中第一个参数为4,因为你看源码中如果不为4、就直接抛异常了,所以直接填4,然后有的studio版本要强转一下argv参数,那就强转一下,好了,ndk环境和代码到此全部结束,接下来只需要写Java代码了。
7、先在MainActiviy中新建一个布局,显示版本号,和更新按钮:
在这里插入图片描述
点击更新的时候,我们从sd卡本地区加载patch差分包,就不模拟从网络了,当然实际开发中肯定是从网络上下载的
8、具体代码就不讲了,非常简单,可以实际开发中可以根据自己的需求去修改相应逻辑:

/**
     * 使用异步任务加载差分包合成
     */

    @SuppressLint("StaticFieldLeak")
    private void update(){
        new AsyncTask<Void, Void, File>() {
            @Override
            protected File doInBackground(Void... voids) {
                //合成文件
                String oldApk = getApplicationInfo().sourceDir;
                String patch = new File(Environment.getExternalStorageDirectory(),"patch").getAbsolutePath();
                String outPut = createNewApk().getAbsolutePath();
                bsPatch(oldApk,patch,outPut);
                return new File(outPut);
            }

            @Override
            protected void onPostExecute(File file) {
                //安装apk
                FileUtils.installApk(MainActivity.this,file);
            }
        }.execute();
    }

    /**
     * 合成文件
     * @return
     */
    private File createNewApk() {
        File newApk = new File(Environment.getExternalStorageDirectory(),"bsdiff.apk");
        if (!newApk.exists()){
            try {
                newApk.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return newApk;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn:
                update();
                break;
        }
    }

9、需要注意事项:
a、在manifest文件中添加sd卡权限,安装包权限,同时还要兼容运行时权限
b、差分增量更新使用场景,如果合成的差分包大于新包的情况下不需要用增量更新,直接用全量更新
c、测试方法,打包两个版本,新版本(要修改版本名称和版本号),就版本大小最好有明显差异,用上面的方法生成差分包,然后将旧版本和差分包patch放到手机sd卡中,安装就版本apk,然后启动后,点击更新,后会合成新版本,然后安装成功,打开看到2.0版本。完事了。
10,源码以及资源附件:附件

猜你喜欢

转载自blog.csdn.net/wb_001/article/details/102766706