鸿蒙-ArkTS和Native之间的交互使用示例-148234479

前言:


鸿蒙(HarmonyOS)的NDK(Native Development Kit)开发允许开发者使用C/C++编写高性能代码,并与Java/JS层进行交互。



首先:


创建Native项目


  1. 选择模板
    新建项目时,选择Native C++模板,系统会自动生成Native层代码结构(包括cpp目录和CMakeLists.txt)。

  2. 项目结构说明


    • entry/src/main/cpp:存放C/C++源码及头文件。

    • CMakeLists.txt

    • 定义Native库的编译规则(如库名称、源码路径、依赖关系)。


编写Native代码


  1. 实现JNI接口
    在Java/JS层声明Native方法(如public native String helloFromJNI()),并通过native-lib.cpp实现对应的JNI函数(需遵循JNIEXPORTJNICALL规范)。

  2. 跨语言交互


    • 使用env->GetStringUTFChars()将Java字符串转换为C字符串。

    • 通过env->NewStringUTF()将C字符串返回给Java层。



编译与构建


  1. 配置CMake
    CMakeLists.txt中指定生成的动态库名称(如add_library(native-lib SHARED native-lib.cpp)),并关联系统库(如libace_napi.z.so)。

  2. 构建HAP包
    执行Build > Build Hap(s),生成包含Native库(.so文件)的HAP安装包。构建日志中可检查NDK编译是否成功。


项目目录:




├──entry/src/main/cpp // cpp代码区
│ ├──thirdparty
│ │ ├──libarchive // 32位和64位三方库
│ │ │ ├──arm64-v8a
│ │ │ └──armeabi-v7a
│ │ ├──xz // 32位和64位文件
│ │ │ ├──arm64-v8a
│ │ │ └──armeabi-v7a
│ │ └───zstd // 32位和64位文件
│ │ ├──arm64-v8a
│ │ └──armeabi-v7a
│ │
│ ├──types/mycompress // 自定义接口
│ │ │────Index.d.ts
│ │ └──oh-package.json5
│ │────CMakeLists.txt // CMake配置
│ │────napi_init.cpp // c方法实现
│ ├──ets
│ │ └──CompressLib.ets // arkts方法转换
│ │
│ └────resources/base/element // 应用资源目录

└──entry/src/main/resources
├──entry/src/main/ets // ets代码区
│ ├──entryability
│ │ └──EntryAbility.ets
│ ├──entrybackupability
│ │ └──EntryBackupAbility.ets
│ └──pages // UI入口
│ └──Index.ets
└──entry/src/main/resources // 应用资源目录

接下来我们来介绍一下项目代码:


1.在CMakeLists.txt文件配置如下:


# the minimum version of CMake.
cmake_minimum_required(VERSION 3.5.0)
project(mycompress)

set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})

if(DEFINED PACKAGE_FIND_FILE)
include(${PACKAGE_FIND_FILE})
endif()

include_directories(${NATIVERENDER_ROOT_PATH}
${NATIVERENDER_ROOT_PATH}/include)

add_library(mycompress SHARED napi_init.cpp)
target_link_libraries(mycompress PUBLIC libace_napi.z.so libhilog_ndk.z.so)

target_link_libraries(mycompress PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/libarchive/${OHOS_ARCH}/lib/libarchive.so)
target_link_libraries(mycompress PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/xz/${OHOS_ARCH}/lib/liblzma.so)
target_link_libraries(mycompress PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/zstd/${OHOS_ARCH}/lib/libzstd.so)

target_include_directories(mycompress PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/libarchive/${OHOS_ARCH}/include)
target_include_directories(mycompress PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/xz/${OHOS_ARCH}/include)
target_include_directories(mycompress PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/zstd/${OHOS_ARCH}/include)


2.在Index.d.ts文件中配置如下:


export const decompress: (inFile: string, outFile: string) => object

export const compress: (inFile: string, outFile: string, format: string) => object

export const getFileList: (path: string,outFile: string,) => object

export const getFileData: (path: string,outFile: string,) => object

3.在napi_init.cpp文件里面进行功能方法实现:


#include 
#include
#include
#include
#include
#include
#include
#include

#define LOG_TAG "ARCHIVE"
#include

