增量更新

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/likuan0214/article/details/78679256

实现思路

实现增量更新的步骤:
1. old.apk和new.apk生成差异包patch
2. old.apk和patch合成更新包merge.apk
3. 安装merge.apk

生成差异包patch

1.进入bsdiff官网,下载bsdiff-4.3.tar.gz
2.解压下载好的bsdiff-4.3.tar.gz,然后编辑Makefile如下:

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

主要是在.ifndef WITHOUT_MAN和.endif前面加一个tab
3.打开bspatch.c添加:

#include <sys/types.h>

4.在bsdiff-4.3目录下执行下面命令

make

5.生成bsdiff和bspatch
这里写图片描述
6.进行简单测试
6.1 old.apk new.apk 生成patch

./bsdiff old.apk new.apk patch

6.2 old.apk + patch生成merge.apk

./bspatch old.apk merge.apk patch

6.3 判断new.apk 和 merge.apk是否一致

MD5 new.apk

28c8131df39f1f0a6402fc26298c9a72

MD5 merge.apk

28c8131df39f1f0a6402fc26298c9a72
发现md5一致,说明合成成功。

old.apk和patch合成更新包

配置ndk

1.新建ndk项目
2.拷贝bspatch.c到cpp目录下
3.发现bspatch.c中需要引入bzlib.h,从bzip2下载bzip2-1.0.6.tar.gz
4.解压bzip2-1.0.6.tar.gz,然后保留里面的.c,.h文件,其余删除即可
这里写图片描述
5.将bzip2拷贝到cpp目录下
6.修改CMakeLists.txt如下

cmake_minimum_required(VERSION 3.4.1)
file(GLOB cpp_path src/main/cpp/bzip2/*.c src/main/cpp/*.c src/main/cpp/*.cpp)
add_library(
             native-lib
             SHARED
             ${cpp_path}
             )

find_library(
              log-lib
              log )

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

7.在cpp目录下新建bspatch.h文件,添加

int bspatchmain(int argc,char * argv[]);

然后bspatch.c和native-lib.cpp分别引入bspatch.h头文件
修改bspatch.c中的main方法为bspatchmain方法
8.将bzip2下面的所有文件中的main方法添加一个前缀,例如:
bzip2recover.c中的main方法改为bzip2recovermain

至此,bspatch的环境已经搭建完成

编写合并安装代码

1.新建BsPatch.java文件

package com.study.bspatchtest;

import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.net.Uri;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;

import java.io.File;

/**
 * Created by ygdx_lk on 17/11/30.
 */

public class BsPatch {
    private static final String TAG = "BsPatch";
    public static native int bsPatch(String oldPath, String newPath, String patchPath);

    private static String getOldPath(Context context) {
        context = context.getApplicationContext();
        ApplicationInfo applicationInfo = context.getApplicationInfo();
        String apkPath = applicationInfo.sourceDir;
        return apkPath;
    }

    public static void testPath(Context context){
        String newPath = Environment.getExternalStorageDirectory() + "/new.apk";
        String patchPath = Environment.getExternalStorageDirectory() + "/patch";
        mergePatch(context, newPath, patchPath);
    }

    public static void mergePatch(Context context, String newPath, String patchPath){
        String oldPath = getOldPath(context);
        if(!TextUtils.isEmpty(oldPath)){
            int result = bsPatch(oldPath, newPath, patchPath);
            if(result == 0){
                Log.i(TAG, "mergePatch: ok");
                installApk(context, newPath);
            }else {
                Log.i(TAG, "mergePatch: error");
            }
        }
    }

    private static void installApk(Context context, String newPath) {
        Intent i = new Intent(Intent.ACTION_VIEW);
        i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        i.setDataAndType(Uri.fromFile(new File(newPath)),
                "application/vnd.android.package-archive");
        context.startActivity(i);
    }
}

2.native-lib.cpp

#include <jni.h>
#include <string>
extern "C"
#include "bspatch.h"

extern "C"
JNIEXPORT jstring
JNICALL
Java_com_study_bspatchtest_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++ update";
    return env->NewStringUTF(hello.c_str());
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_study_bspatchtest_BsPatch_bsPatch(JNIEnv *env, jclass type, jstring oldPath_,
                                           jstring newPath_, jstring patchPath_) {
    char *oldPath = (char *) env->GetStringUTFChars(oldPath_, 0);
    char *newPath = (char *) env->GetStringUTFChars(newPath_, 0);
    char *patchPath = (char *) env->GetStringUTFChars(patchPath_, 0);

    int argc = 4;
    char * argv[argc];
    argv[0] = "bsPatch";
    argv[1] = oldPath;
    argv[2] = newPath;
    argv[3] = patchPath;

    int ret = bspatchmain(argc, argv);

    env->ReleaseStringUTFChars(oldPath_, oldPath);
    env->ReleaseStringUTFChars(newPath_, newPath);
    env->ReleaseStringUTFChars(patchPath_, patchPath);
    return ret;
}

3.在MainActivity方法中添加点击事件

BsPatch.testPath(v.getContext());

4.生成old.apk和new.apk及patch
5.安装old.apk,拷贝path到sdk目录
6.点击运行testPath方法
7.安装成功。(失败的话,一定要记得文件的读写权限)

源码下载

猜你喜欢

转载自blog.csdn.net/likuan0214/article/details/78679256