尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

相机开发:CameraKit调用摄像头与拍照预览(36)

相机开发:CameraKit调用摄像头与拍照预览(36)
📅 发布时间:2026/7/24 22:16:31

在 HarmonyOS 中开发相机应用,开发者可以根据业务需求选择两种不同的技术路线:如果仅需获取即时拍摄的照片或视频,推荐使用CameraPicker(相机选择器);如果需要构建高度自定义的相机应用或实现实时预览分析,则需要使用Camera Kit 核心 API。

以下是这两种方式的完整开发流程与实战代码:

一、 方案一:使用 CameraPicker 快速调用系统相机

CameraPicker 由系统提供交互界面,用户主动点击拍摄并确认后,应用即可获取结果。此方案无需申请相机权限,开发极其简便。

核心代码示例:

import { camera, cameraPicker as picker } from '@kit.CameraKit'; import { fileIo, fileUri } from '@kit.CoreFileKit'; // 1. 配置 PickerProfile(指定保存路径或默认存入媒体库) let pickerProfile: picker.PickerProfile = { cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK, // 若不配置 saveUri,照片/视频默认存入媒体库 }; // 2. 调用 picker 接口获取拍摄结果 async function getPickerResult(context: Context): Promise<picker.PickerResult> { let result = await picker.pick( context, [picker.PickerMediaType.PHOTO, picker.PickerMediaType.VIDEO], pickerProfile ); console.info(`resultCode: ${result.resultCode}, resultUri: ${result.resultUri}`); return result; }

二、 方案二:使用 Camera Kit 实现自定义预览与拍照

构建自定义相机需要严格遵循“权限申请 -> 创建输入输出流 -> 会话管理 -> 启动预览”的流程。

1. 权限配置与动态申请

相机属于敏感权限,必须在module.json5中声明,并在运行时动态申请:

"requestPermissions": [ { "name": "ohos.permission.CAMERA" } ]

在代码中使用abilityAccessCtrl.createAtManager().requestPermissionsFromUser()向用户申请授权。

2. 获取相机设备与创建输入流
import { camera } from '@kit.CameraKit'; // 获取相机管理器并获取支持的相机设备列表 let cameraManager = camera.getCameraManager(context); let cameraDevices = cameraManager.getSupportedCameras(); // 获取后置摄像头并创建输入流 let cameraDevice = cameraDevices.find(device => device.cameraPosition === camera.CameraPosition.CAMERA_POSITION_BACK ); let cameraInput = cameraManager.createCameraInput(cameraDevice); await cameraInput.open(); // 打开相机
3. 创建预览 Surface 与输出流

预览画面必须通过XComponent组件渲染,并获取其surfaceId绑定到预览输出流:

// UI 层声明 XComponent XComponent({ type: XComponentType.SURFACE, controller: this.xComponentController }) .onLoad(async () => { // 获取 surfaceId let surfaceId = this.xComponentController.getXComponentSurfaceId(); // 获取设备支持的预览分辨率(注意宽高比需与 XComponent 保持一致) let cameraOutputCapability = cameraManager.getSupportedOutputCapability(cameraDevice); let previewProfiles = cameraOutputCapability.previewProfiles; // 创建预览输出流 let previewOutput = cameraManager.createPreviewOutput(previewProfiles[0], surfaceId); })
4. 会话管理与启动预览

相机的输入流和输出流必须通过Session进行绑定和调度:

// 创建拍照模式的会话 let photoSession = cameraManager.createSession(camera.SceneMode.NORMAL_PHOTO) as camera.PhotoSession; // 配置会话 photoSession.beginConfig(); photoSession.addInput(cameraInput); photoSession.addOutput(previewOutput); await photoSession.commitConfig(); // 启动会话,此时 XComponent 上即可看到实时预览画面 await photoSession.start();

三、 进阶:拍照输出与模式切换

当需要在预览的基础上实现拍照功能时,需在会话中额外添加PhotoOutput:

