【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( jni 中 main 函数声明 | 命令行处理 | jni 调用 lib7zr.so 函数库处理压缩文件完整代码 )(一)

简介: 【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( jni 中 main 函数声明 | 命令行处理 | jni 调用 lib7zr.so 函数库处理压缩文件完整代码 )(一)

文章目录

一、JNI 中 main 函数声明

二、命令字符串切割并传入 main 函数

三、完整代码示例

1、完整 jni 代码

2、完整 java 代码

3、执行结果

四、参考资料



前置博客 :


【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( 修改 7zr 交叉编译脚本 Android.mk | 交叉编译 lib7zr.so 动态库 )

【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( 拷贝 lib7zr.so 动态库到 Android Studio 工程 | 配置 build.gradle 构建脚本 )

【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( 拷贝 lib7zr.so 动态库头文件到 Android 工程中 | 配置 CMakeLists.txt 构建脚本 )

【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( 测试 lib7zr.so 动态库调用 )





一、JNI 中 main 函数声明


使用 7zr 可执行程序处理压缩文件时时 , 调用的是其主函数 , CPP\7zip\UI\Console\MainAr.cpp 中的 main 函数 , 传入 7z a outputFile inputFile -mx=compressDegree -tcompressType 压缩命令 , 或 7z x [输入文件] -o[输出目录] 解压命令 , 都是使用该主函数接收相关参数 ;


int MY_CDECL main
(
  #ifndef _WIN32
  int numArgs, char *args[]
  #endif
)


int numArgs 参数表示字符串个数 ;


如 7zr a files.7z files -mx=9 -t7z 命令中 , 有 6 66 个字符串 , 由 5 55 个空格隔开 ;


char *args[] 是 指针数组 , 数组中的元素是 char * 类型的指针 , 就是字符串 , 这是个字符串数组 ;



7zr 程序中的主要的头文件是 7zTypes.h , 该头文件中 声明了主要的 类型 和 函数 ; 引入该头文件 ;


#include <7zTypes.h>



声明外部函数 :


// 表示该函数在其它代码中实现
// 这是 CPP\7zip\UI\Console\MainAr.cpp 中的 main 函数
extern int MY_CDECL main
        (
#ifndef _WIN32
        int numArgs, char *args[]
#endif
);


点击声明左侧的双向箭头按钮 , 可以跳转到 MainAr.cpp 的 main 函数位置 ;


image.png


跳转位置 :

image.png







二、命令字符串切割并传入 main 函数


调用 main 函数 , 需要传入对应的参数 , 分别是


int numArgs 字符串个数 ;
char *args[] 字符串数组 ; 指针数组 , 每个数组元素中都有一个 char * 指针元素 , 指向字符串 ;
int MY_CDECL main
(
  #ifndef _WIN32
  int numArgs, char *args[]
  #endif
)


从 Java 传入 C 的指令如下 :


7zr a files.7z files -mx=9 -t7z


使用空格将上述指令切割成 6 66 个字符串 , 然后传入 main 函数 ;


字符串切割过程 :


 

// 命令示例 : 7zr a files.7z files -mx=9 -t7z
    // 参数个数
    int argCount = 0;
    // 存放多个字符串, 最多 20 个字符串 , 每个最多 1024 个字符
    char argArray[20][1024] = {0};
    //分割字符串 将值填入变量
    // 获取  cmd_java 字符串长度
    int cmd_size = strlen(cmd_java);
    // 二维数组 循环控制变量, 第一个是字符串数组 , 第二个是字符串中的字符数组
    int str_index = 0, char_index = 0;
    // 标记字符是否是非空字符, tab, 如果是则设置 1 , 如果不是设置 0
    // 开始时默认 0, 不是空格
    int isChar = 0;
    // 逐个字节遍历 字符
    for(int i = 0; i < cmd_size; i ++){
        // 获取一个字符
        char c = cmd_java[i];
        //LOGI("遍历 %d . %c , cmd_size = %d", i, c, cmd_size);
        switch (c) {
            case ' ': // 判断是否是空格
            case '\t': // 判断是否是 TAB 空格
                if(isChar){
                    // 如果上一个字符不是空格 , 则需要结束当前的字符串
                    argArray[str_index][char_index++] = '\0';
                    // 字符串索引自增 1
                    str_index ++;
                    // 字符串内字符索引归零
                    char_index = 0;
                    // 设置当前的字符为空格标志位 1
                    isChar = 0;
                }else{
                    // 如果之前是空格, 那么现在也是空格 ,
                    // 说明命令中有多个空格 , 此处不做任何处理
                }
                break;
            default:
                isChar = 1;
                // 将当前字符放入数组中
                argArray[str_index][char_index++] = c;
                break;
        }
    }
    // 如果最后一位不是空格 , 则需要手动将最后一个字符串写入到数组中
    if (cmd_java[cmd_size - 1] != ' ' && cmd_java[cmd_size - 1] != '\t') {
        // 如果上一个字符不是空格 , 则需要结束当前的字符串
        argArray[str_index][char_index++] = '\0';
        // 字符串索引自增 1
        str_index ++;
    }
    // 统计字符串个数
    argCount = str_index;
    // 拼装字符串数组
    char *args[] = {0};
    for (int i = 0; i < argCount; ++i) {
        args[i] = argArray[i];
        // 打印字符串数组
        LOGI("%d . %s", i, args[i]);
    }



