开源 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

相关推荐
Aa hui4 分钟前
LVS 集群技术基础
linux·centos·lvs
larance28 分钟前
nginx + uwsgi + systemd 部署 flask
linux·virtualenv·lvs
Georgewu1 小时前
【HarmonyOS 5】鸿蒙页面和组件生命周期函数
harmonyos
海豚调度1 小时前
从批到流,Zoom 基于 DolphinScheduler 的流批统一调度系统演进
大数据·开源·zoom·apache dolphinscheduler·批流一体
秋风起,再归来~1 小时前
【Linux庖丁解牛】— 线程控制!
linux·c++·算法
贾saisai1 小时前
LINUX(三)文件I/O、对文件打开、读、写、偏移量
java·linux·数据库
沉在嵌入式的鱼1 小时前
RK3588移植Openssl库
linux·rk3588·openssl
DIY机器人工房2 小时前
完整的 SquareStudio 注册登录功能实现方案:已经烧录到开发板正常使用
linux·嵌入式硬件·嵌入式·diy机器人工房
杨荧2 小时前
基于大数据的旅游推荐系统 Python+Django+Hive+Vue.js
大数据·前端·vue.js·hive·python·开源·旅游
快手技术2 小时前
快手 AutoThink 大模型 KAT-V1 正式开源,40B 版本比肩满血版 R1,技术报告全公开!
开源