一、介绍

当我们发布新版本的时候,一些用户升级并不是很积极,这就造成了新版本的升级率并不高。而google为了解决了这个问题,提出了Smart App Update,即增量更新(也叫做差分升级)。

增量更新的流程是:用户手机上安装着某个应用,下载了增量包,手机上的apk和增量包合并形成新的包,然后再次安装(注意这个过程是要重新安装的,当然部分应用市场有root权限你可能感知不到)。

那么把整个流程细化为几个关键点:

  1. 用户手机上提取当前安装应用的apk
  2. 如何利用old.apk和new.apk生成增量文件
  3. 增加文件与1中的old.apk合并,然后安装

解决了上述3个问题,就ok了。

借助开源库bsdiff来解决以上两个问题。首先我们先演示一下差分包的形成与合并。

下载bsdiff_win_exe.zip,解压到本地。如下图: 

然后,我们先打出一个安装包,假设为old.apk。对源码做修改后,再打出一个新的安装包new.apk。此处old.apk相当于老版本的应用,而new.apk相当于新版本的应用。接下来,我们利用bsdiff来生成差分包patch.patch。

生成差分包

将上面的old.apk和new.apk放入bsdiff解压后的目录,然后在控制台中执行命令bsdiff old.apk new.apk patch.patch,稍等一会便可以生成差分包patch.patch,如下

合并差分包

合并old.apk和patch.patch,生成新的安装包new.apk。只要此处合并出来的new.apk和上面我们自己打出来的new.apk一样,那么就可以认为它就是我们需要的新版本安装包。

我们来看看如何合并。将old.apk和patch.patch放入bsdiff文件夹,合并之前为: 

然后执行命令bspatch old.apk new.apk patch.patch,稍等一会之后便可以看到合并出的new.apk.如下: 

不出意外,合并而来的new.apk应该和我们自己打出来的new.apk是一模一样的,这可以通过验证两者的md5来认定。

客户端支持增量更新总体和上面的演示差不多,唯一的区别在于客户端要自行编译bspatch.c来实现合并差分包,也就是所谓的ndk开发。

使用第三方库进行合并:https://github.com/cundong/SmartAppUpdates,已经把bspatch的源码加入到jni内了。只要下载它并编译,就可以在应用内嵌入bspatch,实现增量更新了。

配置好NDK,在SmartAppUpdates的目录内执行ndk-build:

\ApkPatchLibrary\app\src\main\jni>ndk-build
[arm64-v8a] Compile        : ApkPatchLibrary <= com_cundong_utils_PatchUtils.c
[arm64-v8a] SharedLibrary  : libApkPatchLibrary.so
[arm64-v8a] Install        : libApkPatchLibrary.so => libs/arm64-v8a/libApkPatchLibrary.so
[x86_64] Compile        : ApkPatchLibrary <= com_cundong_utils_PatchUtils.c
[x86_64] SharedLibrary  : libApkPatchLibrary.so
[x86_64] Install        : libApkPatchLibrary.so => libs/x86_64/libApkPatchLibrary.so
[mips64] Compile        : ApkPatchLibrary <= com_cundong_utils_PatchUtils.c
[mips64] SharedLibrary  : libApkPatchLibrary.so
[mips64] Install        : libApkPatchLibrary.so => libs/mips64/libApkPatchLibrary.so
[armeabi-v7a] Compile thumb  : ApkPatchLibrary <= com_cundong_utils_PatchUtils.c
[armeabi-v7a] SharedLibrary  : libApkPatchLibrary.so
[armeabi-v7a] Install        : libApkPatchLibrary.so => libs/armeabi-v7a/libApkPatchLibrary.so
[armeabi] Compile thumb  : ApkPatchLibrary <= com_cundong_utils_PatchUtils.c
[armeabi] SharedLibrary  : libApkPatchLibrary.so
[armeabi] Install        : libApkPatchLibrary.so => libs/armeabi/libApkPatchLibrary.so
[x86] Compile        : ApkPatchLibrary <= com_cundong_utils_PatchUtils.c
[x86] SharedLibrary  : libApkPatchLibrary.so
[x86] Install        : libApkPatchLibrary.so => libs/x86/libApkPatchLibrary.so
[mips] Compile        : ApkPatchLibrary <= com_cundong_utils_PatchUtils.c
[mips] SharedLibrary  : libApkPatchLibrary.so
[mips] Install        : libApkPatchLibrary.so => libs/mips/libApkPatchLibrary.so
\ApkPatchLibrary\app\src\main\jni>

