尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
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 别忘、权限别忘。拍照只是相机功能的一部分录像、闪光灯、对焦、变焦这些后面有机会再聊。下一篇换个轻松的话题——用加速度计做个摇一摇几行代码就搞定。
RELATED

相关推荐

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/10/8 6:28:26
鹤壁婚宴烟酒怎么备不浪费又体面?

鹤壁婚宴烟酒怎么备不浪费又体面?

我在鹤壁淇滨区开了多年烟酒店。每天接触最多的就是来买酒的顾客。说实话,很多人办宴席时不知道该备多少酒。今天分享几点经验,希望对你有帮助。一、算用量:按桌数和人头来估,最稳当一般来说,每桌十个人,每…

📅 2026/10/8 16:47:53
Steam Deck多系统引导终极指南:3分钟实现无缝系统切换的完整方案

Steam Deck多系统引导终极指南:3分钟实现无缝系统切换的完整方案

Steam Deck多系统引导终极指南:3分钟实现无缝系统切换的完整方案 【免费下载链接】SteamDeck_rEFInd Simple rEFInd install script for the Steam Deck (with GUI customization) 项目地址: https://gitcode.com/gh_mirrors/st/SteamDeck_rEFInd 还在为Stea…

📅 2026/10/8 4:51:50
MORE NEWS

更多资讯

📰

林州特种工培训中心证怎么转异地 值不值得考

林州特种工培训中心证怎么转异地 值不值得考 证书过期了不知道怎么复审延期,你是不是也这样?别急,今天就带你从头到尾理清楚林州特种工培训中心的流程,尤其是证书变更、异地转证、复审这些环节,咱们一起把关卡一个个过。…

📰

工地太忙根本没时间复习考试?漯河考高压电工证流程多久拿证全解析

工地太忙根本没时间复习考试?漯河考高压电工证流程多久拿证全解析 工地太忙根本没时间复习考试?你不是一个人。漯河这边的工地上,每天都在赶工期,高压电工证的考试复习根本挤不出时间。但高压电工证又不是可有可无,它是你从事高压电气作业的“通行证”,…

📰

南阳特种工培训学校内部消息:证书过期了不知道怎么复审延期?别慌,这里有详细流程

南阳特种工培训学校内部消息:证书过期了不知道怎么复审延期?别慌,这里有详细流程 证书过期了不知道怎么复审延期?这不是个别现象,而是很多从事特种作业的人员普遍面临的难题。特别是南阳特种工培训学校的老学员,常常会因为疏忽或不了解最新政策,错过复…

📰

电工证的最新要求你知道吗?外省证转过来值不值得考

电工证的最新要求你知道吗?外省证转过来值不值得考 之前考的证在外省能不能转过来,这个问题你不是一个人在问,我从业这么多年,每天都在处理类似的咨询。尤其是在平顶山房建工程行业,很多人手里有证却用不上,不是因为证不行,而是因为不了解最新要求,甚…

📰

高压电工证年龄规定你知道吗?学历不高也能拿证

高压电工证年龄规定你知道吗?学历不高也能拿证 你是不是也担心自己学历不高,报不了高压电工证?别急,高压电工证年龄规定其实很明确,而且 多久拿证…

📰

工地太忙根本没时间复习考试?长阳电工证怎么考的良心建议来了

工地太忙根本没时间复习考试?长阳电工证怎么考的良心建议来了 工地太忙根本没时间复习考试,这话说得一点都不假。作为一线工人,谁不想多拿个证,多一份保障?可现实是,白天搬砖,晚上还得抽空学习,时间根本不够用。别急,我今天就把 长阳电工证怎么考…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