【鸿蒙开发】第五十六章 Media Library Kit(媒体文件管理服务)
目录
8 使用PickerController将编辑后的图片替换原图
1 简介
Media Library Kit(媒体文件管理服务)提供了管理相册和媒体文件的能力,包括照片和视频,帮助应用快速构建图片视频展示和播放能力。
2. 使用Picker选择媒体库资源
用户有时需要分享图片、视频等用户文件,开发者可以通过特定接口拉起系统图库,用户自行选择待分享的资源,然后最终完成分享。此接口本身无需申请权限,目前适用于界面UIAbility,使用窗口组件触发。具体使用方式如下:
1. 导入选择器模块和文件管理模块。
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { fileIo } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
2. 创建图片-音频类型文件选择选项实例。
const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
3. 配置可选的媒体文件类型和媒体文件的最大数目
photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE; // 过滤选择媒体文件类型为IMAGE。
photoSelectOptions.maxSelectNumber = 5; // 选择媒体文件的最大数目。
4. 创建图库选择器实例,调用PhotoViewPicker.select接口拉起图库界面进行文件选择。文件选择成功后,返回PhotoSelectResult结果集。
let uris: Array<string> = [];
const photoViewPicker = new photoAccessHelper.PhotoViewPicker();
photoViewPicker.select(photoSelectOptions).then((photoSelectResult: photoAccessHelper.PhotoSelectResult) => {
uris = photoSelectResult.photoUris;
console.info('photoViewPicker.select to file succeed and uris are:' + uris);
}).catch((err: BusinessError) => {
console.error(`Invoke photoViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
})
- select返回的uri权限是只读权限,可以根据结果集中uri进行读取文件数据操作。注意不能在picker的回调里直接使用此uri进行打开文件操作,需要定义一个全局变量保存uri,类似使用一个按钮去触发打开文件。可参考指定URI读取文件数据。
- 也可以通过返回的uri获取图片或视频资源。
- 如有获取元数据需求,可以通过文件管理接口和文件URI根据uri获取部分文件属性信息,比如文件大小、访问时间、修改时间、文件名、文件路径等。
2.1 指定URI读取文件数据
1. 待界面从图库返回后,再通过一个类似按钮的组件去调用其他函数,使用fileIo.openSync接口,通过媒体文件uri打开这个文件得到fd。这里需要注意接口权限参数是fileIo.OpenMode.READ_ONLY。
let uri: string = '';
let file = fileIo.openSync(uri, fileIo.OpenMode.READ_ONLY);
console.info('file fd: ' + file.fd);
2. 通过fd使用fileIo.readSync接口读取这个文件内的数据,读取完成后关闭fd。
let buffer = new ArrayBuffer(4096);
let readLen = fileIo.readSync(file.fd, buffer);
console.info('readSync data to file succeed and buffer size is:' + readLen);
fileIo.closeSync(file);
2.2 指定URI获取图片或视频资源
媒体库支持Picker选择媒体文件URI后,根据指定URI获取图片或视频资源,下面以查询指定URI为'file://media/Photo/1/IMG_datetime_0001/displayName.jpg'为例。
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { dataSharePredicates } from '@kit.ArkData';
const context = getContext(this);
let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
class MediaDataHandler implements photoAccessHelper.MediaAssetDataHandler<ArrayBuffer> {
onDataPrepared(data: ArrayBuffer) {
if (data === undefined) {
console.error('Error occurred when preparing data');
return;
}
console.info('on image data prepared');
// 应用自定义对资源数据的处理逻辑。
}
}
async function example() {
let predicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates();
let uri = 'file://media/Photo/1/IMG_datetime_0001/displayName.jpg' // 需保证此uri已存在。
predicates.equalTo(photoAccessHelper.PhotoKeys.URI, uri.toString());
let fetchOptions: photoAccessHelper.FetchOptions = {
fetchColumns: [photoAccessHelper.PhotoKeys.TITLE],
predicates: predicates
};
try {
let fetchResult: photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset> = await phAccessHelper.getAssets(fetchOptions);
let photoAsset: photoAccessHelper.PhotoAsset = await fetchResult.getFirstObject();
console.info('getAssets photoAsset.uri : ' + photoAsset.uri);
// 获取属性值,以标题为例;对于非默认查询的属性,get前需要在fetchColumns中添加对应列名。
console.info('title : ' + photoAsset.get(photoAccessHelper.PhotoKeys.TITLE));
// 请求图片资源数据。
let requestOptions: photoAccessHelper.RequestOptions = {
deliveryMode: photoAccessHelper.DeliveryMode.HIGH_QUALITY_MODE,
}
await photoAccessHelper.MediaAssetManager.requestImageData(context, photoAsset, requestOptions, new MediaDataHandler());
console.info('requestImageData successfully');
fetchResult.close();
} catch (err) {
console.error('getAssets failed with err: ' + err);
}
}
3 保存媒体库资源
当用户需要保存图片、视频等用户文件到图库时,无需在应用中申请相册管理模块权限'ohos.permission.WRITE_IMAGEVIDEO',应用可以通过安全控件或授权弹窗的方式,将用户指定的媒体资源保存到图库中。
3.1 使用安全控件保存媒体库资源
下面以使用安全控件创建一张图片资源为例。
开发步骤
- 设置安全控件按钮属性。
- 创建安全控件按钮。
- 调用MediaAssetChangeRequest.createImageAssetRequest和PhotoAccessHelper.applyChanges接口创建图片资源。
import { photoAccessHelper } from '@kit.MediaLibraryKit';
@Entry
@Component
struct Index {
saveButtonOptions: SaveButtonOptions = {
icon: SaveIconStyle.FULL_FILLED,
text: SaveDescription.SAVE_IMAGE,
buttonType: ButtonType.Capsule
} // 设置安全控件按钮属性。
build() {
Row() {
Column() {
SaveButton(this.saveButtonOptions) // 创建安全控件按钮。
.onClick(async (event, result: SaveButtonOnClickResult) => {
if (result == SaveButtonOnClickResult.SUCCESS) {
try {
let context = getContext();
let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
// 需要确保fileUri对应的资源存在。
let fileUri = 'file://com.example.temptest/data/storage/el2/base/haps/entry/files/test.jpg';
let assetChangeRequest: photoAccessHelper.MediaAssetChangeRequest = photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(context, fileUri);
await phAccessHelper.applyChanges(assetChangeRequest);
console.info('createAsset successfully, uri: ' + assetChangeRequest.getAsset().uri);
} catch (err) {
console.error(`create asset failed with error: ${err.code}, ${err.message}`);
}
} else {
console.error('SaveButtonOnClickResult create asset failed');
}
})
}
.width('100%')
}
.height('100%')
}
}
3.2 使用弹窗授权保存媒体库资源
下面以弹窗授权的方式保存一张图片资源为例。
开发步骤
- 指定待保存到媒体库的位于应用沙箱的应用文件图片uri。
- 指定待保存照片的创建选项,包括文件后缀和照片类型,标题和照片子类型可选。
- 调用showAssetsCreationDialog,基于弹窗授权的方式获取的目标媒体文件uri。
- 将来源于应用沙箱的照片内容写入媒体库的目标uri。
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { fileIo } from '@kit.CoreFileKit';
let context = getContext(this);
let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
async function example() {
try {
// 指定待保存到媒体库的位于应用沙箱的图片uri。
let srcFileUri = 'file://com.example.temptest/data/storage/el2/base/haps/entry/files/test.jpg';
let srcFileUris: Array<string> = [
srcFileUri
];
// 指定待保存照片的创建选项,包括文件后缀和照片类型,标题和照片子类型可选。
let photoCreationConfigs: Array<photoAccessHelper.PhotoCreationConfig> = [
{
title: 'test', // 可选。
fileNameExtension: 'jpg',
photoType: photoAccessHelper.PhotoType.IMAGE,
subtype: photoAccessHelper.PhotoSubtype.DEFAULT, // 可选。
}
];
// 基于弹窗授权的方式获取媒体库的目标uri。
let desFileUris: Array<string> = await phAccessHelper.showAssetsCreationDialog(srcFileUris, photoCreationConfigs);
// 将来源于应用沙箱的照片内容写入媒体库的目标uri。
let desFile: fileIo.File = await fileIo.open(desFileUris[0], fileIo.OpenMode.WRITE_ONLY);
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);
console.info('create asset by dialog successfully');
} catch (err) {
console.error(`failed to create asset by dialog successfully errCode is: ${err.code}, ${err.message}`);
}
}
4 使用PhotoPicker组件访问图片/视频
当应用需要读取用户图片时,开发者可以在应用界面中嵌入PhotoPicker组件,在用户选择所需要的图片资源后,直接返回该图片资源,而不需要授予应用读取图片文件的权限,即可完成图片或视频文件的访问和读取。
界面效果如图所示。
|
宫格页 |
大图页 |
|
|
|
4.1 开发步骤
1. 导入PhotoPicker模块文件。
import {
PhotoPickerComponent,
PickerController,
PickerOptions,
DataType,
BaseItemInfo,
ItemInfo,
PhotoBrowserInfo,
ItemType,
ClickType,
MaxCountType,
PhotoBrowserRange,
PhotoBrowserUIElement,
ReminderMode,
ItemsDeletedCallback,
ExceedMaxSelectedCallback,
CurrentAlbumDeletedCallback
} from '@ohos.file.PhotoPickerComponent';
import photoAccessHelper from '@ohos.file.photoAccessHelper';
2. 创建Picker组件配置选项实例(PickerOptions)和控制实例(PickerController)。
通过PickerOptions,开发者可配置Picker宫格的样式(如勾选框背景色、文本颜色等)、滑动预览方向、最大选择数量等参数,详见PickerOptions API参考。
通过PickerController,应用可向Picker组件发送数据。
// 组件初始化时设置参数信息
pickerOptions: PickerOptions = new PickerOptions();
// 组件初始化完成后,可控制组件部分行为
@State pickerController: PickerController = new PickerController();
// 已选择的图片
@State selectUris: Array<string> = new Array<string>();
//目前选择的图片
@State currentUri: string = '';
//是否显示大图
@State isBrowserShow: boolean = false;
3. 应用界面出现时,初始化组件配置选项实例(PickerOptions)。
// 设置picker宫格页数据类型
this.pickerOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE // 图片和照片都显示;
// 最大选择数量
this.pickerOptions.maxSelectNumber = 5;
// 超出最大选择数量时
this.pickerOptions.maxSelectedReminderMode = ReminderMode.TOAST;
// 是否展示搜索框,默认false
this.pickerOptions.isSearchSupported = true;
// 是否支持拍照,默认false
this.pickerOptions.isPhotoTakingSupported = true;
4. 实现回调函数。
通过实现以下回调事件,可在用户在界面操作时,将相关信息报给应用进行处理。
- 进退大图、切换大图回调,上报的大图相关信息详见PhotoBrowserInfo。
说明
- 回调返回的所有URI均为只读URI,开发者可以根据结果集中的URI读取文件数据。但不能在Picker的回调中直接使用此URI打开文档,需要定义一个全局变量保存URI,样例可参考指定URI读取文件数据、指定URI获取图片或视频资源。
- 如需获取元数据,可通过文件管理和文件URI接口,根据uri获取部分文件属性信息,比如文件大小、访问时间、修改时间、文件名、文件路径等。
- 点击图片(缩略图item),将上报图片/视频信息ItemInfo;点击相机item,可拉起系统相机或应用自行处理。
// 资源被选中回调,返回资源的信息,以及选中方式
private onItemClicked(itemInfo: ItemInfo, clickType: ClickType): boolean {
if (!itemInfo) {
return false;
}
let type: ItemType | undefined = itemInfo.itemType;
let uri: string | undefined = itemInfo.uri;
if (type === ItemType.CAMERA) {
// 点击相机item
return true; // 返回true则拉起系统相机,若应用需要自行处理则返回false。
} else {
if (clickType === ClickType.SELECTED) {
// 应用做自己的业务处理
if (uri) {
this.selectUris.push(uri);
this.pickerOptions.preselectedUris = [...this.selectUris];
}
return true; // 返回true则勾选,否则则不响应勾选。
} else {
if (uri) {
this.selectUris = this.selectUris.filter((item: string) => {
return item != uri;
});
this.pickerOptions.preselectedUris = [...this.selectUris];
}
}
return true;
}
}
// 进入大图的回调
private onEnterPhotoBrowser(photoBrowserInfo: PhotoBrowserInfo): boolean {
this.isBrowserShow = true;
return true;
}
// 退出大图的回调
private onExitPhotoBrowser(photoBrowserInfo: PhotoBrowserInfo): boolean {
this.isBrowserShow = false;
return true;
}
// 接收到该回调后,便可通过pickerController相关接口向picker发送数据,在此之前不生效。
private onPickerControllerReady(): void {
let elements: number[] = [PhotoBrowserUIElement.BACK_BUTTON];
this.pickerController.setPhotoBrowserUIElementVisibility(elements, false); // 设置大图页不显示返回按钮
}
// 大图左右滑动的回调
private onPhotoBrowserChanged(browserItemInfo: BaseItemInfo): boolean {
this.currentUri = browserItemInfo.uri ?? '';
return true;
}
// 已勾选图片被删除时的回调
private onSelectedItemsDeleted(baseItemInfos: Array<BaseItemInfo>): void {
}
// 超过最大选择数量再次点击时的回调
private onExceedMaxSelected(exceedMaxCountType: MaxCountType): void {
}
// 当前相册被删除时的回调
private onCurrentAlbumDeleted(): void {
}
5. 创建PhotoPickerComponent组件。
PhotoPickerComponent({
pickerOptions: this.pickerOptions,
onItemClicked: (itemInfo: ItemInfo, clickType: ClickType): boolean => this.onItemClicked(itemInfo, clickType),
onEnterPhotoBrowser: (photoBrowserInfo: PhotoBrowserInfo): boolean => this.onEnterPhotoBrowser(photoBrowserInfo),
onExitPhotoBrowser: (photoBrowserInfo: PhotoBrowserInfo): boolean => this.onExitPhotoBrowser(photoBrowserInfo),
onPickerControllerReady: (): void => this.onPickerControllerReady(),
onPhotoBrowserChanged: (browserItemInfo: BaseItemInfo): boolean => this.onPhotoBrowserChanged(browserItemInfo),
onSelectedItemsDeleted: (BaseItemInfo: Array<BaseItemInfo>) => this.onSelectedItemsDeleted(BaseItemInfo),
onExceedMaxSelected: (exceedMaxCountType: MaxCountType) => this.onExceedMaxSelected(exceedMaxCountType),
onCurrentAlbumDeleted: () => this.onCurrentAlbumDeleted(),
pickerController: this.pickerController,
})
6. 通过PickerController向Picker组件发送数据,实现控制PhotoPickerComponent组件行为。
4.2 完整示例
import {
PhotoPickerComponent,
PickerController,
PickerOptions,
DataType,
BaseItemInfo,
ItemInfo,
PhotoBrowserInfo,
ItemType,
ClickType,
MaxCountType,
PhotoBrowserRange,
PhotoBrowserUIElement,
ReminderMode,
ItemsDeletedCallback,
ExceedMaxSelectedCallback,
CurrentAlbumDeletedCallback
} from '@ohos.file.PhotoPickerComponent';
import photoAccessHelper from '@ohos.file.photoAccessHelper';
@Entry
@Component
struct PhotoPickerComponentDemo {
// 组件初始化时设置参数信息
pickerOptions: PickerOptions = new PickerOptions();
// 组件初始化完成后,可控制组件部分行为
@State pickerController: PickerController = new PickerController();
// 已选择的图片
@State selectUris: Array<string> = new Array<string>();
//目前选择的图片
@State currentUri: string = '';
//是否显示大图
@State isBrowserShow: boolean = false;
aboutToAppear() {
// 设置picker宫格页数据类型
this.pickerOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE // 图片和照片都显示;
// 最大选择数量
this.pickerOptions.maxSelectNumber = 5;
// 超出最大选择数量时
this.pickerOptions.maxSelectedReminderMode = ReminderMode.TOAST;
// 是否展示搜索框,默认false
this.pickerOptions.isSearchSupported = true;
// 是否支持拍照,默认false
this.pickerOptions.isPhotoTakingSupported = true;
}
// 资源被选中回调,返回资源的信息,以及选中方式
private onItemClicked(itemInfo: ItemInfo, clickType: ClickType): boolean {
if (!itemInfo) {
return false;
}
let type: ItemType | undefined = itemInfo.itemType;
let uri: string | undefined = itemInfo.uri;
if (type === ItemType.CAMERA) {
// 点击相机item
return true; // 返回true则拉起系统相机,若应用需要自行处理则返回false。
} else {
if (clickType === ClickType.SELECTED) {
// 应用做自己的业务处理
if (uri) {
this.selectUris.push(uri);
this.pickerOptions.preselectedUris = [...this.selectUris];
}
return true; // 返回true则勾选,否则则不响应勾选。
} else {
if (uri) {
this.selectUris = this.selectUris.filter((item: string) => {
return item != uri;
});
this.pickerOptions.preselectedUris = [...this.selectUris];
}
}
return true;
}
}
// 进入大图的回调
private onEnterPhotoBrowser(photoBrowserInfo: PhotoBrowserInfo): boolean {
this.isBrowserShow = true;
return true;
}
// 退出大图的回调
private onExitPhotoBrowser(photoBrowserInfo: PhotoBrowserInfo): boolean {
this.isBrowserShow = false;
return true;
}
// 接收到该回调后,便可通过pickerController相关接口向picker发送数据,在此之前不生效。
private onPickerControllerReady(): void {
}
// 大图左右滑动的回调
private onPhotoBrowserChanged(browserItemInfo: BaseItemInfo): boolean {
this.currentUri = browserItemInfo.uri ?? '';
return true;
}
// 已勾选图片被删除时的回调
private onSelectedItemsDeleted(baseItemInfos: Array<BaseItemInfo>): void {
}
// 超过最大选择数量再次点击时的回调
private onExceedMaxSelected(exceedMaxCountType: MaxCountType): void {
}
// 当前相册被删除时的回调
private onCurrentAlbumDeleted(): void {
}
build() {
Flex({
direction: FlexDirection.Column,
alignItems: ItemAlign.Start
}) {
PhotoPickerComponent({
pickerOptions: this.pickerOptions,
onItemClicked: (itemInfo: ItemInfo, clickType: ClickType): boolean => this.onItemClicked(itemInfo, clickType),
onEnterPhotoBrowser: (photoBrowserInfo: PhotoBrowserInfo): boolean => this.onEnterPhotoBrowser(photoBrowserInfo),
onExitPhotoBrowser: (photoBrowserInfo: PhotoBrowserInfo): boolean => this.onExitPhotoBrowser(photoBrowserInfo),
onPickerControllerReady: (): void => this.onPickerControllerReady(),
onPhotoBrowserChanged: (browserItemInfo: BaseItemInfo): boolean => this.onPhotoBrowserChanged(browserItemInfo),
onSelectedItemsDeleted: (BaseItemInfo: Array<BaseItemInfo>) => this.onSelectedItemsDeleted(BaseItemInfo),
onExceedMaxSelected: (exceedMaxCountType: MaxCountType) => this.onExceedMaxSelected(exceedMaxCountType),
onCurrentAlbumDeleted: () => this.onCurrentAlbumDeleted(),
pickerController: this.pickerController,
})
// 这里模拟应用侧底部的选择栏
if (this.isBrowserShow) {
//已选择的图片缩影图
Row() {
ForEach(this.selectUris, (uri: string) => {
if (uri === this.currentUri) {
Image(uri).height(50).width(50)
.onClick(() => {
})
.borderWidth(1)
.borderColor('red')
} else {
Image(uri).height(50).width(50).onClick(() => {
this.pickerController.setData(DataType.SET_SELECTED_URIS, this.selectUris);
this.pickerController.setPhotoBrowserItem(uri, PhotoBrowserRange.ALL);
})
}
}, (uri: string) => JSON.stringify(uri))
}.alignSelf(ItemAlign.Center).margin(this.selectUris.length ? 10 : 0)
} else {
// 进入大图,预览已选择的图片
Button('预览').width('33%').alignSelf(ItemAlign.Start).height('5%').margin(10).onClick(() => {
if (this.selectUris.length > 0) {
this.pickerController.setPhotoBrowserItem(this.selectUris[0], PhotoBrowserRange.SELECTED_ONLY);
}
})
}
}
}
}
5 使用AlbumPicker组件访问相册列表
可以在布局中嵌入AlbumPickerComponent组件,通过此组件,应用无需申请权限,即可访问公共目录中的相册列表。
需配合PhotoPickerComponent一起使用,用户通过AlbumPickerComponent组件选择对应相册并通知PhotoPickerComponent组件刷新成对应相册的图片和视频。
界面效果如图所示。

5.1 开发步骤
1. 导入相册组件模块文件。
import { AlbumPickerComponent, AlbumPickerOptions, AlbumInfo} from '@kit.MediaLibraryKit';
2. 创建相册组件配置选项实例(AlbumPickerOptions)。
// 用于相册组件初始化时设置参数信息
albumOptions: AlbumPickerOptions = new AlbumPickerOptions();
3. 初始化组件配置选项实例(AlbumPickerOptions)。
/**
* 设置相册页颜色模式, 默认AUTO。
* AUTO:跟随系统的模式, LIGHT:浅色模式, DARK:深色模式
*/
this.albumOptions.themeColorMode = PickerColorMode.AUTO;
4. 创建AlbumPickerComponent组件。
AlbumPickerComponent({
// 设置组件选择选项实例
albumPickerOptions: this.albumOptions,
/**
*相册被选中回调,返回相册信息
* AlbumInfo(uri)
*/
onAlbumClick: (albumInfo: AlbumInfo): boolean => this.onAlbumClick(albumInfo),
})
5. 与PhotoPicker组件联动,将相册URI给到应用,根据相册URI更新PhotoPicker组件宫格页内容。
private onAlbumClick(albumInfo: AlbumInfo): boolean {
if (albumInfo?.uri) {
// 根据相册url更新宫格页内容
this.pickerController.setData(DataType.SET_ALBUM_URI, albumInfo.uri);
}
return true;
}
6 使用RecentPhoto组件获取最近一张图片
应用可以在布局中嵌入最近图片组件,通过此组件,应用无需申请权限,即可指定配置访问公共目录中最近的一个图片或视频文件。授予的权限仅包含只读权限。
界面效果如图所示。
①为PhotoPicker宫格页,②为RecentPhoto最近图片的效果。

6.1 开发步骤
1. 导入最近图片组件模块文件。
import { BaseItemInfo } from '@ohos.file.PhotoPickerComponent';
import photoAccessHelper from '@ohos.file.photoAccessHelper';
import {
PhotoSource,
RecentPhotoCheckResultCallback,
RecentPhotoClickCallback,
RecentPhotoComponent,
RecentPhotoOptions
} from '@ohos.file.RecentPhotoComponent';
2. 创建最近图片组件选择选项实例(RecentPhotoOptions)。
// 最近图片组件初始化
recentPhotoOptions: RecentPhotoOptions = new RecentPhotoOptions();
3. 初始化最近图片组件选择选项实例(RecentPhotoOptions)。
// 设置数据类型, IMAGE_VIDEO_TYPE:图片和视频(默认值) IMAGE_TYPE:图片 VIDEO_TYPE:视频 MOVING_PHOTO_IMAGE_TYPE 动态图片
this.recentPhotoOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE;
// 设置最近图片的时间范围,单位(秒), 0表示所有时间。
this.recentPhotoOptions.period = 0;
// 设置资源的来源 ALL:所有 CAMERA:相机 SCREENSHOT:截图
this.recentPhotoOptions.photoSource = PhotoSource.ALL;
4. 创建RecentPhotoComponent组件。
RecentPhotoComponent({
// 设置最近图片组件选择选项实例
recentPhotoOptions: this.recentPhotoOptions,
/**
* 最近图片点击事件
* BaseItemInfo(uri, mimeType, width, height, size, duration)
* return 返回值为true时才会给url授权,才可以显示
*/
onRecentPhotoClick: (recentPhotoInfo: BaseItemInfo): boolean => this.onRecentPhotoClick(recentPhotoInfo),
// 检查是否存在最近的资源
onRecentPhotoCheckResult: (recentPhotoExists: boolean) => this.onReceiveCheckResult(recentPhotoExists),
})
5. 实现相关回调。
实现onReceiveCheckResult回调,可查询是否存在最近图片,仅返回true时才可进一步实现控制是否显示最近图片。
实现onRecentPhotoClick回调,将上报返回图片/视频相关信息BaseItemInfo。
// 返回值为true时,才能获取uri的权限
private onRecentPhotoClick(recentPhotoInfo: BaseItemInfo): boolean {
if (!recentPhotoInfo) {
return false;
}
return true;
}
private onReceiveCheckResult(recentPhotoExists: boolean): void {
if (!recentPhotoExists) {
console.info('not exist recent photo');
}
// 存在最近图片的话,可以实现业务需求, 如去控制RecentPhotoComponent是否显示
}
7 使用PhotoPicker推荐图片
应用在调用PhotoPicker接口时,如果配置了PhotoPicker图片推荐参数,当设备中有满足图片推荐参数的图片,且设备中的图片已经分析完成时,PhotoPicker界面除了展示全量的图片外,还会展示符合条件的推荐图片供用户参考选择,从而缩短用户筛选图片的时间。
- 选择特定类型(RecommendationType)的图片,如身份证、银行卡、驾驶证、行驶证、二维码等。当有符合应用指定类型的图片传入时,将显示对应的图片推荐页。
-
以指定图片类型为二维码为例,PhotoPicker界面上将出现“二维码”的Tab页,展示图库中的二维码图片。

- 在图文编辑时选择图片,系统可以根据应用传入的文本信息,提取出时间、地点、事物或活动,并根据提取的信息,推荐对应的图片展示在PhotoPicker中。
- 举例说明,如设置的推荐参数文本是“国庆节,带着女儿去了上海野生动物园,看到了凶猛的大象,漂亮的火烈鸟,还有她心心念念的大熊猫,小家伙可开心了。”
- 而且手机中有相应的图片,图片分析完成时,会在“推荐”的Tab页中展示出时间是国庆节,地点是上海野生动物园的大熊猫、火烈鸟、大象的图片。

7.1 约束与限制
- PhotoPicker推荐图片的功能依赖于图片分析的结果,只有在媒体库中的图片分析完成后,系统才会进行推荐。
当设备在灭屏充电时,在电量充足、温度正常的情况下,系统将自动进行图片分析。
如果图片带有地理位置信息,设备需要联网才可以正常解析图片中的位置信息。
- 当前仅支持推荐图片类型的文件。
7.2 开发方式
7.2.1 前提条件
开发者可以通过两种方式实现PhotoPicker,拉起系统图库。请选择其中一种方式,实现PhotoPicker。
- 参考PhotoPicker接口的开发指导,实现PhotoPicker。
在配置参数photoAccessHelper.PhotoSelectOptions时,媒体文件类型MIMEType(PhotoViewMIMETypes)需要配置为IMAGE_TYPE或IMAGE_VIDEO_TYPE。
- 参考PhotoPicker组件的开发指导,实现PhotoPicker。
在配置PhotoPickerComponent的属性pickerOptions时,媒体文件类型MIMEType(PhotoViewMIMETypes)需要配置为IMAGE_TYPE或IMAGE_VIDEO_TYPE。
说明
- 当MIMEType配置为IMAGE_TYPE或IMAGE_VIDEO_TYPE,并在后续步骤中配置了推荐参数,将根据参数推荐图片类型的文件。页签“全部”下展示的文件类型与MIMEType配置项一致。
- 当MIMEType配置为其他类型,推荐不生效。正常展示PhotoPicker筛选的全部照片。
7.2.2 根据特定类型推荐图片
当需要推荐特定类型的图片,如身份证、银行卡、驾驶证、行驶证、二维码等,可通过配置RecommendationOptions.recommendationType,指定推荐的图片类型。支持的图片类型可参考RecommendationType。
let recommendationOptions: photoAccessHelper.RecommendationOptions = {
recommendationType: photoAccessHelper.RecommendationType.QR_CODE // 配置枚举类型,不同的枚举值,推荐不同种类的图片
};
this.pickerOptions.recommendationOptions = recommendationOptions;// 将推荐参数赋值给 pickerOptions.recommendationOptions
说明
当前示例以通过Picker组件实现推荐图片为例。
如果使用Picker接口,需要将推荐参数赋值给 photoSelectOptions.recommendationOptions。
7.2.3 根据文本信息推荐图片
当需要在图文编辑时,根据文本信息推荐图片,可通过配置RecommendationOptions.textContextInfo。
说明
如果RecommendationOptions同时配置了recommendationType和textContextInfo,仅textContextInfo生效。
let textInfo: photoAccessHelper.TextContextInfo = {
text: '国庆节,带着女儿去了上海野生动物园,看到了凶猛的大象,漂亮的火烈鸟,还有她心心念念的大熊猫,小家伙可开心了。'
};
let recommendationOptions: photoAccessHelper.RecommendationOptions = {
textContextInfo: textInfo
};
this.pickerOptions.recommendationOptions = recommendationOptions;// 将推荐参数赋值给 pickerOptions.recommendationOptions
说明
当前示例以通过Picker组件实现推荐图片为例。
如果使用Picker接口,需要将推荐参数赋值给 photoSelectOptions.recommendationOptions。
8 使用PickerController将编辑后的图片替换原图
8.1 替换PhotoPicker中显示的图片/视频
应用可获得用户从Picker选择的图片、视频的访问权限,读取图片、视频后进行编辑、修改。完成编辑修改后的图片/视频缓存到应用沙箱后,可调用本API,将编辑结果文件发送给PhotoPicker,并指定替换显示的原图。Picker根据指定将接收的编辑结果文件替换原图片进行显示。
效果如图所示。

8.1.1 开发步骤
1. 导入选择器模块和文件管理模块。
import { PickerController } from '@ohos.file.PhotoPickerComponent';
import { fileUri } from '@kit.CoreFileKit';
2. 创建参数列表。
@State pickerController: PickerController = new PickerController();
@State originUrl: string = ''; // 原图URI
@State replaceUrl: string = ''; // 原图编辑后的沙箱URI
3. 调用replacePhotoPickerPreview()替换图片/视频。
this.pickerController.replacePhotoPickerPreview(this.originUrl, this.replaceUrl, (a, b) => {
console.log("hello this.pickerController.replaceUrl code res:" + b)
})
8.1.2 完整示例
import { PickerController } from '@ohos.file.PhotoPickerComponent';
import { fileUri } from '@kit.CoreFileKit';
@Entry
@Component
struct Index {
@State pickerController: PickerController = new PickerController();
@State originUrl: string = '';
@State replaceUrl: string = '';
build() {
Row() {
Column() {
Button("replace url").width('25%').height('50%').margin({ top: 10 }).onClick(() => {
this.originUrl = 'file://media/photo/test.jpg';
this.replaceUrl = fileUri.getUriFromPath(getContext().filesDir + "/test.jpg").toString();
this.pickerController.replacePhotoPickerPreview(this.originUrl, this.replaceUrl, (err, b) => {
console.log("hello this.pickerController.replaceUrl code res:" + b)
})
})
}
.width('100%')
}
.height('100%')
}
}
8.2 将Picker上替换显示的图片/视频保存到图库
应用指定保存的文件,需在替换显示的范围内。应用调用API后,PhotoPicker将在Picker上成功替换显示的图片、视频保存到图库。确保保存的内容与替换显示的图片、视频一致。
效果如图所示。

8.2.1 开发步骤
1. 导入选择器模块和文件管理模块。
import photoAccessHelper from '@ohos.file.photoAccessHelper';
import { PickerController, PickerOptions, SaveMode } from '@ohos.file.PhotoPickerComponent';
import { fileUri } from '@kit.CoreFileKit';
2. 创建参数列表。
@State pickerController: PickerController = new PickerController();
@State originUrl: string = ''; // 原图URI
@State replaceUrl: string = ''; // 原图编辑后的沙箱URI
3. 调用saveTrustedPhotoAssets()保存图片/视频到图库。
this.pickerController.(this.replaceUris, (a, b) => {
console.log("hello this.pickerController.save as new code a.code:" + a.code + ",a.message:" + a.message + ",res:" + b)
}, photoCreationConfigs, SaveMode.SAVE_AS); // SaveMode: SAVE_AS = 0(另存为),OVERWRITE = 1 (覆盖保存)
该接口使用依赖pickerController.replacePhotoPickerPreview,需要先执行pickerController.replacePhotoPickerPreview后才能执行pickerController.saveTrustedPhotoAssets。
8.2.2 完整示例
import photoAccessHelper from '@ohos.file.photoAccessHelper';
import { PickerController, PickerOptions, SaveMode } from '@ohos.file.PhotoPickerComponent';
import { fileUri } from '@kit.CoreFileKit';
@Entry
@Component
struct Index {
@State pickerController: PickerController = new PickerController();
@State originUrl: string = '';
@State replaceUrl: string = '';
build() {
Row() {
Column() {
Button("replace url").width('25%').height('50%').margin({ top: 10 }).onClick(() => {
this.originUrl = 'file://media/photo/test.jpg';
this.replaceUrl = fileUri.getUriFromPath(getContext().filesDir + "/test.jpg").toString();
this.pickerController.replacePhotoPickerPreview(this.originUrl, this.replaceUrl, (err, b) => {
console.log("hello this.pickerController.replaceUrl code res:" + b)
})
let photoCreationConfig: photoAccessHelper.PhotoCreationConfig = {
title: 'test',
fileNameExtension: 'jpg',
photoType: photoAccessHelper.PhotoType.IMAGE,
subtype: photoAccessHelper.PhotoSubtype.DEFAULT,
};
this.pickerController.saveTrustedPhotoAssets([this.replaceUrl], (err, arr) => {
console.log("testPicker27 this.pickerController.save code res:" + err.code);
}, [photoCreationConfig], SaveMode.SAVE_AS);
})
}
.width('100%')
}
.height('100%')
}
}
9 动态照片
9.1 访问和管理动态照片资源
9.1.1 保存动态照片资源
使用安全控件保存动态照片资源后,可用于获取MovingPhoto对象,从而完成播放动态照片等操作。
使用安全控件保存动态照片资源,无需申请相册管理模块权限'ohos.permission.WRITE_IMAGEVIDEO',允许用户通过点击按钮临时获取存储权限,并将资源直接保存到指定的媒体库路径,使得操作更为便捷。
1、开发步骤
设置安全控件按钮属性。
创建安全控件按钮。
调用MediaAssetChangeRequest.createAssetRequest接口新建一个创建资产的变更请求,指定待创建资产的子类型为动态照片。
调用MediaAssetChangeRequest.addResource接口指定动态照片的图片和视频内容。
以下示例以从应用沙箱的应用文件fileUri指定动态照片的图片和视频内容为例。
开发者可根据实际情况,通过ArrayBuffer的方式指定资源内容,参考MediaAssetChangeRequest.addResource(type: ResourceType, data: ArrayBuffer)。
调用PhotoAccessHelper.applyChanges接口提交创建资产的变更请求。
import { photoAccessHelper } from '@kit.MediaLibraryKit';
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
@State saveButtonOptions: SaveButtonOptions = {
icon: SaveIconStyle.FULL_FILLED,
text: SaveDescription.SAVE_IMAGE,
buttonType: ButtonType.Capsule
} // 设置安全控件按钮属性。
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
SaveButton(this.saveButtonOptions) // 创建安全控件按钮。
.onClick(async (event, result: SaveButtonOnClickResult) => {
if (result == SaveButtonOnClickResult.SUCCESS) {
try {
let context = getContext();
let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
// 需要确保imageFileUri和videoFileUri对应的资源存在,分别表示待创建到媒体库的动态照片的图片和视频。
let imageFileUri = 'file://com.example.temptest/data/storage/el2/base/haps/entry/files/create_moving_photo.jpg';
let videoFileUri = 'file://com.example.temptest/data/storage/el2/base/haps/entry/files/create_moving_photo.mp4';
let assetChangeRequest: photoAccessHelper.MediaAssetChangeRequest = photoAccessHelper.MediaAssetChangeRequest.createAssetRequest(context, photoAccessHelper.PhotoType.IMAGE, "jpg", {
title: "moving_photo",
subtype: photoAccessHelper.PhotoSubtype.MOVING_PHOTO
});
assetChangeRequest.addResource(photoAccessHelper.ResourceType.IMAGE_RESOURCE, imageFileUri);
assetChangeRequest.addResource(photoAccessHelper.ResourceType.VIDEO_RESOURCE, videoFileUri);
await phAccessHelper.applyChanges(assetChangeRequest);
console.info('create moving photo successfully, uri: ' + assetChangeRequest.getAsset().uri);
} catch (err) {
console.error(`create moving photo failed with error: ${err.code}, ${err.message}`);
}
} else {
console.error('SaveButtonOnClickResult create moving photo failed');
}
})
}
.width('100%')
}
.height('100%')
}
}
9.1.2 获取动态照片对象
应用可以通过Picker的方式获取用户媒体库里的动态照片对象,后续可用于在应用内播放动态照片,或是读取动态照片资源进行其他操作(如上传到应用共享给他人浏览等)。
应用也可以通过传入应用沙箱的应用文件图片和视频fileUri的方式构造应用本地的动态照片对象。
9.1.3 获取媒体库动态照片对象
- 通过Picker选择动态照片的媒体文件uri。
- 调用PhotoAccessHelper.getAssets和FetchResult.getFirstObject接口获取uri对应的PhotoAsset资产。
- 调用MediaAssetManager.requestMovingPhoto获取PhotoAsset对应的动态照片对象(MovingPhoto)。
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { dataSharePredicates } from '@kit.ArkData';
let context = getContext(this);
let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
async function example() {
try {
// picker选择动态照片uri。
let photoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.MOVING_PHOTO_IMAGE_TYPE;
photoSelectOptions.maxSelectNumber = 9;
let photoViewPicker = new photoAccessHelper.PhotoViewPicker();
let photoSelectResult = await photoViewPicker.select(photoSelectOptions);
let uris = photoSelectResult.photoUris;
for (let i = 0; i < uris.length; i++) {
// 获取uri对应的PhotoAsset资产。
let predicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates();
predicates.equalTo(photoAccessHelper.PhotoKeys.URI, uris[i]);
let fetchOption: photoAccessHelper.FetchOptions = {
fetchColumns: [],
predicates: predicates
};
let fetchResult: photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset> = await phAccessHelper.getAssets(fetchOption);
let photoAsset: photoAccessHelper.PhotoAsset = await fetchResult.getFirstObject();
// 获取PhotoAsset对应的动态照片对象。
await photoAccessHelper.MediaAssetManager.requestMovingPhoto(context, photoAsset, {
deliveryMode: photoAccessHelper.DeliveryMode.FAST_MODE
}, {
async onDataPrepared(movingPhoto: photoAccessHelper.MovingPhoto) {
if (movingPhoto !== undefined) {
// 应用可自定义对movingPhoto的处理逻辑。
console.info('request moving photo successfully, uri: ' + movingPhoto.getUri());
}
}
})
}
} catch (err) {
console.error(`request moving photo failed with error: ${err.code}, ${err.message}`);
}
}
9.1.4 获取应用沙箱动态照片对象
调用MediaAssetManager.loadMovingPhoto加载应用沙箱的动态照片对象(MovingPhoto)。
import { photoAccessHelper } from '@kit.MediaLibraryKit';
let context = getContext(this);
async function example() {
try {
let imageFileUri = 'file://com.example.temptest/data/storage/el2/base/haps/entry/files/local_moving_photo.jpg';
let videoFileUri = 'file://com.example.temptest/data/storage/el2/base/haps/entry/files/local_moving_photo.mp4';
let movingPhoto = await photoAccessHelper.MediaAssetManager.loadMovingPhoto(context, imageFileUri, videoFileUri);
console.info('load moving photo successfully');
} catch (err) {
console.error(`load moving photo failed with error: ${err.code}, ${err.message}`);
}
}
9.1.5 读取动态照片资源
对于一个动态照片对象,应用可以通过MovingPhoto.requestContent导出图片和视频到应用沙箱,或者读取图片或视频的ArrayBuffer内容。
import { photoAccessHelper } from '@kit.MediaLibraryKit';
async function example(movingPhoto: photoAccessHelper.MovingPhoto) {
try {
let imageFileUri = 'file://com.example.temptest/data/storage/el2/base/haps/entry/files/request_moving_photo.jpg';
let videoFileUri = 'file://com.example.temptest/data/storage/el2/base/haps/entry/files/request_moving_photo.mp4';
await movingPhoto.requestContent(imageFileUri, videoFileUri); // 将动态照片导出到应用沙箱。
let imageData = await movingPhoto.requestContent(photoAccessHelper.ResourceType.IMAGE_RESOURCE); // 读取图片的ArrayBuffer内容。
let videoData = await movingPhoto.requestContent(photoAccessHelper.ResourceType.VIDEO_RESOURCE); // 读取视频的ArrayBuffer内容。
} catch (err) {
console.error(`request content of moving photo failed with error: ${err.code}, ${err.message}`);
}
}
9.2 使用MovingPhotoView播放动态照片
系统提供了MovingPhotoView组件,在一些社交类、图库类应用中,可用于播放动态照片文件。
9.2.1 约束与限制
针对MovingPhotoView组件的使用,有以下约束与限制:
- 当前不支持动态属性设置。
- 当前不支持设置ArkUI通用属性expandSafeArea。
- 该组件长按触发播放时组件区域放大为1.1倍。
- 该组件使用AVPlayer进行播放,同时开启的AVPlayer个数不建议超过3个,超过3个可能会出现视频播放卡顿现象。
9.2.2 开发步骤
1. 导入动态照片模块。
import { MovingPhotoView, MovingPhotoViewController, MovingPhotoViewAttribute } from '@kit.MediaLibraryKit';
2. 获取动态照片对象(MovingPhoto)。
MovingPhoto对象需要通过photoAccessHelper接口创建或获取,MovingPhotoView只接收构造完成的MovingPhoto对象。
src: photoAccessHelper.MovingPhoto | undefined = undefined;
3. 创建动态照片控制器(MovingPhotoViewController),用于控制动态照片的播放状态(如播放、停止)。
controller: MovingPhotoViewController = new MovingPhotoViewController();
4. 创建动态照片组件。
以下参数取值仅为举例,具体每个属性的取值范围,可参考API文档:@ohos.multimedia.movingphotoview。
import { photoAccessHelper, MovingPhotoView, MovingPhotoViewController, MovingPhotoViewAttribute } from '@kit.MediaLibraryKit';
@Entry
@Component
struct Index {
@State src: photoAccessHelper.MovingPhoto | undefined = undefined
@State isMuted: boolean = false
controller: MovingPhotoViewController = new MovingPhotoViewController();
build() {
Column() {
MovingPhotoView({
movingPhoto: this.src,
controller: this.controller
// imageAIOptions: this.options.
})
// 是否静音播放,此处由按钮控制,默认值为false非静音播放。
.muted(this.isMuted)
// 视频显示模式,默认值为Cover。
.objectFit(ImageFit.Cover)
// 播放时触发。
.onStart(() => {
console.log('onStart');
})
// 播放结束触发。
.onFinish(() => {
console.log('onFinish');
})
// 播放停止触发。
.onStop(() => {
console.log('onStop')
})
// 出现错误触发。
.onError(() => {
console.log('onError');
})
Row() {
// 按钮:开始播放。
Button('start')
.onClick(() => {
this.controller.startPlayback()
})
.margin(5)
// 按钮:停止播放。
Button('stop')
.onClick(() => {
this.controller.stopPlayback()
})
.margin(5)
// 按钮:是否静音播放。
Button('mute')
.onClick(() => {
this.isMuted = !this.isMuted
})
.margin(5)
}
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.Center)
.height('15%')
}
}
}
9.2.3 效果展示

更多推荐





所有评论(0)