《HarmonyOS NEXT MediaLibraryKit 完整使用指南》
2026/8/1 12:56:57 网站建设 项目流程

第一部分:初识 MediaLibraryKit

1.1 什么是 MediaLibraryKit?

Media Library Kit(媒体文件管理服务)是 HarmonyOS 上管理相册和媒体文件的核心服务 。你可以把它看作系统相册的“大门”,所有对图片、视频的增删改查操作,都必须通过它来进行 。

它的核心价值在于安全与便捷

  • 安全:应用无法直接访问文件系统,必须通过 MediaLibraryKit 申请权限或使用系统控件,充分保护用户隐私 。

  • 便捷:提供了对象化的 API 设计,接入高效。同时支持端云一体化访问,让开发者无需关心底层存储细节 。

1.2 核心能力概览

  • 权限管理:管理媒体库的读写权限申请与校验。

  • Picker 选择器:通过系统控件拉起图库,用户选择后返回 URI,无需申请读取权限

  • 相册管理:查询、创建、重命名用户相册,获取相册中的媒体资源 。

  • 媒体文件 CRUD:对图片、视频文件进行创建、读取、修改、删除及查询操作 。

  • 动态照片支持:提供动态照片的保存、读取与播放能力 。

  • 变更通知:注册监听,当媒体库内容变化时通知应用 。

第二部分:权限申请与初始化

在操作媒体库之前,必须正确申请权限。

2.1 权限体系

访问媒体库所需权限分为两类 :

权限级别说明
ohos.permission.READ_IMAGEVIDEOuser_granted读取相册中的图片和视频
ohos.permission.WRITE_IMAGEVIDEOuser_granted向相册写入(增、删、改)媒体文件

user_granted级别的权限需要在应用运行时动态向用户申请 。

2.2 完整权限申请流程

arkts

