增量更新(制作差分包笔记)
来源:互联网 发布:剑网三咩太捏脸数据 编辑:程序博客网 时间:2024/05/22 09:41
一、概述
我们原来在应用市场上看到有些应用在升级的时候,一个几十兆的apk,只需要下载一个几兆的增量包便可以完成升级。
主要应用了开源项目bsdiff进行制作。
1、 在服务器上生成一个patch。
2、 下载patch到手机中。
3、 通过补丁获取一个已安装应用的新的安装apk。
4、 安装应用的新版本并删掉旧的版本和patch。
本片文章主要讲如何制作差分包
二、差分包的生成
bsdiff地址 :http://www.daemonology.net/bsdiff/
bsdiff github地址:https://github.com/mendsley/bsdiff
·
1、下载上面的项目源码, 把.c和.cpp还有.h导入到vs中,并解决相应的错误
在vs命令行配置如下 -D _CRT_SECURE_NO_WARNINGS -D _CRT_NONSTDC_NO_DEPRECATE
2 我们主要应用bsdiff.cpp 这个文件中的main方法进行拆分
int main(int argc,char *argv[]){ int fd; u_char *old,*_new; off_t oldsize,newsize; off_t *I,*V; off_t scan,pos,len; off_t lastscan,lastpos,lastoffset; off_t oldscore,scsc; off_t s,Sf,lenf,Sb,lenb; off_t overlap,Ss,lens; off_t i; off_t dblen,eblen; u_char *db,*eb; u_char buf[8]; u_char header[32]; FILE * pf; BZFILE * pfbz2; int bz2err; if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]); /* Allocate oldsize+1 bytes instead of oldsize bytes to ensure that we never try to malloc(0) and get a NULL pointer */ //org: //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]); //new: //Read in chunks, don't rely on read always returns full data! if(((fd=open(argv[1],O_RDONLY|O_BINARY|O_NOINHERIT,0))<0) || ((oldsize=lseek(fd,0,SEEK_END))==-1) || ((old=(u_char*)malloc(oldsize+1))==NULL) || (lseek(fd,0,SEEK_SET)!=0)) err(1,"%s",argv[1]); int r=oldsize; while (r>0 && (i=read(fd,old+oldsize-r,r))>0) r-=i; if (r>0 || close(fd)==-1) err(1,"%s",argv[1]); if(((I=(off_t*)malloc((oldsize+1)*sizeof(off_t)))==NULL) || ((V=(off_t*)malloc((oldsize+1)*sizeof(off_t)))==NULL)) err(1,NULL); qsufsort(I,V,old,oldsize); free(V); /* Allocate newsize+1 bytes instead of newsize bytes to ensure that we never try to malloc(0) and get a NULL pointer */ //org: //if(((fd=open(argv[2],O_RDONLY,0))<0) || // ((newsize=lseek(fd,0,SEEK_END))==-1) || // ((_new=malloc(newsize+1))==NULL) || // (lseek(fd,0,SEEK_SET)!=0) || // (read(fd,_new,newsize)!=newsize) || // (close(fd)==-1)) err(1,"%s",argv[2]); //new: //Read in chunks, don't rely on read always returns full data! if(((fd=open(argv[2],O_RDONLY|O_BINARY|O_NOINHERIT,0))<0) || ((newsize=lseek(fd,0,SEEK_END))==-1) || ((_new=(u_char*)malloc(newsize+1))==NULL) || (lseek(fd,0,SEEK_SET)!=0)) err(1,"%s",argv[2]); r=newsize; while (r>0 && (i=read(fd,_new+newsize-r,r))>0) r-=i; if (r>0 || close(fd)==-1) err(1,"%s",argv[1]); if(((db=(u_char*)malloc(newsize+1))==NULL) || ((eb=(u_char*)malloc(newsize+1))==NULL)) err(1,NULL); dblen=0; eblen=0; /* Create the patch file */ //org: //if ((pf = fopen(argv[3], "w")) == NULL) //new: //if((fd=open(argv[3],O_CREAT|O_TRUNC|O_WRONLY|O_BINARY|O_NOINHERIT,0666))<0) if ((pf = fopen(argv[3], "wb")) == NULL) err(1,"%s",argv[3]); /* Header is 0 8 "BSDIFF40" 8 8 length of bzip2ed ctrl block 16 8 length of bzip2ed diff block 24 8 length of new file */ /* File is 0 32 Header 32 ?? Bzip2ed ctrl block ?? ?? Bzip2ed diff block ?? ?? Bzip2ed extra block */ memcpy(header,"BSDIFF40",8); offtout(0, header + 8); offtout(0, header + 16); offtout(newsize, header + 24); if (fwrite(header, 32, 1, pf) != 1) err(1, "fwrite(%s)", argv[3]); /* Compute the differences, writing ctrl as we go */ if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL) errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err); scan=0;len=0; lastscan=0;lastpos=0;lastoffset=0; while(scan<newsize) { oldscore=0; for(scsc=scan+=len;scan<newsize;scan++) { len=search(I,old,oldsize,_new+scan,newsize-scan, 0,oldsize,&pos); for(;scsc<scan+len;scsc++) if((scsc+lastoffset<oldsize) && (old[scsc+lastoffset] == _new[scsc])) oldscore++; if(((len==oldscore) && (len!=0)) || (len>oldscore+8)) break; if((scan+lastoffset<oldsize) && (old[scan+lastoffset] == _new[scan])) oldscore--; }; if((len!=oldscore) || (scan==newsize)) { s=0;Sf=0;lenf=0; for(i=0;(lastscan+i<scan)&&(lastpos+i<oldsize);) { if(old[lastpos+i]==_new[lastscan+i]) s++; i++; if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; }; }; lenb=0; if(scan<newsize) { s=0;Sb=0; for(i=1;(scan>=lastscan+i)&&(pos>=i);i++) { if(old[pos-i]==_new[scan-i]) s++; if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; }; }; }; if(lastscan+lenf>scan-lenb) { overlap=(lastscan+lenf)-(scan-lenb); s=0;Ss=0;lens=0; for(i=0;i<overlap;i++) { if(_new[lastscan+lenf-overlap+i]== old[lastpos+lenf-overlap+i]) s++; if(_new[scan-lenb+i]== old[pos-lenb+i]) s--; if(s>Ss) { Ss=s; lens=i+1; }; }; lenf+=lens-overlap; lenb-=lens; }; for(i=0;i<lenf;i++) db[dblen+i]=_new[lastscan+i]-old[lastpos+i]; for(i=0;i<(scan-lenb)-(lastscan+lenf);i++) eb[eblen+i]=_new[lastscan+lenf+i]; dblen+=lenf; eblen+=(scan-lenb)-(lastscan+lenf); offtout(lenf,buf); BZ2_bzWrite(&bz2err, pfbz2, buf, 8); if (bz2err != BZ_OK) errx(1, "BZ2_bzWrite, bz2err = %d", bz2err); offtout((scan-lenb)-(lastscan+lenf),buf); BZ2_bzWrite(&bz2err, pfbz2, buf, 8); if (bz2err != BZ_OK) errx(1, "BZ2_bzWrite, bz2err = %d", bz2err); offtout((pos-lenb)-(lastpos+lenf),buf); BZ2_bzWrite(&bz2err, pfbz2, buf, 8); if (bz2err != BZ_OK) errx(1, "BZ2_bzWrite, bz2err = %d", bz2err); lastscan=scan-lenb; lastpos=pos-lenb; lastoffset=pos-scan; }; }; BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL); if (bz2err != BZ_OK) errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err); /* Compute size of compressed ctrl data */ if ((len = ftell(pf)) == -1) err(1, "ftello"); offtout(len-32, header + 8); /* Write compressed diff data */ if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL) errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err); BZ2_bzWrite(&bz2err, pfbz2, db, dblen); if (bz2err != BZ_OK) errx(1, "BZ2_bzWrite, bz2err = %d", bz2err); BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL); if (bz2err != BZ_OK) errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err); /* Compute size of compressed diff data */ if ((newsize = ftell(pf)) == -1) err(1, "ftello"); offtout(newsize - len, header + 16); /* Write compressed extra data */ if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL) errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err); BZ2_bzWrite(&bz2err, pfbz2, eb, eblen); if (bz2err != BZ_OK) errx(1, "BZ2_bzWrite, bz2err = %d", bz2err); BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL); if (bz2err != BZ_OK) errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err); /* Seek to the beginning, write the header, and close the file */ if (fseek(pf, 0, SEEK_SET)) err(1, "fseeko"); if (fwrite(header, 32, 1, pf) != 1) err(1, "fwrite(%s)", argv[3]); if (fclose(pf)) err(1, "fclose"); /* Free the memory we used */ free(db); free(eb); free(I); free(old); free(_new); return 0;}
如上代码可知需要必须为argc=4
argv[0] = “bsdiff”;//无效参数
argv[1] = oldfile;//旧版本地址
argv[2] = newfile;//新版本地址
argv[3] = patchfile;//差分包的位置
由此可知我们jni需要传递的参数有oldfile,newfile,patchfile三个参数
我们新建一个javaweb项目,并在src目录下创建一个java 类如下:
Bsdiff.java
/** * 制作差分包 * @param oldifle 旧路径 * @param patchfile 差分包路径 * */ public native static void bsdiff(String oldifle,String pacrhfile,String newfile);
进入对应的目录执行命令:javah com.saber.update.BsDiff ,并且刷新工程获取到.h文件
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_saber_update_BsDiff */#ifndef _Included_com_saber_update_BsDiff#define _Included_com_saber_update_BsDiff#ifdef __cplusplusextern "C" {#endif/* * Class: com_saber_update_BsDiff * Method: bsdiff * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V */JNIEXPORT void JNICALL Java_com_saber_update_BsDiff_bsdiff (JNIEnv *, jclass, jstring, jstring, jstring);#ifdef __cplusplus}#endif#endif
并且把文件考入到vs中,并在bsdiff.cpp中引入com_saber_update_BsDiff.h,jni.h,jni_md.h
并在bsdiff.cpp中写下调用jni方法
//JNI 调用JNIEXPORT void JNICALL Java_com_saber_update_BsDiff_bsdiff(JNIEnv *env, jclass jcls, jstring oldifle_jstr, jstring pacrhfile_jstr, jstring newfile_jstr){ int argc = 4; char* oldfile = (char*)env->GetStringUTFChars(oldifle_jstr, NULL); char* newfile = (char*)env->GetStringUTFChars(newfile_jstr, NULL); char* patchfile = (char*)env->GetStringUTFChars(pacrhfile_jstr, NULL); char *argv[4]; argv[0] = "bsdiff"; argv[1] = oldfile; argv[2] = newfile; argv[3] = patchfile; bsdiff_main(argc,argv); //回收 env->ReleaseStringUTFChars(oldifle_jstr, oldfile); env->ReleaseStringUTFChars(newfile_jstr, newfile); env->ReleaseStringUTFChars(pacrhfile_jstr, patchfile);}
生成.dll动态库放入web 工程中,并在BsDiff.java中加入如下代码
static { System.loadLibrary("SaberBsdiff"); }
建立一个java文件进行测试
“`
public class TestBsDiff {
private static String newpath="E:/apk/SaBerBsDiff_new.apk";private static String oldpath="E:/apk/SaBerBsDiff_old.apk";private static String path="E:/apk/apk.patch";public static void main(String args[]){ BsDiff.bsdiff(oldpath, path, newpath);}
}
结果如下:
“`
群号:454430053,欢迎入群
- 增量更新(制作差分包笔记)
- NDK学习之增量更新--编译bsdiff得到差分包
- android增量更新中差分包生成以及合成
- 自定义OTA升级包(差分包,增量包,增量更新)
- OTA差分包制作
- 制作ota差分包
- Android增量更新(四)-客户端合并差分包生成新的apk安装包
- 差分包so笔记
- ota差分包制作说明
- Android差分包的制作
- android 7.0 制作ota差分包
- Android M 差分包的制作流程
- android差异化更新(增量更新)
- 手动制作update升级包以及制作差分包
- MTK 平台 Android L版本差分包制作
- Android的增量更新,差分更新--服务器端&客户端
- 增量更新(客户端笔记)
- React Native 实现热部署、差异化增量热更新
- 1017: [JSOI2008]魔兽地图DotR
- Sublime Text 3使用SublimeLinter配置JS,CSS,HTML语法检查
- VR开发-VRTK基本设置
- react-router 2.5 context undefiend replaceState deprecated
- 数据库的索引和数据库查询
- 增量更新(制作差分包笔记)
- Unity3D在mac上使用VSCODE开发
- 备忘录模式(行为类)
- 今天12.7日,卖了氯霉素眼药水
- Codeforces Round #383 (Div. 2) B(打表)
- Serv-U FTP Server 中文版 11.0.0.4安装及使用说明
- I2C笔记
- html标签被当成文本
- 存储过程增删改查