Android之增量更新

    xiaoxiao2021-03-25  8

    Android之增量更新

    标签: 增量更新android源码工具 311人阅读 评论(0) 收藏 举报 本文章已收录于: 分类: Android技巧(18) 作者同类文章 X

    Android增量更新简单描述:

    简单的说,就是在有一个旧版本A的情况下,想在这个基础上更新一个新版本B。那么,我们不需要下载整个B,只需要下载A与B的差分包。将差分包下载到本地后,与旧版本A整合为一个新的apk,这个apk大小与内容与新版本B完全一致,这就是增量更新。

    假如,A的大小是5M,B的大小是8M,那么差分包的大小S=(8-5)+差异文件的依赖(如上下文)。差分包的大小会大于3M。

    Android增量更新如何实现:

    这里我们有用到一对工具,bsdiff.exe、bspatch.exe。可在后续的源码中下载。

    用工具,很容易达到这个效果,有两个步骤:

    假如,你将这对工具放置在如下路径下:D:\zhao.yang\Downloads\test_UpdateSome\test\bsdiff4.3-win32,那么,请先打开cmd,输入命令: cd D:\zhao.yang\Downloads\test_UpdateSome\test\bsdiff4.3-win32 ,按Enter后,再输入命令:cd d: ,进入该目录下。

    (1)新旧版本生成差分包

    命令格式:bsdiff.exe 旧版本apk路径  新版本apk路径 差分包存储路径 

    按这命令格式,我们写出如下命令:

    bsdiff.exe D:\Java\workspace\ApkPatchAndroidDemo\bin\ApkPatchAndroid_old.apk D:\JAVA\workspace\ApkPatchAndroidDemo\bin\ApkPatchAndroid_new.apk D:\JAVA\workspace\ApkPatchAndroidDemo\bin\test.patch

    即可得到相应的差分包test.patch。

    (2)整合差分包与旧版本apk

    命令格式:bspatch.exe 旧版本apk路径 新版本apk路径 差分包存储路径

    按这命令格式,我们写出如下命令:

    bspatch.exe D:\JAVA\workspace\ApkPatchAndroidDemo\bin\ApkPatchAndroid_old.apk D:\JAVA\workspace\ApkPatchAndroidDemo\bin\ApkPatchAndroid_2new.apk D:\JAVA\workspace\ApkPatchAndroidDemo\bin\test.patch

    经过以上两个步骤,我们完成了差分包生成,差分包与旧版本apk的整合,你会发现最后得到的apk就是你需要的apk。到这里,用工具演示的增量更新的步骤就完成了。但是,在android中,当你在做android的增量更新时,是需要源码实现的。

    下方就介绍如何实现:

    Android端整合差分包与旧版本apk的实现

    这里暂时将旧版本apk、差分包都放在SD卡的根目录下。

    这里引入了一位高手写的开源源码,引用JNI实现整合。在主界面上无需写什么代码,只要根据函数参数要求填入参数即可:

    [html] view plain copy print ? package com.example.apkpatch2newapk;      import java.io.File;    import com.dodola.patcher.utils.AppUtils;    import android.os.Bundle;  import android.os.Environment;  import android.app.Activity;  import android.view.Menu;  import android.view.View;  import android.view.View.OnClickListener;  import android.widget.Button;    public class MainActivity extends Activity {              String oldApkPathString=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator +"ApkPatchAndroid_old.apk";      String newApkPathString=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator +"ApkPatchAndOld2New.apk";      String patchPathString=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator +"test.patch";            static {          // 调用.so文件,引入打包库          System.loadLibrary("Patcher");      }        @Override      protected void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_main);          Button btnButton=(Button)findViewById(R.id.btn);          btnButton.setOnClickListener(new OnClickListener() {                            @Override              public void onClick(View v) {                  // TODO Auto-generated method stub                  AppUtils.patcher(oldApkPathString, newApkPathString, patchPathString);              }          });                }    }   package com.example.apkpatch2newapk; import java.io.File; import com.dodola.patcher.utils.AppUtils; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { String oldApkPathString=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator +"ApkPatchAndroid_old.apk"; String newApkPathString=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator +"ApkPatchAndOld2New.apk"; String patchPathString=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator +"test.patch"; static { // 调用.so文件,引入打包库 System.loadLibrary("Patcher"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btnButton=(Button)findViewById(R.id.btn); btnButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub AppUtils.patcher(oldApkPathString, newApkPathString, patchPathString); } }); } } 重点还在于patcher这个函数中。

    [html] view plain copy print ? package com.dodola.patcher.utils;    import java.io.File;    import android.content.Context;  import android.content.Intent;  import android.net.Uri;    /**   *应用程序的工具类   * @author Administrator   *   */  public class AppUtils {        /**       * 安装一个应用程序       * @param context       * @param apkfile       */      public static void installApplication(Context context,File apkfile){        /*   <action android:name="android.intent.action.VIEW" />           <category android:name="android.intent.category.DEFAULT" />           <data android:scheme="content" />           <data android:scheme="file" />           <data android:mimeType="application/vnd.android.package-archive" />*/          Intent intent = new Intent();          intent.setAction("android.intent.action.VIEW");          intent.addCategory("android.intent.category.DEFAULT");  //      intent.setType("application/vnd.android.package-archive");  //      intent.setData(Uri.fromFile(apkfile));          intent.setDataAndType(Uri.fromFile(apkfile), "application/vnd.android.package-archive");          context.startActivity(intent);      }            /**       * 调用.so库中的方法,合并apk       *        * @param old       *            旧Apk地址       * @param newapk       *            新apk地址(名字)       * @param patch       *            增量包地址       */      public static native void patcher(String old, String newapk, String patch);  }   package com.dodola.patcher.utils; import java.io.File; import android.content.Context; import android.content.Intent; import android.net.Uri; /** *应用程序的工具类 * @author Administrator * */ public class AppUtils { /** * 安装一个应用程序 * @param context * @param apkfile */ public static void installApplication(Context context,File apkfile){ /* <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="content" /> <data android:scheme="file" /> <data android:mimeType="application/vnd.android.package-archive" />*/ Intent intent = new Intent(); intent.setAction("android.intent.action.VIEW"); intent.addCategory("android.intent.category.DEFAULT"); // intent.setType("application/vnd.android.package-archive"); // intent.setData(Uri.fromFile(apkfile)); intent.setDataAndType(Uri.fromFile(apkfile), "application/vnd.android.package-archive"); context.startActivity(intent); } /** * 调用.so库中的方法,合并apk * * @param old * 旧Apk地址 * @param newapk * 新apk地址(名字) * @param patch * 增量包地址 */ public static native void patcher(String old, String newapk, String patch); } 整合的开源源码内容,主要是jni实现的c/c++代码,感兴趣的可以在下方的源码下载中看。

    注意:

    (1)不熟悉jni的同学,这里要注意一点,jni的方法与包名是相关的,因此如果想用这个方法,最方便的是把包名也一起复制过去即可。

    (2)该方法是需要用到NDK环境的,如果没有这个环境,可以到如下地址下载: NDK下载链接:http://pan.baidu.com/s/1bn0H75P 密码:6cje

    (3)可在Window-Preferences-NDK中配置下载的NDK。

    源码与工具下载:

    http://download.csdn.net/detail/yangzhaomuma/9448393

    NDK下载链接: http://pan.baidu.com/s/1bn0H75P  密码:6cje 顶 1 踩 0     上一篇Android进程间通讯——多进程共用SharedPreferences 下一篇Android监听——回调模式与观察者模式

    我的同类文章

    Android技巧(18) http://blog.csdn.net •Java(Android)回调函数详解2016-07-22阅读2783 •Android之本地缓存——LruCache(内存缓存)与DiskLruCache(硬盘缓存)统一框架2016-07-02阅读6511 •Android之注解的使用——绑定android控件2016-04-18阅读647 •Android监听——回调模式与观察者模式2016-03-24阅读1607 •Android图片处理之高斯模糊示例——仿微信朋友圈照片模糊效果2016-02-01阅读2734 •Android之数据库—— 一个可配置的简易框架2016-07-05阅读3194 •Android(Java)之多线程结果返回——Future 、FutureTask、Callable、Runnable2016-06-20阅读1094 •Android解析——json解析为javabean2016-03-28阅读1375 •Android进程间通讯——多进程共用SharedPreferences2016-02-22阅读1364 •Android远程接口之AIDL——Parcelable、in、out、inout简例2016-01-25阅读3351 更多文章
    转载请注明原文地址: https://ju.6miu.com/read-200258.html

    最新回复(0)