// 创建拍照输出流 let photoOutput = cameraManager.createPhotoOutput(); // 在会话中添加拍照输出流(需先判断是否支持添加) if (photoSession.canAddOutput(photoOutput)) { photoSession.addOutput(photoOutput); } await photoSession.commitConfig(); // 调用拍照 photoOutput.capture();

如果需要从“拍照模式”切换到“录像模式”,可以通过stop()停止当前会话,移除photoOutput,添加videoOutput后重新commitConfig()并start()。

1、 高级参数控制(闪光灯、对焦与变焦)

在会话处于prepared或运行状态下,开发者可以动态调整相机的各项参数:

  1. 闪光灯控制:通过photoSession.hasFlash()判断设备是否支持闪光灯,若支持,可调用setFlashMode()设置自动、开启或关闭模式。
  2. 对焦模式:通过isFocusModeSupported()检查是否支持连续自动对焦(FOCUS_MODE_CONTINUOUS_AUTO),若支持则调用setFocusMode()启用。
  3. 平滑变焦:通过getZoomRatioRange()获取设备支持的可变焦距比范围,然后调用setZoomRatio()设置具体的缩放比例。注意:传入的缩放值必须在支持范围内,否则系统会直接报错。
2、 折叠屏设备的深度适配

在折叠屏设备上,随着设备的展开或折叠,可用的摄像头可能会发生变化(例如前置镜头被折入内部)。

  1. 开启自动切换:通过isAutoDeviceSwitchSupported()检查设备是否支持自动切换镜头能力。若支持,调用enableAutoDeviceSwitch(true)。系统会自动完成镜头切换、会话配置和参数接续,避免黑屏。
  2. 监听能力变更:当系统自动切换镜头时,由于不同镜头的变焦范围可能不一致,系统会通过on('autoDeviceSwitchStatusChange')回调通知应用。应用需根据isDeviceCapabilityChanged字段重新获取变焦范围并更新 UI。
  3. UI 布局适配:除了镜头切换,还需监听折叠状态变化(foldStatusChange),并配合orientation: follow_desktop动态调整相机的 UI 布局。
3、 严格的资源释放与生命周期管理

相机是极其消耗系统资源的硬件。如果释放不当,极易导致内存泄漏或下次打开相机时黑屏。

  1. 安全释放顺序:必须严格按照stop()->output.release()->cameraInput.close()->session.release()的顺序进行,且每一步都必须包裹在try/catch中,确保即使某一步报错也不会中断后续的释放流程。
  2. 后台释放机制:当应用退至后台时,应立即释放相机资源;当应用回到前台时,再重新创建和启动会话。可通过监听applicationContext.on('applicationStateChange')来实现这一机制。
  3. 模式切换恢复:每次切换拍照或录像模式(即创建新 Session)后,所有的参数设置都会回到默认值。必须在模式切换后主动调用类似syncButtonSettings()的逻辑,将用户的自定义设置重新应用到新会话中。
4、 高级拍照特性与底层细节处理
  1. HDR 与颜色空间:若需拍摄高动态范围照片,需在commitConfig()之前调用session.setColorSpace()设置合适的颜色空间(如DISPLAY_P3或BT2020_HLG_LIMIT)。
  2. 动图(Moving Photo)支持:实现类似 Live Photo 的动图功能需满足三个条件:调用isMovingPhotoSupported()确认支持、调用enableMovingPhoto(true)开启、并在photoAssetAvailable回调中处理生成的资源。
  3. 图像 Stride 对齐处理:在进行底层图像数据处理(如 AI 识别)时,需注意image.Component.rowStride可能大于图像的实际width。如果不进行裁剪对齐处理,解析出的图像会出现竖条纹。

四、 架构分层:MVVM 模式下的相机模块设计

