介紹
本示例主要介紹Native如何將網絡上的圖片及Rawfile中的圖片保存到應用沙箱中。
效果圖預覽
使用說明
rawfile路徑下存有一張圖片sandBoxTest.jpg。
設備連接上網絡。
點擊"保存Rawfile圖片",前端通過調用Native側暴露的saveImageOfRawfileCallback接口將rawfile中的圖片sandBoxTest.jpg保存到應用沙箱中并返回沙箱路徑到前端進行顯示;點擊“保存網絡圖片”,前端通過調用Native側暴露的saveImageOfInternetCallback接口將網絡圖片https://gitee.com/harmonyos-cases/cases/raw/master/CommonAppDevelopment/feature/imagedepthcopy/src/main/resources/rawfile/depthCopy.png保存到應用沙箱中并返回沙箱路徑到前端進行顯示。
具體代碼可參考NativePictureToSandboxView.ets以及native_picture_to_sandbox.cpp。
實現思路
Native保存網絡圖片到沙箱的實現主要步驟如下:
參考libcurl編譯,編譯libcurl.so等相關庫文件。當前編譯后加載libcurl.so時,通過hilog日志發現依賴了libcurl.so libcurl.so.4 libnghttp2.so libnghttp2.so.14 libzstd.so幾個so文件。
其中libcurl.so為開源的跨平臺網絡協議庫,支持七層網絡模型中應用層的各種協議;libnghttp2.so是一個HTTP/2和SPDY協議的實現,用于客戶端,服務器,代理,和服務器推送應用;libzstd.so是一個實現了Zstandard算法的壓縮庫,常用于數據庫、文件系統及網絡傳輸等。將開源庫libcurl相關的so文件以及封裝了libcurl下載功能的libcurlDownload.so放入模塊下的libs相應目錄。
在CMakeLists中導入相關庫文件。
target_link_directories(nativesavepictosandbox PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/)
target_link_libraries(nativesavepictosandbox PUBLIC libace_napi.z.so libcurlDownload.so libhilog_ndk.z.so librawfile.z.so)
- 在前端通過調用Native中的saveImageOfInternetCallback接口獲取沙箱地址并將沙箱地址轉換為url地址綁定到Image組件顯示。傳入的參數為網絡圖片地址、應用的文件路徑、沙箱中的文件名。
Button($r('app.string.nativesavepictosandbox_tbn_InternetPicture'))
.onClick(() => {
// TODO:知識點:通過Native暴露的接口saveImageOfInternetCallback接口獲取下載的網絡圖片保存在沙箱中的路徑
testNapi.saveImageOfInternetCallback(this.internetPicUrl, this.fileDir, this.internetSandBoxFileName, ((result: string) => {
if (result === undefined || result === '') {
AlertDialog.show({
message: $r('app.string.nativesavepictosandbox_internet_file_write_fail'),
alignment: DialogAlignment.Center
});
this.internetSandBoxPath = '';
} else {
this.internetSandBoxPath = fileUri.getUriFromPath(result);
logger.info('[pic2sandbox]', `saveImageOfInternet sandboxPath is ` + result);
}
}))
})
- 在Native的saveImageOfInternetCallback接口中通過調用libcurlDownload.so的接口將網絡圖片寫入沙箱。
// TODO:知識點:使用dlopen動態加載so庫,返回so庫的句柄
void *handler = dlopen(libCurlDownload, RTLD_LAZY);
if (handler == nullptr) {
// 拋出加載庫失敗的錯誤
dlerror();
return;
}
// 聲明函數指針類型
typedef std::string (*DownloadInternetFileFunc)(char *, char *);
DownloadInternetFileFunc downloadInternetWrapper =
reinterpret_cast<DownloadInternetFileFunc>(dlsym(handler, "DownloadInternetFileWrapper"));
if (downloadInternetWrapper) {
// TODO:知識點:調用so的downloadInternetWrapper函數保存網路圖片到沙箱
CallbackInternetContext *internetContext = (CallbackInternetContext *)data;
if (internetContext == nullptr) {
OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "saveImageOfInternet internetContext is null");
return;
}
// 圖片沙箱完整路徑
std::string targetSandboxPath = internetContext->sandboxDir + internetContext->FileName;
OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "saveImageOfInternet 保存沙箱文件:%{public}s",
targetSandboxPath.c_str());
internetContext->result = downloadInternetWrapper((char *)internetContext->internetPicUrl.c_str(),
(char *)targetSandboxPath.c_str());
OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "saveImageOfInternet download finish");
dlclose(handler);
} else {
OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "saveImageOfInternet download function is null");
dlclose(handler);
}
Native保存Rawfile圖片到沙箱的實現主要步驟如下:
- 在前端通過調用Native中的saveImageOfRawfileCallback接口獲取沙箱地址并將沙箱地址轉換為url地址綁定到Image組件顯示。傳入的參數為js的資源對象、rawfile中的圖片名、應用的文件路徑。
Button($r('app.string.nativesavepictosandbox_tbn_RawFilePicture'))
.onClick(() => {
// TODO:知識點:通過Native暴露的接口saveImageOfRawfileCallback接口獲取rawfile中圖片保存在沙箱中的路徑
testNapi.saveImageOfRawfileCallback(this.resMgr, this.rawfilePicPath, this.fileDir, ((result: string) => {
if (result === undefined || result === '') {
AlertDialog.show({
message: $r('app.string.nativesavepictosandbox_rawfile_write_fail'),
alignment: DialogAlignment.Center
});
this.rawfileSandBoxPath = '';
} else {
this.rawfileSandBoxPath = fileUri.getUriFromPath(result);
logger.info('[pic2sandbox]', `saveImageOfRawfile sandboxPath is ` + result);
}
}))
})
- 在Native的saveImageOfRawfileCallback接口中通過Rawfile的API接口以及文件流將圖片資源寫入沙箱。
// 打開Rawfile文件。
RawFile *rawFile = OH_ResourceManager_OpenRawFile(rawFileContext->resMgr,
rawFileContext->rawFileName.c_str());
if (rawFile == nullptr) {
OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "saveImageOfRawfile OpenRawFile fail!");
// 釋放資源
OH_ResourceManager_ReleaseNativeResourceManager(rawFileContext->resMgr);
return;
}
// 獲取文件大小
long imageDataSize = OH_ResourceManager_GetRawFileSize(rawFile);
// 申請內存
std::unique_ptr<char[]> imageData = std::make_unique<char[]>(imageDataSize);
// TODO:知識點:通過Rawfile的API接口讀取Rawfile文件
long rawFileOffset = OH_ResourceManager_ReadRawFile(rawFile, imageData.get(), imageDataSize);
// 保存目標網絡圖片的沙箱路徑
std::string targetSandboxPath = rawFileContext->sandboxDir + rawFileContext->rawFileName;
// TODO:知識點:通過std::ofstream,將讀取的數據寫入沙箱文件
std::ofstream outputFile(targetSandboxPath, std::ios::binary);
if (!outputFile) {
OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "saveImageOfRawfile 創建沙箱目標文件失敗");
// 釋放資源
OH_ResourceManager_CloseRawFile(rawFile);
OH_ResourceManager_ReleaseNativeResourceManager(rawFileContext->resMgr);
return;
}
// 寫文件
outputFile.write(imageData.get(), imageDataSize);
高性能知識點
不涉及
工程結構&模塊類型
nativesavepictosandbox // har類型
|---src\main\ets\view\
| |---NativePictureToSandboxView.ets // 視圖層-圖片寫入沙箱場景主頁面
|---src\main\cpp\
| |---native_picture_to_sandbox.cpp // native層-圖片寫入沙箱業務邏輯
|---src\main\cpp\curl // libcurl三方庫頭文件
寫在最后
- 如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:
- 點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。
- 關注小編,同時可以期待后續文章ing??,不定期分享原創知識。
- 想要獲取更多完整鴻蒙最新學習知識點,請移步前往小編:
https://gitee.com/MNxiaona/733GH/blob/master/jianshu