Incremental upgrade of Android applications

Source: Internet
Author: User

Read http://blog.csdn.net/hmg25/article/details/8100896 before reading this article

What is incremental upgrade? To put it simply, when the application version is updated, the usual practice is to re-download the new version to overwrite the old version, but this has a relatively obvious disadvantage, which is a waste of traffic, especially in GPRS mode. Can we only update the added content of the new version? bsdiff/bzlib2 can help us achieve this. The following describes the specific practices.


1. Generate the difference patch file of the old version and the new version. You can use the Windows version of The bsdiff open-source library.

   bsdiff.exe   ../iReader1.6.2.0(v35).apk   ../iReader1.8.0.1(v40).apk   ../ireader.patch

Second, with the patch file, we can use JNI to call bzlib2 on the Android platform to implement incremental upgrades.

1, first of all to have ndk compiling environment, detailed how to build see: http://blog.csdn.net/tibib/article/details/8504680

2. Compile local methods

// Oldapk_filepath: old storage path newapk_savepath: Path of the generated new version to be stored patchpath: difference ratio file storage path public native int applypatchtooldapk (string oldapk_filepath, string newapk_savepath, string patchpath );

3. Compile the Android. mk configuration file and copy the bzlib2 source code file () to the directory.

Local_path: = $ (call my-DIR) include $ (clear_vars) # This is the target being built. local_module: = libbsdiff # all of the source files that we will compile. # The specific C code is required. I have not carefully studied local_src_files: = tu_bingbing_bsdiff_bsdiffbusiness.c \ bzlib. c \ blocksort. c \ compress. c \ crctable. c \ decompress. c \ Huffman. c \ randtable. c \ bzip2.c \ # No static libraries. local_static_libraries: = \ libbz # also need the JNI headers. local_c_includes + =\$ (jni_h_include) External/Bzip2 # No special compiler flags. local_cflags + = include $ (build_shared_library)

4. Implement local methods

