Tencent interview: incremental upgrade Why upgrade to reduce costs, incremental upgrade principle

In previous years, a whole lot of difference compared to the mobile network environment now, coupled with traffic charges is relatively high, so whenever we release a new version of some users to upgrade is not very positive, which resulted in a new version of the upgrade rate It is not high. And google To solve this problem, Smart App Update, namely incremental updates (also known as differential upgrade).
Although now the network environment has been greatly improved, but an indisputable fact that the application bigger and bigger, therefore, incremental update is still present in a solution APP update package is too large for an effective program. Today, we'll talk about incremental updates.

1. What is an incremental update?

The key lies in how incremental update understanding of the term increments. Usually we think about the development process, often to modify some code today, yesterday, on the basis of, app updates is similar: are often modified on the old version of the app. It would appear that the incremental update is only updating changed places on the basis of the original app, remaining intact.

Compared with the original apk each update should download the complete package approach, the benefits of doing so are obvious: where each change is always relatively small, so a lot of the update package size will be smaller. For example, "Master said" volume of the installation package is about 6m, if not incremental update, users need to download each update installation package around about 6m, and the use of such incremental updates only need to download the program about 2m per the update package can be, compared to the original approach significantly reduces the time to wait for users to download.

2. What are the advantages in incremental upgrade?

Differential advantage

  • Size is very small
  • Security - must be a particular node to be upgraded
  • The whole package is easier to control with respect to

3. Why will reduce upgrade costs

For example there is the old version of the APK 5M, there is a new version of 8M, the update may be only part of 3M (It should be noted here is that the size of the resulting difference subcontractor is not a simple subtraction, because in fact need to include context-sensitive stuff) the benefits of using the difference is obvious upgrade,
then you do not need to download the complete file 8M only need to download updates section on the can, and update some may be 3,4M, can largely reduce the loss of traffic.

4. incremental update of principle

Incremental update principle is very simple, simply put, is a so-called patch update (patch to find new and old versions are not the same place (this process is also called differential), then not the same place extracted by an algorithm ), also known as sub difference. The client is detected when the update, just download the difference to the local sub-contractors, sub-contractors and the difference to the local installation package merge to form a new version of the installation package, and then perform the installation file to check through. Local installation packages currently installed by extracting apk been applied.

Demo: a difference generating packetized combined
as shown below:

Tencent interview: incremental upgrade Why upgrade to reduce costs, incremental upgrade principle

The question now is how to generate a difference subcontracting and subcontracting merge difference. Here, we use open source libraries bsdiffto solve these two problems. First we show you the difference between the formation and consolidation of sub-contractors.

Download bsdiff_win_exe.zip, extract to a local. As shown below:

Tencent interview: incremental upgrade Why upgrade to reduce costs, incremental upgrade principle

Then, we played a first installation package is assumed to old.apk. After making changes to the source code, and then play a new installation package new.apk. Here old.apk equivalent to the old version of the application, which is equivalent to new.apk new version of the application. Next, we use bsdiff to generate a difference subcontracting patch.patch.

The difference generating sub

The above and new.apk old.apk bsdiff decompression into the directory, and then execute the command bsdiff old.apk new.apk patch.patch in the console, wait a minute can generate a difference sub patch.patch, as followsTencent interview: incremental upgrade Why upgrade to reduce costs, incremental upgrade principle

6. Merge poor subcontractor

The combined old.apk and patch.patch, generates a new installation package new.apk. As long as the combined new.apk out here and play above ourselves out of new.apk, then we can think of it as a new version we need to install the package.

Let's look at how to merge. The old.apk and patch.patch into bsdiff folder, before merger

Tencent interview: incremental upgrade Why upgrade to reduce costs, incremental upgrade principle
Then execute the command bspatch old.apk new.apk patch.patch, wait a minute after the merger will be able to see out new.apk as follows:

Tencent interview: incremental upgrade Why upgrade to reduce costs, incremental upgrade principle

不出意外,合并而来的new.apk应该和我们自己打出来的new.apk是一模一样的,这可以通过验证两者的md5来认定。
我们已经弄明白增量更行是怎么一回事。下面,我们就以“师父说”为对象进实践一把。

7.实践:让师父说支持增量更新

客户端支持增量更新总体和上面的演示差不多,唯一的区别在于客户端要自行编译bspatch.c来实现合并差分包,也就是所谓的ndk开发,这里我们首先要下载bsdiff的源码以及bszip的源码,以便后面使用。在as中如何进行ndk开发不是本文的重点。

7.1.编写BsPatchUtil类 BsPatchUtil中只有一个natvie方法patch(String oldApkPath,String newApkPath,String patchPath)用于实现增量包的合并:

