首先我们需要了解什么是增量更新,增量更新通俗点说就是客户端只需要下载新版本与旧版本的差分包,客户端再把差分包与旧版本进行合成得到一个新apk,在安装这个新的apk,这个新的apk其实新版本,实现更新,注意增量更新与热修复的区别。
原理大家可以查看:详情请见这篇文章Android 增量更新完全解析 是增量不是热修复
我们需要了解ndk,jni,以及.so如何生成,下面是我们windows的准备过程
1.下载bsdiff
下载地址:http://www.daemonology.net/bsdiff/bsdiff-4.3.tar.gz
这里需要说明这个包中文件是做什么的:bsdiff.c和bspatch.c都是c文件,bsdiff.c是生成差分包所需要的调用的c文件,bspatch.c是差分包和旧的apk合成所需要的调用的c文件。
我们下载bsdiff这个文件可以制作bsdiff和bspatch这两个工具,bsdiff这个工具是制作差分包的,bspatch这个工具是把差分包和旧的apk合成得到新apk的(这个合成的新的apk其实就是我们服务器的新apk)
在这里我们不用制作有现成的,这是下载windows版本中这两个文件的地址http://download.csdn.net/detail/z191726501/9651809(在网上找到的,博文地址为http://blog.csdn.net/z191726501/article/details/52802104)。
2.下载bzip2这个文件
下载地址:http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz,这个文件其实就是压缩使用的。
准备工作做完了我们就可以开始了。
首先你可以按照我的步骤开始简单的感受下效果:
1.准备两个apk,当然是用一个项目下的。一个old.apk,一个是在旧的apk下修改代码生成新的new.apk;
2.下载上文提到的bsdiff和bspatch这两个工具的地址,并解压;
3.把old.apk和new.apk放到bsdiff和bspatch这两个工具的目录中,打开cmd命令行,进入该目录;
3.cmd命令行中生成old.apk和new.apk的增量文件old-to-new.patch,命令为“bsdiff old.apk new.apk old-to-new.patch”;
4.cmd命令行中使用增量文件old-to-new.patch和old.apk合并成新的new2.apk,命令为“bspathc old.apk new2.apk old-to-new.patch”。,这时候生成一个新的apk,运行这个新的apk,是不是和我们new.apk功能是一样的
下面我们讲怎么在项目中使用:
第一:生成.so 文件
1.配置ndk环境,网上很多资料
2.在bzip2文件中,将其中的.h和.c文件提取出来,然后可以选择连文件夹(其实这个文件夹就是提取出来的只有.h和.c的文件夹)copy到我们module的app/main/jni下。
3.解压下载的bsdiff,将其中的bspatch.c也copy到我们module的app/main/jni下。
4.在app.gradle中,defaultConfig目录下加
ndk {
moduleName = 'bsdiff'
}
5.建一个新类BsPatch,注意System.loadLibrary(“bsdiff”)中的bsdiff与上一步中的moduleName中的值bsdiff一样
public class BsPatch {
static {
System.loadLibrary("bsdiff");
}
public static native int bspatch(String oldApk, String newApk, String patch);
}
6.生成BsPatch这个类的头文件,网上很多资料,例如在Terminal中,切换到项目java目录下执行“javah -jni 包名.类名”,如下图:
7.在bspatch.c中修改
#include <bzlib.h>为 #include "bzip2/bzlib.h",并且在bspatch.c引入头文件#include "com_example_ceshi_myapplication_BsPatch_bspatch.h"
8.在bspatch.c中加如下代码,并且把bspatch.c中的main方法改为patchMethod(只是修改名字),Java_com_example_ceshi_myapplication_BsPatch_bspatch这个方法就是头文件中的函数方法
JNIEXPORT jint JNICALL Java_com_example_ceshi_myapplication_BsPatch_bspatch
(JNIEnv *env, jclass cls,
jstring old, jstring new, jstring patch){
int argc = 4;
char * argv[argc];
argv[0] = "bspatch";
argv[1] = (char*) ((*env)->GetStringUTFChars(env, old, 0));
argv[2] = (char*) ((*env)->GetStringUTFChars(env, new, 0));
argv[3] = (char*) ((*env)->GetStringUTFChars(env, patch, 0));
int ret = patchMethod(argc, argv);
(*env)->ReleaseStringUTFChars(env, old, argv[1]);
(*env)->ReleaseStringUTFChars(env, new, argv[2]);
(*env)->ReleaseStringUTFChars(env, patch, argv[3]);
return ret;
}
9.build中,Rebuild Project ,app\build\intermediates\ndk\debug\lib中可以看到生成的.so文件
10.我们现在就可以使用这个.so文件,这个.so文件就是bspatch.c的.so文件,我们在使用时一定要注意调用.so文件时的包名
**有两种方法生产.so,第一种是利用mk,第二种是利用ndk
mk编译需要写android.mk和application.mk以及在gradle中配置输出路径,如果不配置输出路径则在debug中,但是ndk只需要在gradle中写ndk的配置,输出在debug中**
第二步:新建项目使用.so文件
1.注意是新建项目,当然在上面使用的项目中也可以使用,只不过为了区分如何生成.so和使用.so文件,在AndroidMainfest.xml中加入权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
2.新建ApkExtract类:
public class ApkExtract {
public static String extract(Context context) {
context = context.getApplicationContext();
ApplicationInfo applicationInfo = context.getApplicationInfo();
String apkPath = applicationInfo.sourceDir;
return apkPath;
}
public static void install(Context context, String apkPath) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setDataAndType(Uri.fromFile(new File(apkPath)),
"application/vnd.android.package-archive");
context.startActivity(i);
android.os.Process.killProcess(android.os.Process.myPid());
}
}
3.在MainActivity中:调用doBspatch的方法
private void doBspatch() {
final File destApk = new File(Environment.getExternalStorageDirectory(), "dest.apk");
final File patch = new File(Environment.getExternalStorageDirectory(), "PATCH.patch");
BsPatch.bspatch(ApkExtract.extract(this),
destApk.getAbsolutePath(),
patch.getAbsolutePath());
if (destApk.exists())
ApkExtract.install(this, destApk.getAbsolutePath());
}
4.新建BsPatch类
public class BsPatch {
static {
System.loadLibrary("bsdiff");
}
public static native int bspatch(String oldApk, String newApk, String patch);
}
5.使用windows下bsdiff和bspatch的工具(http://download.csdn.net/detail/z191726501/9651809,上文中提到的),cmd命令行中生成old.apk和new.apk的增量文件old-to-new.patch,命令为“bsdiff old.apk new.apk old-to-new.patch”,得到差分包,把差分包放到手机sd卡根目录
6.运行当前apk得到old.apk,修改代码运行得到new.apk,记住old.apk和新apk的效果区别,然后手机装old.apk,将生成的patch差分包放入手机sd卡根目录,old.apk调用doBspatch()方法就可以看到效果了