日常开发中,拍照功能是很多HarmonyOS App的核心需求(比如相册、扫码、证件照App)。

今天就用最易懂的方式,教你用ArkUI+ArkTS在HarmonyOS 6.0里实现“打开相机→预览→拍照→显示/保存照片”的完整流程,新手也能一看就会!
在这里插入图片描述

核心知识点先理清

不用记复杂概念,先搞懂3个核心“工具”:

  1. Camera组件:ArkUI官方封装的相机组件,负责实时预览相机画面、触发拍照,是实现拍照的核心;
  2. CameraController:相机控制器,用来手动触发拍照、切换前后摄像头、调整拍摄参数;
  3. 权限配置:相机是敏感权限,必须先在配置文件里声明,运行时还要用户授权,否则相机打不开。

第一步:准备环境

  1. 确保DevEco Studio升级到支持HarmonyOS 6.0的版本(建议4.1及以上);
  2. 新建一个Stage模型的ArkTS工程(新手优先选这个,兼容性最好);
  3. 准备一台HarmonyOS 6.0真机(模拟器没有相机功能,必须用真机测试!)。

第二步:配置核心权限

相机和照片存储都需要权限,先在module.json5文件里声明:

{
  "module": {
    // 其他默认配置...
    "requestPermissions": [
      {
        "name": "ohos.permission.CAMERA", // 相机权限(必须)
        "reason": "需要使用相机拍照", // 授权说明(给用户看)
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "always"
        }
      },
      {
        "name": "ohos.permission.WRITE_MEDIA_PHOTOS", // 写入照片权限(保存用)
        "reason": "需要保存拍摄的照片到相册",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "always"
        }
      },
      {
        "name": "ohos.permission.READ_MEDIA_PHOTOS", // 读取照片权限(可选)
        "reason": "需要读取相册照片",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "always"
        }
      }
    ]
  }
}

第三步:基础版拍照(预览+拍照+显示照片)

先实现最核心的功能:打开相机预览→点击按钮拍照→在页面上显示拍好的照片。

完整代码

// index.ets
@Entry
@Component
struct CameraPage {
  // 1. 定义相机控制器
  private cameraController: CameraController = new CameraController()
  // 2. 存储拍摄的照片数据(用于显示)
  @State photoData: PixelMap | null = null
  // 3. 标记是否授权成功
  @State isCameraAuthorized: boolean = false

  build() {
    Column() {
      // 第一步:先申请相机权限
      if (!this.isCameraAuthorized) {
        Button('点击授权相机权限')
          .onClick(() => {
            this.requestCameraPermission()
          })
          .margin(20)
      } else {
        // 第二步:相机预览区域(核心)
        Camera({
          controller: this.cameraController // 绑定控制器
        })
        .width('100%') // 预览区域宽度占满屏幕
        .height(400) // 预览区域高度400vp
        .marginBottom(20)

        // 第三步:拍照按钮
        Button('点击拍照')
          .onClick(() => {
            this.takePhoto()
          })
          .marginBottom(20)

        // 第四步:显示拍摄的照片
        if (this.photoData) {
          Image(this.photoData)
            .width('100%')
            .height(200)
            .borderRadius(10)
            .marginTop(10)
          Text('拍摄的照片预览')
            .fontSize(14)
            .marginTop(5)
        }
      }
    }
    .width('100%')
    .height('100%')
    .padding(20)
    .backgroundColor('#f5f5f5')
    .justifyContent(FlexAlign.Center)
  }

  // 【辅助方法1】申请相机权限
  async requestCameraPermission() {
    try {
      // 申请相机权限
      const result = await requestPermissionsFromUser(['ohos.permission.CAMERA'])
      // 判断授权结果(授权成功返回true)
      this.isCameraAuthorized = result[0] === 0
      if (this.isCameraAuthorized) {
        console.log('相机权限授权成功!')
      } else {
        console.log('相机权限授权失败,无法使用相机')
      }
    } catch (e) {
      console.log('申请权限出错:', e)
    }
  }