enum class ErrorCode {
SUCCESS = 0,
FILE_NOT_FOUND = -1,
FILE_READ_ERROR = -2,
FILE_WRITE_ERROR = -3,
ARCHIVE_ERROR = -4,
UNSUPPORTED_FORMAT = -5,
INVALID_DIRECTORY = -6,
CREATE_TEMP_FILE_ERROR = -7,
RENAME_FILE_ERROR = -8,
};

static const std::unordered_map error_messages = {
{static_cast(ErrorCode::SUCCESS), "Success"},
{static_cast(ErrorCode::FILE_NOT_FOUND), "File not found"},
{static_cast(ErrorCode::FILE_READ_ERROR), "File read error"},
{static_cast(ErrorCode::FILE_WRITE_ERROR), "File write error"},
{static_cast(ErrorCode::ARCHIVE_ERROR), "Archive processing error"},
{static_cast(ErrorCode::UNSUPPORTED_FORMAT), "Unsupported compression format"},
{static_cast(ErrorCode::INVALID_DIRECTORY), "Invalid directory"},
{static_cast(ErrorCode::CREATE_TEMP_FILE_ERROR), "Temporary file creation error"},
{static_cast(ErrorCode::RENAME_FILE_ERROR), "File renaming error"},
};

const char *error_code_to_message(ErrorCode code, const char *custom_message = nullptr) {
auto it = error_messages.find(static_cast(code));
if (it != error_messages.end()) {
return custom_message ? custom_message : it->second;
}

return "Unknown error";
}

static napi_value create_result(napi_env env, ErrorCode code, const char *custom_message = nullptr) {
napi_value result;
napi_create_object(env, &result);

napi_value error_code;
napi_create_int32(env, static_cast(code), &error_code);
napi_set_named_property(env, result, "code", error_code);

const char *message = error_code_to_message(code, custom_message);
napi_value error_message;
napi_create_string_utf8(env, message, NAPI_AUTO_LENGTH, &error_message);
napi_set_named_property(env, result, "message", error_message);
return result;
}

static napi_value list_result(napi_env env, std::string out_list) {

napi_value result;
napi_create_object(env, &result);
napi_value error_code;
napi_create_int32(env, static_cast(0), &error_code);
napi_set_named_property(env, result, "code", error_code);

napi_value error_message;
napi_create_string_utf8(env, out_list.c_str(), NAPI_AUTO_LENGTH, &error_message);
napi_set_named_property(env, result, "message", error_message);
return result;
}

static napi_value Decompress(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value argv[2] = {nullptr};
napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);

size_t in_file_size;
char in_file_buf[256];
napi_get_value_string_utf8(env, argv[0], in_file_buf, sizeof(in_file_buf), &in_file_size);
std::string in_file(in_file_buf, in_file_size);

size_t out_file_size;
char out_file_buf[256];
napi_get_value_string_utf8(env, argv[1], out_file_buf, sizeof(out_file_buf), &out_file_size);
std::string out_file(out_file_buf, out_file_size);

if (in_file.empty() || out_file.empty()) {
return create_result(env, ErrorCode::FILE_NOT_FOUND);
}

// Ensure the output directory ends with a slash
if (!out_file.empty() && out_file.back() != '/') {
out_file += '/';
}

struct archive *a;
struct archive *out;
struct archive_entry *entry;
int r;

a = archive_read_new();
archive_read_support_format_all(a);
archive_read_support_filter_all(a);

out = archive_write_disk_new();
archive_write_disk_set_options(out, ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS);
archive_write_disk_set_standard_lookup(out);

int fd = open(in_file.c_str(), O_RDONLY);
if (fd == -1) {
return create_result(env, ErrorCode::FILE_NOT_FOUND);
}

struct stat statbuf;
if (fstat(fd, &statbuf) == -1) {
close(fd);
return create_result(env, ErrorCode::FILE_READ_ERROR);
}

off_t len = statbuf.st_size;
std::unique_ptr data = std::make_unique(len);

ssize_t bytes_read = read(fd, data.get(), len);
if (bytes_read != len) {
close(fd);
return create_result(env, ErrorCode::FILE_READ_ERROR);
}
close(fd);

r = archive_read_open_memory(a, data.get(), len);
if (r != ARCHIVE_OK) {
return create_result(env, ErrorCode::ARCHIVE_ERROR);
}

const char *original_locale = setlocale(LC_CTYPE, nullptr);
setlocale(LC_CTYPE, "en_US.UTF-8");