到这一步,我们可以得到名为libApkPatchLibrary.so的库,通过com.cundong.utils.PatchUtils模块来调用。

public class PatchUtils {/*** native方法 使用路径为oldApkPath的apk与路径为patchPath的补丁包,合成新的apk,并存储于newApkPath* * 返回:0,说明操作成功* * @param oldApkPath 示例:/sdcard/old.apk* @param newApkPath 示例:/sdcard/new.apk* @param patchPath  示例:/sdcard/xx.patch* @return*/public static native int patch(String oldApkPath, String newApkPath,String patchPath);
}

被调用的相应jni代码为:

/** Class:     com_cundong_utils_PatchUtils* Method:    patch* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I*/
JNIEXPORT jint JNICALL Java_com_cundong_utils_PatchUtils_patch(JNIEnv *env,jobject obj, jstring old, jstring new, jstring patch) {char * ch[4];ch[0] = "bspatch";ch[1] = (char*) ((*env)->GetStringUTFChars(env, old, 0));ch[2] = (char*) ((*env)->GetStringUTFChars(env, new, 0));ch[3] = (char*) ((*env)->GetStringUTFChars(env, patch, 0));__android_log_print(ANDROID_LOG_INFO, "ApkPatchLibrary", "old = %s ", ch[1]);__android_log_print(ANDROID_LOG_INFO, "ApkPatchLibrary", "new = %s ", ch[2]);__android_log_print(ANDROID_LOG_INFO, "ApkPatchLibrary", "patch = %s ", ch[3]);int ret = applypatch(4, ch);__android_log_print(ANDROID_LOG_INFO, "ApkPatchLibrary", "applypatch result = %d ", ret);(*env)->ReleaseStringUTFChars(env, old, ch[1]);(*env)->ReleaseStringUTFChars(env, new, ch[2]);(*env)->ReleaseStringUTFChars(env, patch, ch[3]);return ret;
}

其实applypatch函数就是bspatch代码的main函数,它这里改了个名字。

现在,我们在SmartAppUpdates的Demo项目中测试加入App中的bspatch代码是否能够正常工作:把刚才的old.apk和patch包拷贝到手机的/sdcard/目录,并将如下代码加到App的onCreate()方法内。

PatchUtils.patch(Environment.getExternalStorageDirectory().getPath() + "/old.apk",Environment.getExternalStorageDirectory().getPath() + "/out.apk",Environment.getExternalStorageDirectory().getPath() + "/patch");

运行APP后,按照预期/sdcard/目录会生成out.apk。通过adb shell在手机内执行命令:

/sdcard $ md5sum out.apk
cbb1afdbc32e4d1c62c4d38674a6a3a9  out.apk

可以看到在app程序内嵌入的bspatch也成功的通过了老apk和patch包生成了新的apk,生成的out.apk的MD5值与new.apk是一致的。测试通过。

还有一个框架:https://github.com/ha-excited/BigNews

无需下载本项目,在你项目根build.gradle添加代码:

allprojects {repositories {...maven { url 'https://jitpack.io' }}
}

在你项目模块内的build.gradle添加代码,然后Gradle Sync:

    dependencies {compile 'com.github.ha-excited:BigNews:0.1.2'}

调用方法:

合并: 从差分包/升级包和老安装包合并升级到新安装包,新安装包放在newApkPath。

/**
 * oldApkPath: 老安装包路径
 * newApkPath: 新安装包路径(输出)
 * patchPath: 升级/差分包路径
 * return: 成功返回true,否则为false。
 */
BigNews.make(oldApkPath, newApkPath, patchPath);

还有一个第三方库:https://github.com/jiyouliang2/SmartUpdateDemo

1. 在project的build.gradle添加如下代码(如下图)

allprojects {repositories {maven { url "https://jitpack.io" }}
}

2. 在Module的build.gradle添加依赖(如下图)

compile 'com.github.jiyouliang2:SmartUpdateDemo:1.0.1'

3.添加权限

 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

4.代码中使用

 PatchUtil.patch(旧版本, 新版本, 差分包);