# Include <stdio. h> # include "tu_bingbing_bsdiff_bsdiffbusiness.h" # include "bzlib_private.h" # include <stdlib. h> # include <stdio. h> # include <string. h> # include <err. h> # include <unistd. h> # include <fcntl. h> # include <Android/log. h> static off_t offtin (u_char * BUF) {off_t y; y = Buf [7] & 0x7f; y = y * 256; y + = Buf [6]; y = y * 256; y + = Buf [5]; y = y * 256; y + = Buf [4]; y = y * 256; Y + = Buf [3]; y = y * 256; y + = Buf [2]; y = y * 256; y + = Buf [1]; y = y * 25 6; y + = Buf [0]; If (BUF [7] & 0x80) y =-y; return y;} int applypatch (INT argc, char * argv []) {file * F, * CPF, * DPF, * EPF; bzfile * cpfbz2, * dpfbz2, * epfbz2; int cbz2err, dbz2err, ebz2err; int FD; ssize_t oldsize, newsize; ssize_t bzctrllen, bzdatalen; u_char header [32], Buf [8]; u_char * Old, * New; off_t oldpos, newpos; off_t CTRL [3]; off_t lenread; off_t I; If (argc! = 4) errx (1, "Usage: % s oldfile newfile patchfile \ n", argv [0]); /* open patch file */If (F = fopen (argv [3], "R") = NULL) Err (1, "fopen (% s )", argv [3]);/* File Format: 0 8 "bsdiff40" 8 8x16 8 y 24 8 sizeof (newfile) 32 x Bzip2 (Control Block) 32 + x y Bzip2 (diff block) 32 + x + y ??? Bzip2 (extra block) with control block a set of triples (x, y, z) Meaning "add x bytes from oldfile to X bytes from the diff block; copy y bytes from the extra block; Seek forwards in oldfile by Z bytes ". * // * read header */If (fread (header, 1, 32, f) <32) {If (feof (F) errx (1, "updated upt patch \ n"); err (1, "fread (% s)", argv [3]);} /* Check for appropriate magic */If (memcmp (header, "bsdiff40", 8)! = 0) errx (1, "Upload upt patch \ n");/* read lengths From header */bzctrllen = offtin (header + 8 ); bzdatalen = offtin (header + 16); newsize = offtin (header + 24); If (bzctrllen <0) | (bzdatalen <0) | (newsize <0 )) errx (1, "Upload upt patch \ n");/* close patch file and re-open it via libbzip2 at the right places */If (fclose (f )) err (1, "fclose (% s)", argv [3]); If (CPF = fopen (argv [3], "R") = NULL) err (1, "fopen (% s )", Argv [3]); If (fseeko (CPF, 32, seek_set) Err (1, "fseeko (% s, % LLD)", argv [3], (long) 32); If (cpfbz2 = bz2_bzreadopen (& cbz2err, CPF, 0, 0, null, 0) = NULL) errx (1, "bz2_bzreadopen, bz2err = % d ", cbz2err); If (DPF = fopen (argv [3]," R ") = NULL) Err (1," fopen (% s) ", argv [3]); If (fseeko (DPF, 32 + bzctrllen, seek_set) Err (1," fseeko (% s, % LLD )", argv [3], (long) (32 + bzctrllen); If (DP Fbz2 = bz2_bzreadopen (& dbz2err, DPF, 0, 0, null, 0) = NULL) errx (1, "bz2_bzreadopen, bz2err = % d", dbz2err ); if (EPF = fopen (argv [3], "R") = NULL) Err (1, "fopen (% s)", argv [3]); if (fseeko (EPF, 32 + bzctrllen + bzdatalen, seek_set) Err (1, "fseeko (% s, % LLD)", argv [3], (long) (32 + bzctrllen + bzdatalen); If (epfbz2 = bz2_bzreadopen (& ebz2err, EPF, 0, 0, null, 0) = NULL) errx (1, "bz2_bzr Eadopen, bz2err = % d ", ebz2err); If (FD = open (argv [1], o_rdonly, 0) <0) | (oldsize = lseek (FD, 0, seek_end) =-1) | (old = malloc (oldsize + 1) = NULL) | (lseek (FD, 0, seek_set )! = 0) | (read (FD, old, oldsize )! = Oldsize) | (close (FD) =-1) Err (1, "% s", argv [1]); if (New = malloc (newsize + 1) = NULL) Err (1, null); oldpos = 0; newpos = 0; while (newpos <newsize) {/* read Control Data */for (I = 0; I <= 2; I ++) {lenread = bz2_bzread (& cbz2err, cpfbz2, Buf, 8 ); if (lenread <8) | (cbz2err! = Bz_ OK) & (cbz2err! = Bz_stream_end) errx (1, "Upload upt patch \ n"); CTRL [I] = offtin (BUF );}; /* sanity-check */If (newpos + ctrl [0]> newsize) errx (1, "failed upt patch \ n "); /* read diff string */lenread = bz2_bzread (& dbz2err, dpfbz2, new + newpos, CTRL [0]); If (lenread <Ctrl [0]) | (dbz2err! = Bz_ OK) & (dbz2err! = Bz_stream_end) errx (1, "Upload upt patch \ n");/* Add old data to diff string */for (I = 0; I <Ctrl [0]; I ++) if (oldpos + I> = 0) & (oldpos + I <oldsize) New [newpos + I] + = old [oldpos + I]; /* adjust pointers */newpos + = CTRL [0]; oldpos + = CTRL [0];/* sanity-check */If (newpos + ctrl [1]> newsize) errx (1, "Upload upt patch \ n");/* read extra string */lenread = bz2_bzread (& ebz2err, epfbz2, new + newpos, CTRL [1]); if (lenrea D <Ctrl [1]) | (ebz2err! = Bz_ OK) & (ebz2err! = Bz_stream_end) errx (1, "Upload upt patch \ n");/* adjust pointers */newpos + = CTRL [1]; oldpos + = CTRL [2];};/* clean up the Bzip2 reads */lower (& cbz2err, cpfbz2); bz2_bzreadclose (& dbz2err, dpfbz2); lower (& ebz2err, epfbz2); If (fclose (CPF) | fclose (DPF) | fclose (EPF) Err (1, "fclose (% s)", argv [3]); /* write the new file */If (FD = open (argv [2], o_creat | o_trunc | o_wronly, 0666) <0) | (Write (FD, new, newsize )! = Newsize) | (close (FD) =-1) Err (1, "% s", argv [2]); free (new ); free (old); Return 0;} // path of the APK package before the old upgrade // path of the APK package after the new upgrade // path of the patch file, you can use bsdiff tool to generate // The specific principle can see the http://blog.csdn.net/hmg25/article/details/8100896JNIEXPORT jint jnicall partition (jnienv * ENV, jobject OBJ, jstring old, jstring new, jstring patch) {int argc = 4; char * argv [argc]; 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); int ret = applypatch (argc, argv); (* env)-> releasestringutfchars (ENV, old, argv [1]); (* env)-> releasestringutfchars (ENV, new, argv [2]); (* env)-> releasestringutfchars (ENV, patch, argv [3]); return ret ;}

Finally, the ndk is compiled and the native method is called in Android. You will find that a new version of APK is generated under your input path.


Demo: http://download.csdn.net/detail/tibib/5581905



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.