背景
增量升级的原理
增量升级的操作
OTA系统差分包的制作,使用命令:
- ./build/tools/releasetools/ota_from_target_files
-n -i <</span>旧包> <</span>新包> <</span>差分包名>
./build/tools/releasetools/ota_from_target_files -n -i <旧包> <新包> <差分包名>
- diff_program
= DIFF_PROGRAM_BY_EXT.get(ext, "bsdiff")
diff_program = DIFF_PROGRAM_BY_EXT.get(ext, "bsdiff")
相关的代码
地址 或者在android的代码目录下 \external\bsdiff
- 命令:bsdiff
oldfile newfile patchfile - 例如:
bsdiff xx_v1.0.apk xx_v2.0.apk xx.patch
命令:bsdiff oldfile newfile patchfile 例如: bsdiff xx_v1.0.apk xx_v2.0.apk xx.patch
- bspatch的命令格式为:
- bspatch
oldfile newfile patchfile
bspatch的命令格式为: bspatch oldfile newfile patchfile
不足
小实验
- ├──
bsdiff-4.3 //bsdiff的源码路径,官网获取 - │
├── bsdiff.1 - │
├── bsdiff.c - │
├── bspatch.1 - │
├── bspatch.c - │
└── Makefile - ├──
bsdiff-4.3.tar.gz - ├──
bsdiff4.3-win32 //windows PC端的测试工具 - │
├── Binary diff.txt - │
├── bsdiff.exe - │
├── bspatch.exe - │
└── LICENSE - ├──
bspatch //手机端的测试工具 - ├──
iReader1.6.2.0(v35).apk // 旧版本的apk - └──
iReader1.8.0.1(v40).apk //新版本的apk
├── bsdiff-4.3 //bsdiff的源码路径,官网获取 │ ├── bsdiff.1 │ ├── bsdiff.c │ ├── bspatch.1 │ ├── bspatch.c │ └── Makefile ├── bsdiff-4.3.tar.gz ├── bsdiff4.3-win32 //windows PC端的测试工具 │ ├── Binary diff.txt │ ├── bsdiff.exe │ ├── bspatch.exe │ └── LICENSE ├── bspatch //手机端的测试工具 ├── iReader1.6.2.0(v35).apk // 旧版本的apk └── iReader1.8.0.1(v40).apk //新版本的apk
- bsdiff.exe
../iReader1.6.2.0(v35).apk ../iReader1.8.0.1(v40).apk ../ireader.patch
bsdiff.exe ../iReader1.6.2.0(v35).apk ../iReader1.8.0.1(v40).apk ../ireader.patch
- bspatch.exe
../iReader1.6.2.0(v35).apk ../new.apk ../ireader.patch
bspatch.exe ../iReader1.6.2.0(v35).apk ../new.apk ../ireader.patch
扩展阅读
Full update
bsdiff update
704,512
Courgette update
78,848
大牛们可以去研究下。
最近有些小忙,稍后有时间会对增量升级进行封装下,将合成的代码弄成一个lib库,供java调用。有兴趣的童鞋可以自己操作一下~~~
补充:
很多人不知道怎么进行封装为lib,其实这个和一般的android的C库是一样的,不明白的看看jni相关的知识,原来的测试工程已经找不到了,下边我给出个简单的例子,抛砖引玉,给大家参考下。
- #include
- #include
"com_hmg25_newstart_BSpatch.h" -
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
-
- 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*256;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]); -
-
-
if ((f = fopen(argv[3], "r")) == NULL) -
err(1, "fopen(%s)", argv[3]); -
-
-
-
-
if (fread(header, 1, 32, f) < 32) { -
if (feof(f)) -
errx(1, "Corrupt patch\n"); -
err(1, "fread(%s)", argv[3]); -
} -
-
-
if (memcmp(header, "BSDIFF40", 8) != 0) -
errx(1, "Corrupt patch\n"); -
-
-
bzctrllen=offtin(header+8); -
bzdatalen=offtin(header+16); -
newsize=offtin(header+24); -
if((bzctrllen<<span class="number">0) || (bzdatalen<<span class="number">0) || (newsize<<span class="number">0)) -
errx(1,"Corrupt patch\n"); -
-
-
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 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 long)(32 + bzctrllen)); -
if ((dpfbz2 = 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 long)(32 + bzctrllen + bzdatalen)); -
if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL) -
errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err); -
-
if(((fd=open(argv[1],O_RDONLY,0))<<span class="number">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 -
-
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, "Corrupt patch\n"); -
ctrl[i]=offtin(buf); -
}; -
-
-
if(newpos+ctrl[0]>newsize) -
errx(1,"Corrupt patch\n"); -
-
-
lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]); -
if ((lenread < ctrl[0]) || -
((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END))) -
errx(1, "Corrupt patch\n"); -
-
-
for(i=0;i0];i++) -
if((oldpos+i>=0) && (oldpos+i -
new[newpos+i]+=old[oldpos+i]; -
-
-
newpos+=ctrl[0]; -
oldpos+=ctrl[0]; -
-
-
if(newpos+ctrl[1]>newsize) -
errx(1,"Corrupt patch\n"); -
-
-
lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]); -
if ((lenread < ctrl[1]) || -
((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END))) -
errx(1, "Corrupt patch\n"); -
-
-
newpos+=ctrl[1]; -
oldpos+=ctrl[2]; -
}; -
-
-
BZ2_bzReadClose(&cbz2err, cpfbz2); -
BZ2_bzReadClose(&dbz2err, dpfbz2); -
BZ2_bzReadClose(&ebz2err, epfbz2); -
if (fclose(cpf) || fclose(dpf) || fclose(epf)) -
err(1, "fclose(%s)", argv[3]); -
-
-
if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<<span class="number">0) || -
(write(fd,new,newsize)!=newsize) || (close(fd)==-1)) -
err(1,"%s",argv[2]); -
-
free(new); -
free(old); -
-
return 0; - }
-
- JNIEXPORT
jint JNICALL Java_com_hmg25_newstart_BSpatch_applyPatch(JNIEnv *env, -
jobject obj, jstring old, jstring new , jstring patch){ -
int argc=4; -
char * argv[argc]; -
argv[0]="bspatch"; -
argv[1]=(*env)->GetStringUTFChars(env,old, 0); -
argv[2]=(*env)->GetStringUTFChars(env,new, 0); -
argv[3]=(*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; - }
#include #include "com_hmg25_newstart_BSpatch.h" #include #include #include #include #include #include #include #include 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*256;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]); if ((f = fopen(argv[3], "r")) == NULL) err(1, "fopen(%s)", argv[3]); if (fread(header, 1, 32, f) < 32) { if (feof(f)) errx(1, "Corrupt patch\n"); err(1, "fread(%s)", argv[3]); } if (memcmp(header, "BSDIFF40", 8) != 0) errx(1, "Corrupt patch\n"); bzctrllen=offtin(header+8); bzdatalen=offtin(header+16); newsize=offtin(header+24); if((bzctrllen<0) || (bzdatalen<0) || (newsize<0)) errx(1,"Corrupt patch\n"); 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 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 long)(32 + bzctrllen)); if ((dpfbz2 = 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 long)(32 + bzctrllen + bzdatalen)); if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL) errx(1, "BZ2_bzReadOpen, 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<=2;i++) { lenread = BZ2_bzRead(&cbz2err, cpfbz2, buf, 8); if ((lenread < 8) || ((cbz2err != BZ_OK) && (cbz2err != BZ_STREAM_END))) errx(1, "Corrupt patch\n"); ctrl[i]=offtin(buf); }; if(newpos+ctrl[0]>newsize) errx(1,"Corrupt patch\n"); lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]); if ((lenread < ctrl[0]) || ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END))) errx(1, "Corrupt patch\n"); for(i=0;i=0) && (oldpos+inewsize) errx(1,"Corrupt patch\n"); lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]); if ((lenread < ctrl[1]) || ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END))) errx(1, "Corrupt patch\n"); newpos+=ctrl[1]; oldpos+=ctrl[2]; }; BZ2_bzReadClose(&cbz2err, cpfbz2); BZ2_bzReadClose(&dbz2err, dpfbz2); BZ2_bzReadClose(&ebz2err, epfbz2); if (fclose(cpf) || fclose(dpf) || fclose(epf)) err(1, "fclose(%s)", argv[3]); 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; } JNIEXPORT jint JNICALL Java_com_hmg25_newstart_BSpatch_applyPatch(JNIEnv *env, jobject obj, jstring old, jstring new , jstring patch){ int argc=4; char * argv[argc]; argv[0]="bspatch"; argv[1]=(*env)->GetStringUTFChars(env,old, 0); argv[2]=(*env)->GetStringUTFChars(env,new, 0); argv[3]=(*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; }Android.mk:
- LOCAL_PATH:=
$(call my-dir) - include
$(CLEAR_VARS) -
- #
This is the target being built. - LOCAL_MODULE:=
libbspatch -
-
- #
All of the source files that we will compile. - LOCAL_SRC_FILES:=
\ -
com_hmg25_newstart_BSpatch.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)