鸿蒙(HarmonyOS)开发之无须申请权限写入图片到相册-灵析社区

chole

鸿蒙开发之不申请权限写入图片到相册 写入图片到相册介绍 在上一篇中,猫林老师给大家分享了如何在不申请权限的情况下读取相册内容。这一篇教大家如何写入图片到相册。 这在应用开发中,也是一个很常见的场景,比如我们要做一个文件扫描的功能。那是不是得把扫描的结果保存到图库呢?再比如我们做一个美颜的功能,那把相册里的原始图片读取出来后,经过我们的美容处理,是不是还得把美容后的结果写入回相册呢? 所以这也是我们必须要学习和掌握的内容。其实写入相册也是HarmonyOS管控的比较严的一个权限,但好在HarmonyOS依然考虑到写入相册对于开发者而言也是一个非常常用的一个功能,因而提供了两种方案来实现图片保存到相册,分别是: 安全控件保存 弹窗授权保存 安全控件保存 - 基本使用 这其实就是HarmonyOS提供的一个类似按钮一样的组件,他叫SaveButton,在界面上放一个它即可轻松实现保存,我们先看看它长啥样。我们在界面上写一个SaveButton,如下图 可以看到,从外形上看,就是一个带图标的按钮。当然,如果你要是觉得这个按钮的图标、文字不是你想要的,你还可以在使用时传递参数来修改。 对应的参数有 icon:设置图标,如果写SaveButton时写了{},并给了其他参数,唯独没给icon,则没有图标。如果要设置,仅能设置两个值,分别代表线条图标,填充图标。分别为:1SaveIconStyle.FULL_FILLEDSaveIconStyle.LINES这两个值没太大变化可以理解为前一个线条粗一条,后一个线条细一点 text: 设置文字,但是仅提供固定的几个文字让你选择,无法自定义。 buttonType:设置按钮样式、胶囊、圆形、普通(跟按钮的三大样式一样) 举个🌰,如下图 回到正题,如何使用它保存图片到相册呢?我们需要给它加点击事件 参数1:事件对象 参数2:用户授权结果,因为这个按钮自带弹框,问用户是否允许保存到图库,如下图。所以我们需要拿到用户的点击结果,只有点击了允许,我们才往下执行代码。那如何判断用户点了允许呢?就是根据SaveButtonOnClickResult,它有两个值:如果返回的结果是SUCCESS即为用户授权,如为:TEMPORARY_AUTHORIZATION_FAILED即为授权失败 安全控件保存 - 实现写入图片到图库(相册) 根据官方说明,需要两大步 调用MediaAssetChangeRequest类的的createImageAssetRequest方法创建一个资产变更请求 调用PhotoAccessHelper实例对象的 applyChanges方法,传入上述请求。用来提交本次媒体变更请求。 这里先解释下MediaAssetChangeRequest这个类,这个类是专门用来向系统做资产变更请求的。 那什么是手机资产呢?可以简单粗暴的理解为手机里的任意文件数据都是资产。比如图片是资产、视频也是资产。对资产做变更说人话就相当于是对这些文件做改变。所以,我们要写入一个图片到相册,就相当于是资产变更。就需要用到MediaAssetChangeRequest这个类。可是,根据我们刚刚说的,任意文件都叫资产,而我们这次要做的是给相册创建一张新图片,因此使用这个类的createImageAssetRequest方法,代表创建一个图片资产变更请求对象。 正如上面所说MediaAssetChangeRequest.createImageAssetRequest仅仅只是得到一个图片资产变更请求的对象,还得同意这个请求才行。怎么同意呢?即用PhotoAccessHelper实例对象的 applyChanges方法来向系统提交本次请求。 以上是对概念的解释,我们聊聊代码使用 MediaAssetChangeRequest类的的createImageAssetRequest方法需要传入两个参数。1. 当前上下文。 2. 图片的uri。 PhotoAccessHelper实例对象的 applyChanges方法,首先需要创建PhotoAccessHelper类的实例(这是一个专门用来管理相册的实例),再调用applyChanges。而PhotoAccessHelper的实例是通过photoAccessHelper.getPhotoAccessHelper方法,传入当前上下文对象得到的 对应代码如下 读取相册图片,并根据它创建一张一模一样的新图片写入到相册功能,代码如下 这一段代码不多,倒是概念需要理解。总而言之核心就是:准备一个创建图片的请求(通过URI指定创建什么图片),然后向系统提交本次请求 安全控件保存 - 优缺点总结 优点:代码简单,固定的两大步:创建请求、提交请求 缺点:必须再在界面上提供一个额外按钮,且此按钮无法深度自定义 弹窗授权保存 - 基本使用 这是一套不用在界面上额外添加按钮,或者也可以深度进行按钮定制的一套方式。 其开发步骤虽对比安全控件步骤略多,但依然属于比较简单实现的一种方式(我们后续如果做文档扫描功能,会用这种方式更恰当)。 我们来看看大概的实现步骤: 指定待保存到图库(相册)的图片URI 指定待保存照片的创建选项,包括文件后缀和照片类型,文件标题等 调用showAssetsCreationDialog,基于弹窗授权的方式获取媒体库的目标uri 将来源照片内容写入到媒体库的目标uri(需要用到fs文件流读取原图,写入目标图) 根据步骤,我们来看看大致实现代码,如下 这里因为篇幅关系,就不解释文件流了。跟Node、Java等语言中的文件流概念完全一致。无非就是读取、写入两套。这里略过不表。 这里需要解释的代码是:photoCreationConfigs用来设置写入到相册里的文件之文件名、文件类型、后缀等 showAssetsCreationDialog会出来一个弹窗 当然,如果你实在看不懂代码,猫林老师给你个绝招:这段代码你会复制即可。然后需要改的部分仅仅只有两处 来源图片URI也即srcFileUri这个变量,把这个变量改成你要写入到相册的原始图片路径。 photoCreationConfigs这个变量里,把要写入的新图片文件名改了 弹窗授权保存 - 实现写入图片到图库 我们继续实现一个读取相册图片,并根据它创建一张一模一样的新图片写入到相册功能,代码如下 import { photoAccessHelper } from '@kit.MediaLibraryKit'; import { fileIo } from '@kit.CoreFileKit'; @Entry @Component struct Index { @State imgUri: string = '' build() { Column({ space: 20 }) { // 选择图片 Button('选择图片') .width('80%') .onClick(() => { // 实例化选择器 let photoPicker = new photoAccessHelper.PhotoViewPicker() // 开始选择图片,设置只允许选择图片,且最大选择1张 photoPicker.select({ MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE, maxSelectNumber: 1 }) .then((res: photoAccessHelper.PhotoSelectResult) => { // 读取成功则赋值给变量去展示到界面 this.imgUri = res.photoUris[0] }) .catch((err: Error) => { // 出错回调 console.log(err.message) }) }) Button('保存图片') .width('80%') .onClick(async () => { try { // 仅仅替换成我们想要写入的原本图片URI let srcFileUri = this.imgUri; // 因为接下来的方法需要传入的是来源URI数组,所以包装成数组 let srcFileUris: Array = [ srcFileUri ]; // 指定待保存照片的创建选项,包括文件后缀和照片类型,标题和照片子类型可选 let photoCreationConfigs: Array = [ { title: 'test', // 可选,文件名 fileNameExtension: 'jpg', // 文件后缀 photoType: photoAccessHelper.PhotoType.IMAGE, // 文件类型 } ]; // 获得当前上下文 let context = getContext(this); let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context); // 基于弹窗授权的方式获取媒体库的目标uri // 这句代码会弹出一个窗提示框,并显示出待写入相册的图片,问用户是否允许保存 let desFileUris: Array = await phAccessHelper.showAssetsCreationDialog(srcFileUris, photoCreationConfigs); // 设置一个写入文件流,文件位置为上面设置的相册位置 let desFile: fileIo.File = await fileIo.open(desFileUris[0], fileIo.OpenMode.WRITE_ONLY); // 设置一个读取文件流,文件位置为之前的来源图片URI let srcFile: fileIo.File = await fileIo.open(srcFileUri, fileIo.OpenMode.READ_ONLY); // 开始将读出来的文件流复制给写文件流(即往相册写内容) await fileIo.copyFile(srcFile.fd, desFile.fd); // 关闭文件流 fileIo.closeSync(srcFile); fileIo.closeSync(desFile); } catch (err) { console.error(`failed to create asset by dialog successfully errCode is: ${err.code}, ${err.message}`); } }) } .width('100%') .height('100%') } } 细心的读者已经发现了,这个代码仅仅就是复制基本使用里的代码,只是替换了srcFileUri这个变量的值。这也能实现图片写入。 总结 由于HarmonyOS对用户的隐私绝对保护,导致相册读写的权限难以申请。好在HarmonyOS提供了这种无须申请权限即可读取与写入相册的方法。 虽看代码感觉繁琐略多,但实际上代码都是固定的,例如上述的弹窗授权。我们仅需改改来源图片URI即可 本篇内容请一定要有印象。因为后续我们要是制作文档扫描功能会用到

阅读量:977

点赞量:36

收藏量:0