增量更新:通过bsdiff.exe工具将oldapk和newapk进行比较并生成一个差分包patch,用户需要更新时只需要下载差分包到本地通过 native方法将oldapk和差分包patch进行合并,生成newapk。
所需资源下载: https://download.youkuaiyun.com/download/qq_29651765/10804911
开始写Demo:新建Android项目 并勾选
1.进入项目打开cpp文件夹,把下载的bspatch.c复制到cpp文件夹内。
2.然后打开下载的文件bsdiff and bzip2------> bzip2-1.0.6 ---> bzip2-1.0.6----->Makefile
3.这里是ndk合并差分包所需要的资源文件,这些资源文件在Makefile同目录中,在cpp文件下新建bzip包,把这些资源文件复制到项目cpp/bzip文件夹下。
4.打开app的build.gradle文件指定保留的so库
cmake { cppFlags "" //只保留指定的so库 abiFilters 'armeabi-v7a' }
到这里准备工作基本做完。
5.配置ndk文件
1).打开CMakeLists.txt 配置如下(红色字体为需要添加的地方)
cmake_minimum_required(VERSION 3.4.1) #加载cpp文件夹下的所有c文件 file(GLOB bzip_source src/main/cpp/bzip/*.c) add_library( # Sets the name of the library. native-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). src/main/cpp/native-lib.cpp src/main/cpp/bspatch.c ${bzip_source} ) include_directories(src/main/cpp/bzip) find_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log ) target_link_libraries( # Specifies the target library. native-lib # Links the target library to the log library # included in the NDK. ${log-lib} )
2).在MainActivity中新建native方法用于合成newapk。
native void bspatch(String oldapk, String patch, String outapk);
3).在natvie-lib.cpp文件中创建对应的jni方法
#include <jni.h> #include <string> extern "C"{ extern int bspatch_main(int argc,char * argv[]); } extern "C" JNIEXPORT void JNICALL Java_app_zengliang_com_zengliang_MainActivity_bspatch(JNIEnv *env,jobject instance,jstring oldapk_,jstring patch_,jstring outapk_){ const char *oldapk=env->GetStringUTFChars(oldapk_,0); const char *patch=env->GetStringUTFChars(patch_,0); const char *outapk=env->GetStringUTFChars(outapk_,0); char *argv[]={"",const_cast<char *>(oldapk),const_cast<char *>(outapk),const_cast<char *>(patch)}; //调用bspatch.c的main方法进行合成newapk(为了不和其他c文件main方法名字冲突这里改为bspatch_main,同时需要在bspatch.c 中修改为bspatch_main) bspatch_main(4,argv); env->ReleaseStringUTFChars(oldapk_,oldapk); env->ReleaseStringUTFChars(patch_,patch); env->ReleaseStringUTFChars(outapk_,outapk); }
6.编写MainActivity中合成方法。
1).(首先添加sdcard读写权限)
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
public void update(View view) { new AsyncTask<Void, Void, File>() { @Override protected File doInBackground(Void... voids) { //获取路径原app String oldapk = getApplication().getApplicationInfo().sourceDir; //获取差分包路径 String patch = getPath("patch"); //生成的新app的路径 String outapk = getPath("new.apk"); bspatch(oldapk, patch, outapk); return new File(outapk); } @Override protected void onPostExecute(File file) { super.onPostExecute(file); //安装app installApk(file); } }.execute(); } //获取某文件在sd卡的绝对路径 private String getPath(String name) { return new File(Environment.getExternalStorageDirectory(), name).getAbsolutePath(); } private void installApk(File newapk) { if (!newapk.exists()) { return; } Intent intent = new Intent(Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { Uri fileUri = UriParseUtils.getUriFromeFile(this, newapk); intent.setDataAndType(fileUri, "application/vnd.android.package-archive"); } else { intent.setDataAndType(Uri.fromFile(newapk), "application/vnd.android.package-archive"); } startActivity(intent); } native void bspatch(String oldapk, String patch, String outapk);
2).在AndroidManifest中添加如下代码(为了适配7.0+文件权限)
<provider android:name="android.support.v4.content.FileProvider" android:authorities="xxx.xxx.fileprovider"(这里修改为自己的包名) android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" /> </provider>
provider_paths.xml 标记为sdcard根目录
<?xml version="1.0" encoding="utf-8"?> <path> <root-path name="root_path" path="."/> </path>
代码编写完成
测试:
1.首先rebuild出一个1.0版本的app。
2.修改版本号为2.0并在MainActivty中添加一个背景图片(用于区分是否成功合成),然后rebuild出一个2.0版本的app。
3.在下载的资源文件中打开含有bsdiff.exe文件的文件夹并把rebuild的两个apk复制过来,cmd打开命令行运行命令
bsdiff.exe app-1.apk app-2.apk patch 点击回车会发现此文件夹下多出了个patch文件。
4.把patch文件复制到sdcard根目录(开发中需要把patch从服务器下载到sdcard进行合并,这里只做演示), 安装app1
打开点击更新调用update(View view)方法,就会进入安装页面。
注:本人对ndk也不太熟悉,只是讲了下大概如何配置,就当笔记看了,见笑。