HarmonyOS7 相机拍照:Camera Kit 从预览到保存完整流程
文章目录前言Camera Kit 架构权限配置创建预览拍照实现保存到相册前后置切换踩坑记录写在最后前言相机开发可以说是移动端最复杂的功能之一。HarmonyOS7 把相机能力收敛到 Camera Kit 里架构比以前清晰了不少但流程还是长——创建管理器、选摄像头、建会话、配流、启动预览、拍照、保存……少一步都不行。我第一次写的时候漏了commitConfig预览死活出不来排查了两小时。今天把完整流程捋一遍每一步都有代码和讲解照着走不会翻车。Camera Kit 架构Camera Kit 分三层搞清层级关系才不会迷CameraManager ← 管理层创建/获取所有相机对象 ├── CameraInput ← 输入层选哪个摄像头前/后 ├── PreviewOutput ← 输出层-预览流画面实时显示 ├── PhotoOutput ← 输出层-拍照流拍照后的图片数据 └── PhotoSession ← 会话层把输入和输出串起来 ├── addInput() ├── addOutput() ├── commitConfig() └── start()简单理解CameraManager 是总管CameraInput 是眼睛PreviewOutput/PhotoOutput 是嘴巴Session 把它们绑一起才能工作。权限配置相机开发要两个权限module.json5里必须声明{requestPermissions:[{name:ohos.permission.CAMERA},{name:ohos.permission.WRITE_IMAGEVIDEO}]}CAMERA是拍照权限WRITE_IMAGEVIDEO是保存到相册的权限。都要动态申请静态声明不够import{abilityAccessCtrl,common}fromkit.AbilityKitasyncrequestPermissions():Promiseboolean{constatManagerabilityAccessCtrl.createAtManager()constcontextgetContext(this)ascommon.UIAbilityContextconstpermissions[ohos.permission.CAMERA,ohos.permission.WRITE_IMAGEVIDEO]constresultawaitatManager.requestPermissionsFromUser(context,permissions)returnresult.authResults.every((r:number)r0)}别忘了在onPageShow或按钮点击时调这个方法。用户第一次弹授权弹窗可能拒绝要做好拒绝后的提示处理。创建预览预览是相机开发的第一步也是最关键的一步——预览出不来后面全白搭。import{camera}fromkit.CameraKitprivatecameraManager:camera.CameraManager|nullnullprivatepreviewOutput:camera.PreviewOutput|nullnullprivatephotoOutput:camera.PhotoOutput|nullnullprivatesession:camera.PhotoSession|nullnullprivatesurfaceId:stringasyncinitCamera(surfaceId:string){this.surfaceIdsurfaceId// 1. 获取 CameraManagerconstcontextgetContext(this)ascommon.UIAbilityContextthis.cameraManagercamera.getCameraManager(context)// 2. 获取可用摄像头constcamerasthis.cameraManager.getSupportedCameras()if(cameras.length0){console.error(没有可用摄像头)return}constbackCameracameras[0]// 默认后置// 3. 创建 CameraInputconstcameraInputthis.cameraManager.createCameraInput(backCamera)cameraInput.open()// 4. 创建 PreviewOutputconstoutputCapabilitythis.cameraManager.getSupportedOutputCapability(backCamera)constpreviewProfileoutputCapability.previewProfiles[0]this.previewOutputthis.cameraManager.createPreviewOutput(previewProfile,surfaceId)// 5. 创建 PhotoOutputconstphotoProfileoutputCapability.photoProfiles[0]this.photoOutputthis.cameraManager.createPhotoOutput(photoProfile)// 6. 创建 Session 并配置this.sessionthis.cameraManager.createPhotoSession(cameraInput,this.previewOutput,this.photoOutput)awaitthis.session.commitConfig()awaitthis.session.start()}关键讲解surfaceId从 XComponent 组件获取用来承载预览画面。UI 层要放一个XComponentXComponent({id:cameraXComponent,type:XComponentType.SURFACE,libraryname:}).onLoad((){this.initCamera(this.xComponentController.getXComponentSurfaceId())})outputCapability拿到摄像头支持的配置取第一个就行。想精细控制可以遍历选合适的分辨率commitConfig()一定要调我就是忘了这步预览黑屏排查两小时。配置改了也得重新 commit拍照实现预览跑起来了拍照就简单了——三步走// 1. 先注册照片可用回调setupPhotoCallback(){if(!this.photoOutput)returnthis.photoOutput.on(photoAvailable,(errCode:BusinessError,photo:camera.Photo){if(errCode||!photo){console.error(拍照失败: errCode?.code)return}constimageObjphoto.main imageObj.getComponent(image.ComponentType.JPEG,(err,component){if(err||!component?.byteBuffer)returnthis.saveToGallery(component.byteBuffer)imageObj.release()// ← 这行绝对不能漏})})}// 2. 触发拍照takePhoto(){if(!this.photoOutput)returnconstsettings:camera.PhotoCaptureSetting{quality:camera.QualityLevel.QUALITY_LEVEL_HIGH,rotation:camera.ImageRotation.ROTATION_0,mirror:false}this.photoOutput.capture(settings)}关键 API 讲解photoOutput.on(photoAvailable, ...)拍照成功后的数据回调。必须在拍照前注册不然照片数据拿不到photo.main获取主图还有photo.thumbnail可以拿缩略图getComponent(image.ComponentType.JPEG)从 Image 对象提取 JPEG 数据返回ArrayBufferimageObj.release()释放资源不调会导致 BufferQueue 阻塞后续拍照全部失败。这是最高频的坑photoOutput.capture(settings)触发拍照。settings 可选不传也行保存到相册拿到图片 Buffer 后保存到系统相册import{photoAccessHelper}fromkit.MediaLibraryKitimport{fileIo}fromkit.CoreFileKitasyncsaveToGallery(buffer:ArrayBuffer){consthelperphotoAccessHelper.getPhotoAccessHelper(getContext(this))consturiawaithelper.createAsset(photoAccessHelper.PhotoType.IMAGE,jpg)constfilefileIo.openSync(uri,fileIo.OpenMode.READ_WRITE)fileIo.writeSync(file.fd,buffer)fileIo.closeSync(file.fd)console.info(保存成功: uri)}createAsset在相册创建一条空记录并返回 URI然后用fileIo把数据写进去。整个流程就是先开个房间号再把行李搬进去。前后置切换切换摄像头不是简单换个 CameraInput得重新建 SessionStateisBackCamera:booleantrueasyncswitchCamera(){if(!this.cameraManager)return// 先停当前会话awaitthis.session?.stop()constcamerasthis.cameraManager.getSupportedCameras()consttargetCamerathis.isBackCamera?cameras[1]:cameras[0]this.isBackCamera!this.isBackCameraconstcameraInputthis.cameraManager.createCameraInput(targetCamera)awaitcameraInput.open()// 重建 Sessionthis.sessionthis.cameraManager.createPhotoSession(cameraInput,this.previewOutput!,this.photoOutput!)awaitthis.session.commitConfig()awaitthis.session.start()}别想着只换 Input 不重建 Session——试过不行。Session 绑定了 Input得整体重建。踩坑记录坑表现解决没调commitConfig()预览黑屏Session 配置完必须 commit没调imageObj.release()第二次拍照失败回调里必须释放没动态申请权限直接闪退requestPermissionsFromUsersurfaceId为空预览不显示在 XComponentonLoad里获取后置摄像头不是 cameras[0]预览画面是前置通过cameraPosition筛选权限拒绝后直接调相机崩溃先判断授权结果写在最后Camera Kit 的流程确实长但每一步都有存在的理由。核心就是那张架构图——Manager → Input/Output → Session搞清这个逻辑链流程就不会乱。最坑的三个点我都踩过了commitConfig 别忘、release 别忘、权限别忘。拍照只是相机功能的一部分录像、闪光灯、对焦、变焦这些后面有机会再聊。下一篇换个轻松的话题——用加速度计做个摇一摇几行代码就搞定。

相关新闻

MoocDownloader终极指南:3分钟掌握中国大学MOOC离线下载技巧

MoocDownloader终极指南:3分钟掌握中国大学MOOC离线下载技巧

MoocDownloader终极指南:3分钟掌握中国大学MOOC离线下载技巧 【免费下载链接】MoocDownloader An MOOC downloader implemented by .NET. 一枚由 .NET 实现的 MOOC 下载器. 项目地址: https://gitcode.com/gh_mirrors/mo/MoocDownloader 你是否经常因为网络不…

2026/7/22 21:52:19 阅读更多 →
State状态模式

State状态模式

1. reducerState中的每个键 都有自己独立的reducer,通过指定的reducer函数进行数据的更新即,对于每个节点的返回值,state有自己的一套更新策略,可以人工通过reducer进行定制2. 一个使用reducer的例子(Annotated&#x…

2026/7/22 22:21:29 阅读更多 →
低代码工单系统的SLA管理能力深度解析

低代码工单系统的SLA管理能力深度解析

做运维或者售后管理的人,SLA(服务级别协议)这个词肯定不陌生。能否自动监控SLA、自动预警、自动升级,是衡量一个工单系统是否专业的核心指标。 最近我在帮一家设备制造企业搭建工单系统,老板明确要求必须支持SLA管理&a…

2026/7/24 7:34:34 阅读更多 →

最新新闻

C++网络编程实战:TCP粘包拆包问题与长度前缀法解决方案

C++网络编程实战:TCP粘包拆包问题与长度前缀法解决方案

1. 项目概述:为什么TCP通信需要“长度前缀法”? 如果你写过C的网络程序,特别是基于TCP协议的客户端/服务器应用,大概率踩过一个经典的坑:发送端明明连续调用了两次 send 函数发送了两条独立的消息,比如“…

2026/7/24 15:43:35 阅读更多 →
TPSM846C23数字电源模块核心寄存器配置与PMBus应用实战

TPSM846C23数字电源模块核心寄存器配置与PMBus应用实战

1. 项目概述:从模拟到数字,电源管理的范式转变干了十几年硬件设计,从早期的纯模拟电源到后来的数字PWM控制器,再到如今高度集成的数字电源模块,我最大的感触就是:电源设计正在从一个纯粹的“模拟艺术”演变…

2026/7/24 15:43:35 阅读更多 →
STM8S上可用的M24C64 EEPROM页写驱动,含I2C硬件适配接口

STM8S上可用的M24C64 EEPROM页写驱动,含I2C硬件适配接口

本文还有配套的精品资源,点击获取 简介:这套代码专为STM8S系列单片机设计,直接支持M24C64 EEPROM芯片的页写功能,每页32字节,自动处理跨页地址、写入等待和错误反馈;包含stm8s_eval_i2c_ee.c和stm8s_eva…

2026/7/24 15:43:35 阅读更多 →
AM5718-HIREL引脚复用配置实战:从IO Set约束到高速接口设计

AM5718-HIREL引脚复用配置实战:从IO Set约束到高速接口设计

1. 项目概述与核心价值在嵌入式硬件设计领域,尤其是面对像TI AM5718-HIREL这类集成了双核Cortex-A15、双核C66x DSP以及多个视频协处理器的高性能异构SoC时,引脚复用(Pin Mux)的配置往往是项目成败的第一个技术分水岭。这绝不仅仅…

2026/7/24 15:43:35 阅读更多 →
Matlab一键多图融合工具:输入2-6张散焦图,自动输出全清晰BMP合成图

Matlab一键多图融合工具:输入2-6张散焦图,自动输出全清晰BMP合成图

本文还有配套的精品资源,点击获取 简介:一套即装即用的Matlab图像融合工具,专为处理同一场景下多张局部清晰、整体散焦的静态图像设计,常见于显微成像、光学检测等场景。运行主脚本holemain.m,自动完成清晰区域识别…

2026/7/24 15:43:35 阅读更多 →
国产开源大模型实践指南:从GLM-5.2到Kimi K3的部署与应用

国产开源大模型实践指南:从GLM-5.2到Kimi K3的部署与应用

在实际 AI 开发和应用中,模型权重是决定模型能力和性能的核心资产。长期以来,高质量的开源权重模型多由海外机构或企业主导发布。然而,近年来,由中国团队主导研发和开源的一系列权重模型正迅速崛起,不仅在中文理解和生…

2026/7/24 15:42:34 阅读更多 →

日新闻

用Highcharts 创建可拖拽三维散点立方体3D图表

用Highcharts 创建可拖拽三维散点立方体3D图表

该案例基于Highcharts scatter3d 三维散点图实现空间立方体散点可视化,核心特色:三维 X/Y/Z 三轴空间,所有散点分布在 0~10 立方体空间内;散点使用径向渐变实现立体 3D 圆球质感;支持鼠标 / 触屏拖拽画布,…

2026/7/24 0:00:29 阅读更多 →
AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口 AppCertDlls 位于 HKLM\System\CurrentControlSet\Control\Session Manager\AppCertDlls。本文的程序功能是只读列出这个键在 64 位和 32 位注册表视图中的全部值,并显示每条值的来源、名称、类型和可安全显示的数…

2026/7/24 0:00:29 阅读更多 →
我的编程之路:第一篇博客

我的编程之路:第一篇博客

大家好,我是一名编程初学者,同时这也是我编程学习之路上的第一篇博客。在这里,我想要向大家介绍我的一些想法和规划。a.自我介绍我是一个刚刚接触编程的新手,目前在学习c语言,我对编程世界充满了强烈的好奇。当然&…

2026/7/24 0:00:29 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/24 3:59:20 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/24 1:23:39 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 17:49:47 阅读更多 →

月新闻