Codeegg’s 785th tweet

Size girls see the world

Introduction to Android incremental updates

To be clear, Android incremental updates and hot fixes are different technical concepts.

Hot fixes are generally used when a Bug needs to be fixed in a released app. Developers modify the code and release patches so that the app can be updated without the need for a re-installation. Mainstream solutions have a Tinker (https://github.com/Tencent/tinker), AndFix (https://github.com/alibaba/AndFix), etc.

The purpose of incremental update is to reduce the volume of the package that needs to be downloaded to update the APP. For example, the volume of APK package is several hundred meters, but sometimes the update only needs to download more than ten meters of the installation package to complete the update.

The principle of incremental update is simply to find the differences between the new version and the old version through the binary algorithm, and extract the differences to generate the so-called patch package (differential subcontract). When the mobile terminal checks the update, it only needs to apply to the server to download the corresponding patch package, and then merge the difference package with its old version APK to generate the latest version APK. The final installation of the apK generated by the merge completes the version update.

The realization of the function is mainly with the help of third party difference tools, equivalent to doing records, convenient later recall.

Demonstration of incremental update process

There are two main processes for incremental updates. First, the background compares the latest APK (V1.0.1) with the previous version (v1.0.0) and generates subcontracting. The second step is to download the corresponding subpackage on the mobile terminal and merge it locally to generate the complete latest APK and guide the user to install it.

For difference and merge apk package, need bsdiff (https://www.pokorra.de/coding/bsdiff.html) tools to achieve

Download bsdiff_win_exe.zip and unzip it locally


Where bsdiff.exe is the tool used by Window to generate subcontracting, and bspatch is the tool used to synthesize subcontracting

2.1 Generation of subcontracting

First of all, type an old APK (v1.0.0.apk) and a new APk (v1.0.1.apk) respectively and store them in the directory that you extracted previously.


Then open the Windows command line tool, switch to the directory, and type the command bsdiff v1.0.0.apk v1.0.1.apk patch.patch


You can see the generated subpackage patch.patch in the directory


2.2 Composite subcontracting

Keep in the current directory and type bspatch v1.0.0.apk new.apk patch.patch


You will see the complete installation package new.apk synthesized in the current directory


The generated new.apk is exactly the same as v1.0.1.apk, just install it.

Incremental updates for Android applications

The above procedure is to demonstrate the process and is now applied to the Android side. During the incremental update process, Android mobile is only responsible for downloading and merging subpackages and guiding users to install them. Therefore, assume that the corresponding subcontracting has been downloaded. There are three main steps: the first is to obtain its own old APK path; The second is to integrate the difference tool into Android. The third is to call the method to merge the subcontracting and guide the user to install.

3.1 Obtaining the Installed Old APK Path

// Get the current running APK pathString oldApk = getApplicationInfo().sourceDir;Copy the code
Copy the code

3.2 Integrate the differential merge function into Android

Bsdiff open source tool source for. C file, that is, the Android side needs to configure JNI (following is based on CMake).

To facilitate integration, required functions have been packaged into the SO package. You can import the SO package directly. Skip this step. Baidu network backup link (https://pan.baidu.com/share/init?surl=yBx3u5eAD7p30qPCjtfm2A) (8 ia7 extraction code:)

Bsdiff (https://www.pokorra.de/coding/bsdiff.html) source dependent bszip (http://www.bzip.org/downloads.html).

3.2.1 Import required Source files

  • Unzip the bsdiff-4.3.tar.gz file and copy the bspatch.c file to your Android CPP directory


  • Unzip the bzip2-1.0.6.tar.gz file and copy the required source files to the Android CPP /bzip directory as shown


  • Modify the contents of the bspatch.c file

(1) Modify the import declaration of bzlib.h: open the bspatch. C file and modify the header file


2) Find the main method and rename it execute_patch


3.2.2 Configuring the CMakLists. TXT file

Cmake_minimum_required (VERSION 3.4.1 track)# find the path of the specified pattern in the file system, such as /* file matching the root directory (note the path)file(GLOB bzip_source ${CMAKE_SOURCE_DIR}/bzip/*.c)# set up local dynamic library compilation to generate dynamic libraryadd_library(# module name    native-lib# Dynamic library/sharing ok    SHARED# the source file    native-lib.cppConfigure the corresponding file references    bspatch.c    ${bzip_source})find_library(    log-lib    log)target_link_libraries(    native-lib    ${log-lib})Copy the code

Copy the code

3.2.3 Adding calling methods to native-lib. CPP

extern "C" {extern int execute_patch(int argc, char *argv[]);}extern "C"JNIEXPORT void JNICALLJava_com_example_myapplication_utilities_BsPatchUtil_patch(JNIEnv *env, jobject instance, jstring oldApk_,                                                 jstring patch_, jstring output_){// Convert a Java string to a char pointer    const char *oldApk = env->GetStringUTFChars(oldApk_, 0);    const char *patch = env->GetStringUTFChars(patch_, 0);    const char *output = env->GetStringUTFChars(output_, 0);    //bspatch ,oldfile ,newfile ,patchfile    char *argv[] = {"", const_cast<char *>(oldApk), const_cast<char *>(output),                    const_cast<char *>(patch)};    execute_patch(4, argv);// Release the corresponding pointer gc    env->ReleaseStringUTFChars(oldApk_, oldApk);    env->ReleaseStringUTFChars(patch_, patch);    env->ReleaseStringUTFChars(output_, output);}Copy the code
Copy the code

Note: The Java_com_example_myapplication_utilities_BsPatchUtil_patch method name needs to be changed based on the actual definition

3.3 Defining methods: The Java layer uses composition functionality

Define a BsPatchUtil class and call c code :(this method name should correspond to the Java_com_example_myapplication_utilities_BsPatchUtil_patch method name mentioned above)

public class BsPatchUtil {    static {        System.loadLibrary("native-lib");    }/ * ** @param oldApkPath Old APK file path* @param newApkPath New APK file path* @param patchPath Storage path of the generated subpackage* /    public static  native void patch(String oldApkPath, String newApkPath, String patchPath);}Copy the code
Copy the code

3.4 Composite subcontracting

// The path to the installed old APKval oldApk = applicationInfo.sourceDir// Subcontract pathval patch = ...// Store path of the synthesized new APKval output = ...// Synthesize apK packageBsPatchUtil.patch(oldApk, patch, output)Copy the code

Copy the code

Synthetic subcontracting needs to run in child threads to prevent blocking the main thread. Finally, boot the user to install the newly generated APK.

Related articles:

  • How did I manage to open the complex App for 1s?

  • I’ve doubled my assets! You still don’t know what blockchain is?

  • Good developers need these 10 steps!

Question of the day:

Why do people use incremental updates?

Exclusive upgrade community: I Finally Figured it out