《HarmonyOS NEXT MediaLibraryKit 完整使用指南》

《HarmonyOS NEXT MediaLibraryKit 完整使用指南》
第一部分初识 MediaLibraryKit1.1 什么是 MediaLibraryKitMedia 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 完整权限申请流程arktsimport { 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(): Promiseboolean { 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): Promiseboolean { 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): Promiseboolean { 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): PromisephotoAccessHelper.PhotoAccessHelper | null { const granted await permissionManager.ensurePermissions(context); if (!granted) { console.error(权限未授予无法访问媒体库); return null; } return getPhotoAccessHelper(context); }第三部分使用 Picker 选择媒体文件无需读取权限这是最用户友好的方式。应用通过PhotoViewPicker拉起系统相册界面用户选择后返回文件 URI整个过程应用未获取读取权限保障了用户隐私 。3.1 选择单张/多张图片arktsimport { 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: Arraystring 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接口打开并读取文件内容 。arktsimport { 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_IMAGEVIDEO和WRITE_IMAGEVIDEO权限。4.1 查询相册arktsimport { 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 查询相册中的媒体文件arktsasync 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 保存网络图片到相册这是一个经典场景下载网络图片并保存到系统相册。流程是申请权限 - 创建图片资源 - 打开文件流 - 下载并写入 - 关闭文件。arktsimport { 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接口 。arktsclass ImageDataHandler implements photoAccessHelper.MediaAssetDataHandlerArrayBuffer { 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中指定subtype为MOVING_PHOTO然后分别添加图片和视频资源 。播放动态照片使用MediaAssetManager.requestMovingPhoto接口获取MovingPhoto对象然后传递给MovingPhotoView组件进行播放。MovingPhotoViewController可控制播放、停止等操作 。5.2 设备升级场景的权限继承当设备从 API 9 及以下版本升级到 HarmonyOS 5.0 及以上时旧版本的媒体文件访问权限会失效。应用需要调用requestPhotoUrisReadPermission接口向用户请求重新授权这些文件 。arkts// 假设 uris 是从应用数据中读取的旧版文件 URI 列表 let uris: Arraystring [file://media/Photo/1/...]; try { phAccessHelper.requestPhotoUrisReadPermission(uris).then((result: Arraystring) { if (result) { console.info(授权成功新的 URI 列表: JSON.stringify(result)); // 使用新的 URI 访问文件 } else { console.info(用户拒绝了授权); } }); } catch(error) { console.error(请求权限继承失败: JSON.stringify(error)); }总结MediaLibraryKit 构建了一道兼顾安全与便捷的桥梁。对于基础场景如仅需选择图片应优先使用无需权限的Picker组件当需要深入管理相册时则通过PhotoAccessHelper进行复杂操作。从网络下载到相册、查询媒体文件、管理动态照片乃至处理版本升级的权限问题这套 API 都提供了清晰且完整的解决方案。