写点什么

最受欢迎的三方库之 picker_utils

  • 2025-06-27
    安徽
  • 本文字数:9145 字

    阅读完需:约 30 分钟

picker_utils (API12+)

🏆简介与推荐

picker_utilsharmony-utils 拆分出来的一个子库,包含 PickerUtil、PhotoHelper、ScanUtil。


主要解决:当使用 harmony-utils 三方库且未使用 picker 能力时,隐私政策中无需声明相机权限与储存权限。

🌞下载安装

ohpm i @pura/picker_utils


OpenHarmony ohpm 环境配置等更多内容,请参考如何安装 OpenHarmony ohpm 包<br>

📚API 详解 使用案例

📂模块介绍

PickerUtil(拍照、文件选择和保存,工具类)使用案例

PhotoHelper(相册相关,工具类)使用案例

ScanUtil(码工具类(扫码、码图生成、图片识码))使用案例


import { router } from '@kit.ArkUI';import { DateUtil, FileUtil, ImageUtil, LogUtil, PreferencesUtil, StrUtil, ToastUtil } from '@pura/harmony-utils';import { DescribeBean } from '../../model/DescribeBean';import { BusinessError } from '@kit.BasicServicesKit';import { image } from '@kit.ImageKit';import { MockSetup } from '@ohos/hamock';import { TitleBarView } from '../../component/TitleBarView';import { camera, cameraPicker } from '@kit.CameraKit';import { picker } from '@kit.CoreFileKit';import { CameraOptions, PickerUtil } from '@pura/picker_utils';

