[Android实例] 【第一节】android增量升级之生成so文件

来源:互联网 发布:中国空巢老人数据 编辑:程序博客网 时间:2024/05/17 05:13

转载:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=903590&highlight=增量&_dsign=f69e6238

对于android项目,我们常常会遇到这样一种情况,比如某一版本的线上应用,突然发现了一个BUG,修改后发现不值当为这个BUG进行一次版本升级,那么怎么去解决在同一版本上修改线上应用的BUG呢,Google给了我们一种解决方案Smart App update,也就是应用增量升级。
那么,何谓增量升级呢?简单的来说,也就是把同一版本的新旧两个apk进行差分,得到一个差异包,然后在旧的应用中下载该差异包和旧的apk进行合并成新的apk,然后去安装新的apk,该合成的apk和差分前新apk是一样的,这样就可以做到应用的增量升级。一般来说,获取到的差异包较之新的apk来说小了很多,这样就可以减少用户的下载流量。
增量升级需要用到jni开发,所以我们需要去生成合并差异包的so文件,这里我们需要准备的工具有:eclipse,NDK环境(这里用的是ndk9以上的版本),bsdiff文件,bzip2文件(这两个文件在下面附件中给出)。
第一步:创建一个android项目,比如SmartAppUpdateSo,设定好包名(此处为以后引用so文件的方法做准备),例如com.smartapp.update。右键点击项目 -> Android tools -> Add Native Support...,在弹出窗里填写你要生成的so文件名称,如SmartAppUpdate,这样我们就能在项目中看到jni和obj两个文件夹了,删除jni文件夹下的SmartAppUpdate.cpp文件。
第二步:新建BatchUtils工具类,在类中增加方法

  1. private native static int patchApk(String oldApkPath, String newApkPath,
  2. String patchPath);
复制代码
打开cmd界面,进入到项目的bin\classes路径下,执行javah com.smartapp.update.BatchUtils命令,我们就能在bin\classes路径下发现一个命名为com_smartapp_update_BatchUtils.h的文件,打开该文件,里面的内容为
  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include <jni.h>
  3. /* Header for class com_smartapp_update_BatchUtils */

  4. #ifndef _Included_com_smartapp_update_BatchUtils
  5. #define _Included_com_smartapp_update_BatchUtils
  6. #ifdef __cplusplus
  7. extern "C" {
  8. #endif
  9. /*
  10. * Class: com_smartapp_update_BatchUtils
  11. * Method: patchApk
  12. * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
  13. */
  14. JNIEXPORT jint JNICALL Java_com_smartapp_update_BatchUtils_patchApk
  15. (JNIEnv *, jclass, jstring, jstring, jstring);

  16. #ifdef __cplusplus
  17. }
  18. #endif
  19. #endif
复制代码
第三步:将com_smartapp_update_BatchUtils.h文件拷贝到项目的jni文件夹下,然后将bzip2文件中的相关文件也拷贝到项目的jni文件夹下,需要拷贝的文件有:
  1. blocksort.c
  2. bzip2.c
  3. bzip2recover.c
  4. bzlib_private.h
  5. bzlib.c
  6. bzlib.h
  7. compress.c
  8. crctable.c
  9. decompress.c
  10. dlltest.c
  11. huffman.c
  12. mk251.c
  13. randtable.c
  14. spewG.c
  15. unzcrash.c
复制代码
第四步:将bsdiff中的bspatch.c文件拷贝到项目的jni文件夹中,并将其重命名为com_smartapp_update_BatchUtils.c,打开该文件,修改其中的内容: 1. 将头文件替换掉,原内容为:
  1. #if 0
  2. __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59:06 cperciva Exp [ DISCUZ_CODE_3 ]quot;);
  3. #endif

  4. #include <bzlib.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <err.h>
  9. #include <unistd.h>
  10. #include <fcntl.h>
复制代码
替换后的内容为:
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <err.h>
  5. #include <unistd.h>
  6. #include <fcntl.h>
  7. #include <android/log.h>
  8. #include <jni.h>

  9. #include "bzlib.c"
  10. #include "crctable.c"
  11. #include "compress.c"
  12. #include "decompress.c"
  13. #include "randtable.c"
  14. #include "blocksort.c"
  15. #include "huffman.c"

  16. #include "com_smartapp_update_BatchUtils.h"
