news 2026/7/14 20:48:32

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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:string='ohos.want.action.imageCapture';

ohos.want.action.imageCapture是 HarmonyOS 预定义的系统公共事件,用于唤起系统相机应用进行拍照。


二、权限申请前置检查

在调用系统相机之前,必须先申请ohos.permission.CAMERA权限。项目中将权限申请抽取为独立的PermissionGuard服务:

import{PermissionGuard,PermissionResult}from'../services/PermissionGuard';privateasyncopenCamera(){constcontext=getContext(this)ascommon.UIAbilityContext;constpermissionResult:PermissionResult=awaitPermissionGuard.requestCamera(context);if(!permissionResult.granted){this.noticeText=permissionResult.message;return;}// ... 继续打开相机}

PermissionGuard.requestCamera内部调用abilityAccessCtrl.createAtManager().requestPermissionsFromUser,向用户弹出权限请求对话框。若用户拒绝,会通过noticeText提示用户前往设置中开启权限。

// PermissionGuard.etsstaticasyncrequestCamera(context:common.UIAbilityContext):Promise<PermissionResult>{returnPermissionGuard.request(context,['ohos.permission.CAMERA'],'请在设置里打开相机权限后继续');}

三、启动系统相机

权限通过后,通过 UIAbilityContext 的startAbilityForResult方法启动系统相机:

context.startAbilityForResult({action:CAMERA_WANT_ACTION}).then((result:common.AbilityResult)=>{consturi=this.getImageUriFromResult(result);this.capturePhoto(uri,'拍照图片');if(uri!==''){this.noticeText='拍照完成,已用新图片覆盖当前预览';}}).catch(()=>{this.noticeText='相机未成功返回,已载入示例画作便于继续流程';this.capturePhoto();});

关键点解析

要点说明
startAbilityForResult启动系统 Ability 并异步等待返回结果,适用于需要获取返回数据的场景
Want对象只需传入action字段,无需指定uritype,系统相机自动处理
Promise 回调then接收拍照成功的结果,catch处理用户取消或相机异常的情况
兜底策略即使拍照失败,也会调用capturePhoto()(无参数),让流程可以继续

这种"兜底策略"设计非常巧妙——即使用户没有成功拍照,仍会使用示例画作填充,保证用户体验不中断。


四、解析相机返回结果

系统相机返回的AbilityResult结构因设备型号和系统版本而异,为了兼容不同机型,getImageUriFromResult方法实现了多层 fallback 解析:

privategetImageUriFromResult(result:common.AbilityResult):string{// 第一层:直接获取 want.uriif(result.want&&result.want.uri){returnresult.want.uri;}// 第二层:当 want.uri 为空时,从 parameters 中查找if(!result.want||!result.want.parameters){return'';}constparameters=result.want.parameters;consturiKeys:string[]=['uri','imageUri','resourceUri','select-item-list'];for(leti=0;i<uriKeys.length;i++){constvalue=parameters[uriKeys[i]];if(typeofvalue==='string'){returnvalue;}if(Array.isArray(value)&&value.length>0&&typeofvalue[0]==='string'){returnvalue[0];}}return'';}

解析策略说明

  1. result.want.uri(优先级最高):部分系统版本会将图片 URI 直接放在want对象的顶层uri字段。
  2. result.want.parameters遍历(兼容模式):在不同 HarmonyOS 版本上,返回的 key 名可能不同,代码尝试了uriimageUriresourceUriselect-item-list四种常见 key 名。
  3. 值类型兼容:同一个 key 在某些版本上是字符串,在某些版本上是数组(单选时数组长度为 1),代码对两种类型都做了处理。
  4. 兜底返回空字符串:所有查找方式均失败时返回空,上层逻辑会载入示例画作。

五、拍照后的统一处理

无论来自相机还是相册的图片,最终都走capturePhoto方法统一处理:

privatecapturePhoto(uri:string='',sourceLabel:string='拍照图片'){if(uri!==''){this.capturedImageUri=uri;this.imageSourceLabel=sourceLabel;}this.hasPhoto=true;this.activeStep=1;// 进入"准备图片"步骤this.generationProgress=35;// 更新进度条this.noticeText='已采集画作,可以直接生成动画';}

该方法做了三件事:

  • 存储图片信息:保存 URI 和来源标签(“拍照图片"或"相册图片”)
  • 更新状态:标记hasPhoto = true,推进步骤到第 1 步
  • 反馈用户:更新进度值(35%)和提示文字

六、子组件与父组件通信 (@Link)

PhotoRecognitionComponent组件将内部状态通过@Link装饰器暴露给父组件PhotoRecognitionPage,实现双向数据同步:

子组件定义

@Componentexportstruct PhotoRecognitionComponent{@LinkgenerationProgress:number;@LinknoticeText:string;@StateprivatehasPhoto:boolean=false;@StateprivatecapturedImageUri:string='';// ...}
  • @Link:与父组件共享状态,子组件对generationProgressnoticeText的修改会直接反映到父组件 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 系统相机调用的最佳实践:

知识点实现方式
启动系统相机startAbilityForResult+ohos.want.action.imageCapture
权限申请PermissionGuard.requestCamera封装
结果解析多层 fallback 解析AbilityResult.want
状态同步@Link双向绑定父子组件数据
异常兜底catch 中自动载入示例画作

下一节我们将探讨另一种图片采集方式——通过PhotoViewPicker从相册中选择图片,以及它相对相机模式的不同场景和权限模型差异。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/13 5:08:13

税务申报工具:税法规则与自动计算的系统

税务申报工具&#xff1a;税法规则与自动计算的系统 在数字化时代&#xff0c;税务申报工具已成为企业和个人高效处理税务事务的重要助手。这类工具通过内置的税法规则和自动计算功能&#xff0c;大幅降低了税务申报的复杂度&#xff0c;减少了人为错误的风险。无论是企业财务…

作者头像 李华
网站建设 2026/7/13 5:08:15

Java的java.lang.foreign.MemorySegment内存访问模式与缓存友好性优化

Java的java.lang.foreign.MemorySegment是JDK 16引入的Panama项目核心组件&#xff0c;旨在提供高效、安全的外部内存访问能力。随着现代应用对性能要求的提升&#xff0c;尤其是大数据、游戏引擎等场景&#xff0c;如何优化内存访问模式以适配CPU缓存特性成为关键。MemorySegm…

作者头像 李华
网站建设 2026/7/13 5:11:17

AI之长效智能体Hermes Agent

Hermes Agent 是由 Nous Research 开源的有状态、可进化、常驻式自主智能体;其技术本质在于将大模型的单次对话能力,转化为可沉淀、可复用、可迭代的长期数字资产。实现后台持续驻留、跨会话记忆永存以及任务经验的自动进化。 运行约束与前置条件;其底层的长效运行机制依赖…

作者头像 李华
网站建设 2026/7/13 5:08:33

实时更新策略

实时更新策略&#xff1a;数据时代的动态管理艺术 在信息爆炸的今天&#xff0c;实时更新策略已成为企业、平台乃至个人保持竞争力的核心手段。无论是电商平台的库存同步、新闻媒体的热点推送&#xff0c;还是智能算法的即时优化&#xff0c;实时更新策略都能显著提升效率与用…

作者头像 李华