HarmonyOS APP《画伴梦工厂》开发第9篇:相机开发实战——调用系统相机拍照

📅 2026/6/30 2:11:35
HarmonyOS APP《画伴梦工厂》开发第9篇:相机开发实战——调用系统相机拍照
第2.1篇相机开发实战——调用系统相机拍照难度⭐⭐ 进阶前置知识第 1.6 篇 页面路由与生命周期涉及源文件products/default/src/main/ets/components/CreationComponents.ets概述在画伴梦工厂中用户需要拍摄自己的画作然后将其转化为动画。HarmonyOS 提供了startAbilityForResult接口让我们可以启动系统相机拍照并获取返回的图片 URI。本文将详细拆解这一流程涵盖 Want 配置、权限申请、结果回调解析以及父子组件之间的数据同步。一、相机 Want 动作常量启动系统相机需要指定一个标准的 Want Action告诉系统我们要执行图像捕获操作constCAMERA_WANT_ACTION:stringohos.want.action.imageCapture;ohos.want.action.imageCapture是 HarmonyOS 预定义的系统公共事件用于唤起系统相机应用进行拍照。二、权限申请前置检查在调用系统相机之前必须先申请ohos.permission.CAMERA权限。项目中将权限申请抽取为独立的PermissionGuard服务import{PermissionGuard,PermissionResult}from../services/PermissionGuard;privateasyncopenCamera(){constcontextgetContext(this)ascommon.UIAbilityContext;constpermissionResult:PermissionResultawaitPermissionGuard.requestCamera(context);if(!permissionResult.granted){this.noticeTextpermissionResult.message;return;}// ... 继续打开相机}PermissionGuard.requestCamera内部调用abilityAccessCtrl.createAtManager().requestPermissionsFromUser向用户弹出权限请求对话框。若用户拒绝会通过noticeText提示用户前往设置中开启权限。// PermissionGuard.etsstaticasyncrequestCamera(context:common.UIAbilityContext):PromisePermissionResult{returnPermissionGuard.request(context,[ohos.permission.CAMERA],请在设置里打开相机权限后继续);}三、启动系统相机权限通过后通过 UIAbilityContext 的startAbilityForResult方法启动系统相机context.startAbilityForResult({action:CAMERA_WANT_ACTION}).then((result:common.AbilityResult){consturithis.getImageUriFromResult(result);this.capturePhoto(uri,拍照图片);if(uri!){this.noticeText拍照完成已用新图片覆盖当前预览;}}).catch((){this.noticeText相机未成功返回已载入示例画作便于继续流程;this.capturePhoto();});关键点解析要点说明startAbilityForResult启动系统 Ability 并异步等待返回结果适用于需要获取返回数据的场景Want对象只需传入action字段无需指定uri或type系统相机自动处理Promise 回调then接收拍照成功的结果catch处理用户取消或相机异常的情况兜底策略即使拍照失败也会调用capturePhoto()无参数让流程可以继续这种兜底策略设计非常巧妙——即使用户没有成功拍照仍会使用示例画作填充保证用户体验不中断。四、解析相机返回结果系统相机返回的AbilityResult结构因设备型号和系统版本而异为了兼容不同机型getImageUriFromResult方法实现了多层 fallback 解析privategetImageUriFromResult(result:common.AbilityResult):string{// 第一层直接获取 want.uriif(result.wantresult.want.uri){returnresult.want.uri;}// 第二层当 want.uri 为空时从 parameters 中查找if(!result.want||!result.want.parameters){return;}constparametersresult.want.parameters;consturiKeys:string[][uri,imageUri,resourceUri,select-item-list];for(leti0;iuriKeys.length;i){constvalueparameters[uriKeys[i]];if(typeofvaluestring){returnvalue;}if(Array.isArray(value)value.length0typeofvalue[0]string){returnvalue[0];}}return;}解析策略说明result.want.uri优先级最高部分系统版本会将图片 URI 直接放在want对象的顶层uri字段。result.want.parameters遍历兼容模式在不同 HarmonyOS 版本上返回的 key 名可能不同代码尝试了uri、imageUri、resourceUri、select-item-list四种常见 key 名。值类型兼容同一个 key 在某些版本上是字符串在某些版本上是数组单选时数组长度为 1代码对两种类型都做了处理。兜底返回空字符串所有查找方式均失败时返回空上层逻辑会载入示例画作。五、拍照后的统一处理无论来自相机还是相册的图片最终都走capturePhoto方法统一处理privatecapturePhoto(uri:string,sourceLabel:string拍照图片){if(uri!){this.capturedImageUriuri;this.imageSourceLabelsourceLabel;}this.hasPhototrue;this.activeStep1;// 进入准备图片步骤this.generationProgress35;// 更新进度条this.noticeText已采集画作可以直接生成动画;}该方法做了三件事存储图片信息保存 URI 和来源标签“拍照图片或相册图片”更新状态标记hasPhoto true推进步骤到第 1 步反馈用户更新进度值35%和提示文字六、子组件与父组件通信 (Link)PhotoRecognitionComponent组件将内部状态通过Link装饰器暴露给父组件PhotoRecognitionPage实现双向数据同步子组件定义Componentexportstruct PhotoRecognitionComponent{LinkgenerationProgress:number;LinknoticeText:string;StateprivatehasPhoto:booleanfalse;StateprivatecapturedImageUri:string;// ...}Link与父组件共享状态子组件对generationProgress和noticeText的修改会直接反映到父组件 UI 上。State组件私有状态仅在组件内部可见对外部透明。父组件调用PhotoRecognitionComponent({generationProgress:$generationProgress,noticeText:$noticeText})父组件通过$语法传递状态变量的引用子组件即可通过Link接收并双向绑定。七、用户界面触发在 UI 层用户通过点击拍照采集按钮触发整个流程Button(拍照采集).onClick((){if(!this.recognizing){this.openCamera();}})同时检查recognizing状态避免在生成动画过程中重复触发相机操作。八、完整流程时序图用户点击拍照采集 │ ▼ PermissionGuard.requestCamera() │ ├── 用户拒绝 → noticeText 提示 → 结束 │ └── 用户授权 │ ▼ startAbilityForResult({ action: ohos.want.action.imageCapture }) │ ├── 成功 → getImageUriFromResult() 提取 URI → capturePhoto(uri) │ └── 失败/取消 → capturePhoto()载入示例画作 │ ▼ hasPhoto true activeStep 1 generationProgress 35总结本文通过画伴梦工厂的相机拍照功能完整演示了 HarmonyOS 系统相机调用的最佳实践知识点实现方式启动系统相机startAbilityForResultohos.want.action.imageCapture权限申请PermissionGuard.requestCamera封装结果解析多层 fallback 解析AbilityResult.want状态同步Link双向绑定父子组件数据异常兜底catch 中自动载入示例画作下一节我们将探讨另一种图片采集方式——通过PhotoViewPicker从相册中选择图片以及它相对相机模式的不同场景和权限模型差异。