const char *error_string;

while (true) {
r = archive_read_next_header(a, &entry);
if (r != ARCHIVE_OK) {
error_string = archive_error_string(a);
if (error_string) {
OH_LOG_ERROR(LOG_APP, "Unable to read next header: %{public}s", error_string);
}
break;
}

const char *current_path = archive_entry_pathname(entry);
std::string full_output_path = out_file + current_path;
archive_entry_set_pathname(entry, full_output_path.c_str());

r = archive_write_header(out, entry);
if (r != ARCHIVE_OK) {
error_string = archive_error_string(a);
OH_LOG_ERROR(LOG_APP, "Unable to write header for file: %{public}s, error: %{public}s", current_path, error_string);
} else {
const void *buff;
size_t size;
int64_t offset;
while ((r = archive_read_data_block(a, &buff, &size, &offset)) == ARCHIVE_OK) {
r = archive_write_data_block(out, buff, size, offset);
if (r != ARCHIVE_OK) {
error_string = archive_error_string(a);
OH_LOG_ERROR(LOG_APP, "Unable to write data for file: %{public}s, error: %{public}s", current_path, error_string);
break;
}
}
if (r == ARCHIVE_EOF) {
r = ARCHIVE_OK; // Reset error code if EOF reached
}
}
archive_entry_clear(entry);
}

archive_read_close(a);
archive_read_free(a);
archive_write_close(out);
archive_write_free(out);

setlocale(LC_CTYPE, original_locale);

return create_result(env, r == ARCHIVE_EOF ? ErrorCode::SUCCESS : ErrorCode::ARCHIVE_ERROR, error_string);
}

bool is_directory(const std::string &path) {
struct stat path_stat;
return stat(path.c_str(), &path_stat) == 0 && S_ISDIR(path_stat.st_mode);
}

std::string get_name(const std::string &file) {
const char *name = strrchr(file.c_str(), '/');
return name ? std::string(name + 1) : file;
}

std::string get_dir(const std::string &file) {
const char *last_slash = strrchr(file.c_str(), '/');
return last_slash ? std::string(file.c_str(), last_slash - file.c_str()) : "";
}

void compress_file(struct archive *out, const std::string &file_path, const std::string &base_file_path) {
struct stat st;
if (stat(file_path.c_str(), &st) != 0) {
OH_LOG_ERROR(LOG_APP, "Unable to stat file: %{public}s", file_path.c_str());
return;
}

struct archive_entry *entry = archive_entry_new();
archive_entry_set_pathname(entry, base_file_path.c_str());
archive_entry_set_size(entry, st.st_size);
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_perm(entry, st.st_mode & 0777);
archive_write_header(out, entry);

int fd = open(file_path.c_str(), O_RDONLY);
if (fd == -1) {
OH_LOG_ERROR(LOG_APP, "Unable to open file: %{public}s", file_path.c_str());
archive_entry_free(entry);
return;
}

char buffer[1024 * 1024];
ssize_t bytes_read;
while ((bytes_read = read(fd, buffer, sizeof(buffer))) > 0) {
archive_write_data(out, buffer, bytes_read);
}
close(fd);
archive_entry_free(entry);
}

void compress_directory(struct archive *a, struct archive *out, const std::string &dir_path, const std::string &base_dir) {
DIR *dir = opendir(dir_path.c_str());
if (dir == nullptr) {
OH_LOG_ERROR(LOG_APP, "Unable to open directory: %{public}s", dir_path.c_str());
return;
}

struct dirent *entry;
bool is_empty = true;
while ((entry = readdir(dir)) != nullptr) {
if (entry->d_type == DT_DIR && strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
is_empty = false;
std::string sub_dir_path = dir_path + "/" + entry->d_name;
std::string sub_base_dir = base_dir.empty() ? entry->d_name : base_dir + "/" + entry->d_name;
compress_directory(a, out, sub_dir_path, sub_base_dir);
} else if (entry->d_type == DT_REG) {
is_empty = false;
std::string file_path = dir_path + "/" + entry->d_name;
std::string base_file_path = base_dir.empty() ? entry->d_name : base_dir + "/" + entry->d_name;
compress_file(out, file_path, base_file_path);
}
}
closedir(dir);

if (is_empty) {
struct archive_entry *entry = archive_entry_new();
archive_entry_set_pathname(entry, base_dir.empty() ? get_name(dir_path).c_str() : base_dir.c_str());
archive_entry_set_filetype(entry, AE_IFDIR);
archive_entry_set_perm(entry, 0755);
archive_write_header(out, entry);
archive_entry_free(entry);
}
}