import { photoAccessHelper } from '@kit.MediaLibraryKit'; import { abilityAccessCtrl, bundleManager, Permissions } from '@kit.AbilityKit'; import { BusinessError } from '@kit.BasicServicesKit'; class MediaPermissionManager { private readonly REQUIRED_PERMISSIONS: Permissions[] = [ 'ohos.permission.READ_IMAGEVIDEO', 'ohos.permission.WRITE_IMAGEVIDEO', ]; // 检查权限是否已授予 async checkPermissions(): Promise<boolean> { const atManager = abilityAccessCtrl.createAtManager(); const bundleInfo = await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT); const bundleName = bundleInfo.name; for (const permission of this.REQUIRED_PERMISSIONS) { const grantStatus = await atManager.checkAccessToken(bundleName, permission); if (grantStatus !== abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) { return false; } } return true; } // 请求权限(会弹出系统授权对话框) async requestPermissions(context: Context): Promise<boolean> { const atManager = abilityAccessCtrl.createAtManager(); try { const result = await atManager.requestPermissionsFromUser(context, this.REQUIRED_PERMISSIONS); // 检查授权结果 for (let i = 0; i < result.authResults.length; i++) { if (result.authResults[i] !== 0) { console.warn(`权限被拒绝: ${this.REQUIRED_PERMISSIONS[i]}`); return false; } } console.info('所有媒体库权限已授权'); return true; } catch (err) { const error = err as BusinessError; console.error(`请求权限失败: ${error.message}`); return false; } } // 确保权限已授予 async ensurePermissions(context: Context): Promise<boolean> { const hasPermission = await this.checkPermissions(); if (hasPermission) return true; return await this.requestPermissions(context); } } // 获取 PhotoAccessHelper 实例 function getPhotoAccessHelper(context: Context): photoAccessHelper.PhotoAccessHelper { return photoAccessHelper.getPhotoAccessHelper(context); } // 使用示例 const permissionManager = new MediaPermissionManager(); async function initMediaLibrary(context: Context): Promise<photoAccessHelper.PhotoAccessHelper | null> { const granted = await permissionManager.ensurePermissions(context); if (!granted) { console.error('权限未授予,无法访问媒体库'); return null; } return getPhotoAccessHelper(context); }

第三部分:使用 Picker 选择媒体文件(无需读取权限)

这是最用户友好的方式。应用通过PhotoViewPicker拉起系统相册界面,用户选择后返回文件 URI,整个过程应用未获取读取权限,保障了用户隐私 。

3.1 选择单张/多张图片

arkts

import { photoAccessHelper } from '@kit.MediaLibraryKit'; import { BusinessError } from '@kit.BasicServicesKit'; async function selectPhotos() { // 1. 创建选择选项 const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions(); photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE; // 只选图片 photoSelectOptions.maxSelectNumber = 5; // 最多选择5张 // 2. 创建选择器实例并拉起界面 const photoPicker = new photoAccessHelper.PhotoViewPicker(); try { const photoSelectResult: photoAccessHelper.PhotoSelectResult = await photoPicker.select(photoSelectOptions); const uris: Array<string> = photoSelectResult.photoUris; console.info('选择了图片,URIs: ' + JSON.stringify(uris)); // 后续可使用 uris 数组中的 URI 进行显示或处理 // 注意:通过 picker 返回的 URI 只有只读权限 [citation:7] } catch (err) { const error = err as BusinessError; console.error(`选择图片失败,错误码: ${error.code}, 信息: ${error.message}`); } }

3.2 选择视频

代码与选择图片类似,只需修改MIMEType即可:

arkts

// 过滤选择媒体文件类型为视频 photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE;

3.3 读取 Picker 返回的 URI 数据

select返回的 URI 是只读的。可以通过fileIo接口打开并读取文件内容 。

arkts

import { fileIo } from '@kit.CoreFileKit'; async function readFileFromUri(uri: string) { try { // 以只读方式打开文件 const file = fileIo.openSync(uri, fileIo.OpenMode.READ_ONLY); console.info('文件描述符: ' + file.fd); // 读取数据到缓冲区 const buffer = new ArrayBuffer(4096); const readLen = fileIo.readSync(file.fd, buffer); console.info('成功读取了 ' + readLen + ' 字节'); // 关闭文件描述符,防止资源泄露 fileIo.closeSync(file); } catch (err) { console.error('读取文件失败: ' + err); } }

第四部分:相册与媒体文件管理(需要权限)

当需要进行写入、删除或查询所有媒体文件时,就需要之前申请的READ_IMAGEVIDEOWRITE_IMAGEVIDEO权限。

4.1 查询相册

arkts

import { dataSharePredicates } from '@kit.ArkData'; async function getAllAlbums(phAccessHelper: photoAccessHelper.PhotoAccessHelper) { const fetchOptions: photoAccessHelper.FetchOptions = { fetchColumns: [ photoAccessHelper.AlbumKey.ALBUM_ID, photoAccessHelper.AlbumKey.ALBUM_NAME, photoAccessHelper.AlbumKey.ALBUM_COUNT, ], predicates: new dataSharePredicates.DataSharePredicates(), }; try { // 获取用户相册,子类型为通用类型 const albumFetchResult = await phAccessHelper.getAlbums( photoAccessHelper.AlbumType.USER, photoAccessHelper.AlbumSubType.USER_GENERIC, fetchOptions ); const albums: photoAccessHelper.Album[] = []; while (true) { try { const album = await albumFetchResult.getNextObject(); albums.push(album); } catch (err) { // 当没有更多对象时,会抛出错误,我们在此退出循环 break; } } console.info(`查询到 ${albums.length} 个相册`); albumFetchResult.close(); // 记得释放资源 return albums; } catch (err) { console.error('查询相册失败: ' + err); return []; } }

4.2 查询相册中的媒体文件

arkts

async function getPhotosInAlbum(album: photoAccessHelper.Album) { const fetchOptions: photoAccessHelper.FetchOptions = { fetchColumns: [ photoAccessHelper.PhotoKeys.URI, photoAccessHelper.PhotoKeys.DISPLAY_NAME, photoAccessHelper.PhotoKeys.DATE_ADDED, photoAccessHelper.PhotoKeys.SIZE, ], predicates: new dataSharePredicates.DataSharePredicates(), }; try { const photoFetchResult = await album.getAssets(fetchOptions); const photos: photoAccessHelper.PhotoAsset[] = []; while (true) { try { const photo = await photoFetchResult.getNextObject(); photos.push(photo); } catch (err) { break; } } console.info(`相册中有 ${photos.length} 张照片`); photoFetchResult.close(); return photos; } catch (err) { console.error('查询照片失败: ' + err); return []; } }

4.3 保存网络图片到相册

这是一个经典场景:下载网络图片并保存到系统相册。流程是:申请权限 -> 创建图片资源 -> 打开文件流 -> 下载并写入 -> 关闭文件

arkts

import { http } from '@kit.NetworkKit'; import fs from '@ohos.file.fs'; async function saveNetworkImageToAlbum(context: Context, url: string) { // 1. 确保权限已授予(参考第二部分) // ... 权限检查代码 ... try { // 2. 获取 PhotoAccessHelper 实例 const phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context); // 3. 在相册中创建一个空白图片资源,返回其 URI const uri = await phAccessHelper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg'); console.info('创建图片资源成功,URI: ' + uri); // 4. 通过 URI 打开文件,获取文件描述符 (fd) const file = fs.openSync(uri, fs.OpenMode.READ_WRITE); // 5. 发起 HTTP 请求,将数据流式写入文件 const httpRequest = http.createHttp(); let totalSize = 0; // 监听数据接收事件,分段写入 httpRequest.on('dataReceive', (data: ArrayBuffer) => { const writeLen = fs.writeSync(file.fd, data); totalSize += writeLen; }); // 监听数据结束事件,关闭文件 httpRequest.on('dataEnd', () => { fs.closeSync(file); httpRequest.destroy(); // 销毁请求 console.info(`图片下载完成,总大小: ${totalSize} 字节`); }); // 发起流式请求 await httpRequest.requestInStream(url, { method: http.RequestMethod.GET, connectTimeout: 30000, }); } catch (err) { console.error('保存图片失败: ' + err); } }

4.4 获取图片资源数据

如果需要获取图片的像素数据或缩略图,可以使用MediaAssetManager.requestImageData接口 。

arkts

class ImageDataHandler implements photoAccessHelper.MediaAssetDataHandler<ArrayBuffer> { onDataPrepared(data: ArrayBuffer) { if (data === undefined) { console.error('准备图片数据失败'); return; } console.info('图片数据准备完成,大小: ' + data.byteLength); // 在这里处理图片数据,例如进行人脸检测 [citation:3] } } async function requestImageData(context: Context, photoAsset: photoAccessHelper.PhotoAsset) { const requestOptions: photoAccessHelper.RequestOptions = { deliveryMode: photoAccessHelper.DeliveryMode.HIGH_QUALITY_MODE, // 请求高质量图片 }; try { await photoAccessHelper.MediaAssetManager.requestImageData( context, photoAsset, requestOptions, new ImageDataHandler() ); console.info('请求图片数据成功'); } catch (err) { console.error('请求图片数据失败: ' + err); } }

第五部分:进阶主题

5.1 动态照片处理

HarmonyOS 对动态照片(Moving Photo)提供了完整的支持。

  • 保存动态照片:可以使用MediaAssetChangeRequest,在CreateOptions中指定subtypeMOVING_PHOTO,然后分别添加图片和视频资源 。

  • 播放动态照片:使用MediaAssetManager.requestMovingPhoto接口获取MovingPhoto对象,然后传递给MovingPhotoView组件进行播放。MovingPhotoViewController可控制播放、停止等操作 。

5.2 设备升级场景的权限继承

当设备从 API 9 及以下版本升级到 HarmonyOS 5.0 及以上时,旧版本的媒体文件访问权限会失效。应用需要调用requestPhotoUrisReadPermission接口,向用户请求重新授权这些文件 。

arkts

// 假设 uris 是从应用数据中读取的旧版文件 URI 列表 let uris: Array<string> = ['file://media/Photo/1/...']; try { phAccessHelper.requestPhotoUrisReadPermission(uris).then((result: Array<string>) => { if (result) { console.info('授权成功,新的 URI 列表: ' + JSON.stringify(result)); // 使用新的 URI 访问文件 } else { console.info('用户拒绝了授权'); } }); } catch(error) { console.error('请求权限继承失败: ' + JSON.stringify(error)); }

总结

MediaLibraryKit 构建了一道兼顾安全与便捷的桥梁。对于基础场景(如仅需选择图片),应优先使用无需权限的Picker组件;当需要深入管理相册时,则通过PhotoAccessHelper进行复杂操作。从网络下载到相册、查询媒体文件、管理动态照片乃至处理版本升级的权限问题,这套 API 都提供了清晰且完整的解决方案。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询