前言
保存图片功能几乎是每个应用程序必备的功能之一,当用户遇到喜欢的图片时可以保存到手机相册。那么在鸿蒙中保存图片是否也需要申请用户存储权限以及如何将图片保存到相册,本文将详细讲述怎么保存网络图片,指定布局生成图片保存至相册的功能实现。
实现效果
需求分析
一般在 Android 或 iOS 上保存图片都需要申请应用存储权限,否则将禁止访问应用存储,不能保存图片到磁盘中。在鸿蒙系统中当然也有存储权限,但是鸿蒙系统对于权限管理十分严格,一般情况下,禁止用户申请访问存储权限。但是提供了系统级别的安全控件,不需要用户手动申请权限,用于存储的直接访问。
- 可以使用系统提供的安全控件实现权限的直接访问。
- 同时也提供申请权限方式进行存储权限的访问。
- 使用网络请求将图片转成流,然后保存成图片。
技术实现
申请权限方式
- 权限申请
const permissions: Array<Permissions> = [ 'ohos.permission.WRITE_IMAGEVIDEO' ]; const context = getContext(this) as common.UIAbilityContext; const atManager = abilityAccessCtrl.createAtManager(); await atManager.requestPermissionsFromUser(context, permissions);
- 权限判断
PermissionUtil.checkAccessToken(permissions[0]).then((status)=>{ if (status == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) { FileSaveManager.getPicture(this.imagePath) }else{ PermissionUtil.openPermissionsInSystemSettings(getContext(this) as common.UIAbilityContext) } })
安全控件方式
SaveButton({ text: SaveDescription.SAVE_IMAGE, buttonType: ButtonType.Normal }) .fontColor(Color.White) .fontWeight(FontWeight.Medium) .onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => { if (result == SaveButtonOnClickResult.SUCCESS) { try { this.saveImage() } catch (error) { console.error("error is " + JSON.stringify(error)); } } })
可以看出通过系统安全控件 SaveButton 可以临时访问系统存储,不需要申请任何权限。更好的保护用户隐私安全,这也是鸿蒙官方提倡使用的方式。
网络图片保存
- 下载图片,并将数据转化为 ArrayBuffer 类型。
/** * 通过http的request方法从网络下载图片资源 */ static async getPicture(url:string) { http.createHttp() .request(url, (error: Error, data: http.HttpResponse) => { if (error) { showShortCenterToast("图片保存失败") return; } // 判断网络获取到的资源是否为ArrayBuffer类型 if (data.result instanceof ArrayBuffer) { FileSaveManager.saveImageToPhoto(data.result as ArrayBuffer) } } ) }
- 保存图片到相册
/** * 保存ArrayBuffer到图库 * @param buffer:图片ArrayBuffer * @returns */ static async saveImageToPhoto(buffer: ArrayBuffer | string): Promise<void> { const context = getContext() as common.UIAbilityContext; // 获取getPhotoAccessHelper需要的context const helper = photoAccessHelper.getPhotoAccessHelper(context); // 获取相册管理模块的实例 const uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg'); // 指定待创建的文件类型、后缀和创建选项,创建图片或视频资源 const file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); let r = await fs.write(file.fd, buffer); await fs.close(file.fd); showShortCenterToast("图片保存成功") }
指定布局保存
在 Android 或 iOS 中,经常会遇到需要保存指定样式的布 View 为图片。Android 中则需要使用 View 的绘制,将布局绘制出来后,再进行保存。但是在鸿蒙中实现起来就比较简单。
1. 将需要保存的 View 布局指定 Id。
Column() { //布局样式 } .id("root")
- 通过 id 将 View 保存成图片。
componentSnapshot.get("photo", (error: Error, pixmap: image.PixelMap) => { if (error) { console.log("error: " + JSON.stringify(error)) return; } const packOpts : image.PackingOption = { format:"image/jpeg", quality:98 }; imagePackerApi.packing(pixmap, packOpts).then( async (data : ArrayBuffer) => { FileSaveManager.saveImageToPhoto(data) }).catch((error : BusinessError) => { console.error('Failed to pack the image. And the error is: ' + error); }) })
总结
对比 Android 或 iOS 来说,鸿蒙在实现功能上相对简单,比较容易上手。但是鸿蒙对于用户权限的获取要求比较严格,正式上线一般都需要使用系统提供的安全组件访问应用程序的相册或存储,日常开发中需要十分注意,以免影响项目的正常上线。