public class BsPatchUtil {
    static {
        System.loadLibrary("apkpatch");
}

public static  native int patch(String oldApkPath, String newApkPath, String patchPath);

7.2.编写C代码

在实现BsPatchUtil之前,我们需要将bspatch.c以及bzip的相关代码拷贝到jni目录下(bzip只保留.h头文件和.c文件)。并将bspatch.c中的main()方法名修改为executePatch(),并且修改其中bzip的引入头为#include "bzip2/bzlib.h".目录结构如下:

Tencent interview: incremental upgrade Why upgrade to reduce costs, incremental upgrade principle

注意:上图当中的em.c是一个空文件,用来避免在window下编译产生的未知错误。

接下来我们就可以在bspatch_util.c中实现相关的代码了:


#include "com_closedevice_fastapp_util_BsPatchUtil.h"

JNIEXPORT jint JNICALL Java_com_closedevice_fastapp_util_BsPatchUtil_patch
        (JNIEnv *env, jclass clazz, jstring old, jstring new, jstring patch){
        int args=4;
        char *argv[args];
    argv[0] = "bspatch";
    argv[1] = (char*)((*env)->GetStringUTFChars(env, old, 0));
    argv[2] = (char*)((*env)->GetStringUTFChars(env, new, 0));
    argv[3] = (char*)((*env)->GetStringUTFChars(env, patch, 0));

    //此处executePathch()就是上面我们修改出的
    int result = executePatch(args, argv);

    (*env)->ReleaseStringUTFChars(env, old, argv[1]);
    (*env)->ReleaseStringUTFChars(env, new, argv[2]);
    (*env)->ReleaseStringUTFChars(env, patch, argv[3]);

    return result;
}

至此,大部分工作已经完成了。配置app moudle中的build.gradle中添加ndk配置

defaultConfig {
        applicationId "com.closedevice.fastapp"
        minSdkVersion 14
        targetSdkVersion 24
        versionCode 1
        versionName "1.0.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        //ndk配置
        ndk{
            moduleName "apkpatch"
            abiFilters "armeabi", "armeabi-v7a","x86"
        }
    }

接下来,我们编译试试(ndk环境的配置这里不做说明,自行配置即可),不出意外会遇到以下错误:

Tencent interview: incremental upgrade Why upgrade to reduce costs, incremental upgrade principle

该问题的解决方法也非常简单,注释掉对应文件的main()方法即可。重新编译,不出意外没什么问题了。接下来,我们就需要在合适的地方合并差分包了。

7.3.合并差分包

上面的过程做完之后,就可以通过BsPatchUtil.patch()来合并当前安装包和差分包了。

Here, we assume that the difference between subcontractors have been downloaded from the server to the local.

First look at how to get the current installation package. We installed the application is usually, under data / app, you can get its path through the code below:

public static String getApkInstalledSrc(){
        return BaseApplication.context().getApplicationInfo().sourceDir;
    }

The following can be merged by BsPatchUtil.patch (String oldApkPath, String newApkPath, String pathPath). Two things to note here:

  1. The combined local recommendations on external storage (SDcard) which
  2. The merger process is time-consuming, it need be placed in the sub-thread.

7.4. Installation

Any update package after the download is completed first thing to do is to perform MD5 checksum to confirm that the update package is downloaded from the formal way. Similarly, for the update package after the merger, the first thing to do is to perform MD5 checksum, after verification by, then install it:

 public static void installAPK(Context context, File file) {
        Intent intent = new Intent();
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setAction(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.fromFile(file),
                "application/vnd.android.package-archive");
        context.startActivity(intent);
    }

Up to now, the incremental update has been completed. Can now incremental package and install the package after the merger deleted.

General code as follows:

private void smartupdate() {
        Observable.create(new Observable.OnSubscribe<File>() {
            @Override
            public void call(Subscriber<? super File> subscriber) {
                //定义生成的新包
                File newApk = new File(Environment.getExternalStorageDirectory(), "newApk.apk");

                //假设patch.patch文件已经下载到sdcard上,切已经校验通过
                File patch = new File(Environment.getExternalStorageDirectory(), "patch.patch");

                if(!patch.exists()){
                    subscriber.onError(new IOException("patch file not exist!"));
                    return;

                //合并差分包
                BsPatchUtil.patch(OSUtil.getApkInstalledSrc(), newApk.getAbsolutePath(), patch.getAbsolutePath());
                if (newApk.exists()) {
                    subscriber.onNext(newApk);
                    subscriber.onCompleted();
                    patch.delete();
                }else{
                    subscriber.onError(new IOException("bspatch failed,file not exist!"));
                }

            }
        }).subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe(new Action0() {
                    @Override
                    public void call() {
                        showDialog("正在应用差分包");
                    }
                })
                .subscribe(new Subscriber<File>() {
                    @Override
                    public void onCompleted() {
                        hideDialog();
                    }

                    @Override
                    public void onError(Throwable e) {
                        hideDialog();
                        LogUtils.d(e.getMessage());
                    }

                    @Override
                    public void onNext(File file) {
                        OSUtil.installAPK(getActivity(),file);
                    }
                });

    }

8. incremental update disadvantages

Although incremental update allows effective solution to the problem of excessive update package, but the following problems exist:

8.1. The client and server need to add the appropriate support. Each release, the server needs to subcontract all previous versions of the older generation corresponding to the difference is, and returns the corresponding update package based on client side request, maintenance will become relatively complex. The client needs to be done for poor subcontracting more detailed verification, prevent errors, in addition, the client should be able to determine the current use is based on incremental update or a full update server to update the switch.
8.2. Apk difference between the packet is too small, such as below 2m, the difference generated at this time there are still hundreds of sub-k, this time using incremental update more harm than good, and after forming a difference sub-process is very time consuming combined. In addition, the changes between versions is very large, usually it is time to change the large version of the good, such as from v 1.0.0 to 2.0.0, this time using a full update is also good.

In the Master says have been added to the main code, self-practice. Results are as follows:

Tencent interview: incremental upgrade Why upgrade to reduce costs, incremental upgrade principle

Guess you like

Origin blog.51cto.com/14332859/2424574