鸿蒙相机开发入门篇(官方实践版)

鸿蒙相机开发入门篇(官方实践版)

--- 从系统能力声明到可运行的拍照预览应用


一、前言

很多刚接触鸿蒙开发的同学,在尝试使用相机时会遇到两个常见问题:

  1. 为什么明明引入了相机模块,却提示"系统能力缺失"?
  2. 为什么写了相机逻辑,却看不到预览画面?

这篇文章将带你从 0 到 1 完成一个能"预览 + 拍照"的相机应用,完全基于 HarmonyOS NEXT 官方最佳实践,并结合 UI 层和交互讲解。


二、基础准备

1. 必要权限与系统能力声明

鸿蒙系统使用 SystemCapability(系统能力标识) 来声明模块功能。

在相机开发中,你必须在 module.json5 文件中声明以下内容:

json 复制代码
{
  "module": {
    "name": "entry",
    "requestPermissions": [
      { "name": "ohos.permission.CAMERA" },
      { "name": "ohos.permission.MICROPHONE" },
      { "name": "ohos.permission.WRITE_MEDIA" }
    ],
    "systemCapabilities": [
      "SystemCapability.Multimedia.Camera.Core",
      "SystemCapability.Multimedia.Camera.Basic",
      "SystemCapability.Multimedia.Camera.Metadata"
    ]
  }
}

⚠️ 注意:

鸿蒙要求编译时声明能力,否则构建期就会报错,这点和 Android 运行时动态声明完全不同。


三、创建相机基础结构

在鸿蒙中,Camera 模块的核心接口位于 @ohos.multimedia.camera

下面我们先构建一个基础拍照页面:

kotlin 复制代码
// pages/CameraPage.ets
import camera from '@ohos.multimedia.camera';
import media from '@ohos.multimedia.media';
import fileio from '@ohos.fileio';

@Entry
@Component
struct CameraPage {
  controller: camera.CameraManager = camera.getCameraManager(globalThis.context);
  previewOutput?: camera.PreviewOutput;
  photoOutput?: camera.PhotoOutput;
  cameraInput?: camera.CameraInput;

  build() {
    Column() {
      // 预览区域
      if (this.previewOutput) {
        // 使用 SurfaceId 渲染相机画面
        XComponent({ id: 'cameraView', type: XComponentType.SURFACE })
          .onLoad((context) => {
            this.startPreview(context);
          })
          .width('100%')
          .height('80%')
      }

      // 拍照按钮
      Button('拍照')
        .onClick(() => this.takePhoto())
        .width('50%')
        .height(50)
        .backgroundColor('#007DFF')
        .fontColor('#fff')
        .borderRadius(25)
    }
  }

  async startPreview(context) {
    const cameras = this.controller.getSupportedCameras();
    this.cameraInput = this.controller.createCameraInput(cameras[0]);
    this.previewOutput = this.controller.createPreviewOutput(context);
    this.photoOutput = this.controller.createPhotoOutput();

    const session = this.controller.createSession(camera.SessionType.SESSION_TYPE_NORMAL);
    await session.beginConfig();
    session.addInput(this.cameraInput);
    session.addOutput(this.previewOutput);
    session.addOutput(this.photoOutput);
    await session.commitConfig();
    session.start();

    await this.cameraInput.open();
    this.previewOutput.start();
  }

  async takePhoto() {
    if (!this.photoOutput) return;
    const photoPath = `/data/storage/el2/base/photos/${Date.now()}.jpg`;
    await this.photoOutput.capture(photoPath);
    prompt.showToast({ message: '拍照成功!', duration: 1500 });
  }
}

四、代码讲解

模块 说明
CameraManager 管理相机设备(前置/后置等)
CameraInput 表示相机输入(光学传感器)
PreviewOutput 负责输出实时预览帧(绑定 UI Surface)
PhotoOutput 负责拍照输出(生成 JPEG 文件)
Session 管理相机的输入输出会话,必须配置后才能启动

五、UI 层与交互优化

为了让拍照体验更自然,可以加入一个简洁的取景框样式与快门动效:

kotlin 复制代码
// 快门动画效果
@State shutterEffect: boolean = false

Button('拍照')
  .onClick(() => {
    this.shutterEffect = true
    setTimeout(() => (this.shutterEffect = false), 150)
    this.takePhoto()
  })
  .scale({ x: this.shutterEffect ? 0.9 : 1.0 })
  .animation({ duration: 150, curve: Curve.EaseInOut })
相关推荐
webxin6664 小时前
页面动画和延迟加载动画的实现
前端·javascript
逛逛GitHub4 小时前
这个牛逼的股票市场平台,在 GitHub 上开源了。
前端·github
细节控菜鸡4 小时前
【排查实录】Web 页面能打开,服务器能通接口,客户端却访问失败?原因全在这!
运维·服务器·前端
今天头发还在吗4 小时前
React + Ant Design 日期选择器避免显示“Invalid Date“的解决方案
前端·react.js·前端框架·ant design
时雨__5 小时前
利用AndVX6开发流程图——问题总结
前端
云枫晖5 小时前
深入浅出npm:现代JavaScript项目基石
前端·javascript·node.js
不一样的少年_5 小时前
你家孩子又偷玩网页游戏? 试试这个防沉迷工具
前端·javascript·浏览器
春秋半夏5 小时前
vue2二次封装el-select支持collapse-tags-tooltip
前端