文档管理中心

保存媒体库资源

保存图片、视频等用户文件到图库时,无需申请相册管理模块权限'ohos.permission.WRITE_IMAGEVIDEO',应用可以通过安全控件授权弹窗的方式,将用户指定的媒体资源保存到图库中。

注意

Media Library Kit提供图片和视频的管理能力,当需要读取和保存音频文件时,请使用AudioViewPicker(音频选择器对象)

获取支持保存的资源格式

下面以获取支持保存的图片类型资源格式为例。

开发步骤

调用phAccessHelper.getSupportedPhotoFormats接口获取支持保存的图片类型资源格式。

收起
自动换行
深色代码主题
复制
  1. import { photoAccessHelper } from '@kit.MediaLibraryKit';
  2. import { common } from '@kit.AbilityKit';
  3. @Entry({ routeName : 'Scene1' })
  4. @Component
  5. export struct Scene1 {
  6. @State outputText: string = 'Supported formats:\n';
  7. build() {
  8. NavDestination() {
  9. Column({ space: 20 }) {
  10. // ...
  11. Button('example')
  12. .width('80%')
  13. .height(50)
  14. .fontSize(16)
  15. .onClick(async () => {
  16. let context: Context = this.getUIContext().getHostContext() as common.UIAbilityContext;
  17. let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
  18. this.outputText = await example(phAccessHelper);
  19. })
  20. // ...
  21. }
  22. .width('100%')
  23. .height('100%')
  24. }
  25. .title('Supported Formats')
  26. }
  27. }
  28. async function example(phAccessHelper: photoAccessHelper.PhotoAccessHelper): Promise<string> {
  29. try {
  30. let outputText = 'Supported formats:\n';
  31. // The value 1 means the supported image formats, and 2 means the supported video formats.
  32. let imageFormat = await phAccessHelper.getSupportedPhotoFormats(photoAccessHelper.PhotoType.IMAGE);
  33. let result = '';
  34. for (let i = 0; i < imageFormat.length; i++) {
  35. result += imageFormat[i];
  36. if (i !== imageFormat.length - 1) {
  37. result += ', ';
  38. }
  39. }
  40. outputText += result;
  41. console.info('getSupportedPhotoFormats success, data is ' + outputText);
  42. return 'getSupportedPhotoFormats success, data is\n' + outputText;
  43. } catch (error) {
  44. console.error('getSupportedPhotoFormats failed, errCode is', error);
  45. return 'getSupportedPhotoFormats failed, errCode is\n' + JSON.stringify(error);
  46. }
  47. }

使用安全控件保存媒体库资源

安全控件的介绍可参考SaveButton。保存前可以通过调用registerChange接口注册对默认URI(DEFAULT_PHOTO_URI)的监听。资源保存成功后,根据接收到该资源的NOTIFY_ADD通知完成后续业务。

下面以使用安全控件创建一张图片资源为例。

开发步骤

  1. 设置安全控件按钮属性。
  2. 创建安全控件按钮。
  3. 调用registerChange接口注册对默认URI(DEFAULT_PHOTO_URI)的监听。
  4. 调用MediaAssetChangeRequest.createImageAssetRequestPhotoAccessHelper.applyChanges接口创建图片资源。
  5. 调用getAsset接口获取保存的资产,并获取资产URI。在接收到资产URI的NOTIFY_ADD通知后,完成后续业务。
收起
自动换行
深色代码主题
复制
  1. import { photoAccessHelper } from '@kit.MediaLibraryKit';
  2. import { common } from '@kit.AbilityKit';
  3. import { dataSharePredicates } from '@kit.ArkData';
  4. // ...
  5. @Entry({ routeName : 'Scene2' })
  6. @Component
  7. export struct Scene2 {
  8. @State statusMessage: string = '';
  9. @State imageSource: string = '';
  10. uriString: string = '';
  11. saveButtonOptions: SaveButtonOptions = {
  12. icon: SaveIconStyle.FULL_FILLED,
  13. text: SaveDescription.SAVE_IMAGE,
  14. buttonType: ButtonType.Capsule
  15. }// Set properties of SaveButton.
  16. // ...
  17. onCallback = (changeData: photoAccessHelper.ChangeData) => {
  18. for (let i = 0; i < changeData.uris.length; i++) {
  19. // 保存媒体库资源成功后,会监听到类型为NOTIFY_ADD的资产URI。
  20. if (changeData.uris[i] === this.uriString && changeData.type === photoAccessHelper.NotifyType.NOTIFY_ADD) {
  21. let predicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates();
  22. predicates.equalTo(photoAccessHelper.PhotoKeys.URI, changeData.uris[i]);
  23. let fetchOptions: photoAccessHelper.FetchOptions = {
  24. fetchColumns: [],
  25. predicates: predicates
  26. };
  27. let context: Context = this.getUIContext().getHostContext() as common.UIAbilityContext;
  28. let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
  29. phAccessHelper.getAssets(fetchOptions, async (err, fetchResult) => {
  30. if (fetchResult !== undefined) {
  31. let photoAsset: photoAccessHelper.PhotoAsset = await fetchResult.getFirstObject();
  32. if (photoAsset !== undefined) {
  33. console.info('getAssets successfully');
  34. }
  35. }
  36. phAccessHelper.unRegisterChange(photoAccessHelper.DefaultChangeUri.DEFAULT_PHOTO_URI);
  37. });
  38. }
  39. }
  40. }
  41. build() {
  42. NavDestination() {
  43. Column({ space: 20 }) {
  44. // ...
  45. SaveButton(this.saveButtonOptions) // Create a button with SaveButton.
  46. .onClick(async (event, result: SaveButtonOnClickResult) => {
  47. if (result == SaveButtonOnClickResult.SUCCESS) {
  48. try {
  49. let context: Context = this.getUIContext().getHostContext() as common.UIAbilityContext;
  50. let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
  51. // 注册默认监听
  52. phAccessHelper.registerChange(
  53. photoAccessHelper.DefaultChangeUri.DEFAULT_PHOTO_URI, true, this.onCallback);
  54. // 需要确保fileUri对应的资源存在。
  55. let fileUri = 'file://' + context.filesDir + '/test.jpg';
  56. let assetChangeRequest: photoAccessHelper.MediaAssetChangeRequest =
  57. photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(context, fileUri);
  58. await phAccessHelper.applyChanges(assetChangeRequest);
  59. this.uriString = assetChangeRequest.getAsset().uri;
  60. this.statusMessage = 'createAsset successfully, uri: ' + this.uriString;
  61. console.info('createAsset successfully, uri: ' + this.uriString);
  62. } catch (err) {
  63. this.statusMessage = `create asset failed with error: ${err.code}, ${err.message}`;
  64. console.error(`create asset failed with error: ${err.code}, ${err.message}`);
  65. }
  66. } else {
  67. this.statusMessage = 'SaveButtonOnClickResult create asset failed';
  68. console.error('SaveButtonOnClickResult create asset failed');
  69. }
  70. })
  71. // ...
  72. }
  73. .width('100%')
  74. .height('100%')
  75. }
  76. .title('SaveButton Example')
  77. }
  78. }

