ndk11_增量更新,哈夫曼算法在windows,linux服务器和安卓客户端的使用

一、增量更新原理

  • 2.普通更新流程图


  • 3.增量更新流程图


  • 4.哈夫曼算法
  • 5.热修复、插件化和增量更新的区别

二、生成windows环境的差分工具

  • 1.下载Windows环境的源码
  • 2.创建VS工程

    为了方便管理在自己的VS工程里面创建include 和 src 两个文件夹

    将头文件放入include 源文件放入src

  • 3.关联头文件
  • 4.关联源文件
  • 5.配置VS头文件路径(引入include目录)
  • 6.VS解决 _CRT_SECURE_NO_WARNINGS 警告

    右键工程 ---> 属性 ---> c++ -----> 命令行 添加 -D _CRT_SECURE_NO_WARNINGS

  • 7.关闭sdl 安全检查

      error C4996: 'setmode': The POSIX name for this item is deprecated.
       Instead, use the ISO C++ conformant name: _setmode. See online help for 
      details.    d:\develop\visual_studio\workspacec++\hubindiffdemo\hubindiffdemo\src\bzlib.c   1422    1   hubinDiffDemo
    
  • 8.运行成功后生成了差分工具 hubinDiff.exe 位于Debug目录下(也可以配置生成hubinDiff.dll动态库,切换平台后需要重新设置以上步骤)

      cd到差分工具所在路径下为apk生成差分包
      
      hubinDiff.exe appOld.apk appNew.apk  app.patch
    

三、windows服务器jni动态生成差分包

  • 1.定义native方法

      /*
       *oldPath  :旧版本apk路径
       *newPath  :新版本apk路径
       *patchPath:差分包生成路径
       **/
      public static native void diff(string oldPath,String newPath,String patchPath);
    
  • 2.JNI层调用差分算法

    //将第bsdiff.cpp源文件228行main()入口函数:int main(int argc,char *argv[]) 
    //更名为int bsdiff_main(int argc,char *argv[])
    
    JNIEXPORT void JNICALL Java_hubin_diff
    (JNIEnv *env, jclass jazz,jstring oldPath_jst, jstring newPath_jst, jstring patchPath_jst)
    {
        int argc = 4;
        char *argv[4];
    
        char *oldPath = (char*)env->GetStringUTFChars(oldPath_jst, NULL);
        char *newpath = (char*)env->GetStringUTFChars(newPath_jst, NULL);
        char *patchPath = (char*)env->GetStringUTFChars(patchPath_jst, NULL);
        argv[0] = "bsdiff_Tim";
        argv[1] = oldPath;
        argv[2] = newpath;
        argv[3] = patchPath;
    
        bsdiff_main(argc,argv); //调用差分算法
    
        env->ReleaseStringUTFChars(oldPath_jst, oldPath);
        env->ReleaseStringUTFChars(newPath_jst, newpath);
        env->ReleaseStringUTFChars(patchPath_jst, patchPath);
    
    }

