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

举报
韩曙亮 发表于 2022/01/10 23:20:05 2022/01/10
【摘要】 文章目录 一、拷贝 p7zip 源码中的头文件到 Android Studio 项目中二、完整代码示例1、Java 层代码2、JNI 层代码3、日志头文件4、执行结果 四、参考资料 ...



前置博客 :





一、拷贝 p7zip 源码中的头文件到 Android Studio 项目中



在上一篇博客 【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( 拷贝 lib7zr.so 动态库头文件到 Android 工程中 | 配置 CMakeLists.txt 构建脚本 ) 中 , 将 lib7zr.so 动态库需要的头文件都拷贝到了 Android Studio 工程中 , 并配置了 CMakeLists.txt 构建脚本 ;

本篇博客开发 JNI 类 , 验证 lib7zr.so 动态库 ;

【Android 安装包优化】Android 中使用 7zr 可执行程序 解压缩文件 博客的 Android 项目的基础上进行开发 ;


首先加载 libnative-lib.so 动态库 , 这是 CMakeLists.txt 编译出来的动态库 , 声明 native 方法 ;

class MainActivity : AppCompatActivity() {
    companion object {
        init {
            System.loadLibrary("native-lib")
        }
    }
    external fun executeCmd(cmd: String): Unit
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在 JNI 层的 C++ 文件中实现上述 native 方法 , MainActivity 类的包名是 kim.hsl.a7_zip , 因此 executeCmd 方法对应的 JNI 层的方法是 Java_kim_hsl_a7_1zip_MainActivity_executeCmd ;

extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_a7_1zip_MainActivity_executeCmd(JNIEnv* env, jobject thiz, jstring cmd) {
    LOGI("7zTypes SZ_OK = %d", SZ_OK );
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5




二、完整代码示例





1、Java 层代码


Java 层代码 :

package kim.hsl.a7_zip

import android.os.Build
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import java.io.*

class MainActivity : AppCompatActivity() {
    companion object {
        val TAG = "MainActivity"

        init {
            System.loadLibrary("native-lib")
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        copy7zr()

        compress7z()

        uncompress7z()

        executeCmd("7z")
    }

    /**
     * 将 7zr 文件拷贝到应用私有目录
     */
    fun copy7zr() {
        Log.i(TAG, "开始拷贝 7zr 文件")

        // /data/user/0/kim.hsl.a7_zip/files/7zr
        var exeFile = File(filesDir, "7zr")
        Log.i(TAG, "filesDir = ${filesDir.absolutePath} , exeFile = ${exeFile.absolutePath}")

        // 查看该文件是否存在, 如果存在设置该文件可执行
        // 如果不存在 , 拷贝文件
        if (exeFile.exists()) {
            exeFile.setExecutable(true)
            Log.i(TAG, "内置存储空间存在该 /data/user/0/kim.hsl.a7_zip/files/7zr 文件")
            return
        } else {
            Log.i(TAG, "内置存储空间不存在 7zr 可执行文件 , 开始拷贝文件")
        }

        // 如果不存在 , 拷贝文件
        var inputStream: InputStream = assets.open("libs/arm64-v8a/7zr")
        // /data/user/0/kim.hsl.a7_zip/files/7zr
        var fileOutputStream: FileOutputStream = FileOutputStream(exeFile)

        Log.i(TAG, "Build.CPU_ABI = ${Build.CPU_ABI}")

        // 不同 CPU 架构拷贝不同的可执行程序
        if (Build.CPU_ABI.startsWith("armeabi-v7a")) {
            inputStream = assets.open("libs/armeabi-v7a/7zr")

        } else if (Build.CPU_ABI.startsWith("arm64-v8a")) {
            inputStream = assets.open("libs/arm64-v8a/7zr")

        } else if (Build.CPU_ABI.startsWith("x86")) {
            inputStream = assets.open("libs/x86/7zr")

        } else if (Build.CPU_ABI.startsWith("x86_64")) {
            inputStream = assets.open("libs/x86_64/7zr")
        }

        // 拷贝文件
        var buffer: ByteArray = ByteArray(1024)
        var readCount = inputStream.read(buffer);
        while (readCount != -1) {
            fileOutputStream.write(buffer)
            readCount = inputStream.read(buffer);
        }
        fileOutputStream.flush()
        fileOutputStream.close()

        Log.i(TAG, "拷贝 7zr 文件结束")
    }

    /**
     * 使用 7zr 进行压缩
     */
    fun compress7z() {
        // /data/user/0/kim.hsl.a7_zip/files/7zr
        var exeFile = File(filesDir, "7zr")
        // 执行前赋予可执行权限
        exeFile.setExecutable(true)

        var file_7z = File("${filesDir.absolutePath}/files.7z")
        if(file_7z.exists()){
            file_7z.delete()
        }

        var cmd = "${exeFile.absolutePath} a ${filesDir.absolutePath}/files.7z ${filesDir.absolutePath} -mx=9 -t7z"
        Log.i(TAG, "压缩命令 : $cmd")

        var process: Process = Runtime.getRuntime().exec(cmd)

        // 读取命令执行过程数据
        var reader = BufferedReader(InputStreamReader(process.inputStream))
        while (true) {
            val line = reader.readLine()
            if (line != null) {
                Log.i(TAG, "$line")
            }else{
                break
            }
        }

        val exitValue = process.exitValue()
        Log.i(TAG, "压缩文件 , 执行完毕 , exitValue = $exitValue")
    }

    /**
     * 判定命令是否执行完毕
     * 调用 process.exitValue 方法 , 如果没有执行完毕 , 会抛异常,
     * 如果执行完毕会返回一个确定的值
     */
    fun isComplete(process: Process): Boolean {
        try {
            // 已经执行完毕
            process.exitValue()
            return true
        } catch (e: IllegalThreadStateException) {
            // 未执行完毕
            return false
        }
    }

    /**
     * 使用 7zr 进行解压缩
     */
    fun uncompress7z() {
        // /data/user/0/kim.hsl.a7_zip/files/7zr
        var exeFile = File(filesDir, "7zr")
        // 执行前赋予可执行权限
        exeFile.setExecutable(true)

        // 删除解压目录
        var unzip_file = File("${filesDir.absolutePath}/unzip_file")
        if(unzip_file.exists()){
            recursionDeleteFile(unzip_file)
        }

        var cmd = "${exeFile.absolutePath} x ${filesDir.absolutePath}/files.7z -o${filesDir.absolutePath}/unzip_file"
        Log.i(TAG, "解压缩命令 : $cmd")

        var process: Process = Runtime.getRuntime().exec(cmd)

        // 读取命令执行过程数据
        var reader = BufferedReader(InputStreamReader(process.inputStream))
        while (true) {
            val line = reader.readLine()
            if (line != null) {
                Log.i(TAG, "$line")
            }else{
                break
            }
        }

        val exitValue = process.exitValue()
        Log.i(TAG, "解压缩文件 , 执行完毕 , exitValue = $exitValue")
    }

    /**
     * 递归删除文件
     */
    fun recursionDeleteFile(file: File) {
        if (file.isDirectory) {
            // 如果是目录 , 则递归删除
            file.listFiles().forEach {
                // ForEach 循环删除目录
                recursionDeleteFile(it)
            }
        } else {
            // 如果是文件直接删除
            file.delete()
        }
    }

    external fun executeCmd(cmd: String): Unit
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187


2、JNI 层代码


#include <jni.h>
#include <string>
#include <7zTypes.h>
#include "logging_macros.h"

extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_a7_1zip_MainActivity_executeCmd(JNIEnv* env, jobject thiz, jstring cmd) {
    LOGI("7zTypes SZ_OK = %d", SZ_OK );
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10


3、日志头文件


日志打印头文件 :

//
// Created by octop on 2021/5/6.
//

#ifndef INC_7_ZIP_LOGGING_MACROS_H
#define INC_7_ZIP_LOGGING_MACROS_H

#include <android/log.h>

#if 1
#ifndef MODULE_NAME
#define MODULE_NAME  "octopus"
#endif

#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, MODULE_NAME, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, MODULE_NAME, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,MODULE_NAME, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,MODULE_NAME, __VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,MODULE_NAME, __VA_ARGS__)

#define ASSERT(cond, ...) if (!(cond)) {__android_log_assert(#cond, MODULE_NAME, __VA_ARGS__);}
#else

#define LOGV(...)
#define LOGD(...)
#define LOGI(...)
#define LOGW(...)
#define LOGE(...)
#define LOGF(...)
#define ASSERT(cond, ...)

#endif

#endif //INC_7_ZIP_LOGGING_MACROS_H


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36


4、执行结果


执行结果 :

在这里插入图片描述

2021-05-06 20:44:57.920 8966-8966/kim.hsl.a7_zip I/MainActivity: 开始拷贝 7zr 文件
2021-05-06 20:44:57.921 8966-8966/kim.hsl.a7_zip I/MainActivity: filesDir = /data/user/0/kim.hsl.a7_zip/files , exeFile = /data/user/0/kim.hsl.a7_zip/files/7zr
2021-05-06 20:44:57.924 8966-8966/kim.hsl.a7_zip I/MainActivity: 内置存储空间存在该 /data/user/0/kim.hsl.a7_zip/files/7zr 文件
2021-05-06 20:44:57.925 8966-8966/kim.hsl.a7_zip I/MainActivity: 压缩命令 : /data/user/0/kim.hsl.a7_zip/files/7zr a /data/user/0/kim.hsl.a7_zip/files/files.7z /data/user/0/kim.hsl.a7_zip/files -mx=9 -t7z
2021-05-06 20:45:00.074 8966-8966/kim.hsl.a7_zip I/MainActivity: 7-Zip (a) [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
2021-05-06 20:45:00.074 8966-8966/kim.hsl.a7_zip I/MainActivity: p7zip Version 16.02 (locale=utf8,Utf16=on,HugeFiles=on,64 bits,8 CPUs LE)
2021-05-06 20:45:00.074 8966-8966/kim.hsl.a7_zip I/MainActivity: Scanning the drive:
2021-05-06 20:45:00.074 8966-8966/kim.hsl.a7_zip I/MainActivity: 13 folders, 6 files, 5965824 bytes (5826 KiB)
2021-05-06 20:45:00.074 8966-8966/kim.hsl.a7_zip I/MainActivity: Creating archive: /data/user/0/kim.hsl.a7_zip/files/files.7z
2021-05-06 20:45:00.075 8966-8966/kim.hsl.a7_zip I/MainActivity: Items to compress: 19
2021-05-06 20:45:00.075 8966-8966/kim.hsl.a7_zip I/MainActivity: Files read from disk: 6
2021-05-06 20:45:00.075 8966-8966/kim.hsl.a7_zip I/MainActivity: Archive size: 309075 bytes (302 KiB)
2021-05-06 20:45:00.075 8966-8966/kim.hsl.a7_zip I/MainActivity: Everything is Ok
2021-05-06 20:45:00.075 8966-8966/kim.hsl.a7_zip I/MainActivity: 压缩文件 , 执行完毕 , exitValue = 0
2021-05-06 20:45:00.078 8966-8966/kim.hsl.a7_zip I/MainActivity: 解压缩命令 : /data/user/0/kim.hsl.a7_zip/files/7zr x /data/user/0/kim.hsl.a7_zip/files/files.7z -o/data/user/0/kim.hsl.a7_zip/files/unzip_file
2021-05-06 20:45:00.088 8966-8966/kim.hsl.a7_zip I/MainActivity: 7-Zip (a) [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
2021-05-06 20:45:00.088 8966-8966/kim.hsl.a7_zip I/MainActivity: p7zip Version 16.02 (locale=utf8,Utf16=on,HugeFiles=on,64 bits,8 CPUs LE)
2021-05-06 20:45:00.088 8966-8966/kim.hsl.a7_zip I/MainActivity: Scanning the drive for archives:
2021-05-06 20:45:00.088 8966-8966/kim.hsl.a7_zip I/MainActivity: 1 file, 309075 bytes (302 KiB)
2021-05-06 20:45:00.088 8966-8966/kim.hsl.a7_zip I/MainActivity: Extracting archive: /data/user/0/kim.hsl.a7_zip/files/files.7z
2021-05-06 20:45:00.135 8966-8966/kim.hsl.a7_zip I/MainActivity: --
2021-05-06 20:45:00.135 8966-8966/kim.hsl.a7_zip I/MainActivity: Path = /data/user/0/kim.hsl.a7_zip/files/files.7z
2021-05-06 20:45:00.135 8966-8966/kim.hsl.a7_zip I/MainActivity: Type = 7z
2021-05-06 20:45:00.135 8966-8966/kim.hsl.a7_zip I/MainActivity: Physical Size = 309075
2021-05-06 20:45:00.135 8966-8966/kim.hsl.a7_zip I/MainActivity: Headers Size = 298
2021-05-06 20:45:00.135 8966-8966/kim.hsl.a7_zip I/MainActivity: Method = LZMA2:6m
2021-05-06 20:45:00.135 8966-8966/kim.hsl.a7_zip I/MainActivity: Solid = +
2021-05-06 20:45:00.135 8966-8966/kim.hsl.a7_zip I/MainActivity: Blocks = 1
2021-05-06 20:45:00.135 8966-8966/kim.hsl.a7_zip I/MainActivity: Everything is Ok
2021-05-06 20:45:00.135 8966-8966/kim.hsl.a7_zip I/MainActivity: Folders: 13
2021-05-06 20:45:00.135 8966-8966/kim.hsl.a7_zip I/MainActivity: Files: 6
2021-05-06 20:45:00.135 8966-8966/kim.hsl.a7_zip I/MainActivity: Size:       5965824
2021-05-06 20:45:00.135 8966-8966/kim.hsl.a7_zip I/MainActivity: Compressed: 309075
2021-05-06 20:45:00.135 8966-8966/kim.hsl.a7_zip I/MainActivity: 解压缩文件 , 执行完毕 , exitValue = 0
2021-05-06 20:45:00.135 8966-8966/kim.hsl.a7_zip I/octopus: 7zTypes SZ_OK = 0

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35




四、参考资料



参考资料 :


Android NDK 编译构建脚本参考文档 :

博客资源 : 源码 , 编译后的可执行文件, 在 7zip\p7zip_16.02\CPP\ANDROID\7zr\libs\ 目录下 ;

文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。

原文链接:hanshuliang.blog.csdn.net/article/details/116455961

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。