复制代码
2. 将main方法名称替换成applypatch 3. 在文件内添加方法
  1. JNIEXPORT jint JNICALL Java_com_smartapp_update_BatchUtils_patchApk(JNIEnv *env,
  2. jobject obj, jstring old, jstring new, jstring patch) {

  3. char * ch[4];
  4. ch[0] = "bspatch";
  5. ch[1] = (char*) ((*env)->GetStringUTFChars(env, old, 0));
  6. ch[2] = (char*) ((*env)->GetStringUTFChars(env, new, 0));
  7. ch[3] = (char*) ((*env)->GetStringUTFChars(env, patch, 0));

  8. __android_log_print(ANDROID_LOG_INFO, "ApkPatchLibrary", "old = %s ", ch[1]);
  9. __android_log_print(ANDROID_LOG_INFO, "ApkPatchLibrary", "new = %s ", ch[2]);
  10. __android_log_print(ANDROID_LOG_INFO, "ApkPatchLibrary", "patch = %s ", ch[3]);

  11. int ret = applypatch(4, ch);

  12. __android_log_print(ANDROID_LOG_INFO, "ApkPatchLibrary", "applypatch result = %d ", ret);

  13. (*env)->ReleaseStringUTFChars(env, old, ch[1]);
  14. (*env)->ReleaseStringUTFChars(env, new, ch[2]);
  15. (*env)->ReleaseStringUTFChars(env, patch, ch[3]);

  16. return ret;
  17. }
复制代码
第五步:修改Android.mk文件内容
  1. LOCAL_PATH := $(call my-dir)

  2. include $(CLEAR_VARS)

  3. LOCAL_MODULE := SmartAppUpdate
  4. LOCAL_SRC_FILES := com_smartapp_update_BatchUtils.c

  5. LOCAL_LDLIBS := -lz -llog

  6. include $(BUILD_SHARED_LIBRARY)
复制代码
第六步:右键点击项目 -> properties,在弹出窗中点击Buiders,选择New...,在新弹出窗中选择Program,点击OK,此时弹出一个Edit Configuration弹窗。 1. Name中填写SmartAppUpdateBuilder
2. 选择Main标签,在Location一栏中点击Browse File System,选择你NDK安装路径下的ndk-build.cmd文件,Working Directory一栏中点击Browse Workspace,选择该项目的jni文件夹
3. 选择Refresh标签,勾选Refresh resources upon completion,选择The entire workspace,勾选上Recursively include sub-folders
4. 选择BuildOptions,勾选Allocte Console,After a "Clean",During manual builds,During auto builds,Specify working set of relevant resources ,点击Specify Resources,在弹出窗中勾选该项目jni文件夹,点击Apply,点击OK,这样我们就能在Buiders列表中看见新建的SmartAppUpdateBuilder,点击OK
第七步:等待片刻,我们会发现在obj文件夹下自动编译出一些文件,而其中obj\local\armeabi下的libSmartAppUpdate.so文件就是我们需要的so文件,那么生成增量升级的so文件的教程到此为止,至于如何去使用该so文件进行增量升级,请看【第二节】android增量升级之使用so文件进行增量升级

android,解决方案, android, 增量升级, android, android

bsdiff-4.3.zip

2015-8-19 11:41 上传

点击文件名下载附件

下载积分: e币 -3 元

8.8 KB, 下载次数: 5, 下载积分: e币 -3 元

bzip2-1.0.6.zip

2015-8-19 11:41 上传

点击文件名下载附件

下载积分: e币 -3 元

786.8 KB, 下载次数: 7, 下载积分: e币 -3 元

SmartAppUpdateSo.zip

2015-8-19 12:00 上传

点击文件名下载附件

下载积分: e币 -3 元

911.28 KB, 下载次数: 4, 下载积分: e币 -3 元

【第二节】

在第一节中,我讲了如何生成增量升级的so文件,没看的童鞋点【第一节】android增量升级之生成so文件,在这一节中,我讲一下如何去使用so文件进行增量升级。
第一步:建立一个新项目,如SmartAppUpdate,包名命名为com.smartapp.update,为什么要这么命名包名,是因为在第一节中,我们的BatchUtils文件是建立在com.smartapp.update包下的,而里面native方法生成的com_smartapp_update_BatchUtils.h文件也是以此包名命名的,所以为了调用so文件中的该native方法,所以我们需要在新项目中增加com.smartapp.update包,并将第一个项目中的BatchUtils.java文件拷贝到该包下
第二步:因为BatchUtils.java中的native方法是私有方法,所以我们需要在该类中增加下面的方法去调用该方法

  1. public static int applyPatchToOwn(Context context, String newApkPath,
  2. String patchPath) throws IOException {
  3. String old = context.getApplicationInfo().sourceDir;
  4. return patchApk(old, newApkPath, patchPath);
  5. }
复制代码
第三步:在新项目中的libs文件夹下新建文件夹armeabi,并将libSmartAppUpdate.so文件拷贝到该文件夹下,并在MainActivity.java类中增加以下代码,去加载该so文件
  1. static {
  2. System.loadLibrary("SmartAppUpdate");
  3. }
