开源 Arkts 鸿蒙应用 开发(八)多媒体--相册和相机

 文章的目的为了记录使用Arkts 进行Harmony app 开发学习的经历。本职为嵌入式软件开发,公司安排开发app,临时学习,完成app的开发。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。

  相关链接:

开源 Arkts 鸿蒙应用 开发(一)工程文件分析-优快云博客

开源 Arkts 鸿蒙应用 开发(二)封装库.har制作和应用-优快云博客

开源 Arkts 鸿蒙应用 开发(三)Arkts的介绍-优快云博客

开源 Arkts 鸿蒙应用 开发(四)布局和常用控件-优快云博客

开源 Arkts 鸿蒙应用 开发(五)控件组成和复杂控件-优快云博客

开源 Arkts 鸿蒙应用 开发(六)数据持久--文件和首选项存储-优快云博客

开源 Arkts 鸿蒙应用 开发(七)数据持久--sqlite关系数据库-优快云博客

开源 Arkts 鸿蒙应用 开发(八)多媒体--相册和相机-优快云博客

开源 Arkts 鸿蒙应用 开发(九)通讯--tcp客户端-优快云博客

开源 Arkts 鸿蒙应用 开发(十)通讯--Http数据传输-优快云博客

 推荐链接:

开源 java android app 开发(一)开发环境的搭建-优快云博客

开源 java android app 开发(二)工程文件结构-优快云博客

开源 java android app 开发(三)GUI界面布局和常用组件-优快云博客

开源 java android app 开发(四)GUI界面重要组件-优快云博客

开源 java android app 开发(五)文件和数据库存储-优快云博客

开源 java android app 开发(六)多媒体使用-优快云博客

开源 java android app 开发(七)通讯之Tcp和Http-优快云博客

开源 java android app 开发(八)通讯之Mqtt和Ble-优快云博客

开源 java android app 开发(九)后台之线程和服务-优快云博客

开源 java android app 开发(十)广播机制-优快云博客

开源 java android app 开发(十一)调试、发布-优快云博客

开源 java android app 开发(十二)封库.aar-优快云博客

推荐链接:

开源C# .net mvc 开发(一)WEB搭建_c#部署web程序-优快云博客

开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-优快云博客

开源 C# .net mvc 开发(三)WEB内外网访问(VS发布、IIS配置网站、花生壳外网穿刺访问)_c# mvc 域名下不可訪問內網,內網下可以訪問域名-优快云博客

开源 C# .net mvc 开发(四)工程结构、页面提交以及显示_c#工程结构-优快云博客

开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-优快云博客

本章内容主要是鸿蒙的多媒体使用,主要功能包括从相册选择图片、拍摄照片以及将图片保存到应用沙箱目录。

1.使用流程

2.相册和相机的使用

3.保存到沙箱

4.所有代码

5.显示效果

一、使用流程图

二、相册和相机的使用

2.1  使用PhotoViewPicker选择图片

         Button("打开相册照片")
            .width('100%')
            .height(40)
            .onClick(async () => {
              try {
                let PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
                PhotoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
                PhotoSelectOptions.maxSelectNumber = 1;
                let photoPicker = new photoAccessHelper.PhotoViewPicker();
                photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult: photoAccessHelper.PhotoSelectResult) => {
                  this.imageUri = PhotoSelectResult.photoUris[0] ? PhotoSelectResult.photoUris[0] : this.imageUri;
                  hilog.info(0x0000, TAG, 'PhotoViewPicker.select succeed, uri: ' + JSON.stringify(PhotoSelectResult));
                }).catch((err: BusinessError) => {
                  hilog.error(0x0000, TAG, `PhotoViewPicker.select failed, error: ${err.code}, ${err.message}`);
                });
              } catch (error) {
                let err: BusinessError = error as BusinessError;
                hilog.error(0x0000, TAG, `PhotoViewPicker failed, error: ${err.code}, ${err.message}`);
              }
              this.isShowGet = false;
            })