除了上述通过fileUri从应用沙箱指定资源内容的方式,开发者还可以通过ArrayBuffer的方式添加资源内容,详情请参考addResource接口。

使用弹窗授权保存媒体库资源

下面以弹窗授权的方式保存一张图片资源为例。

开发步骤

  1. 指定待保存到媒体库的应用文件uri(需为应用沙箱路径)。

  2. 指定待保存照片的创建选项,包括文件后缀和照片类型,标题和照片子类型可选。

  3. 调用showAssetsCreationDialog,基于弹窗授权的方式获取的目标媒体文件uri。

    弹框需要显示应用名称,无法直接获取应用名称,依赖于配置项的label和icon,因此调用此接口时请确保module.json5文件中的abilities标签中配置了label和icon项。当传入uri为沙箱路径时,可正常保存图片/视频,但无界面预览。

  4. 将应用沙箱的照片内容写入媒体库的目标URI。

收起
自动换行
深色代码主题
复制
  1. import { photoAccessHelper } from '@kit.MediaLibraryKit';
  2. import { common } from '@kit.AbilityKit';
  3. import { fileIo } from '@kit.CoreFileKit';
  4. // ...
  5. async function example(
  6. phAccessHelper: photoAccessHelper.PhotoAccessHelper,
  7. context: common.UIAbilityContext
  8. ): Promise<string> {
  9. let desFile: fileIo.File | null = null;
  10. let srcFile: fileIo.File | null = null;
  11. try {
  12. // 指定要保存到应用程序沙盒目录中的图片的URI。
  13. let srcFileUri = context.filesDir + '/test.jpg';
  14. let srcFileUris: string[] = [
  15. srcFileUri
  16. ];
  17. // 设置要保存的图片的参数:文件扩展名、图片类型、标题和子类型(后两者为可选)。
  18. let photoCreationConfigs: photoAccessHelper.PhotoCreationConfig[] = [
  19. {
  20. title: 'test', // This parameter is optional.
  21. fileNameExtension: 'jpg',
  22. photoType: photoAccessHelper.PhotoType.IMAGE,
  23. subtype: photoAccessHelper.PhotoSubtype.DEFAULT,
  24. }
  25. ];
  26. console.info('Source URI: ' + srcFileUri);
  27. // 基于弹窗授权获取媒体库中的目标URI。
  28. let desFileUris: string[] =
  29. await phAccessHelper.showAssetsCreationDialog(srcFileUris, photoCreationConfigs);
  30. console.info('Destination URIs: ' + JSON.stringify(desFileUris));
  31. // 将图片从沙盒目录写入媒体库中的目标URI。
  32. desFile = await fileIo.open(desFileUris[0], fileIo.OpenMode.WRITE_ONLY);
  33. srcFile = await fileIo.open(srcFileUri, fileIo.OpenMode.READ_ONLY);
  34. await fileIo.copyFile(srcFile.fd, desFile.fd);
  35. console.info('create asset by dialog successfully');
  36. return 'create asset by dialog successfully';
  37. } catch (err) {
  38. console.error(`failed to create asset by dialog successfully errCode is: ${err.code}, ${err.message}`);
  39. return `failed to create asset by dialog successfully errCode is: ${err.code}, ${err.message}`;
  40. } finally {
  41. if (srcFile) {
  42. fileIo.closeSync(srcFile);
  43. }
  44. if (desFile) {
  45. fileIo.closeSync(desFile);
  46. }
  47. }
  48. }
请输入您想要搜索的关键词