純血鴻蒙APP實戰開發——Native保存圖片到應用沙箱

介紹

本示例主要介紹Native如何將網絡上的圖片及Rawfile中的圖片保存到應用沙箱中。

效果圖預覽

使用說明

  1. rawfile路徑下存有一張圖片sandBoxTest.jpg。

  2. 設備連接上網絡。

  3. 點擊"保存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保存網絡圖片到沙箱的實現主要步驟如下:

  1. 參考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算法的壓縮庫,常用于數據庫、文件系統及網絡傳輸等。

  2. 將開源庫libcurl相關的so文件以及封裝了libcurl下載功能的libcurlDownload.so放入模塊下的libs相應目錄。

  3. 在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)
  1. 在前端通過調用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);
              }
            }))
          })
  1. 在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圖片到沙箱的實現主要步驟如下:

  1. 在前端通過調用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);
              }
            }))
          })
  1. 在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
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容