HarmonyOS鸿蒙Next中项目中resources目录下的文件,C++层/native侧应该怎么访问
HarmonyOS鸿蒙Next中项目中resources目录下的文件,C++层/native侧应该怎么访问
开发场景: 从网络下载文件,然后把文件的访问路径通过 N-API 传递给 C++
目前问题:
- 目前的做法是从下载目录或者工程静态目录resources下,将文件拷贝到沙盒中,然后将沙盒中的路径发给C++ 我想了解一下,目前是需要这种实现方式吗? 可以类似安卓通过开通权限C++直接访问某些目录文件吗 目前有将文件拷贝到沙盒中的API方法吗? 谢谢
解决措施
可以通过createModuleContext(moduleName)接口创建同应用中不同module的上下文,获取到resourceManager对象后,在Native侧使用Native Rawfile接口操作Rawfile目录和文件来跨模块访问资源。
具体使用方式可参考以下代码:
-
在src/main/cpp/CMakeLists.txt文件中,添加依赖资源librawfile.z.so。
target_link_libraries(nativecrossmoduleaccessres PUBLIC libace_napi.z.so libace_napi.z.so libhilog_ndk.z.so librawfile.z.so)
-
在src/main/cpp/types/libentry/index.d.ts文件中,声明应用侧函数getRawFileContent。
import { resourceManager } from "@kit.LocalizationKit"; export const getRawFileContent: (resMgr: resourceManager.ResourceManager, path: string) => Uint8Array;
-
在src/main/cpp/napi_init.cpp文件中实现功能代码。
#include "napi/native_api.h" #include <rawfile/raw_file.h> #include <rawfile/raw_file_manager.h> #include "hilog/log.h" const int GLOBAL_RESMGR = 0xFF00; const char *TAG = "[Sample_rawfile]"; namespace { napi_value CreateJsArrayValue(napi_env env, std::unique_ptr<uint8_t[]> &data, long length) { napi_value buffer; napi_status status = napi_create_external_arraybuffer( env, data.get(), length, [](napi_env env, void *data, void *hint) { delete[] static_cast<char *>(data); }, nullptr, &buffer); if (status != napi_ok) { OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "Failed to create external array buffer"); return nullptr; } napi_value result = nullptr; status = napi_create_typedarray(env, napi_uint8_array, length, buffer, 0, &result); if (status != napi_ok) { OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "Failed to create media typed array"); return nullptr; } data.release(); return result; } } static napi_value GetRawFileContent(napi_env env, napi_callback_info info) { OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "GetFileContent Begin"); size_t requireArgc = 3; size_t argc = 2; napi_value argv[2] = { nullptr }; // 获取参数信息 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); // argv[0]即为函数第一个参数Js资源对象,OH_ResourceManager_InitNativeResourceManager转为Native对象。 NativeResourceManager *mNativeResMgr = OH_ResourceManager_InitNativeResourceManager(env, argv[0]); size_t strSize; char strBuf[256]; napi_get_value_string_utf8(env, argv[1], strBuf, sizeof(strBuf), &strSize); std::string filename(strBuf, strSize); // 获取rawfile指针对象 RawFile *rawFile = OH_ResourceManager_OpenRawFile(mNativeResMgr, filename.c_str()); if (rawFile != nullptr) { OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "OH_ResourceManager_OpenRawFile success"); } // 获取rawfile大小并申请内存 long len = OH_ResourceManager_GetRawFileSize(rawFile); std::unique_ptr<uint8_t[]> data= std::make_unique<uint8_t[]>(len); // 一次性读取rawfile全部内容 int res = OH_ResourceManager_ReadRawFile(rawFile, data.get(), len); // 关闭打开的指针对象 OH_ResourceManager_CloseRawFile(rawFile); OH_ResourceManager_ReleaseNativeResourceManager(mNativeResMgr); // 转为js对象 return CreateJsArrayValue(env, data, len); }
-
ArkTS侧调用,此处需要传入资源对象。
import testNapi from 'libnativecrossmoduleaccessres.so'; @Entry @Component struct Index { @State message: string = 'Native Cross Module Access Resource'; private resMgr = getContext().createModuleContext('NativeAccessRes').resourceManager; // 获取本应用包的资源对象 build() { Row() { Column() { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) .onClick(() => { let rawfileContext = testNapi.getRawFileContent(this.resMgr, 'rawfile.txt'); console.log("rawfileContext" + rawfileContext); }) } .width('100%') } .height('100%') } }
转载自如何在Native侧跨模块访问资源-NDK开发-NDK开发-应用框架开发-开发 - 华为HarmonyOS开发者 (huawei.com)
更多关于HarmonyOS鸿蒙Next中项目中resources目录下的文件,C++层/native侧应该怎么访问的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中,C++层或native侧访问resources
目录下的文件,可以通过OH_ResourceManager
接口实现。首先使用OH_ResourceManager_Init
初始化资源管理器,然后通过OH_ResourceManager_GetResource
获取资源文件路径或内容。具体资源路径可通过OH_ResourceManager_GetResourcePath
获取,资源内容可通过OH_ResourceManager_GetResourceData
读取。确保在config.json
中正确配置资源路径。
在HarmonyOS Next中,C++/native层访问resources目录文件的最佳实践是通过沙盒机制。目前确实需要先将文件从resources或下载目录拷贝到应用沙盒中,再将沙盒路径传递给C++层。
关于具体实现:
- 资源文件访问:推荐使用
@ohos.fileio
模块的copy
接口将resources文件拷贝到应用沙盒目录(context.filesDir
) - 下载文件处理:网络下载的文件应直接保存到沙盒目录,无需二次拷贝
- 路径传递:将沙盒中的文件路径通过NAPI传递给C++层
当前HarmonyOS的安全机制限制了native层直接访问非沙盒目录,这是出于安全考虑的设计。与Android不同,HarmonyOS没有提供直接开放目录权限给native层访问的机制。
对于文件操作,可以使用@ohos.file.fs
模块的相关API进行文件拷贝和管理。例如使用copyFile()
方法将文件复制到沙盒目录。