2.2  用cameraPicker调用设备相机

          Button("相机拍摄照片")
            .width('100%')
            .height(40)
            .onClick(async () => {
              // [Start pick_file]
              try {
                let pickerProfile: cameraPicker.PickerProfile =
                  { cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK };
                //Select the action of pulling up the camera to take pictures.
                let pickerResult: cameraPicker.PickerResult = await cameraPicker.pick(this.getUIContext().getHostContext(),
                  [cameraPicker.PickerMediaType.PHOTO], pickerProfile);
                //Return the photo uri to the application.
                this.imageUri = pickerResult.resultUri ? pickerResult.resultUri : this.imageUri;
                hilog.info(0x0000, TAG, 'cameraPicker.pick succeed, uri: ' + JSON.stringify(pickerResult));
              } catch (error) {
                let err = error as BusinessError;
                hilog.error(0x0000, TAG, `cameraPicker.pick failed, error: ${err.code}, ${err.message}`);
              }
              // [End pick_file]
              this.isShowGet = false;
            })

三、保存到沙箱,特别的是大量使用async/await处理异步操作

 async saveImageToSandbox() {
    // 1. 检查图片URI
    if (!this.imageUri) {
      this.getUIContext().getPromptAction().showToast({
        message: $r('app.string.no_image_alert'),
        duration: 2000
      });
      return;
    }

    try {
      // 2. 等待图片复制到沙箱
      await copyImg2Sandbox(this.imageUri, this.path);

      // 3. 创建ImageSource
      this.imageSource = image.createImageSource(this.path);

      // 4. 并行获取图片信息
      await Promise.all([
        new Promise<void>((resolve, reject) => {
          this.imageSource!.getImageInfo((error, info) => {
            error ? reject(error) : resolve();
          });
        }),
        this.imageSource.getImageProperties([
          image.PropertyKey.IMAGE_WIDTH,
          image.PropertyKey.IMAGE_LENGTH,
          image.PropertyKey.F_NUMBER
        ])
      ]);

      // 5. 创建PixelMap(确保这一步成功)
      this.pixelMap = await this.imageSource.createPixelMap();
      if (!this.pixelMap) {
        throw new Error('Failed to create PixelMap');
      }

      // 6. 保存到文件
      await pixelMap2File(this.pixelMap, this.path);

      this.getUIContext().getPromptAction().showToast({
        message: $r('app.string.save_in_sandbox_success'),
        duration: 2000
      });
      this.isShowSave = false;

    } catch (error) {
      this.handleSaveError(error as BusinessError);
    }
  }

四、所有代码,新建工程后,只修改Index.ets就可以

Index.ets代码




import { image } from '@kit.ImageKit';
import { PhotoPickerComponent, PickerController, photoAccessHelper, ReminderMode } from '@kit.MediaLibraryKit';
import { cameraPicker, camera } from '@kit.CameraKit';
import { picker } from '@kit.CoreFileKit';
import { promptAction } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { copyImg2Sandbox, pixelMap2File } from '../common/utils/Utils';

const TAG = 'IMAGE_APP';

@Entry
@Component
struct Index {
  @State path: string = this.getUIContext().getHostContext()!.filesDir + '/image.jpg';
  @State pixelMapPath: string = this.getUIContext().getHostContext()!.filesDir + '/pixelMap.jpg';
  @State imageUri: string | undefined = undefined;
  @State imageSource: image.ImageSource | undefined = undefined;
  @State pixelMap: image.PixelMap | undefined = undefined;
  @State isShowGet: boolean = false;
  @State isShowPicker: boolean = false;
  @State isShowSave: boolean = false;
  @State pickerController: PickerController = new PickerController();