在大型应用中,直接在 UI 组件中处理复杂的相机逻辑会导致代码臃肿且难以维护。建议引入 MVVM 模式进行分层解耦:

  1. View 层(UI 组件):XComponent组件仅负责渲染相机预览画面,不包含任何业务逻辑。它通过@Link或@Prop接收来自 ViewModel 的状态(如预览分辨率、闪光灯状态),并通过事件回调通知 ViewModel 用户的交互(如点击拍照、切换摄像头)。
  2. ViewModel 层(状态与逻辑):作为相机模块的核心管理者,ViewModel 持有CameraManager、PhotoSession等核心对象。它处理所有业务逻辑,如权限校验、设备切换、参数调整、模式切换等,并更新状态以驱动 UI 变化。
  3. Model 层(数据源):定义相机模块的数据结构和配置,如支持的分辨率列表、闪光灯模式等,可以来自本地配置或远程接口,实现相机模块的动态化配置。

五、 性能优化:渲染与交互体验

相机应用对性能要求极高,任何卡顿都会严重影响用户体验。

  1. XComponent 渲染优化:XComponent的宽高比必须与预览输出的分辨率保持一致,否则会导致画面拉伸或黑边。建议在onLoad回调中动态计算并设置XComponent的尺寸,确保预览画面完美填充。
  2. 异步操作与线程管理:相机的初始化、参数设置、拍照等操作都是耗时的。必须在异步线程中执行这些操作,避免阻塞主线程。可以使用TaskPool或Worker来处理复杂的图像处理任务,确保 UI 的流畅性。
  3. 内存管理:相机预览和拍照会产生大量的图像数据。必须及时释放不再使用的Image对象,避免内存泄漏。在处理图像数据时,建议使用ArrayBuffer的零拷贝特性,减少内存分配和拷贝的开销。

六、 生命周期管理:严格的资源释放与状态恢复

相机是极其消耗系统资源的硬件。如果管理不当,极易导致内存泄漏或下次打开相机时黑屏。

  1. 安全释放顺序:必须严格按照session.stop()->output.release()->cameraInput.close()->session.release()的顺序进行,且每一步都必须包裹在try/catch中,确保即使某一步报错也不会中断后续的释放流程。
  2. 后台释放机制:当应用退至后台时,应立即释放相机资源;当应用回到前台时,再重新创建和启动会话。可通过监听applicationContext.on('applicationStateChange')来实现这一机制。
  3. 模式切换恢复:每次切换拍照或录像模式(即创建新 Session)后,所有的参数设置都会回到默认值。必须在模式切换后主动调用类似syncButtonSettings()的逻辑,将用户的自定义设置重新应用到新会话中。

相关新闻

  • 第二讲:C语言数据类型和变量
  • 3步完成Switch大气层系统安装:从新手到高手的实用指南
  • 2026 年新消息:滨湖品质可靠的双玻百叶隔断施工公司怎么联系,办公室里这款常用隔断,竟藏着你不知道的省钱小技巧,解决70%的办公空间痛点 - 行业推荐官【认证】

最新新闻

  • Windows键盘重映射终极指南:用SharpKeys打造你的个性化键盘布局
  • Steam创意工坊模组免费下载终极指南:跨平台玩家的完美解决方案
  • HarmonyOS7 暗黑模式:3 步让你的 App 支持深色主题
  • MCU芯片AS32X601如何使用 DMA 单次模式搬运 ADC 多通道采样数据?
  • 「盘点」界面控件DevExtreme (v23.1, v23.2)可访问性增强
  • 零成本AI股票分析:5分钟打造你的个人智能投资助手

日新闻

  • 武汉卡地亚LOVE钻戒与钻石项链回收变现攻略|多家门店行情参考 - 大牌深度测评
  • 2026年无锡地区健康管理如何考量?四家机构业务体系概览
  • 2026图片去水印软件哪个好用 手机电脑免费工具盘点 - 免费软件工具方法教程

周新闻

  • SaaS软件行业GEO实践:AI搜索时代的品牌可见性与获客新路径
  • 什么是PCTFE?医药高端包装的“防潮王牌“材料
  • 【JVM调优实战】16-可视化利器-JConsole-VisualVM-JMC

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号