最近项目中要使用增量更新去下载更新我们app内部的H5离线资源包,现把遇到的问题总结一下
用到的库
都要科学上网
- bsdiff 第一次进入官网感觉很懵逼,没找到download的字眼,不要急,慢慢往下找,倒数第五行有个“here”的链接,点它就能下载了
- bzip2 这个要去sourceforge网站里面搜索bzip2这个库,才能下载
环境配置
Android Studio加入NDK
已经加过的请忽略,步骤:Preferences -> Android SDK -> SDK Tools
首先找右下角:
- Show Package Details
再勾选以下几个:
- CMake (选择3.6版本的)
- LLDB (选择3.1版本)
- NDK
哦了选好之后直接Apply就行了。
测试NDK环境是否配置好了
可以新建一个project,勾选Include C++ support
,然后看能不能run起来。
引入bspatch库
为啥只要bspatch,因为增量更新的patch包是在服务端生成的,我们客户端只需下载到对应的增量patch包,调用bspatch命令生成最新版的文件就行了。
1.在项目的src/main目录下新建cpp目录,把第一步下载的文件拷贝进去,最终的目录结构如下:
第一步下载的文件是整个项目的代码库,里面很多东西用不到,整理好的代码文件在这里:cpp.zip
添加CMakeLists.txt
这个是配置我们上一步加入的C代码目录的文件,文件内容如下:
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
native-lib
SHARED
src/main/cpp/bspatch.c
src/main/cpp/bsdiff.c
src/main/cpp/bs.c
src/main/cpp/bzip2/blocksort.c
src/main/cpp/bzip2/bzip2.c
src/main/cpp/bzip2/bzip2recover.c
src/main/cpp/bzip2/bzlib.c
src/main/cpp/bzip2/compress.c
src/main/cpp/bzip2/crctable.c
src/main/cpp/bzip2/decompress.c
src/main/cpp/bzip2/huffman.c
src/main/cpp/bzip2/randtable.c
)
find_library(
log-lib
log )
target_link_libraries(
native-lib
${log-lib} )
native-lib
是用来指定jni library的名称,随便写,只要保持调用的时候统一就行了。
然后修改module的build.gradle文件:
android {
compileSdkVersion Integer.valueOf(compile_sdk_version)
buildToolsVersion build_tool_version
defaultConfig {
minSdkVersion Integer.valueOf(min_sdk_version)
targetSdkVersion Integer.valueOf(target_sdk_version)
// 注意
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
}
}
}
lintOptions {
abortOnError false
}
// 注意
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
两个标注“注意”的地方记得加上就行啦。
添加java代码
在Android工程中添加调用jni的代码,随便写哪都行,看自己的需求,我是新建了一个类,代码如下:
public class H5ResourcePatch {
private static H5ResourcePatch INSTANCE = new H5ResourcePatch();
private H5ResourcePatch() {
}
static {
System.loadLibrary("native-lib");
}
public static H5ResourcePatch getINSTANCE() {
return INSTANCE;
}
/**
* 合并旧文件与patch文件,生成新版文件
* @param oldFile 老文件路径
* @param newFile 新文件路径
* @param patch patch文件路径
* @return 0:合并成功,其他:失败
*/
public native int patch(String oldFile, String newFile, String patch);
}
注意loadLibrary方法传递的参数,要跟你CMakeLists.txt中的命名一致。
然后就是patch方法,这时候会报错,因为我们没有实现对应的c代码,接下来往下看。
编写bs.c bs.h文件
在cpp目录下新建bs.h
文件:
#ifndef BSDIFFPATCH_BS_H
#define BSDIFFPATCH_BS_H
#endif //BSDIFFPATCH_BS_H
#include <malloc.h>
#include <jni.h>
int myPatch(int argc, char **argv);
JNIEXPORT jint JNICALL
Java_cn_blackfish_android_hybrid_bspatch_H5ResourcePatch_patch
(JNIEnv *env, jobject instance, jstring oldpath_, jstring newpath_,jstring patch_);
Java_cn_blackfish_android_hybrid_bspatch_H5ResourcePatch_patch
这一大长串就对应了刚才报错的patch方法,如何写呢?回到你的patch方法,右键点击,有个copy reference,复制过来把.
都换成_
就行啦。
bs.c文件是我们头文件的方法实现:
#include "bs.h"
JNIEXPORT jint JNICALL
Java_cn_blackfish_android_hybrid_bspatch_H5ResourcePatch_patch
(JNIEnv *env, jobject instance, jstring oldpath_, jstring newpath_,jstring patch_) {
const char* argv[4];
argv[0] = "bspatch";
argv[1] = (*env)->GetStringUTFChars(env,oldpath_, 0);
argv[2] = (*env)->GetStringUTFChars(env,newpath_, 0);
argv[3] = (*env)->GetStringUTFChars(env, patch_, 0);
myPatch(4, (char **) argv);
(*env)->ReleaseStringUTFChars(env,oldpath_, argv[1]);
(*env)->ReleaseStringUTFChars(env,newpath_, argv[2]);
(*env)->ReleaseStringUTFChars(env,patch_,argv[3]);
return 0;
}
最后一步,很重要
打开bspatch.c
代码文件,找到里面的main()
方法,修改为myPatch
,名字随意改,只要根你bs.c
文件中调用一致就行了。
至此,环境配置工作就全部完成了,sync一下,跑个demo试试吧,不过不要高兴的太早,编译过程中肯定会遇到N多问题,我也一样,但是基本上都能在网上搜索到,如果某个问题卡住你太久,那请留言,我们一起看下,希望对你有所帮助,有问题请不吝指正!共同努力进步~
qq:294958260,或者微信:bayin3698