Android App增量更新详解及实例代码

Android App增量更新实例--Smart App Updates

       介绍

  你所看到的,是一个用于Android应用程序增量更新的开源库。

  包括客户端、服务端两部分代码。

  原理

  自从 Android 4.1 开始,Google引入了应用程序的增量更新。

  Link: http://developer.android.com/about/versions/jelly-bean.html

Smart app updates is a new feature of Google Play that introduces a better way of delivering app updates to devices. When developers publish an update, Google Play now delivers only the bits that have changed to devices, rather than the entire APK. This makes the updates much lighter-weight in most cases, so they are faster to download, save the device's battery, and conserve bandwidth usage on users' mobile data plan. On average, a smart app update is about 1/3 the sizeof a full APK update.

  增量更新的原理非常简单,就是将手机上已安装apk与服务器端最新apk进行二进制对比,并得到差分包,用户更新程序时,只需要下载差分包,并在本地使用差分包与已安装apk,合成新版apk。

  例如,当前手机中已安装微博V1,大小为12.8MB,现在微博发布了最新版V2,大小为15.4MB,我们对两个版本的apk文件查分比对之后,发现差异只有3M,那么用户就只需要要下载一个3M的差分包,使用旧版apk与这个差分包,合成得到一个新版本apk,提醒用户安装即可,不需要整包下载15.4M的微博V2版apk。

  apk文件的差分、合成,可以通过开源的二进制比较工具bsdiff来实现(Link:http://www.daemonology.net/bsdiff/)

  因为bsdiff依赖bzip2,所以我们还需要用到bzip2(Link:http://www.bzip.org/downloads.html)

  bsdiff中,bsdiff.c用于生成查分包,bspatch.c用于合成文件。

  接下来,我们分开说,需要做3件事。

  1.在服务器端,生成这两个版本微博的差分包;

  2.在手机客户端,使用已安装的旧版apk与这个差分包,合成为一个新版微博apk;

  3.校验新合成的微博客户端文件是否完成,签名时候和已安装客户端一致,如一致,提示用户安装。

  过程分析

  1 生成差分包

  这一步需要在服务器端来实现,一般来说,每当apk有新版本需要提示用户升级,都需要运营人员在后台管理端上传新apk,上传时就应该由程序生成之前所有旧版本们与最新版的差分包。

  例如: 你的apk已经发布了3个版,V1.0、V2.0、V3.0,这时候你要在后台发布V4.0,那么,当你在服务器上传最新的V4.0包时,服务器端就应该立即生成以下差分包:

  V1.0 ——> V4.0的差分包;

  V2.0 ——> V4.0的差分包;

  V3.0 ——> V4.0的差分包;

  ApkPatchLibraryServer工程即为Java语言实现的服务器端查分程序。

  下面对ApkPatchLibraryServer做一些简单说明:

  1.1 C部分

  ApkPatchLibraryServer/jni 中,除了以下4个:

  com_cundong_utils_DiffUtils.c com_cundong_utils_DiffUtils.h com_cundong_utils_PatchUtils.c com_cundong_utils_PatchUtils.h

  全部来自bzip。

  com_cundong_utils_DiffUtils.c com_cundong_utils_DiffUtils.h

  用于生成差分包。

  com_cundong_utils_PatchUtils.c com_cundong_utils_PatchUtils.h

  用于合成新apk文件。

  其中,com_cundong_utils_DiffUtils.c修改自 bsdiff/bsdiff.c,com_cundong_utils_PatchUtils.c修改自bsdiff/bspatch.c。

  我们在需要将jni中的C文件,build输出为动态链接库,以供Java调用(Window环境下生成的文件名为libApkPatchLibraryServer.dll,Unix-like系统下为libApkPatchLibraryServer.so,OSX下为libApkPatchLibraryServer.dylib)。

  Build成功后,将该动态链接库文件,加入环境变量,供Java语言调用。

  1.2 Java部分

  com.cundong.utils包,为调用C语言的Java实现; com.cundong.apkdiff包,为apk查分程序的Demo; com.cundong.apkpatch包,为apk合并程序的Demo;

  调用com.cundong.utils.DiffUtils中genDiff()方法,可以通过传入的新旧apk路径,得到差分包。

Java代码

/**
 * 类说明:   apk diff 工具类
 *
 * @author Cundong
 * @date  2013-9-6
 * @version 1.0
 */
public class DiffUtils { 

  /**
   * 本地方法 比较路径为oldPath的apk与newPath的apk之间差异,并生成patch包,存储于patchPath
   *
   * @param oldPath
   * @param newPath
   * @param patchPath
   * @return
   */
  public static native int genDiff(String oldApkPath, String newApkPath, String patchPath);
}

  调用com.cundong.utils.PatchUtils中patch()方法,可以通过旧apk与差分包,合成为新apk。

Java代码

/**
 * 类说明:  APK Patch工具类
 *
 * @author Cundong
 * @date  2013-9-6
 * @version 1.0
 */
public class PatchUtils { 

  /**
   * native方法
   * 使用路径为oldApkPath的apk与路径为patchPath的补丁包,合成新的apk,并存储于newApkPath
   * @param oldApkPath
   * @param newApkPath
   * @param patchPath
   * @return
   */
  public static native int patch(String oldApkPath, String newApkPath,
      String patchPath);
}

  2.使用旧版apk与差分包,在客户端合成新apk

  需要在手机客户端实现,ApkPatchLibrary工程封装了这个过程。

  2.1 C部分

  ApkPatchLibrary/jni/bzip2目录中所有文件都来自bzip2项目。

  ApkPatchLibrary/jni/com_cundong_utils_PatchUtils.c、ApkPatchLibrary/jni/com_cundong_utils_PatchUtils.c实现文件的合并过程,其中com_cundong_utils_PatchUtils.c修改自bsdiff/bspatch.c。

  我们需要用NDK编译出一个libApkPatchLibrary.so文件,生成的so文件位于libs/armeabi/ 下,其他 Android 工程便可以使用该libApkPatchLibrary.so文件来合成apk。

  2.2 Java部分

  com.cundong.utils包,为调用C语言的Java实现;

  调用,com.cundong.utils.PatchUtils中patch()方法,可以通过旧apk与差分包,合成为新apk。

Java代码

/**
 * 类说明:  APK Patch工具类
 *
 * @author Cundong
 * @date  2013-9-6
 * @version 1.0
 */
public class PatchUtils { 

  /**
   * native方法
   * 使用路径为oldApkPath的apk与路径为patchPath的补丁包,合成新的apk,并存储于newApkPath
   * @param oldApkPath
   * @param newApkPath
   * @param patchPath
   * @return
   */
  public static native int patch(String oldApkPath, String newApkPath,
      String patchPath);
}

  3.校验新合成的apk文件

  新包和成之后,还需要对客户端合成的apk包与最新版本apk包进行MD5或SHA1校验,如果校验码不一致,说明合成过程有问题,新合成的包将不能被安装。

  注意事项

  增量更新的前提条件,是在手机客户端能让我们读取到当前应用程序安装后的源apk,如果获取不到源apk,那么就无法进行增量更新了。

  另外,如果你的应用程序不是很大,比如只有2、3M,那么完全没有必要使用增量更新,增量更新适用于apk包比较大的情况,比如游戏客户端。

  GitHub地址

  GitHub:https://github.com/cundong/SmartAppUpdates

  一些说明

  源码中,包含以下文件:

  1.ApkPatchLibraryServer:Java语言实现的,服务器端生成差分包工程;

  2.ApkPatchLibrary:客户端使用的apk合成库;

  3.ApkPatchLibraryDemo:引用ApkPatchLibrary Library 的Demo,以新浪微博客户端的升级为例,假设手机上安装的是V4.5.0,最新版是V4.5.5,用户需要从V4.5.0升级到V4.5.5。

  4.TestApk:用于测试的,旧版本的微博客户端,以及使用ApkPatchLibraryServer生成的新旧新浪微博差分包。

通过此文,希望能帮助到有需要的朋友,谢谢大家对本站的支持!

(0)

相关推荐

  • Android应用强制更新APP的示例代码

    Android应用强制更新的用途十分广泛,特别上刚上线的应用肯定会存在或多或少的bug,特别是涉及移动支付这一块的内容,如果出错了会造成比较大的损失,所以强制更新显得尤为重要. 一般来说,强制更新的策略就是: 应用启动时请求后台,后台发送应用最新版本的信息(包括应用版本号.名称.更新内容说明.下载包的服务器地址.是否强制更新的标志位)等等. 下面我们就将根据以上思路来写实现代码. 1.AndroidManifest配置版本信息 在AndroidManifest.xml里定义了每个Android

  • Android App实现应用内部自动更新的最基本方法示例

    这只是初步的实现,并没有加入自动编译等功能.需要手动更改更新的xml文件和最新的apk.    共涉及到四个文件! 一.客户端 AndroidUpdateTestActivity:程序首页 main.xml:首页布局 Update:更新类 softupdate_progress:更新等待界面 Updage package majier.test; import java.io.File; import java.io.FileOutputStream; import java.io.IOExce

  • Android如何实现APP自动更新

    先来看看要实现的效果图: 对于安卓用户来说,手机应用市场说满天飞可是一点都不夸张,比如小米,魅族,百度,360,机锋,应用宝等等,当我们想上线一款新版本APP时,先不说渠道打包的麻烦,单纯指上传APP到各大应用市场的工作量就已经很大了,好不容易我们把APP都上传完了,突然发现一个会导致应用闪退的小Bug,这时那个崩溃啊,明明不是很大的改动,难道我们还要再去重新去把各大应用市场的版本再上传更新一次?相信我,运营人员肯定会弄死你的!! 有问题,自然就会有解决问题的方案,因此我们就会想到如果在APP里

  • Android-App增量更新的使用姿势

    简述 增量更新,根据字面理解,就是下载增加的那部分来达到更新的目的,实际就是这个意思. 原理 用一个旧的Apk安装与一个新的Apk安装包使用 bsdiff工具 ,执行命令生成一个差异文件,此差异文件就是我们修改需要更新下载的那部分. 引入代码及so文件 首先,根据你的系统的架构选择不同的so文件放到你的工程中 接着,需要把加载so文件的Java类引入到你的工程中,引入时,需注意,不能修改这个类的包名. 到此,增量更新引入完成. 使用 下载bsdiff工具,然后执行命令:bsdiff,会显示出命令

  • android实现通知栏下载更新app示例

    1.设计思路,使用VersionCode定义为版本升级参数.android为我们定义版本提供了2个属性: 复制代码 代码如下: <manifest package="com.cnblogs.tianxia.subway"android:versionCode="1" <!--Integer类型,系统不显示给用户-->android:versionName="1.0"<!--String类型,系统显示用户-->>

  • Android应用App更新实例详解

    前言:现在一般的Android软件都是需要不断更新的,当你打开某个app的时候,如果有新的版本,它会提示你有新版本需要更新.该项目实现的就是这个功能.并且有强制更新和更新提示两种方式,当有更新时,会弹出一个提示框,点击下载,则在通知来创建一个进度条进行下载,点击取消,则取消更新. 效果: 开发环境:AndroidStudio2.1.2+gradle-2.10 部分代码: public class UpdateVersionController { private Context context;

  • Android应用APP自动更新功能的代码实现

    由于Android项目开源所致,市面上出现了N多安卓软件市场.为了让我们开发的软件有更多的用户使用,我们需要向N多市场发布,软件升级后,我们也必须到安卓市场上进行更新,给我们增加了工作量.因此我们有必要给我们的Android应用增加自动更新的功能. 既然实现自动更新,我们首先必须让我们的应用知道是否存在新版本的软件,因此我们可以在自己的网站上放置配置文件,存放软件的版本信息: <update> <version>2</version> <name>baidu

  • Android App增量更新详解及实例代码

    Android App增量更新实例--Smart App Updates        介绍 你所看到的,是一个用于Android应用程序增量更新的开源库. 包括客户端.服务端两部分代码. 原理 自从 Android 4.1 开始,Google引入了应用程序的增量更新. Link: http://developer.android.com/about/versions/jelly-bean.html Smart app updates is a new feature of Google Pla

  • Android UI 实现老虎机详解及实例代码

    Android UI 实现老虎机详解 listview 的使用步骤 简单的listview老虎机实现 1.实现效果图 2.需要掌握的知识 listview的使用步骤 listview的Adapter接口的实现 listview中的MVC 3.知识详解 ListView 是一个控件,一个在垂直滚动的列表中显示条目的一个控件,这些条目的内容来自于一个ListAdapter .EditText Button TextView ImageView Checkbox 五大布局. 1.布局添加Listvie

  • Android json数据解析详解及实例代码

     Android json数据解析详解 移动开发经常要与服务器数据交互,也常使用json数据格式,那就说说Android json解析. 1.最简单json格式解析如下: //解析json ry { JSONTokener jsonParser = new JSONTokener(strResult); JSONObject jsonObj = (JSONObject) jsonParser.nextValue(); String strsportsTitle = jsonObj.getStri

  • Android 轻松实现语音识别详解及实例代码

    使用Intent调用语音识别程序 说明 Android中主要通过RecognizerIntent来实现语音识别,其实代码比较简单,但是如果找不到语音识别设备,就会抛出异常 ActivityNotFoundException,所以我们需要捕捉这个异常.而且语音识别在模拟器上是无法测试的,因为语音识别是访问google 云端数据,所以如果手机的网络没有开启,就无法实现识别声音的!一定要开启手机的网络,如果手机不存在语音识别功能的话,也是无法启用识别! 注意:使用前需要安装语音识别程序.如<语音搜索>

  • Android listview与adapter详解及实例代码

    一个ListView通常有两个职责. (1)将数据填充到布局. (2)处理用户的选择点击等操作. 第一点很好理解,ListView就是实现这个功能的.第二点也不难做到,在后面的学习中读者会发现,这非常简单. 一个ListView的创建需要3个元素. (1)ListView中的每一列的View. (2)填入View的数据或者图片等. (3)连接数据与ListView的适配器. 也就是说,要使用ListView,首先要了解什么是适配器.适配器是一个连接数据和AdapterView(ListView就

  • Android 自定义gradle property详解及实例代码

    Android 自定义gradle property 在Android studio上运行项目,gradle的配置是必不可少的,但是随着项目的逐渐成长,迎面而来的就是.各种依赖包的添加,数不胜数的签名,渠道包等,整个gradle变得很乱,这样其实我们可以将gradle的部分内容分离出来放在另一个自定义gradle内. 如这时我们添加的Plugin 就只要对其赋值就可以了. 步骤: 在总项目根目录下创建 dependencies.gradle文件(名字可以自定义) 根目录下创建的自定义内容如下:

  • Android Spinner与适配器模式详解及实例代码

    最近做项目对Android Spinner 使用,这里简单写个小例子,来测试如何使用. Spinner 是一个下拉列表,往安卓界面中拖拽一个Spinner控件,在属性中设置Android:entries="@array/spinner_data" 其中spinner_data为在string中设置的数组.数组中由固定写好的值.此时便可在界面设置好下拉列表. <Spinner android:id="@+id/spinner1" android:layout_w

  • Android 消息队列模型详解及实例

    Android 消息队列模型详解及实例 Android系统的消息队列和消息循环都是针对具体线程的,一个线程可以存在(当然也可以不存在)一个消息队列(Message Queue)和一个消息循环(Looper).Android中除了UI线程(主线程),创建的工作线程默认是没有消息循环和消息队列的.如果想让该线程具有消息队列和消息循环,并具有消息处理机制,就需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环.如以下代码所示: class

  • Android Tab 控件详解及实例

    Android Tab 控件详解及实例 在桌面应用中Tab控件使用得非常普遍,那么我们经常在Android中也见到以Tab进行布局的客户端.那么Android中的Tab是如何使用的呢? 1.Activity package com.wicresoft.activity; import com.wicresoft.myandroid.R; import android.app.TabActivity; import android.os.Bundle; import android.util.Lo

  • Android canvas drawBitmap方法详解及实例

     Android canvas drawBitmap方法详解及实例 之前自己在自定义view,用到canvas.drawBitmap(Bitmap, SrcRect, DesRect, Paint)的时候,对其中的第2和3个参数的含义含糊不清.看源码函数也没理解,然后看了一些其他的博客加上自己的理解,整理如下.首先,我们看一张图片,今天就要绘制这张图片. 然后将图片用红色的线条分成4个部分,如下: 我们自定义一个View,代码如下: public class PoterDuffLoadingVi

随机推荐