  // 【辅助方法2】触发拍照
  async takePhoto() {
    try {
      // 调用控制器的拍照方法,获取照片数据
      const photoResult = await this.cameraController.capturePhoto({
        quality: CameraPhotoQuality.NORMAL // 拍摄质量:普通(可选HIGH/LOW)
      })
      // 将照片数据转换成PixelMap(用于Image组件显示)
      this.photoData = photoResult.pixelMap
      console.log('拍照成功!')
    } catch (e) {
      console.log('拍照失败:', e)
    }
  }
}

代码逐行解释(重点)

  1. 权限申请requestCameraPermission方法通过requestPermissionsFromUser向用户申请相机权限,只有授权成功才能显示相机预览;
  2. Camera组件:绑定控制器后,就能实时显示相机画面,宽高可以根据需求调整;
  3. 拍照逻辑capturePhoto方法触发拍照,指定拍摄质量(NORMAL/LOW/HIGH),返回的photoResult包含照片的PixelMap数据;
  4. 照片显示:把PixelMap数据传给Image组件,就能在页面上看到拍好的照片。

运行效果

  1. 打开App,点击“授权相机权限”,在弹窗里选择“允许”;
  2. 页面显示相机实时预览画面;
  3. 点击“拍照”按钮,下方立刻显示刚拍的照片。

第四步:进阶玩法(保存照片到相册+切换前后摄像头)

基础版只能临时显示照片,退出App就没了;还想切换前后摄像头?这部分教你实现!

完整进阶代码

// index.ets
import image from '@ohos.multimedia.image'; // 导入图片处理库
import photoAccessHelper from '@ohos.file.photoAccessHelper'; // 导入相册操作库

@Entry
@Component
struct AdvancedCameraPage {
  private cameraController: CameraController = new CameraController()
  @State photoData: PixelMap | null = null
  @State isCameraAuthorized: boolean = false
  @State currentCamera: string = 'back' // 当前摄像头:back(后置)/front(前置)

  build() {
    Column() {
      if (!this.isCameraAuthorized) {
        Button('点击授权相机+存储权限')
          .onClick(() => {
            this.requestAllPermissions()
          })
          .margin(20)
      } else {
        // 相机预览
        Camera({
          controller: this.cameraController,
          position: this.currentCamera === 'back' ? CameraPosition.BACK : CameraPosition.FRONT
        })
        .width('100%')
        .height(400)
        .marginBottom(20)

        // 控制按钮区域
        Row() {
          // 切换摄像头按钮
          Button(`切换${this.currentCamera === 'back' ? '前置' : '后置'}摄像头`)
            .onClick(() => {
              this.switchCamera()
            })
            .margin(10)

          // 拍照按钮
          Button('拍照')
            .onClick(() => {
              this.takePhotoAndSave()
            })
            .margin(10)
        }
        .justifyContent(FlexAlign.Center)

        // 照片预览
        if (this.photoData) {
          Image(this.photoData)
            .width('100%')
            .height(200)
            .borderRadius(10)
            .marginTop(20)
          Text('拍摄的照片(已保存到相册)')
            .fontSize(14)
            .marginTop(5)
        }
      }
    }
    .width('100%')
    .height('100%')
    .padding(20)
    .backgroundColor('#f5f5f5')
    .justifyContent(FlexAlign.Center)
  }

  // 申请相机+存储权限
  async requestAllPermissions() {
    try {
      const permissions = ['ohos.permission.CAMERA', 'ohos.permission.WRITE_MEDIA_PHOTOS']
      const result = await requestPermissionsFromUser(permissions)
      this.isCameraAuthorized = result[0] === 0 && result[1] === 0
      if (this.isCameraAuthorized) {
        console.log('相机+存储权限授权成功!')
      } else {
        console.log('权限授权失败')
      }
    } catch (e) {
      console.log('申请权限出错:', e)
    }
  }