最终的字符串个数是 argCount , 字符串数组 args ;


将这两个参数传入 main 函数即可 ;






三、完整代码示例




1、完整 jni 代码


完整 jni 层 C++ 代码如下 :


#include <jni.h>
#include <string>
#include <7zTypes.h>
#include "logging_macros.h"
// 表示该函数在其它代码中实现
// 这是 CPP\7zip\UI\Console\MainAr.cpp 中的 main 函数
extern int MY_CDECL main
        (
#ifndef _WIN32
        int numArgs, char *args[]
#endif
);
extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_a7_1zip_MainActivity_executeCmd(JNIEnv* env, jobject thiz, jstring cmd) {
    // 将 Java 字符串转为 C 字符串
    const char *cmd_java = env->GetStringUTFChars(cmd, 0);
    LOGI("jni 中处理压缩文件命令 : %s", cmd_java);
    // 命令示例 : 7zr a files.7z files -mx=9 -t7z
    // 参数个数
    int argCount = 0;
    // 存放多个字符串, 最多 20 个字符串 , 每个最多 1024 个字符
    char argArray[20][1024] = {0};
    //分割字符串 将值填入变量
    // 获取  cmd_java 字符串长度
    int cmd_size = strlen(cmd_java);
    // 二维数组 循环控制变量, 第一个是字符串数组 , 第二个是字符串中的字符数组
    int str_index = 0, char_index = 0;
    // 标记字符是否是非空字符, tab, 如果是则设置 1 , 如果不是设置 0
    // 开始时默认 0, 不是空格
    int isChar = 0;
    // 逐个字节遍历 字符
    for(int i = 0; i < cmd_size; i ++){
        // 获取一个字符
        char c = cmd_java[i];
        //LOGI("遍历 %d . %c , cmd_size = %d", i, c, cmd_size);
        switch (c) {
            case ' ': // 判断是否是空格
            case '\t': // 判断是否是 TAB 空格
                if(isChar){
                    // 如果上一个字符不是空格 , 则需要结束当前的字符串
                    argArray[str_index][char_index++] = '\0';
                    // 字符串索引自增 1
                    str_index ++;
                    // 字符串内字符索引归零
                    char_index = 0;
                    // 设置当前的字符为空格标志位 1
                    isChar = 0;
                }else{
                    // 如果之前是空格, 那么现在也是空格 ,
                    // 说明命令中有多个空格 , 此处不做任何处理
                }
                break;
            default:
                isChar = 1;
                // 将当前字符放入数组中
                argArray[str_index][char_index++] = c;
                break;
        }
    }
    // 如果最后一位不是空格 , 则需要手动将最后一个字符串写入到数组中
    if (cmd_java[cmd_size - 1] != ' ' && cmd_java[cmd_size - 1] != '\t') {
        // 如果上一个字符不是空格 , 则需要结束当前的字符串
        argArray[str_index][char_index++] = '\0';
        // 字符串索引自增 1
        str_index ++;
    }
    // 统计字符串个数
    argCount = str_index;
    // 拼装字符串数组
    char *args[] = {0};
    for (int i = 0; i < argCount; ++i) {
        args[i] = argArray[i];
        // 打印字符串数组
        LOGI("%d . %s", i, args[i]);
    }
    // 量参数传入 main 函数
    main(argCount, args);
    // 释放 Java 字符串以及 C 字符串
    env->ReleaseStringUTFChars(cmd, cmd_java);
    LOGI("7zr 命令执行完毕 !");
}


目录
相关文章
|
8月前
|
安全 Java 网络安全
Android远程连接和登录FTPS服务代码(commons.net库)
Android远程连接和登录FTPS服务代码(commons.net库)
122 1
|
8月前
|
Android开发 Swift iOS开发
探索安卓与iOS开发的差异:从代码到用户体验
【10月更文挑战第5天】在移动应用开发的广阔天地中,安卓和iOS两大平台各占半壁江山。它们在技术架构、开发环境及用户体验上有着根本的不同。本文通过比较这两种平台的开发过程,揭示背后的设计理念和技术选择如何影响最终产品。我们将深入探讨各自平台的代码示例,理解开发者面临的挑战,以及这些差异如何塑造用户的日常体验。
|
9月前
|
存储 Java Android开发
🔥Android开发大神揭秘:从菜鸟到高手,你的代码为何总是慢人一步?💻
在Android开发中,每位开发者都渴望应用响应迅速、体验流畅。然而,代码执行缓慢却是常见问题。本文将跟随一位大神的脚步,剖析三大典型案例:主线程阻塞导致卡顿、内存泄漏引发性能下降及不合理布局引起的渲染问题,并提供优化方案。通过学习这些技巧,你将能够显著提升应用性能,从新手蜕变为高手。
109 2
|
10月前
|
JSON JavaScript 前端开发
Android调用Vue中的JavaScript代码
Android调用Vue中的JavaScript代码
159 3
|
17天前
|
安全 Java Android开发
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
43 0
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
|
3月前
|
JavaScript Linux 网络安全
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
575 76
|
4月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
293 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
4月前
|
JavaScript 搜索推荐 Android开发
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
121 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
|
4月前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
106 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
5月前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
262 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程