Incremental-update-master

项目地址: ccj659/Incremental-update-master
简介:采用 bsdiff 开源库 Android 的增量更新,差分更新 服务器端&客户端,
更多: 作者    提 Bug   
标签:

增量更新- 服务器端&客户端-

incremental update 采用 bsdiff 开源库 的增量更新,差分更新 服务器端&客户端,

差分(增量)更新


前言

随着应用越来越大,应用更新耗时间和流量的问题,就显得格外突出.

目前原生 app 的更新分为两种:重新下载源文件,还有一种就是差分包更新,也叫增量更新.

在有些应用市场,例如 google play,会对安装包进行拆分和合并,来达到差分更新的目的.

首先解释一下差分包: 差分包是 apk 新版本和旧版本之间的包,可以称之为 patch.

应用流程:


操作流程

  • 确保客户端是 old_app
  • 改变 app 大小生成新的 new_app
  • 执行服务器生成 patch 程序
  • 将 patch 包放在服务器供客户端下载
  • 服务器合并安装

实现原理:

1.相应下载

自己的 github 项目(包括服务器端,android 端,C++端),阅读此文之前,最好下载完毕研究一下https://github.com/ccj659/incremental-update-master

原理是采用的是 bsdiff,而它是一个优秀的开源 C 库,大家可以去看下

linux 的相关 diff/patch 下载 http://www.daemonology.net/bsdiff/

windows 上的 bsdiff http://sites.inka.de/tesla/others.html#bsdiff

相关依赖 bzip 文档及下载http://www.bzip.org/downloads.html

2.原理分析

Binary diff 是依赖 bzip 压缩库的开源库,其实是一种文件比较的一种算法实现,是一个二进制比较工具. 这里有两个文件:老版本的 app:old_app.apk 新版本的 app:new_app.apk. 首先是 Binarys diff:

1.首先将老文件 old_app 转为二进制文件.

2.在新文件 new_app 中找到和老文件相同的二进制数据.

3.在新文件生成的二进制数据中,分离 new_app 中老文件数据和新的二进制数据 patch.

4.将 patch 数据打上新数据的标签,重新打包生成 apk.patch.

然后是 Binarys patch: 1.通过 bzip 压缩算法,将 old_app 和 patch 重新打包. 关于 bzip,

实现过程

windows 服务器端

1.分析 bsdiff.cpp 源码,找到 main 入口

/*阅读源码得知,此处第一个参数 argc 必须是 4,argv 是一个字符串指针数组*//***如下,此处需要四个参数 1.随便的值,2.ldfile     3.newfile 4.patchfile***************************/int bsdiff_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;/**********************如下,此处需要四个参数 1.随便的值,2.ldfile 3.newfile 4.patchfile***************************/if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);/* Allocate oldsize+1 bytes instead of oldsize bytes to ensurethat 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]);

2.新建 javaWeb 项目,并生成需要的头文件.

生成的操作步骤请看我的

JNI 开发极简教程

3.根据下载的 bsdiff4.3-win32-src 代码,生成 dll 动态库,用于得到差分包

在 visual studio 下 新建 C++项目,并导入 bsdiff 源码(c,cpp,h)

要注意的是,编译过程并不是一帆风顺的,这里需要做什么修正.

用了不安全的函数->在首处添加 #define _CRT_SECURE_NO_WARNINGS

用了过时的函数->添加 #define _CRT_NONSTDC_NO_DEPRECATE

如果还报错,可以选择关闭 SDL 检查

4.修改 bsdiff.cpp 源文件编写 JNI 函数供 Java 层调用(注意统一编码)

1.在此文件中,引入头文件 #include"app_update_service_AppBsDiff.h". 并实现其中的方法(在文件末尾实现).
2.将 main 函数作为 jni 调用的函数.即将 main 函数改名为 bsdiff_main,然后由 jni 调用.

/*
* Class:     app_update_service_AppBsDiff
* Method:    diff
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
*/JNIEXPORT void JNICALL Java_app_update_service_AppBsDiff_diff
(JNIEnv *env, jclass jcls, jstring oldfile_jstr, jstring newfile_jstr, jstring patchfile_jstr){int argc = 4;char* oldfile = (char*)env->GetStringUTFChars(oldfile_jstr, NULL);char* newfile = (char*)env->GetStringUTFChars(newfile_jstr, NULL);char* patchfile = (char*)env->GetStringUTFChars(patchfile_jstr, NULL);//参数(第一个参数无效)char *argv[4];argv[0] = "bsdiff";argv[1] = oldfile;argv[2] = newfile;argv[3] = patchfile;bsdiff_main(argc, argv);env->ReleaseStringUTFChars(oldfile_jstr, oldfile);env->ReleaseStringUTFChars(newfile_jstr, newfile);env->ReleaseStringUTFChars(patchfile_jstr, patchfile);
}