Android--增量更新相关推荐

  1. android cpp做成so库,Android增量更新(二)—制作合成文件so库

    ###前言 在上节中,我们已经学习了`Android增量更新`的实现原理,那么在Android开发的移动端,我们需要涉及到的其实是`文件合成`的这个流程. 那么,今天就来讲讲增量更新合成流程的实现吧. ...

  2. Android 增量更新实现

    如果app依赖本地更新,更新比较频繁的话,每次更新都要让用户下载完整安装包,用户体验会比较差.目前,很多应用商店都实现了apk的增量更新 正常apk更新逻辑: 打包V1.0版本,大小30M,用户安装完 ...

  3. Android增量更新框架

    Android增量更新框架 框架介绍 功能简介 简易效果图 增量更新配置 快速使用 Api详解 项目地址 框架介绍 功能简介 Android App更新框架,包含增量更新.多线程下载等功能.一句代码链 ...

  4. android中热更新模式,热更新再牛,也少不了Android 增量更新

    码个蛋(codeegg)第 785 次推文 作者: C_YQ 原文: https://juejin.im/post/5da845cdf265da5b7244c63e 码妞看世界 接骨草~ 虽然没有增量 ...

  5. Android 增量更新实例(Smart App Updates)

    http://892848153.iteye.com/blog/2022851 转自:http://my.oschina.net/liucundong/blog/160436 目录[-] 官方说明 实 ...

  6. Android增量更新——bsdiffbspatch

    原址 现在公司对于app增量更新的需求越来越多,因为增量更新不仅仅可以节省流量,更重要的一点是减少用户更新app的时间,有益于用户体验.    这篇文章将介绍运用patch差分包的形式实现增量更新.为 ...

  7. Android 增量更新

    随着社会的发展,虽然对于一个用户而言,流量不值钱,每个用户的手机会有多少个G的流量,或者不限制流量,或者经常使用wifi.所以目前在Android端流量的优化,可能没有那么重要了.但是当我们的用户更新 ...

  8. android增量更新详细解读

    1 增量更新的意义 a 神马是增量更新? 这个概念很早就被提出,但是目前的形式,小厂用的很少,大厂用的比较多:企鹅的QQ和微信里面都有增量更新着玩意:到底神马是增量更新? 首先增量更新主要用于新版本a ...

  9. Android 增量更新完全解析 是增量不是热修复

    本文在我的微信公众号:鸿洋(hongyangAndroid)首发. 转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/5276165 ...

  10. android差分升级原理,BigNews Android 增量更新框架差分包升级 @codeKK c开源站

    支持增量包/差分包/升级包 原理:在服务器端使用 bsdiff 工具将新老安装包的差异打包为一个体积较小的差分包/升级包,然后在 App 端通过 bspatch 工具(和 bsdiff 配套的)用差分 ...

最新文章

  1. Android编程 系统资源的介绍
  2. 计算机制作印章,制作印章软件【处理办法】
  3. CentOS-创建yum本地源
  4. arch模型的思路_ARCH模型
  5. 让机器学会看图说话:Image Caption任务最新综述
  6. Resize源码详解(参考Opencv4.1)
  7. C# 简单日志文本输出
  8. 华为服务器虚拟化概念,华为服务器虚拟化助力IT信息化建设
  9. HashMap的key可以是可变的对象吗???
  10. 微分算子求解微分方程
  11. 洞态IAST源码分析及吐槽
  12. centos 7.6 安装mariadb
  13. 趣学python编程下载_父与子的程序编写之旅:与小卡特一起学PythonPDF高清完整版一键下载|百度云盘...
  14. 制造上云 佛山南海携手阿里云建创新中心
  15. Springboot中国古代史在线学习网站 毕业设计-附源码260839
  16. java空气质量指数AQI算法
  17. 商品绑定可用的优惠券(多对多的绑定且一张优惠券只能使用于一个商品)
  18. CSMA/CD 协议 详解
  19. python 基本知识总结1
  20. crash工具使用方法

热门文章

  1. 当下阶段,很多人对于区块链的认识依然是不全面的
  2. “查看更多”与“隐藏”
  3. MySQL模拟题及参考答案
  4. Predicting Sharp and Accurate Occlusion Boundaries in Monocular Depth Estimation Using Displacement
  5. 团队作业——项目验收与总结博客(麻瓜制造者)
  6. js对象数组根据某一属性查找对象
  7. 计算WPL·哈夫曼树构建及带权路径长计算
  8. 毕业设计-基于机器视觉的指针式仪表读数自动识别研究与实现
  9. 8.1 正弦波振荡电路(2)
  10. 解决:Xvfb 缺少cyrillic 100dpi 75dpi 100dpi 75dpi