Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

移植linux x86 C库 到android arm平台【交叉编译实现应用增量更新】

$
0
0

     增量更新有区别于全量更新,当服务器有新版本时候,客户端上传自己的版本号到服务器,服务器根据该版本与最新版本的 apk 生成差分包,客户端下载差分包以后与手机上已经安装的旧版本做合并生成新版apk。这种更新方式最大限度的节省了用户流量与下载等待时间。用到的开源库是大名鼎鼎的bsdiff和bzlib,他们的原理后面会分析。下面介绍整个增量更新的实现过程:

1. linux上gcc编译 bsdiff ,用以生成服务器端的差分工具

   执行编译生成yzyBsdiff可执行文件(如果想生成so加--shared):    

   gcc -fPIC blocksort.c bsdiff.c bzip2.c bzip2recover.c  compress.c crctable.c decompress.c huffman.c  randtable.c spewG.c unzcrash.c  bzlib.c -o yzyBsdiff


遇到的问题

  • bsdiff.c:33:19: fatal error: bzlib.h: 没有那个文件或目录 #include <bzlib.h>                                改为"bzlib.h"
  • 不能有多个main方法,只能保留一个main(bsdiff.c里面的,其他的重命名),操作系统认为一个进程只能有为一个的main函数
  • 不能写两个相同的文件编译,会报重复定义
把Demo_version_1.apk  和 Demo_version_2.apk两个版本的apk用刚刚生成的yzyBsdiff做差分生成patch文件,
        
      ./yzyBsdiff app-debug_old.apk app-debug_new.apk app.patch

2. linux上通过NDK交叉编译得到android arm 的 bspatch.so用以在Android端做增量更新合并 

首先设置环境变量

 export NDKROOT=~/dev/android-ndk-r9c
 export SYSROOT=$NDKROOT/platforms/android-19/arch-arm
 export GCC=$NDKROOT/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-gc


编译生成可执行文件,保留main函数,为啥要加fPIC  !必须加,否则会报 magic 7F45(如果anroid NDK调用so的话这一步可以掠过)

$GCC -fPIC -o yzybsPatchArm bspatch.c bzip2/blocksort.c  bzip2/bzip2.c bzip2/bzip2recover.c bzip2/bzlib.c bzip2/compress.c bzip2/crctable.c bzip2/decompress.c bzip2/huffman.c bzip2/randtable.c bzip2/spewG.c bzip2/unzcrash.c --sysroot=$SYSROOT



编译生成so

第一步 生成.o文件

$GCC -fPIC -c  bspatch.c bzip2/blocksort.c  bzip2/bzip2.c bzip2/bzip2recover.c bzip2/bzlib.c bzip2/compress.c bzip2/crctable.c bzip2/decompress.c bzip2/huffman.c bzip2/randtable.c bzip2/spewG.c bzip2/unzcrash.c --sysroot=$SYSROOT



第二步 生成.so

$GCC -shared -Wl,-soname,libbspatchlib.so -o libbspatchlib.so blocksort.o   bspatch.o    bzip2.o  bzip2recover.o  bzlib.o  compress.o  crctable.o  decompress.o  huffman.o  randtable.o  spewG.o  unzcrash.o --sysroot=$SYSROOT


可以使用file命令查看生成的so是否正确

yzy@yzy-P5QL-PRO:~/dev/workspace/bspatch/diffPatch$ file libbspatchlib.so 
libbspatchlib.so: ELF 32-bit LSB  shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, not stripped


3. Android端集成生成的libbspatchlib.so生成合并后apk

客户端程序通过https下载patch包与本地旧apk就行合并,生成新的apk,并安装达到增量更新的目的,下载patch包和通知更新的操作比较简单,博文并没给出。

关于如何把交叉编译生成的libbspatchlib.so集成到请参考我的另外一个博文:http://blog.csdn.net/nexttake/article/details/77202018


JNIEXPORT jint JNICALL Java_xxxx  (JNIEnv *env, jclass jazz, jstring oldPath_jstr, jstring newPath_jstr, jstring patchPatch_jst) {

    int ret= -1;
    LOGD(" jni patch begin");

    char *oldPath = (*env) -> GetStringUTFChars(env, oldPath_jstr, JNI_FALSE);//已经安装的旧版本的apk的路径
    char *newPath = (*env) -> GetStringUTFChars(env, newPath_jstr, JNI_FALSE);//新生成的新版apk 的路径,合并完成以后启动系统安装器
    char *patchPath = (*env) -> GetStringUTFChars(env, patchPatch_jst, JNI_FALSE);//从服务器下载的差分包patch的路径

    int argc = 4;
    char *argv[4];

    argv[0] = "TimBsPatch";
    argv[1] = oldPath;
    argv[2] = newPath;
    argv[3] = patchPath;

    //如果成功ret等于0
    ret = bspatch_main(argc,argv);//这个函数在bspatch.c中,执行完成以后新版本的apk就会保存到newPath
(*env) -> ReleaseStringUTFChars(env, oldPath_jstr, oldPath);
    (*env) -> ReleaseStringUTFChars(env, newPath_jstr, newPath);
    (*env) -> ReleaseStringUTFChars(env, patchPatch_jst, patchPath);
    return ret;



PS.

在android-studio中编译bspath源代码(将bspatch源码拷贝进as),其实在AS里面编译本质就是用NDK在交叉编译了.......,以后补充



最佳实践:

  1. 差分包的下载要使用https
  2. 当版本改动较大时候建议还是全量更新
  3. 某些手机可能会有无法读取已经安装的旧版本apk的流的问题

     项目源码会上传到csdn


作者:nexttake 发表于2017/8/26 17:54:24 原文链接
阅读:344 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>