static napi_value Compress(napi_env env, napi_callback_info info) {
size_t argc = 3;
napi_value argv[3] = {nullptr};
napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);

size_t in_file_size;
char in_file_buf[256];
napi_get_value_string_utf8(env, argv[0], in_file_buf, sizeof(in_file_buf), &in_file_size);
std::string in_file(in_file_buf, in_file_size);

size_t out_file_size;
char out_file_buf[256];
napi_get_value_string_utf8(env, argv[1], out_file_buf, sizeof(out_file_buf), &out_file_size);
std::string out_file(out_file_buf, out_file_size);

size_t format_size;
char format_buf[10];
napi_get_value_string_utf8(env, argv[2], format_buf, sizeof(format_buf), &format_size);
std::string format(format_buf, format_size);

std::string dir_path = get_dir(out_file);
std::string temp_file_path = dir_path.empty() ? "/tmp/temp_archive_XXXXXX" : dir_path + "/temp_archive_XXXXXX";

int temp_fd = mkstemp(&temp_file_path[0]);
if (temp_fd == -1) {
return create_result(env, ErrorCode::CREATE_TEMP_FILE_ERROR);
}

struct archive *a;
struct archive *out;
a = archive_read_disk_new();
archive_read_disk_set_standard_lookup(a);

out = archive_write_new();
if (format == "7z") {
archive_write_set_format_7zip(out);
} else if (format == "tar") {
archive_write_set_format_pax_restricted(out);
} else if (format == "zip") {
archive_write_set_format_zip(out);
} else if (format == "gz") {
archive_write_set_format_gnutar(out);
archive_write_add_filter_gzip(out);
} else if (format == "xz") {
archive_write_set_format_gnutar(out);
archive_write_add_filter_xz(out);
} else {
return create_result(env, ErrorCode::UNSUPPORTED_FORMAT);
}

if (archive_write_open_fd(out, temp_fd) != ARCHIVE_OK) {
close(temp_fd);
return create_result(env, ErrorCode::ARCHIVE_ERROR, archive_error_string(out));
}

const char *original_locale = setlocale(LC_CTYPE, nullptr);
setlocale(LC_CTYPE, "en_US.UTF-8");

if (is_directory(in_file)) {
if (in_file.back() == '/') {
compress_directory(a, out, in_file.substr(0, in_file.size() - 1), "");
} else {
compress_directory(a, out, in_file, get_name(in_file));
}
} else {
compress_file(out, in_file, get_name(in_file));
}

archive_write_close(out);
archive_write_free(out);
archive_read_free(a);
close(temp_fd);

setlocale(LC_CTYPE, original_locale);

if (rename(temp_file_path.c_str(), out_file.c_str()) != 0) {
return create_result(env, ErrorCode::RENAME_FILE_ERROR);
}

return create_result(env, ErrorCode::SUCCESS);
}

static napi_value getFileList(napi_env env, napi_callback_info info) {

size_t argc = 2;
napi_value argv[2] = {nullptr};
napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);

size_t in_file_size;
char archive_path[256];
napi_get_value_string_utf8(env, argv[0], archive_path, sizeof(archive_path), &in_file_size);
std::string in_file(archive_path, in_file_size);

size_t out_file_size;
char target_path[256];
napi_get_value_string_utf8(env, argv[1], target_path, sizeof(target_path), &out_file_size);
std::string out_file(target_path, out_file_size);

struct archive *a = archive_read_new();
archive_read_support_format_all(a);
archive_read_support_filter_all(a);
//archive_read_set_options(a, "charset=UTF-8"); // 明确指定编码

setlocale(LC_CTYPE, "en_US.UTF-8");

if (archive_read_open_filename(a, archive_path, 10240) != ARCHIVE_OK) {
fprintf(stderr, "Error opening archive: %s\n", archive_error_string(a));
return NULL;
}

char* paths[256];
int capacity = 0;
int size = 0;

std::string out_list;

struct archive_entry* entry;
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
const char* pathname = archive_entry_pathname(entry);
out_list = out_list+strdup(pathname) +"-,";
// 复制路径字符串
}

