感觉还是有必要记一下。容易忘记的人。
增量更新不同于热修复,从字面意思就知道,他是在原有apk的基础上做一个增加的。常用于版本的迭代,他可以大大节省用户的流量。
and.....。
增量更新关键在于生成补丁包。(最难的这个已经有工具替我们实现了),然后就是将原来的apk和补丁包合成生成新的apk。
windows 系统下要获取bsdiff.exe 和bspatch.exe 还是比较麻烦的。(我是网上直接拿了两个已经生成好的可执行文件),当然生成补丁包还是放在服务端的,客户端要做的就是将服务端的补丁包下载下来,然后合成新的apk。
--------------------------------------------------分割----------------------------------------------------------
我这边就简单记入如何生成用于合成补丁的so 库。
1.studio 的ndk环境配置。(下载,配置环境变量)
2在 gradle.properties 中加入 android.useDeprecatedNdk=true
3.在新建的项目中新建一个包含native 方法的类。(build一下)
public class PatchUtils {
static {
System.loadLibrary("自定义库名");
}
public static native int patch(String oldApkPath, String newApkPath, String patchPath);
}
4.现在我们需要去生成一个.h文件,关联对应的native方法。(可以通过命令行,这边用另外一种)
在setting-->Tools-->External tool--> "+" 中配置两个命令。
5.1 javah($JdkPath$ 这个替代符可以在右侧insert macro... 进行选择。)
5.2 ndk-build 的配置
6 在main 目录下新建一个jni文件夹,然后右键含有native方法的类,选择External tool,执行javah命令(注意先Build),可以看到在jni 文件夹中生成了一个.h的头文件。
接下来就是合成,(合成的关键还是用到原来bsdiff 工具中的c代码)我们可以直接拷贝过来用。将其中bzip2文件夹拷贝到jni中,留下文件夹中的.c .h文件。
在拷贝bspatch.c,引入刚刚生成的.h文件并实现他的方法体。(将该c文件中的main方法修改为applypatch)。
JNIEXPORT jint JNICALL Java_com_yang_patchtest_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));
int ret = applypatch(4, ch);
(*env)->ReleaseStringUTFChars(env, old, ch[1]);
(*env)->ReleaseStringUTFChars(env, new, ch[2]);
(*env)->ReleaseStringUTFChars(env, patch, ch[3]);
return ret;
}
创建android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := patchLib
LOCAL_SRC_FILES := bspatch.c
include $(BUILD_SHARED_LIBRARY)
- 右键jni文件夹External tool 执行ndk-build 命令,可以看到在libs 中生成我们的so文件。而这些so库,即可用于我们客户端的补丁合成了。
至此so库已经生成,那么我删掉jni文件夹,便可以直接调用上面的native方法生成新的apk。
-----------------------------------------------分割----------------------------------------------------------
那假如我想把上面生成好的so 库用到其他的app中呢:
我直接引用so 库的话是不行的(当然要是包名、类名以及方法名都一样的话,就不说了)
这个过程和上面也是有点类似。
1 .前面5步骤都是一样的。
2 .将需要的 so 文件以及对应的.h文件(可有可无,只要知道方法名即可) 拷贝到jni下的新建patches文件夹下。
2 再新建一个.c文件。 调用的so 库中的方法
#include "patches/include/com_yang_patchtest_PatchUtils.h"
#include "com_yang_mypatch_PatchUtils.h"
JNIEXPORT jint JNICALL Java_com_yang_mypatch_PatchUtils_toPatch(JNIEnv *env,
jobject obj, jstring old, jstring new, jstring patch) {
return Java_com_yang_patchtest_PatchUtils_patch(env,obj,old,new,patch);
}
3 创建android.mk 和application.mk
android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := patchLib
LOCAL_SRC_FILES := patches/libpatchLib.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/patches/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := mypatches
LOCAL_SRC_FILES := mytest.c
LOCAL_SHARED_LIBRARIES := patchLib
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
application.mk
APP_STL:=gnustl_static
APP_CPPFLAGS:=-frtti -fexceptions
APP_ABI := armeabi
一般开发中只需要armeabi即可,当然上面的so 库也是armeabi的。
4.执行前面讲过的ndk-build 命令可以看到生成2 个so 库。
5.删掉jni文件夹,就可以直接使用so 了 (libs 要转到app 下一级,gradle 要指定jniLibs。android studio 默认是jniLibs)
关于mk文件的几个重要参数:
LOCAL_MODULE:模块名称。
LOCAL_SRC_FILES:参与编译的源文件
APP_ABI:cpu架构平台类型。