  async saveImageToSandbox() {
    // 1. 检查图片URI
    if (!this.imageUri) {
      this.getUIContext().getPromptAction().showToast({
        message: $r('app.string.no_image_alert'),
        duration: 2000
      });
      return;
    }

    try {
      // 2. 等待图片复制到沙箱
      await copyImg2Sandbox(this.imageUri, this.path);

      // 3. 创建ImageSource
      this.imageSource = image.createImageSource(this.path);

      // 4. 并行获取图片信息
      await Promise.all([
        new Promise<void>((resolve, reject) => {
          this.imageSource!.getImageInfo((error, info) => {
            error ? reject(error) : resolve();
          });
        }),
        this.imageSource.getImageProperties([
          image.PropertyKey.IMAGE_WIDTH,
          image.PropertyKey.IMAGE_LENGTH,
          image.PropertyKey.F_NUMBER
        ])
      ]);

      // 5. 创建PixelMap(确保这一步成功)
      this.pixelMap = await this.imageSource.createPixelMap();
      if (!this.pixelMap) {
        throw new Error('Failed to create PixelMap');
      }

      // 6. 保存到文件
      await pixelMap2File(this.pixelMap, this.path);

      this.getUIContext().getPromptAction().showToast({
        message: $r('app.string.save_in_sandbox_success'),
        duration: 2000
      });
      this.isShowSave = false;

    } catch (error) {
      this.handleSaveError(error as BusinessError);
    }
  }

  // 错误处理方法
  private handleSaveError(error: BusinessError) {
    hilog.error(0x0000, TAG, `保存失败: ${error.code}, ${error.message}`);

    let message = "save_failed";
    if (error.message.includes('createPixelMap')) {
      message = "pixelmap_creation_failed";
    } else if (error.message.includes('copyImg2Sandbox')) {
      message = "copy_failed";
    }

    this.getUIContext().getPromptAction().showToast({
      message,
      duration: 2000
    });
  }

  build() {
    Navigation() {
      Column() {
        Image(this.imageUri)
          .height(400)
          .margin({ top: 16 })

        Column({ space: 12 }) {

          Button("打开相册照片")
            .width('100%')
            .height(40)
            .onClick(async () => {
              try {
                let PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
                PhotoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
                PhotoSelectOptions.maxSelectNumber = 1;
                let photoPicker = new photoAccessHelper.PhotoViewPicker();
                photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult: photoAccessHelper.PhotoSelectResult) => {
                  this.imageUri = PhotoSelectResult.photoUris[0] ? PhotoSelectResult.photoUris[0] : this.imageUri;
                  hilog.info(0x0000, TAG, 'PhotoViewPicker.select succeed, uri: ' + JSON.stringify(PhotoSelectResult));
                }).catch((err: BusinessError) => {
                  hilog.error(0x0000, TAG, `PhotoViewPicker.select failed, error: ${err.code}, ${err.message}`);
                });
              } catch (error) {
                let err: BusinessError = error as BusinessError;
                hilog.error(0x0000, TAG, `PhotoViewPicker failed, error: ${err.code}, ${err.message}`);
              }
              this.isShowGet = false;
            })

          Button("相机拍摄照片")
            .width('100%')
            .height(40)
            .onClick(async () => {
              // [Start pick_file]
              try {
                let pickerProfile: cameraPicker.PickerProfile =
                  { cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK };
                //Select the action of pulling up the camera to take pictures.
                let pickerResult: cameraPicker.PickerResult = await cameraPicker.pick(this.getUIContext().getHostContext(),
                  [cameraPicker.PickerMediaType.PHOTO], pickerProfile);
                //Return the photo uri to the application.
                this.imageUri = pickerResult.resultUri ? pickerResult.resultUri : this.imageUri;
                hilog.info(0x0000, TAG, 'cameraPicker.pick succeed, uri: ' + JSON.stringify(pickerResult));
              } catch (error) {
                let err = error as BusinessError;
                hilog.error(0x0000, TAG, `cameraPicker.pick failed, error: ${err.code}, ${err.message}`);
              }
              // [End pick_file]
              this.isShowGet = false;
            })



          Button("保存照片到APP目录")
            .width('100%')
            .height(40)
            .onClick(async () => {
              this.saveImageToSandbox();

            })

        }
        .width('100%')
        .height(150)
        .padding({ left: 16, right: 16 })
        .margin({ bottom: 16 })
        .justifyContent(FlexAlign.SpaceBetween)
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.SpaceBetween)
    }
    .width('100%')
    .height('100%')
    .title($r('app.string.title'))
  }
}

五、显示效果

5.1  app图片和打开相册后图片

5.2  保存到APP目录后图片所存位置图,点击DevEco的右下角的 Device File Browser

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值