return list_result(env, out_list);
}

static napi_value getFileData(napi_env env, napi_callback_info info){//获取单个文件

size_t argc = 2;
napi_value argv[2] = {nullptr};
napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);

size_t in_file_size;
char archive_path[256];
napi_get_value_string_utf8(env, argv[0], archive_path, sizeof(archive_path), &in_file_size);
std::string in_file(archive_path, in_file_size);

size_t out_file_size;
char target_path[256];
napi_get_value_string_utf8(env, argv[1], target_path, sizeof(target_path), &out_file_size);
std::string out_file(target_path, out_file_size);


struct archive *a = archive_read_new();
archive_read_support_format_all(a);
archive_read_support_filter_all(a);
setlocale(LC_CTYPE, "en_US.UTF-8");

if (archive_read_open_filename(a, archive_path, 10240) != ARCHIVE_OK) {
fprintf(stderr, "Error opening archive: %s\n", archive_error_string(a));
return nullptr;
}

struct archive_entry *entry;
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
const char *entry_path = archive_entry_pathname(entry);
if (strcmp(entry_path, target_path) == 0) {
// 创建父目录
char *last_sep = strrchr(target_path, '/');
if (last_sep) {
*last_sep = '\0';
mkdir(target_path, 0755); // 简化处理,实际需递归创建
*last_sep = '/';
}
// 写入文件
FILE *fp = fopen(target_path, "wb");
const void *buff;
size_t size;
off_t offset;
while (archive_read_data_block(a, &buff, &size, &offset) == ARCHIVE_OK) {
fwrite(buff, 1, size, fp);
}
fclose(fp);
printf("Extracted: %s\n", target_path);
break;
}
}

archive_read_close(a);
archive_read_free(a);


return create_result(env, ErrorCode::SUCCESS);

}

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor desc[] = {
{"decompress", nullptr, Decompress, nullptr, nullptr, nullptr, napi_default, nullptr},
{"compress", nullptr, Compress, nullptr, nullptr, nullptr, napi_default, nullptr},
{"getFileList", nullptr, getFileList, nullptr, nullptr, nullptr, napi_default, nullptr},
{"getFileData", nullptr, getFileData, nullptr, nullptr, nullptr, napi_default, nullptr},

};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
EXTERN_C_END

static napi_module mycompress = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = Init,
.nm_modname = "mycompress",
.nm_priv = nullptr,
.reserved = {0},
};

extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&mycompress); }

4.最后在CompressLib.ets文件里面调用:


import mycompress from 'libmyarchive.so'

export namespace CompressLib {
export interface Result {
code: number
message: string
}
export type CompressFormat = '7z' | 'tar' | 'zip' | 'gz' | 'xz'| 'rar'


export async function decompress(inFile: string, outFile: string): Promise {
return mycompress.decompress(inFile, outFile) as Result
}


export async function compress(inFile: string, outFile: string, format: CompressFormat): Promise {
return mycompress.compress(inFile, outFile, format) as Result
}

export async function getFileList(inFile: string,outFile: string): Promise {
return mycompress.getFileList(inFile,outFile) as Result
}

export async function getFileData(inFile: string,outFile: string): Promise {
return mycompress.getFileData(inFile,outFile) as Result
}
}

项目的UI文件用简单的ets编写:


在oh-package.json5配置依赖


"dependencies": {
"@mycompress/compress": "file:../compress"
}

在page/Index.ets里面使用:


import { fileIo as fs, ListFileOptions } from '@kit.CoreFileKit'
import { CompressLib } from '@mycompress/compress'


