最近看了安卓增量更新的文章,自己尝试了下,无奈自己用的windows的系统,出现了各种问题,经过查资料,终于成功,现在总结下并分享下经验。(参考鸿洋的增量更新博客)
首先我们配置下NDK的环境,配置好的同学请下翻
public class IncrementalUpdate extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView content=new TextView(this);
content.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doBspatch();
}
});
content.setText(R.string.incrementalupdate);
setContentView(content);
}
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());
}
}
上文中BsPatch类是调用NDK的,ApkExtract类是安装应用的,贴代码
BsPatch.java类
public class BsPatch {
static {
System.loadLibrary("bsdiff");
}
public static native int bspatch(String oldApk, String newApk, String patch);
}
ApkExtract.java类
public class ApkExtract {
public static String extract(Context context) {
context = context.getApplicationContext();
ApplicationInfo applicationInfo = context.getApplicationInfo();
String apkPath = applicationInfo.sourceDir;
Log.d("hongyang", apkPath);
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);
}
}
创建JNI文件夹
头文件我们是有了,然后我们在项目的main文件夹下创建一个文件夹,命名为jni
将刚才的头文件拷贝到该目录下面
JNI编写前的准备(bsdiff和bzip2)
在编写C代码前,我们先要下载两个文件,一个是bsdiff,一个bzip2,注意,这两个文件是linux上的文件,将下载好的两个文件在ubuntu系统上提取出来,将bsdiff-4.3下的bspatch.c拷贝出来放到我们studio的jni目录下待用,然后在jni目录下建一个文件夹,命名为bzip2,然后再回到ubuntu系统将bzip2-1.0.5文件夹下的C文件(.c)和头文件(.h)提取出来,拷贝到我们刚才再studio上建好的bzip2的文件夹下,还是贴上图吧
ubuntu上文件体系
studio拷贝好的文件目录
- C代码的编写
准备工作就绪,下来我们就编写C代码,其实没啥编写的,我们打开bspatch.c,先给他加上
#include "jni.h"
#include "bzip2/bzlib.h"
#include "com_test_util_BsPatch.h"
第二步,复制下面的代码到bspatch.c
JNIEXPORT jint JNICALL Java_com_test_util_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;
}
第三步,保险起见,找到com_test_util_BsPatch.h,我的是这个哈,你们的就不一定了,就因为不一定,所以可能会错,复制BsPatch.h方法名替换上图中的方法的名字(Java_com_test_util_BsPatch_bspatch)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bzip2/blocksort.c \
bzip2/bzip2.c \
bzip2/bzip2recover.c \
bzip2/bzlib.c \
bzip2/compress.c \
bzip2/crctable.c \
bzip2/decompress.c \
bzip2/dlltest.c \
bzip2/huffman.c \
bzip2/mk251.c \
bzip2/randtable.c \
bzip2/spewG.c \
bzip2/unzcrash.c
LOCAL_LDLIBS := -lm -llog -ljnigraphics
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/bar
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := bsdiff
LOCAL_SRC_FILES := bspatch.c
LOCAL_LDLIBS := -lm -llog -ljnigraphics
LOCAL_SHARED_LIBRARIES := bar
include $(BUILD_SHARED_LIBRARY)
下面的是Application.mk的
APP_ABI := all
APP_PLATFORM:= android-19
APP_OPTIM := release
android.useDeprecatedNdk=true
so文件的位置
测试前准备
我们先回到ubuntu系统,将先前下载并提取的文件进行编译(编译命令请百度),编译好后,将上面studio的项目打包个APK,然后在项目基础上添加或修改一些东西(最好比较明显的体现增量更新成功,比如字体换个颜色)后,生成APK,将2个Apk放在ubuntu的同一个目录下,然后cd到该目录下执行以下命令
bsdiff old.apk new.apk old-to-new.patch
然后将old.apk和old-to-new.patch同时放在手机SD卡下,并安装old.apk,注意看activity的代码,你会发现要给这两个文件改下名字的old.apk–>dest.apk和old-to-new.patch–>PATCH.patch
运行触发代码自己看看效果吧!如果有问题,欢迎回复哈