/** * 拍照、文件(文件、图片、视频、音频)选择和保存,工具类 */@Entry@Componentstruct Index { private scroller: Scroller = new Scroller(); @State describe: DescribeBean = router.getParams() as DescribeBean; @State uriStr: string = '' @State filePath: string = ''; //本地图片path @State cacheUri: string = ''; //缓存本地Uri,上次保存的Uri。

@MockSetup mock() { this.describe = new DescribeBean("PickerUtil", "拍照、文件(文件、图片、视频、音频)选择和保存,工具类"); }

async aboutToAppear(): Promise<void> { this.cacheUri = PreferencesUtil.getStringSync("picker_cache_uri"); let pixelMap = await ImageUtil.getPixelMapFromMedia($r("app.media.test_as4")) this.filePath = await ImageUtil.savePixelMap(pixelMap, FileUtil.getFilesDirPath(""), "漂亮小姐姐.png") LogUtil.error("filePath: " + this.filePath); }
build() { Column() { TitleBarView({ describe: this.describe }) Divider() Scroll(this.scroller) { Column() { Button("cameraEasy()") .btnStyle() .onClick(async () => { PickerUtil.cameraEasy().then((uri) => { this.uriStr = `调用相机,返回uri:\n${uri}`; }).catch((err: BusinessError) => { this.uriStr = `调用相机,异常:\n${JSON.stringify(err)}`; }); }) Button("camera()") .btnStyle() .onClick(async () => { let options: CameraOptions = { mediaTypes: [cameraPicker.PickerMediaType.PHOTO], cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK } PickerUtil.camera(options).then((result) => { this.uriStr = `调用相机,返回uri:\n${result.resultUri}`; }).catch((err: BusinessError) => { this.uriStr = `调用相机,异常:\n${JSON.stringify(err)}`; }); }) Button("selectPhoto()") .btnStyle() .onClick(() => { PickerUtil.selectPhoto().then((uris) => { this.uriStr = `调用相册,返回uris:\n${uris.join('\n')}`; }).catch((err: BusinessError) => { this.uriStr = `调用相册,异常:\n${JSON.stringify(err)}`; }); }) Button("savePhoto()") .btnStyle() .onClick(() => { let imgName = `大漂亮_${DateUtil.getTodayTime()}.png`; let imgName1 = `小漂亮_${DateUtil.getTodayTime()}.png`; PickerUtil.savePhoto([imgName, imgName1]).then(async (uris) => { let uri = uris[0]; this.uriStr = `调用保存图片,返回uris:\n${uri}` let file = FileUtil.openSync(uri); FileUtil.copyFile(this.filePath, file.fd).then(() => { this.uriStr = `保存图片,返回uris:\n${uri}` ToastUtil.showToast("图片1保存成功"); })
let file1 = FileUtil.openSync(uris[1]); let pixelMap1 = await ImageUtil.getPixelMapFromMedia($r("app.media.test_as3")) let packOpts: image.PackingOption = { format: 'image/png', quality: 100 } ImageUtil.packToFileFromPixelMap(pixelMap1, file1.fd, packOpts).then(() => { this.uriStr = `保存图片,返回uris:\n${uris[1]}` ToastUtil.showToast("图片2保存成功"); }) }).catch((err: BusinessError) => { this.uriStr = `调用保存图片,异常:\n${JSON.stringify(err)}` }) }) Button("selectDocument()") .btnStyle() .onClick(() => { let options: picker.DocumentSelectOptions = { maxSelectNumber: 9, //选择媒体文件数量的最大值,默认9。 selectMode: picker.DocumentSelectMode.FILE, //支持选择的资源类型,默认文件 // fileSuffixFilters: ['图片(.png, .jpg)|.png,.jpg', '文档|.txt', '视频|.mp4', '.pdf'], //选择文件的后缀类型['后缀类型描述|后缀类型'](可选) 若选择项存在多个后缀名,则每一个后缀名之间用英文逗号进行分隔(可选),后缀类型名不能超过100,选择所有文件:'所有文件(*.*)|.*'; // defaultFilePathUri: "file://docs/storage/Users/currentUser/Download/com.harmony.utils", //指定选择的文件或者目录路径(可选) // authMode: true //选择是否对指定文件或目录授权,true为授权,当为true时,defaultFilePathUri为必选参数。 } PickerUtil.selectDocument(options).then((uris) => { this.uriStr = `调用文件管理,返回uris:\n${uris.join('\n')}` }).catch((err: BusinessError) => { this.uriStr = `调用文件管理,异常:\n${JSON.stringify(err)}` }); }) Button("saveDocumentEasy()") .btnStyle() .onClick(() => { let fileName = `test_easy_${DateUtil.getTodayTime()}.txt`; PickerUtil.saveDocumentEasy([fileName]).then((paths) => { let path = paths[0]; this.cacheUri = FileUtil.getUriFromPath(path); PreferencesUtil.put("picker_cache_uri", this.cacheUri); let txtStr = `“harmony-utils 一款高效的OpenHarmony/HarmonyOS工具包,封装了常用工具类,提供一系列简单易用的方法。帮助开发者快速构建鸿蒙应用。\n\n`; FileUtil.writeEasy(path, txtStr).then(() => { this.uriStr = `文件保存成功,返回uris:\n${path}`; ToastUtil.showToast("文件保存成功!"); }).catch((err: BusinessError) => { this.uriStr = `文件保存,异常:\n${JSON.stringify(err)}`; }) }).catch((err: BusinessError) => { this.uriStr = `调用保存文件,异常:\n${JSON.stringify(err)}`; }) }) Button("saveDocument()") .btnStyle() .onClick(() => { let fileName = `test_${DateUtil.getTodayTime()}.txt`; PickerUtil.saveDocument({newFileNames:[fileName]}).then((uris) => { let uri = uris[0]; this.cacheUri = uri PreferencesUtil.put("picker_cache_uri", this.cacheUri); let txtStr = `“harmony-utils 一款高效的OpenHarmony/HarmonyOS工具包,封装了常用工具类,提供一系列简单易用的方法。帮助开发者快速构建鸿蒙应用。\n\n`; FileUtil.writeEasy(uri, txtStr).then(() => { this.uriStr = `文件保存成功,返回uris:\n${uri}`; ToastUtil.showToast("文件保存成功!"); }).catch((err: BusinessError) => { this.uriStr = `文件保存,异常:\n${JSON.stringify(err)}`; }) }).catch((err: BusinessError) => { this.uriStr = `调用保存文件,异常:\n${JSON.stringify(err)}`; }) }) Button("selectAudio()") .btnStyle() .onClick(() => { PickerUtil.selectAudio().then((uris) => { this.uriStr = `调用文件管理,返回uris:\n${uris.join('\n')}`; }).catch((err: BusinessError) => { this.uriStr = `调用文件管理,异常:\n${JSON.stringify(err)}`; }); }) Button("saveAudio()") .btnStyle() .onClick(() => { let fileName = `AudioViewPicker001.mp3`; PickerUtil.saveAudio([fileName]).then((uris) => { let uri = uris[0]; this.uriStr = `音频文件,返回uris:\n${uri}`; }).catch((err: BusinessError) => { this.uriStr = `调用保存文件,异常:\n${JSON.stringify(err)}`; }) })
Text(this.uriStr) .visibility(StrUtil.isNotEmpty(this.uriStr) ? Visibility.Visible : Visibility.None) .textStyle() .margin(12)
Blank().layoutWeight(1) } .margin({ top: 5, bottom: 5 }) } .layoutWeight(1) } .width('100%') .height('100%') .justifyContent(FlexAlign.Start) .backgroundColor($r('app.color.main_background')) }}

@Stylesfunction btnStyle() { .width('90%') .margin({ top: 10, bottom: 5 })}
@Stylesfunction textStyle() { .width('95%') .padding(10) .shadow(ShadowStyle.OUTER_DEFAULT_XS) .margin({ top: 5, bottom: 10 }) .border({ width: 1, color: Color.Grey, radius: 10, style: BorderStyle.Dashed })}
复制代码


import { router } from '@kit.ArkUI';import {  DateUtil,  FileUtil,  ImageUtil,  LogUtil,  PermissionUtil,  StrUtil,  ToastUtil,  WantUtil} from '@pura/harmony-utils';import { DescribeBean } from '../../model/DescribeBean';import { BusinessError } from '@kit.BasicServicesKit';import { Permissions } from '@kit.AbilityKit';import { image } from '@kit.ImageKit';import { photoAccessHelper } from '@kit.MediaLibraryKit';import { MockSetup } from '@ohos/hamock';import { TitleBarView } from '../../component/TitleBarView';import { DialogHelper } from '@pura/harmony-dialog';import { PhotoHelper, PickerUtil } from '@pura/picker_utils';

/** * 相册选择和保存,工具类 */@Entry@Componentstruct Index { private scroller: Scroller = new Scroller(); @State describe: DescribeBean = router.getParams() as DescribeBean; @State uriStr: string = '' @State pixelMap?: image.PixelMap = undefined @State filePath: string = ''; //本地图片path @State filePath2: string = ''; //本地图片path private saveButtonOptions: SaveButtonOptions = { icon: SaveIconStyle.FULL_FILLED, text: SaveDescription.SAVE_IMAGE, buttonType: ButtonType.Capsule } //设置安全控件按钮属性
@MockSetup mock() { this.describe = new DescribeBean("PhotoHelper", "相册选择和保存,工具类"); }
async aboutToAppear(): Promise<void> { let pixelMap = await ImageUtil.getPixelMapFromMedia($r("app.media.test_as4")); this.filePath = await ImageUtil.savePixelMap(pixelMap, FileUtil.getFilesDirPath(""), "漂亮小姐姐.png"); LogUtil.error("filePath: " + this.filePath); let pixelMap2 = await ImageUtil.getPixelMapFromMedia($r("app.media.test_as2")); this.filePath2 = await ImageUtil.savePixelMap(pixelMap2, FileUtil.getFilesDirPath(""), "为梦想窒息.png"); }
onBackPress(): boolean { return false; }
build() { Column() { TitleBarView({ describe: this.describe }) Divider() Scroll(this.scroller) { Column() { Button("select()-默认使用") .btnStyle() .onClick(() => this.selectDefault()) Button("select()-多选") .btnStyle() .onClick(() => this.selectMore()) Button("selectEasy()-单选") .btnStyle() .onClick(() => this.selectSingle()) Button("save()") .btnStyle() .onClick(() => this.save()) Button("showAssetsCreationDialogEasy()") .btnStyle() .onClick(() => this.showAssetsCreationDialog()) SaveButton(this.saveButtonOptions) .onClick(() => this.saveButton()) Button("getPhotoAsset()") .btnStyle() .onClick(() => this.getPhotoAsset())
Text(this.uriStr) .visibility(StrUtil.isNotEmpty(this.uriStr) ? Visibility.Visible : Visibility.None) .textStyle() Image(this.pixelMap) .objectFit(ImageFit.Fill) .autoResize(true) .textStyle()
Blank().layoutWeight(1) } .margin({ top: 5, bottom: 5 }) .width('100%') } .width('100%') .layoutWeight(1) } .width('100%') .height('100%') .justifyContent(FlexAlign.Start) .backgroundColor($r('app.color.main_background')) }

//相册选择图片 selectDefault(){ PhotoHelper.select().then((result) => { let uris = result.photoUris; this.uriStr = `调用相册,返回uris:\n${uris.join('\n')}`; }).catch((err: BusinessError) => { this.uriStr = `调用相册,异常:\n${JSON.stringify(err)}`; }); }
//相册选择图片/视频(多选) selectMore(){ let options: photoAccessHelper.PhotoSelectOptions = { MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE, maxSelectNumber: 12, isPhotoTakingSupported: false, isSearchSupported: false, isEditSupported: false, isOriginalSupported: true } PhotoHelper.selectEasy(options).then((uris) => { this.uriStr = `调用相册,返回uris:\n${uris.join('\n')}`; }).catch((err: BusinessError) => { this.uriStr = `调用相册,异常:\n${JSON.stringify(err)}`; }); }
//相册选择图片(单选) selectSingle(){ let options: photoAccessHelper.PhotoSelectOptions = { MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE, maxSelectNumber: 1, isOriginalSupported: true, isPreviewForSingleSelectionSupported: true //单选模式下是否需要进大图预览 } PhotoHelper.selectEasy(options).then((uris) => { this.uriStr = `调用相册,返回uris:\n${uris.join('\n')}`; }).catch((err: BusinessError) => { this.uriStr = `调用相册,异常:\n${JSON.stringify(err)}`; }); }

//图片保存进相册(已申请权限使用该方法) save(){ let ps: Permissions[] = ['ohos.permission.WRITE_IMAGEVIDEO']; PermissionUtil.requestPermissions(ps).then((result) => { if (result) { let imgName = `漂亮小姐姐_${DateUtil.getTodayTime()}`; PhotoHelper.save(photoAccessHelper.PhotoType.IMAGE, 'jpg', { title: imgName }).then(async (uri) => { if (uri) { this.uriStr = `保存图片成功,返回uris:\n${uri}`; let file = FileUtil.openSync(uri); FileUtil.copyFile(this.filePath, file.fd).then(() => { FileUtil.close(file.fd); ToastUtil.showToast("图片保存成功"); }) } }).catch((err: BusinessError) => { this.uriStr = `调用保存图片,异常:\n${JSON.stringify(err)}`; }) } else { ToastUtil.showLong("请在设置中打开权限"); WantUtil.toAppSetting(); } }) }

//弹窗授权保存,图片保存进相册。 showAssetsCreationDialog(){ let uri = FileUtil.getUriFromPath(this.filePath); let uri2 = FileUtil.getUriFromPath(this.filePath2); PhotoHelper.showAssetsCreationDialogEasy([uri, uri2]).then((result) => { this.uriStr = `图片保存成功,返回uris:\n${JSON.stringify(result, null, 2)}`; DialogHelper.showToast("图片保存成功!"); }).catch((error: BusinessError) => { this.uriStr = `保存图片失败 ~ code: ${error.code} -·- message: ${error.message}`; DialogHelper.showToast("图片保存失败!"); }); }

//安全控件保存,图片保存进相册。 saveButton() { let uri = FileUtil.getUriFromPath(this.filePath); PhotoHelper.applyChanges(uri).then((result) => { this.uriStr = `保存图片成功:${result.uri}`; }).catch((err: BusinessError) => { this.uriStr = `保存图片失败:${JSON.stringify(err)}`; }); }

//读取图片/视频的信息 getPhotoAsset(){ PickerUtil.selectPhoto().then(async (uris) => { if (uris && uris.length > 0) { PhotoHelper.getPhotoAsset(uris[0]).then((photoAsset) => { try { let name = photoAsset?.get(photoAccessHelper.PhotoKeys.DISPLAY_NAME); let type = photoAsset?.get(photoAccessHelper.PhotoKeys.PHOTO_TYPE); let title = photoAsset?.get(photoAccessHelper.PhotoKeys.TITLE.toString()); let size = photoAsset?.get(photoAccessHelper.PhotoKeys.SIZE.toString()); let with1 = photoAsset?.get(photoAccessHelper.PhotoKeys.WIDTH.toString()); let height = photoAsset?.get(photoAccessHelper.PhotoKeys.HEIGHT.toString()); let date = photoAsset?.get(photoAccessHelper.PhotoKeys.DATE_TAKEN.toString()); let orientation = photoAsset?.get(photoAccessHelper.PhotoKeys.ORIENTATION.toString()); this.uriStr = `图片信息:\n文件名:${name}\n文件类型:${type}\n文件大小:${size}\n图片宽度:${with1}\n图片高度:${height}\n拍摄日期:${date}\n文件标题:${title}\n图片文件的方向:${orientation}` } catch (err) { LogUtil.error("读取图片信息失败:" + JSON.stringify(err)); } photoAsset?.getThumbnail((err, pixelMap) => { if (err) { LogUtil.error("缩略图-异常:" + JSON.stringify(err)); return; } this.pixelMap = pixelMap; }) }).catch((err: BusinessError) => { this.uriStr = `读取图片异常:\n${JSON.stringify(err)}`; }); } else { ToastUtil.showToast("请选择图片"); } }).catch((err: BusinessError) => { this.uriStr = `异常:\n${JSON.stringify(err)}`; }); }

}

@Stylesfunction btnStyle() { .width('90%') .margin({ top: 10, bottom: 5 })}
@Stylesfunction textStyle() { .width('95%') .padding(10) .shadow(ShadowStyle.OUTER_DEFAULT_XS) .margin({ top: 5, bottom: 10 }) .border({ width: 1, color: Color.Grey, radius: 10, style: BorderStyle.Dashed })}
复制代码


🍎沟通与交流🙏

使用过程中发现任何问题都可以提 Issue 给我们;


当然,我们也非常欢迎你给我们发 PR

🌏开源协议

本项目基于 Apache License 2.0 ,在拷贝和借鉴代码时,请大家务必注明出处。

用户头像

还未添加个人签名 2025-05-14 加入

还未添加个人简介

评论

发布
暂无评论
最受欢迎的三方库之picker_utils_HarmonyOS_桃花镇童长老_InfoQ写作社区