@Entry
@Component
struct Index {
private readonly context = getContext()
private readonly inFile = `${this.context.tempDir}/src`
//
private readonly formats: CompressLib.CompressFormat[] = ['7z', 'tar', 'zip', 'gz', 'xz','rar']
@State format: CompressLib.CompressFormat = '7z'

private outFile:string = `${this.context.filesDir}/compress`

async aboutToAppear() {
let curDir = this.inFile
for (let i = 0; i < 5; i++) {
if (!fs.accessSync(curDir)) {
await fs.mkdir(curDir, true)
}

const filepath = `${curDir}/${i}.txt`
if (!fs.accessSync(filepath)) {
const f = await fs.open(filepath, fs.OpenMode.CREATE | fs.OpenMode.WRITE_ONLY)
fs.write(f.fd, `test_${i}\ntest_${i}\ntest_${i}`)
fs.close(f)
}
curDir += `/${i}`
}
}

build() {
Column({space:10}) {
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
ForEach(this.formats, (format: CompressLib.CompressFormat) => {
Column() {
Text(format)
Radio({ value: format, group: 'radioGroup' })
.width(25)
.height(25)
.checked(this.format === format)
.onChange((isChecked: boolean) => {
if (isChecked) {
this.format = format
}
})
}
})
}.padding({ top: 30 })


Column(){
Text(`>>>>>>文件Test.txt<<<<<<`)
.width('90%')
.textAlign(TextAlign.Center)

Button('压缩').width('90%')
.onClick(async ()=>{

const ret = await CompressLib.compress(this.inFile, this.outFile, this.format)
if (ret.code === 0) {
console.log('压缩成功')
} else {
console.log(`压缩失败,code: ${ret.code}, message: ${ret.message}`)
}

})

}.layoutWeight(1)
.justifyContent(FlexAlign.SpaceAround)

Column(){
Text(`>>>>>>文件Test.zip<<<<<<`)
.width('90%')
.textAlign(TextAlign.Center)


Button('获取列表').width('90%')
.onClick(async ()=>{

const ret = await CompressLib.getFileList(this.inFile, this.outFile)
if (ret.code === 0) {
console.log('压缩成功')
} else {
console.log(`压缩失败,code: ${ret.code}, message: ${ret.message}`)
}

})
}.layoutWeight(1)
.justifyContent(FlexAlign.SpaceAround)

Column(){
Text(`>>>>>>文件Test.zip<<<<<<`)
.width('90%')
.textAlign(TextAlign.Center)

Button('获取单个文件').width('90%')
.onClick(async ()=>{
const ret = await CompressLib.getFileData(this.inFile, this.outFile)
if (ret.code === 0) {
console.log('压缩成功')
} else {
console.log(`压缩失败,code: ${ret.code}, message: ${ret.message}`)
}

})
}.layoutWeight(1)
.justifyContent(FlexAlign.SpaceAround)

Column(){
Text(`>>>>>>文件Test.zip<<<<<<`)
.width('90%')
.textAlign(TextAlign.Center)

Button('解压').width('90%')
.onClick(async ()=>{

const ret = await CompressLib.decompress(this.inFile, this.outFile)
if (ret.code === 0) {
console.log('压缩成功')
} else {
console.log(`压缩失败,code: ${ret.code}, message: ${ret.message}`)
}

})
}.layoutWeight(1)
.justifyContent(FlexAlign.SpaceAround)

}
.justifyContent(FlexAlign.Start)
.height('100%')
.width('100%')
}
}

综上,一个基本的NDK实现解压缩功能就完成了。


Demo链接:Stevenllv/compress_demo


学习路径如下:


1. 鸿蒙-ArkTS和Native之间的交互使用1——创建NDK工程-CSDN博客


2.鸿蒙-ArkTS和Native之间的交互使用2——如何调用Napi-CSDN博客


3.鸿蒙-ArkTS和Native之间的交互使用3——使用Node-API接口创建基本数据类型-CSDN博客


4.鸿蒙-ArkTS和Native之间的交互使用4——使用Node-API接口进行object相关开发-CSDN博客


5.鸿蒙-ArkTS和Native之间的交互使用5——使用原生Zip模块开发解压缩功能-CSDN博客


6.鸿蒙-ArkTS和Native之间的交互使用6——使用三方库jszip开发解压缩功能-CSDN博客


7.鸿蒙-ArkTS和Native之间的交互使用7——使用三方库 libarchive开发解压缩功能-CSDN博客


8.鸿蒙-ArkTS和Native之间的交互使用8——使用 libarchive创建compress的napi压缩接口-CSDN博客


9.鸿蒙-ArkTS和Native之间的交互使用9——使用 libarchive创建Decompress的napi压缩接口-CSDN博客


10.鸿蒙-ArkTS和Native之间的交互使用10——使用 libarchive创建getCompressList的napi压缩接口-CSDN博客


11.鸿蒙-ArkTS和Native之间的交互使用11——使用 libarchive创建getExtractFile的napi压缩接口-CSDN博客



posted @ 2025-06-28 15:43  同步—TLNX  阅读(73)  评论(0)    收藏  举报