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

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

相关链接:

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

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

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

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

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

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

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

android 链接(十三章):

开源 java android app 开发(一)开发环境的搭建_csdn 开源 java android app-CSDN博客

.net mvc链接(八章):

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

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

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

相关推荐
一只栖枝2 小时前
华为 HCIE 大数据认证中 Linux 命令行的运用及价值
大数据·linux·运维·华为·华为认证·hcie·it
wuicer5 小时前
ubuntu 20.04 安装anaconda以及安装spyder
linux·运维·ubuntu
cui__OaO6 小时前
Linux软件编程--线程
linux·开发语言·线程·互斥锁·死锁·信号量·嵌入式学习
小狗爱吃黄桃罐头6 小时前
正点原子【第四期】Linux之驱动开发篇学习笔记-1.1 Linux驱动开发与裸机开发的区别
linux·驱动开发·学习
zhanshuo6 小时前
在鸿蒙里优雅地处理网络错误:从 Demo 到实战案例
harmonyos
zhanshuo6 小时前
在鸿蒙中实现深色/浅色模式切换:从原理到可运行 Demo
harmonyos
小晶晶京京7 小时前
day34-LNMP详解
linux·运维·服务器
画个太阳作晴天7 小时前
A12预装app
linux·服务器·前端
fengyehongWorld7 小时前
Linux crontab定时任务
linux·运维
shuangrenlong8 小时前
ubuntu更新chrome版本
linux·chrome·ubuntu