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

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

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


一、前言

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

  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 })
相关推荐
Rysxt_1 天前
Vuex 教程 从入门到实践
前端·javascript·vue.js
by__csdn1 天前
Node.js版本与npm版本的对应关系
前端·npm·node.js
AI_56781 天前
Webpack性能优化终极指南:4步实现闪电打包
前端·webpack·性能优化
威风的虫1 天前
ES6 数组方法:告别循环,拥抱函数式编程
开发语言·前端·javascript
小杨快跑~1 天前
ES6 Promise:告别回调地狱的异步编程革命
前端·javascript·ecmascript·es6
linweidong1 天前
VIVO前端面试题及参考答案
前端·跨域·localstorage·重绘·浏览器兼容·git管理·前端重构
有意义1 天前
从零搭建:json-server+Bootstrap+OpenAI 全栈 AI 小项目
前端·后端·llm
温宇飞1 天前
CCState:为大型 Web 应用设计的状态管理库
前端
r0ad1 天前
读诗的时候我却使用了自己研发的Chrome元素截图插件
前端·javascript·chrome
IT_陈寒1 天前
React性能优化实战:这5个Hooks技巧让我的应用快了40%
前端·人工智能·后端