美文网首页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服务

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