第15章 HarmonyOs开发图解之 相机

HarmonyOS 学习系统 | 阶段三:高级深耕期


学习目标

序号 能力
1 掌握 HarmonyOS 相机开发的核心流程(获取设备 -> 配置 -> 预览 -> 拍照)
2 理解 CameraKit、Camera、FrameConfig 三层架构
3 能够实现预览、拍照、连拍和录像功能

核心图解

HarmonyOS 多媒体框架全景图

内容讲解

15.1 相机开发概述

HarmonyOS 的相机开发基于三层架构:CameraKit(选角导演,选择摄像头) -> Camera(摄影机,实际拍摄设备) -> FrameConfig(拍摄脚本,定义预览/拍照/连拍)。Surface 则是监视器屏幕,决定了画面显示在哪里。

生活化类比:相机开发就像"指挥一场拍摄"

CameraKit 是选角导演(选择哪个摄像头——前置/后置),Camera 是摄影机(实际的拍摄设备),FrameConfig 是拍摄脚本(定义拍什么类型——预览/拍照/连拍),Surface 是监视器屏幕(画面显示在哪里)。流程是:先选角(获取相机 ID),再架设摄影机(createCamera),然后排练(configure 配置 Surface),最后开拍(triggerLoopingCapture 预览 / triggerSingleCapture 拍照)。

15.2 相机开发核心流程

// 1. 获取相机设备列表
CameraKit cameraKit = CameraKit.getInstance(context);
String[] cameraIds = cameraKit.getCameraIds();

// 2. 创建相机实例
cameraKit.createCamera(cameraIds[0], cameraStateCallback, eventHandler);

// 3. 相机创建成功回调中配置 Surface
@Override
public void onCreated(Camera camera) {
    CameraConfig.Builder builder = new CameraConfig.Builder();
    builder.addSurface(previewSurface);   // 预览 Surface
    builder.addSurface(pictureSurface);    // 拍照 Surface
    builder.setFrameStateCallback(frameStateCallback, eventHandler);
    camera.configure(builder.build());
}

// 4. 配置完成回调中开始预览
@Override
public void onConfigured(Camera camera) {
    FrameConfig previewConfig = camera.getFrameConfigBuilder(
        FrameConfig.FRAME_CONFIG_PREVIEW).build();
    camera.triggerLoopingCapture(previewConfig); // 开始预览
}

// 5. 拍照
FrameConfig pictureConfig = camera.getFrameConfigBuilder(
    FrameConfig.FRAME_CONFIG_PICTURE).build();
camera.triggerSingleCapture(pictureConfig);

15.3 相机能力查询

不同设备的相机能力差异极大,开发前务必查询:

// 查询相机支持的分辨率和帧率
CameraAbility ability = cameraKit.getCameraAbility(cameraIds[0]);
Size[] sizes = ability.getSupportedSizes(FrameConfig.FRAME_CONFIG_PREVIEW);
for (Size size : sizes) {
    HiLog.info(TAG, "支持预览分辨率: " + size.width + "x" + size.height);
}

15.4 相机权限清单

权限 用途 必要性
ohos.permission.CAMERA 使用相机硬件 必选
ohos.permission.MICROPHONE 录像时录音 可选
ohos.permission.WRITE_MEDIA 保存照片/视频到外部存储 可选
ohos.permission.MEDIA_LOCATION 保存位置信息到照片 可选

代码速查卡

API 功能 示例
CameraKit.getInstance(ctx) 获取 CameraKit 实例 CameraKit.getInstance(context)
getCameraIds() 获取相机 ID 列表 cameraKit.getCameraIds()
createCamera(id, cb, handler) 创建相机实例 cameraKit.createCamera(ids[0], cb, handler)
configure(config) 配置相机 Surface camera.configure(config)
triggerLoopingCapture(fc) 开始预览(循环捕获) camera.triggerLoopingCapture(previewConfig)
triggerSingleCapture(fc) 拍照(单次捕获) camera.triggerSingleCapture(pictureConfig)
getCameraAbility(id) 查询相机能力 cameraKit.getCameraAbility(cameraId)
release() 释放相机资源 camera.release()

与 Android/iOS 对比

特性 HarmonyOS Android iOS
相机 API CameraKit + Camera Camera2 API / CameraX AVFoundation (AVCaptureSession)
预览方式 SurfaceProvider + Surface SurfaceView / PreviewView AVCaptureVideoPreviewLayer
拍照方式 triggerSingleCapture ImageReader + CaptureRequest AVCapturePhotoOutput
相机选择 cameraIds[0]/[1] CameraCharacteristics.LENS_FACING AVCaptureDevice.default()
能力查询 getCameraAbility() CameraCharacteristics AVCaptureDevice.DeviceType

⚠️ 踩坑回忆录

为什么相机一直打开失败?

我写了一个带相机的 App,启动时直接调用 CameraKit.getInstance(),结果总是返回 null。排查后发现——另一个相机 App 还在后台运行!HarmonyOS 规定同一时刻只有一个相机应用能运行,因为摄像头是独占硬件资源。正确做法是先检查相机是否可用,提示用户关闭其他相机 App,或者使用 try-catch 捕获异常并给出友好提示。

另外,不同设备的相机能力差异极大。我曾在 A 设备上完美运行的 4K 预览,在 B 设备上直接黑屏——因为 B 设备最高只支持 1080P 预览。开发前务必用 CameraKit.getCameraAbility() 查询支持的分辨率和帧率,不要硬编码。


必做实操任务

序号 任务 难度
1 实现相机预览功能,在 SurfaceProvider 上显示实时画面
2 实现拍照功能,将照片保存到本地
3 实现前后摄像头切换
4 查询设备相机能力并展示支持的分辨率列表
5 实现连拍功能(triggerBurstCapture)

学习检查清单

  • 能说出相机开发的核心流程(CameraKit -> Camera -> FrameConfig)
  • 能实现相机预览并在 SurfaceProvider 上显示
  • 能实现拍照并保存照片
  • 知道相机是独占资源,需要处理被占用的情况
  • 能使用 getCameraAbility 查询设备相机能力
  • 能正确声明相机相关权限
  • 能在 Ability 生命周期中正确释放相机资源
  • 理解 FRAME_CONFIG_PREVIEW 和 FRAME_CONFIG_PICTURE 的区别

进阶方向

  • 结合第 13 章视频能力,实现视频录制 App
  • 实现自定义相机 UI(手动对焦、曝光调节、滤镜等)
  • 探索相机与 AI 能力的结合(人脸检测、扫码等)
    理解 FRAME_CONFIG_PREVIEW 和 FRAME_CONFIG_PICTURE 的区别

进阶方向

  • 结合第 13 章视频能力,实现视频录制 App
  • 实现自定义相机 UI(手动对焦、曝光调节、滤镜等)
  • 探索相机与 AI 能力的结合(人脸检测、扫码等)
Logo

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

更多推荐