美文网首页Android开发Android开发经验谈Android 开发技术分享
ndk11_增量更新,哈夫曼算法在windows,linux服务

ndk11_增量更新,哈夫曼算法在windows,linux服务

作者: IT魔幻师 | 来源:发表于2017-11-10 18:14 被阅读66次

一、增量更新原理

  • 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);
        }
    }

相关文章

  • ndk11_增量更新,哈夫曼算法在windows,linux服务

    一、增量更新原理 1.增量更新原理bspatch依赖bzip2进行压缩 使用哈夫曼算法 主要用来做差分和合并的bs...

  • 算法解析:哈夫曼(huffman)压缩算法

    前言 本篇将介绍哈夫曼压缩算法(Huffman compression) 哈夫曼压缩算法(Huffman comp...

  • 最优树与哈夫曼编码

    大学的时候《离散数学》讲过哈夫曼算法,过了很多年后,只记得哈夫曼算法加压缩与解压上有很大优势,但不太记得哈夫曼算法...

  • 基于哈夫曼算法的压缩解压缩程序--python实现

    一.实现效果 【压缩】 【解压缩】 【压缩效率】 二.哈夫曼算法 哈夫曼又称霍夫曼编码,是一种编码方式,哈夫曼编码...

  • 构造哈夫曼树

    构造huffman树的算法: 算法思想:哈夫曼算法采用自底向上逐步合并的方法,构造哈夫曼树:步骤1)构造n颗单叶结...

  • 【恋上数据结构与算法一】(十六)哈夫曼树

    哈夫曼编码(Huffman Coding) ◼ 哈夫曼编码,又称为霍夫曼编码,它是现代压缩算法的基础 ◼ 假设要把...

  • 数据结构-哈夫曼树

    哈夫曼编码(Huffman Coding) ◼ 哈夫曼编码,又称为霍夫曼编码,它是现代压缩算法的基础◼ 假设要把字...

  • 哈夫曼编码

    实验目的: (1) 掌握二叉树的定义; (2) 掌握哈夫曼树和哈夫曼编码算法的实现。 实验内容: 实现一个哈夫曼编...

  • 19-哈夫曼树

    哈夫曼编码(Huffman Coding) 哈夫曼编码,又称霍夫曼编码,它是现代压缩算法的基础。 假如我们现在有这...

  • 二十五、哈夫曼树

    哈夫曼编码(Huffman Coding) 哈夫曼编码,又称为霍夫曼编码,它是现代压缩算法的基础 假设要把字符串【...

网友评论

    本文标题:ndk11_增量更新,哈夫曼算法在windows,linux服务

    本文链接:https://www.haomeiwen.com/subject/xlsapxtx.html