5.编译,生成解决方案,生成 E:\WorkSpace\VSWork\app_bsdiff\x64\Debug\app_bsdiff.dll 文件

如何生成,请参照下面的教程

JNI 开发极简教程

6.将 dll.放入 web 工程的根目录.将应用生成的两个新旧 apk 放到指定目录,运行即可 c 生成差分包 apk.patch

详情参照我的代码 --增量更新 github

7.将生成的 apk.patch 放到 web 服务器上供客户端下载.

这边的服务器上传配置等,我还没来得及整理,可百度...

android 客户端(类似于服务器端)

客户端要做的就是 bspatch,整合 old_app 和 patch 生成 new_app.

代码参考-github 的 android 应用项目 app_update-

1.编写 native 方法,生成头文件(别忘了添加相应权限).

2.添加本地支持

博文请参考 eclipse 搭建 NDK 开发环境

3.将 bzip2 源码,bspatch.c 引入到项目的 jni 目录,并且将 android.mk 中的 bspatch.cpp 改为 bspatch.c

4.修改 bspatch.c 源码,并实现 native 方法.

详情请参考代码-github 的 android 应用项目 app_update-


//合并
JNIEXPORT void JNICALL Java_com_example_app_1update_utils_BsPatch_patch(JNIEnv *env, jclass jcls, jstring oldfile_jstr, jstring newfile_jstr, jstring patchfile_jstr){int argc = 4;char* oldfile = (char*)(*env)->GetStringUTFChars(env,oldfile_jstr, NULL);char* newfile = (char*)(*env)->GetStringUTFChars(env,newfile_jstr, NULL);char* patchfile = (char*)(*env)->GetStringUTFChars(env,patchfile_jstr, NULL);//参数(第一个参数无效)char *argv[4];argv[0] = "bspatch";argv[1] = oldfile;argv[2] = newfile;argv[3] = patchfile;bspatch_main(argc,argv);(*env)->ReleaseStringUTFChars(env,oldfile_jstr, oldfile);(*env)->ReleaseStringUTFChars(env,newfile_jstr, newfile);(*env)->ReleaseStringUTFChars(env,patchfile_jstr, patchfile);}

5.编写更新下载方法

详情请参考代码-github 的 android 应用项目 app_update-

public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findViewById(R.id.btn_update).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubApkUpdateTask apkUpdateTask=new ApkUpdateTask();apkUpdateTask.execute();}});}class ApkUpdateTask extends AsyncTask<Void, Void, Boolean>{@Overrideprotected Boolean doInBackground(Void... params) {try {//1.下载差分包Log.d("ccj", "开始下载");File patchFile = DownloadUtils.download(Constants.URL_PATCH_DOWNLOAD);//获取当前应用的 apk 文件/data/app/appString oldfile = ApkUtils.getSourceApkPath(MainActivity.this, getPackageName());//2.合并得到最新版本的 APK 文件String newfile = Constants.NEW_APK_PATH;String patchfile = patchFile.getAbsolutePath();BsPatch.patch(oldfile, newfile, patchfile);Log.i("ccj", "oldfile:"+oldfile);Log.i("ccj", "newfile:"+newfile);Log.i("ccj", "patch:"+patchfile);} catch (Exception e) {e.printStackTrace();return false;}return true;}@Overrideprotected void onPostExecute(Boolean result) {super.onPostExecute(result);Log.d("ccj", "下载完成");//3.安装if(result){Toast.makeText(MainActivity.this, "您正在进行更新", Toast.LENGTH_SHORT).show();ApkUtils.installApk(MainActivity.this, Constants.NEW_APK_PATH);}}}}

操作流程

  • 确保客户端是 old_app
  • 改变 app 大小生成新的 new_app
  • 执行服务器生成 patch 程序
  • 将 patch 包放在服务器供客户端下载
  • 服务器合并安装


About Me

  • 我的 github
  • 我的 csdn 博客

采用 bsdiff 开源库 Android 的增量更新,差分更新 服务器端客户端相关推荐

  1. android 沉浸式开源库,Android沉浸式状态栏

    关于Android沉浸式状态栏, 网上已经有很多开源库, 虽然开源库可以解决某些特定布局下的沉浸式状态栏问题, 但是遇到比较特殊的布局就无法解决了, 所以了解一下沉浸式状态栏如何实现是有必要的. 无论 ...

  2. android旋转动画开源库,android 围绕中心旋转动画

    本文主要介绍Android中如何使用rotate实现图片不停旋转的效果.Android 平台提供了两类动画,一类是 Tween 动画,即通过对场景里的对象不断做图像变换(平移.缩放.旋转)产生动画效果 ...

  3. 采用FFMPEG开源库和vs2008 mfc 写一个H264播放器(1)

    /*    FFMPEG动态库使用  */ 1 将一下文件拷入工程当前目录下面 http://pan.baidu.com/disk/home#dir/path=%2FFFMPEG 2 设置项目属性 1 ...

  4. Android应用增量升级

    阅读此文之前请先阅读  http://blog.csdn.net/hmg25/article/details/8100896 何为增量升级,简单说下,当应用版本要更新时通常的做法是重新下载新的版本去覆 ...

  5. 发布开源库的踩坑经历:jitpack.io

    前言 很多小伙伴自己写了一个库,打算开源出来,但是直接给别人发jar包或者aar包,别人使用都很不方便,而且版本更新也不方便,所以很多小伙伴把开源库放到了远程仓库里(如maven或jcenter),但 ...

  6. 2019最新Android常用开源库总结(持续更新,建议收藏)

    热文导读|   点击标题阅读 如何才能成为优秀的架构师? 23种设计模式及案例整理分享(建议收藏) 程序员的35个坏习惯,你有几条? 作者:欢子-3824 来源:https://blog.csdn.n ...

  7. android标题栏添加按钮_2019最新Android常用开源库总结(持续更新,建议收藏)

    热文导读|   点击标题阅读 如何才能成为优秀的架构师? 23种设计模式及案例整理分享(建议收藏) 程序员的35个坏习惯,你有几条? 作者:欢子-3824 来源:https://blog.csdn.n ...

  8. Android开源项目以及开源库集合(持续更新中)

    UI Awesome-MaterialDesign – MaterialDesignCenter改名为Awesome-MaterialDesign,优化了布局,新增了不少库. awesome-andr ...

  9. Android常用热门开源库汇总(持续更新)

    原文转载:https://www.yundashi168.com/344.html 请及时关注原文网站,因为后续持续更新都在原网站更新.请多多点赞和关注. 前言 收集了一些比较常见的开源库,特此记录( ...

最新文章

  1. Python统计学-006:描述统计-方差
  2. 【MM模块】 Blanket Purchase Orders 框架订单
  3. MySQL的常见存储引擎介绍与参数设置调优
  4. jtable mysql数据库_使用MySQL数据库语法错误填充jTable
  5. Hibernate - HHH000352: Unable to release batch statement
  6. CHM乱码解决方案!
  7. 数据库设计需要注意什么
  8. NeatUpload的安装使用,可传大文件,显示进度条
  9. 计算机网络知识点脑图 王道 考研
  10. 捷联惯导系统(SINS)误差模型
  11. linux u盘读取速度,linux dd命令测试U盘读写速度
  12. php 限制字数_PHP中如何正确统计中文字数
  13. mysql中括号_如何快速学习mySQL数据库常规通配符及运算符的用法?
  14. 国产系统为什么用linux,为什么国产操作系统不用Unix,而是集体用Linux
  15. 知识图谱发展的难点 构建行业知识图谱的重要性
  16. 航空售票系统--数据库代码部分
  17. 2021年起重机械指挥考试总结及起重机械指挥考试技巧
  18. 图神经网络的图网络学习(上)
  19. (四)Redis——搭建哨兵机制
  20. 用C语言比较三个数的大小

热门文章

  1. 通过拖坠自动生成html页面,网页制造开端—html.ppt
  2. java调用大漠插件
  3. 问责制Accountability
  4. volatile关键字对编译器优化的影响
  5. 4.4 ipu_param_mem.h头文件分析
  6. 基于SSM婚恋网交友平台
  7. conductor 的concurrentExecLimit及rateLimit 实现分析
  8. P110 课时111.多线程更新UI数据
  9. hs8346v5联通 说明书_HS8546V5 移动界面 分区、jffs2原厂备份数据 备份恢复教程
  10. 发现美团的一个新锅,可能程序员背不动了