  // 切换前后摄像头
  switchCamera() {
    try {
      this.currentCamera = this.currentCamera === 'back' ? 'front' : 'back'
      // 调用控制器切换摄像头
      this.cameraController.switchCamera(this.currentCamera === 'back' ? CameraPosition.BACK : CameraPosition.FRONT)
      console.log(`切换到${this.currentCamera}摄像头成功`)
    } catch (e) {
      console.log('切换摄像头失败:', e)
    }
  }

  // 拍照并保存到相册
  async takePhotoAndSave() {
    try {
      // 1. 拍照获取照片数据
      const photoResult = await this.cameraController.capturePhoto({
        quality: CameraPhotoQuality.HIGH // 高质量拍摄
      })
      this.photoData = photoResult.pixelMap

      // 2. 将PixelMap转换成文件流,保存到相册
      const context = getContext(this) as any
      const helper = photoAccessHelper.getPhotoAccessHelper(context)
      // 创建照片保存的参数
      const photoSaveOptions = {
        title: `IMG_${new Date().getTime()}.jpg`, // 照片命名(时间戳避免重复)
        tags: ['camera_photo'], // 标签(可选)
        mimeType: 'image/jpeg' // 格式
      }
      // 创建保存的文件
      const photoUri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, photoSaveOptions)
      // 获取文件写入流
      const file = await helper.openAsset(photoUri, 'w')
      // 将PixelMap编码成JPEG格式并写入文件
      const encodeOptions = { format: image.ImageFormat.JPEG, quality: 100 }
      const buffer = await photoResult.pixelMap.encodeToBuffer(encodeOptions)
      await file.write(buffer)
      // 关闭文件流
      await file.close()

      console.log('照片保存到相册成功!')
    } catch (e) {
      console.log('拍照/保存失败:', e)
    }
  }
}

核心进阶功能解释

  1. 切换前后摄像头
    • 通过CameraPosition.BACK/FRONT指定摄像头;
    • 调用cameraController.switchCamera方法切换,简单又高效;
  2. 保存照片到相册
    • 导入photoAccessHelper库操作相册;
    • 用时间戳给照片命名,避免重复;
    • 将拍照得到的PixelMap编码成JPEG格式,写入相册文件中;
  3. 高质量拍摄:把quality设为CameraPhotoQuality.HIGH,拍出来的照片更清晰(代价是文件更大)。

避坑指南(新手必看)

  1. 模拟器无法测试:HarmonyOS模拟器没有相机硬件,必须用真机!
  2. 权限授权失败
    • 一定要在module.json5里声明权限,且reason不能空;
    • 运行时用户如果拒绝授权,要提示用户去设置里开启;
  3. 保存照片失败
    • 必须申请WRITE_MEDIA_PHOTOS权限,否则无法写入相册;
    • 照片命名不能有特殊字符,建议用时间戳;
  4. 切换摄像头失败
    • 部分设备没有前置摄像头,要加异常处理;
    • 切换前确保相机已经正常预览(权限已授权)。

总结

HarmonyOS 6.0实现拍照功能的核心流程就3步:

  1. 配置并申请相机/存储权限;
  2. 用Camera组件显示预览,CameraController控制拍摄/切换摄像头;
  3. 处理照片数据(显示/保存到相册)。

如果大家想考取鸿蒙开发者认证的,欢迎加入我的专属考试链接中:https://developer.huawei.com/consumer/cn/training/classDetail/6ce9d5a998724a849ec634f318107d37?type=1?ha_source=hmosclass&ha_sourceId=89000248

新手先从基础版跑通“拍照+显示”,再逐步加保存、切换摄像头的功能,一步步来,很快就能掌握!

如果想实现扫码、美颜拍照等进阶功能,评论区说,咱们再补充~

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