复制代码
第四步:添加逻辑代码,在项目中,我做了两个布局,分别是升级前的和升级后的展示界面,升级前的界面为activity_main.xml,升级后的界面为activity_main_new.xml,在onCreate方法中注释不同的代码实现不同的界面效果。
  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. beforeUpdate();
  5. afterUpdate();
  6. }
复制代码
新增Utils类添加相应的一些方法。
新增UpdateApkTask类进行旧apk和差异包合成操作。(备注:该差异包需要手动拷贝到手机指定路径下)

不要忘记添加权限
  1. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
  2. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
复制代码
第五步:用工具去生成差异包,并拷贝到手机指定路径下,在此提供一个window电脑使用的差分差异包工具bsdiff4.3-win32,请在附件中下载。该工具何以进行差分差异包,也可以进行合并就apk和差异包生成新apk。具体使用方法如下:
先获取两个不同的apk,如该项目中先在oncreate方法中注释掉afterUpdate()方法,生成一个apk,然后再注释掉beforeUpdate()方法,生成另一个apk,将两个apk拷贝到电脑指定路径下。
然后打开cmd,进入到bsdiff4.3-win32工具所在位置
拆分差异包命令如下:
  1. bsdiff 旧apk地址 新apk地址 生成差异包地址
  2. 如:bsdiff C:\Users\krubo\Desktop\aaa\SmartAppUpdate.apk C:\Users\krubo\Desktop\aaa\SmartAppUpdate_new.apk C:\Users\krubo\Desktop\aaa\SmartAppUpdate.patch
复制代码
我们就能看见在指定位置下生成了差异包SmartAppUpdate.patch 合成新APK命令如下:
  1. bspatch 旧apk地址 新apk地址 差异包地址
  2. 如:bspatch C:\Users\krubo\Desktop\aaa\SmartAppUpdate.apk C:\Users\krubo\Desktop\aaa\SmartAppUpdate_new_patch.apk C:\Users\krubo\Desktop\aaa\SmartAppUpdate.patch
复制代码
我们就能看见在指定位置下生成了新apk SmartAppUpdate_new_patch.apk
比较SmartAppUpdate_new.apk和SmartAppUpdate_new_patch.apk,就会发现,这两个apk是一模一样的。
第六步:将第五步中生成的差异包SmartAppUpdate.patch拷贝到手机的指定路径下,然后安装旧的apk,也就是注释掉afterUpdate()方法生成的apk,然后点击升级按钮,等待片刻,我们就能看见新apk安装界面,安装完成后,点击进入,发现里面的界面已改变,至此,使用so文件进行增量升级教程已结束。【第三节】android增量升级之提供服务端代码,整理项目

android,android, android, android

apk.zip

2015-8-19 17:26 上传

点击文件名下载附件

855.94 KB, 下载次数: 4

bsdiff4.3-win32.zip

2015-8-19 17:26 上传

点击文件名下载附件

73.52 KB, 下载次数: 4

SmartAppUpdate.zip

2015-8-19 17:26 上传

点击文件名下载附件

1.59 MB, 下载次数: 1

【第三节】


在之前的两节中分别讲了 第一节】android增量升级之生成so文件【第二节】android增量升级之使用so文件进行增量升级,没看的童鞋可以去看一下,这一节,我这边提供一个下载差异包的服务端,并且增加app中下载合并差异包的操作。
一、ApkPatchServer项目,该项目的使用springmvc粗略架构的一个项目,项目里总共只有两个类,一个是DiffApk.java,另一个是ApkPatchController.java
DiffApk.java是调用电脑里的bsdiff.exe工具进行差分新旧apk获取差异包的,我们可以直接run as -> java application运行。
ApkPatchController.java是提供接口的类,里面有一个提供下载差异包的方法,调用接口需要先将该项目部署到tomcat上运行,下载的接口为

  1. http://localhost:8080/ApkPatchServer/rest/download
复制代码
服务端运行的顺序是,先使用DiffApk类获取差异包,然后启动服务器,这样就能调用接口下载差异包了。 二、SmartAppUpdate项目,该项目在第二节项目的基础上增加了FileDownloadThread.java类,可以进行差异包下载操作。增加权限
  1. <uses-permission android:name="android.permission.INTERNET" />
复制代码
备注:ApkPatchServer项目中代码里一些路径是根据本人的电脑设置的,所以需要童鞋们根据自己的电脑进行修改

android,服务端, 项目, android, android

apk.zip

2015-8-19 21:11 上传

点击文件名下载附件

951.64 KB, 下载次数: 4

ApkPatchServer.zip

2015-8-19 21:11 上传

点击文件名下载附件

5.98 MB, 下载次数: 5

SmartAppUpdate.zip




0 0