四、生成Linux环境的差分工具

  • 1.在官网下载Linux平台的bspatch源码

  • 2.拷贝bsdiff里面的源文件和bzip2里面的.c和.h源文件

  • 3.将bsdiff.c的源文件中的 #include <bzlib.h> 改成 #include "bzlib.h"
  • 4.将除了bsdiff.c的其他源文件中的main方法改成其它名字

  • 5.将所有源文件传输到linux服务器的文件夹下(/home/Bsdiff)

  • 6.cd到Bsdiff文件夹下修改其权限为全部可执行 命令:chmod 777 ./*

  • 7.使用gcc编译生成hubinBsDiff, 下面命令行中“...”表示其它所有的源文件

      gcc fPIC blocksort.c decompress.c bsdiff.c  randtable.c  bzip2.c huffman.c compress.c bzlib.c crctable.c -o hubinBsDiff   
    
  • 8.使用hubinBsDiff生成差分包

      hubinBsDiff appOld.apk appNew.apk  app.patch
    
  • 9.补充:如果需要生成so库,需要引入jni头文件,已经用javah生存的头文件并使用如下命令:

      gcc -I/usr/local/jdk/jdk1.8.0_152/include/linux -I/usr/local/jdk/jdk1.8.0_152/include -fPIC blocksort.c decompress.c bsdiff.c  randtable.c  bzip2.c huffman.c compress.c bzlib.c crctable.c  -shared -o libhubiniBsDiff.so
    
      备注:-I/usr/local/jdk/jdk1.8.0_152/include/linux 和 -I/usr/local/jdk/jdk1.8.0_152/include表示jni头文件所在的路径
    

五、android平台合并

  • 1.同上步骤,拷贝所有linux版本源码至工程的cpp目录下重命名所有源文件中的main方法,引入正确的头文件路径,
  • 2.配置CmakeList

      cmake_minimum_required(VERSION 3.4.1)
      
      file(GLOB my_c_path src/main/cpp/bzip2/*.c)
      add_library( TimBisPatch
                   SHARED
      
                   ${my_c_path}  #添加bzip2目录下的所有源文件
                   src/main/cpp/bspatch.c)
      
      find_library(  log-lib
                    log )
      
      target_link_libraries(TimBisPatch
      
                             ${log-lib} )
    
  • 3.java层native方法

      public native static int patch(String oldfile, String newFile, String patchFile);
    
  • 4.JNI层调用bspatch.c中改名后的main方法

    JNIEXPORT jint JNICALL Java_hubin_BsPatch_patch
            (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);
        char *newPath = (*env) -> GetStringUTFChars(env, newPath_jstr, JNI_FALSE);
        char *patchPath = (*env) -> GetStringUTFChars(env, patchPatch_jst, JNI_FALSE);
    
        int argc = 4;
        char *argv[4];
    
        argv[0] = "hubinBsPatch"; //随便定义一个名字
        argv[1] = oldPath;   //老版本apk路径
        argv[2] = newPath;  //新版本apk路径
        argv[3] = patchPath;  //差分包所在路径
    
        //如果成功ret等于0
        ret = bspatch_main(argc,argv); //调用合并算法

        (*env) -> ReleaseStringUTFChars(env, oldPath_jstr, oldPath);
        (*env) -> ReleaseStringUTFChars(env, newPath_jstr, newPath);
        (*env) -> ReleaseStringUTFChars(env, patchPatch_jst, patchPath);
        return ret;
    
    }
    import android.content.Context;
    import android.content.Intent;
    import android.content.pm.ApplicationInfo;
    import android.content.pm.PackageInfo;
    import android.content.pm.PackageManager;
    import android.net.Uri;
    import android.text.TextUtils;
    import android.util.Log;

    public class ApkUtils {
        //获取APK版本号 根据 key uuid判断(渠道 版本)
        public static int getVersionCode (Context context, String packageName) {
            PackageManager pm = context.getPackageManager();
            try {
                PackageInfo info = pm.getPackageInfo(packageName, 0);
                Log.d("Tim","getVersionCode = "+info.versionCode);
                return info.versionCode;
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
                return 0;
            }
        }
    
        /**
         * 获取已安装Apk文件的源Apk文件
         * 如:/data/app/my.apk
         *
         * @param context
         * @param packageName
         * @return
         */
        public static String getSourceApkPath(Context context, String packageName) {
            if (TextUtils.isEmpty(packageName))
                return null;
    
            try {
                ApplicationInfo appInfo = context.getPackageManager()
                        .getApplicationInfo(packageName, 0);
                return appInfo.sourceDir;
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
            return null;
        }
    
    
    
        /**
         * 安装Apk
         *
         * @param context
         * @param apkPath
         */
        public static void installApk(Context context, String apkPath) {
    
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.parse("file://" + apkPath),
                    "application/vnd.android.package-archive");
    
            context.startActivity(intent);
        }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 增量更新在Android开发中是一种很常见的技术。 增量更新的原理 增量更新的原理非常简单,就是将本地apk与服务...
    re冷星阅读 5,478评论 3 3
  • 版权声明:本文为LooperJing原创文章,转载请注明出处! 前言 如果要对一个 APP 进行更新,你会怎么做呢...
    LooperJing阅读 8,845评论 0 28
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,833评论 19 139
  • 最近就是在练习ndk开发,刚好遇到android增量更新的话题,主要是工具的运用,略带使用第三方so库的流程~~~...
    红黑军团号阅读 3,677评论 1 3
  • @[增量更新,差分包,bsdiff/patch] 背景 随着Android app的不断迭代升级,功能越来越多,a...
    SunYo阅读 15,269评论 2 7

友情链接更多精彩内容