鸿蒙保存图片到相册

在其它手机端,若想保存图片到相册,需要申请对应的权限,而鸿蒙中对应的权限为受限开放权限,普通应用一般不让申请,这个时候我们可以使用安全保存控件来临时申请权限,用于保存图片到相册。

受限开放权限

应用权限分为三类,一类是对所有应用开放,所有应用均可申请使用;一类是受限开放权限,仅少量符合特殊场景的应用可在通过审批后,使用受限权限;最后一类是仅对MDM(Mobile Device Management)设备管理应用开放。

保存图片到相机涉及到的权限是ohos.permission.WRITE_IMAGEVIDEO,仅特殊场景与功能才可申请此权限,例如应用需要克隆、备份或同步图片/视频类文件,其它场景下使用安全控件来临时申请权限。

使用安全控件保存本地图片到相机

我们先使用安全控件让用户点击临时获取权限,获取到权限后,再使用photoAccessHelper来将我们本地的图片保存在相册,示例如下

import { photoAccessHelper } from '@kit.MediaLibraryKit'

@Entry
@ComponentV2
struct Index {

  build() {
    Column() {
      SaveButton({ icon: SaveIconStyle.LINES, text: SaveDescription.SAVE_TO_GALLERY, buttonType: ButtonType.Capsule })
        .onClick(() => {
          this.savePhotoToGallery().then(() => {
            this.getUIContext().getPromptAction().showToast({ message: '保存成功' })
          }).catch((err: Error) => {
            this.getUIContext().getPromptAction().showToast({ message: err.message })
          })
        })
    }
  }

  public async savePhotoToGallery(): Promise<void> {
    const ctx = getContext()
    const helper = photoAccessHelper.getPhotoAccessHelper(ctx)
    const src = ctx.resourceDir + '/icon.png'
    const request = photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(ctx, src)
    return helper.applyChanges(request)
  }
}

以上示例请保证icon.png在本地真实的存在。当我们使用helper调用applyChanges时,因为是在安全控件点击后调用的,临时获取权限,可以正常执行,若不在安全控件内,则需保证已获取对应的权限。

## 使用安全控件保存服务端图片到相机

服务端图片我们一般使用下载服务将图片下载到本地,若本地不需要备份,则直接将下载好的图片buffer保存到相册即可。我们将本地图片转成buffer来模拟服务端下载后的图片,再使用photoAccessHelper创建一个相册图片资源,并将我们的图片buffer写入到这个图片资源中,就可以将图片保存到相册了,示例如下

import { photoAccessHelper } from '@kit.MediaLibraryKit'
import fs from '@ohos.file.fs'
@Entry
@ComponentV2
struct Index {

  build() {
    Column() {
      SaveButton({ icon: SaveIconStyle.LINES, text: SaveDescription.SAVE_TO_GALLERY, buttonType: ButtonType.Capsule })
        .onClick(() => {
          this.savePhotoToGallery().then(() => {
            this.getUIContext().getPromptAction().showToast({ message: '保存成功' })
          }).catch((err: Error) => {
            this.getUIContext().getPromptAction().showToast({ message: err.message })
          })
        })
    }
  }

  public async savePhotoToGallery(): Promise<void> {
    const ctx = getContext()
    const helper = photoAccessHelper.getPhotoAccessHelper(ctx)
    return Promise.all([helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'png').then((uri) => {
      return fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
    }), ctx.resourceManager.getMediaContent($r('app.media.app_icon').id, 0)]).then((array) => {
      fs.writeSync(array[0].fd, array[1].buffer)
      fs.closeSync(array[0].fd)
    })
  }
}

使用保存确认弹窗保存图片

前面的方式都是强依赖于安全控件,但在有些场景下,我们没办法使用安全控件,比如在H5页面中,再比如在Flutter页面中等等,这个时候我们可以借助保存确认弹窗来保存图片。当我们通过photoAccessHelper调用showAssetsCreationDialog时,系统会弹出一个确认弹窗,用户点击允许,则我们可以将图片保存到相册,若用户点击禁止,则不能保存图片到相册。使用这种方式,我们就不用强依赖于安全控件了,示例如下

import { photoAccessHelper } from '@kit.MediaLibraryKit'
import fs from '@ohos.file.fs'

@Entry
@ComponentV2
struct Index {
  @Local isShowHome: boolean = false

  build() {
    Column() {
      Button('保存图片到相册').onClick(()=>{
        this.savePhotoToGallery().then(() => {
          this.getUIContext().getPromptAction().showToast({ message: '保存成功' })
        }).catch((err: Error) => {
          this.getUIContext().getPromptAction().showToast({ message: err.message })
        })
      })
    }
  }

  public async savePhotoToGallery(): Promise<void> {
    const ctx = getContext()
    const helper = photoAccessHelper.getPhotoAccessHelper(ctx)
    const src = ctx.resourceDir + '/icon.png'
    const desFileUris = await helper.showAssetsCreationDialog([src], [{
      title: 'test',
      fileNameExtension: 'png',
      photoType: photoAccessHelper.PhotoType.IMAGE
    }])
    const desFile = fs.openSync(desFileUris[0], fs.OpenMode.WRITE_ONLY)
    const srcFile = fs.openSync(src, fs.OpenMode.READ_ONLY)
    fs.copyFileSync(srcFile.fd, desFile.fd)
    fs.closeSync(srcFile)
    fs.closeSync(desFile)
  }
}

以上示例请保存icon.png在本地真实存在。

posted @ 2024-12-31 10:34  龙儿筝  阅读(182)  评论(0编辑  收藏  举报