HarmonyOS 6.1.1:Camera 自动构图与自动对焦

HarmonyOS 6.1.1:Camera 自动构图与自动对焦 相机行为受镜头、传感器、会话、权限、设备方向和主体环境共同影响SDK 声明只能证明接口存在不能替读者证明某台设备一定支持自动构图或某次拍摄一定完成。因此本文把问题收窄为一条可验收的工程链如何查询能力如何建立会话如何观察focusStateChange如何在同一条件下重复两轮并把模拟器、真机和拍摄文件分成不同证据层。先界定本文能证明的范围本机 API 24 SDK 文件ohos.multimedia.camera.d.ts确认kit.CameraKit导出camera与cameraPicker自动构图类型包含AUTO_FRAMING 2标注为since 24聚焦能力可通过FocusQuery.isFocusModeSupported(afMode)查询模式可通过Focus.getFocusMode()、Focus.setFocusMode()读取和设置会话提供on(focusStateChange, callback)。这些是声明层事实版本边界清楚但它们没有回答三个运行问题当前设备是否支持、当前镜头是否能使用、在固定场景中状态是否真的发生变化。所以本文不会把“声明存在”改写为“功能可用”。在没有华为真机时我只完成了横屏 Pad 准备页的构建、安装、启动和状态展示页面默认把权限记为unknown把AUTO_FRAMING与聚焦模式记为notQueried把focusState记为“未观察”把拍摄结果记为idle。这几个值看起来不如绿色成功醒目却是当前证据能够支持的准确结论。模拟器能证明布局和降级提示不足以证明后摄预览、自动构图、自动对焦或拍摄文件。影像验证不是一个布尔开关把“自动对焦”写成一个布尔值会丢掉调试最需要的信息。能力查询是设备层状态权限是系统授权状态会话是资源生命周期焦点状态是过程回调拍摄文件是最终产物。它们之间有先后关系却不能互相替代。例如isFocusModeSupported返回支持只能说明模式有机会被调用会话创建失败时仍然没有可观察的焦点变化。相反收到一次focusStateChange也不能自动证明最终照片清晰因为回调是过程事实清晰度还要看固定主体和最终文件。建议把一次验证拆成下面的阶段进入前检查设备标识与系统版本首次运行记录权限结果创建后摄会话并查询AUTO_FRAMING与目标聚焦模式在统一的主体、距离、光线和横屏方向下执行第一轮保存预览状态、焦点回调和拍摄结果恢复同一条件执行第二轮最后才比较两轮结果。对不支持、拒绝、会话异常和拍摄失败都保留原始状态与错误码。对影像工程来说“不支持”是设备矩阵中的一个合法分支不应被测试脚本抹掉。横屏 Pad 页面如何安排证据Demo 使用横向屏幕左侧约三成宽度放固定条件、设备要求和运行入口右侧约七成宽度保留给主要结果。左侧必须紧凑否则条件卡会压缩预览右侧必须成为视觉主区否则截图会看不到真正需要核对的状态。两个区域独立滚动意味着左侧条件可以始终作为参照右侧的预览、回调时间线和最终照片可以继续展开。这种布局不是装饰选择而是为了让一次截图同时包含“在什么条件下测”和“测到了什么”。图中右侧明确写出“真机验证尚未开始”并把相机权限、AUTO_FRAMING、聚焦模式、focusState和拍摄结果列为独立字段。它证明的是准备页已经运行以及未伪造结果不能据此写成“自动构图不支持”因为当前值是notQueried并没有进行能力查询。左侧的固定主体、镜头和轮次条件则为明日真机测试提供可复现的起点。能力查询要早于会话操作影像页面的第一个按钮不应直接叫“开始拍摄”。在资源和能力尚未确认前启动完整会话会让错误混杂在权限、镜头和模式之间。更稳妥的入口是先取得明确设备信息再读取支持矩阵只有支持时才显示对应操作不支持时给出降级路径。下面的片段是最小的查询边界重点是把supported与“已经产生视觉结果”分开。interfaceCameraCapability{autoFraming:notQueried|supported|unsupported;focusMode:notQueried|supported|unsupported;}asyncfunctionqueryCapabilities(focus:Focus):PromiseCameraCapability{constautoFramingawaitqueryAutoFramingSupport();constfocusSupportedawaitfocus.isFocusModeSupported(FocusMode.CONTINUOUS_AUTO);return{autoFraming:autoFraming?supported:unsupported,focusMode:focusSupported?supported:unsupported};}示例中的queryAutoFramingSupport代表工程中与设备能力声明对应的查询步骤不应在没有真实接口返回时写死为true。实际项目应将查询值、查询时间、镜头方向和设备型号一起写入本轮测试记录。FocusMode.CONTINUOUS_AUTO也只是目标模式示意真机执行时要以本机 API 声明和设备支持矩阵为准。重要的不是让片段看起来能在任何设备复制而是让读者知道能力查询是一个可追踪的输入。查询失败时不要把状态折叠成unsupported。前者可能是权限尚未授予、会话还没有建立或设备服务异常后者才是明确的能力边界。UI 可以显示“查询失败请重试”和错误码测试报告则把失败原因放到运行层。这样后续换设备或换镜头时工程师才能区分能力差异和环境问题。查询记录应包含什么一次能力查询最小也要有“谁在何时查询了哪一个镜头、返回了什么、是否进入下一步”四类信息。这里的“谁”不是用户身份而是去敏后的测试设备标签和应用版本“哪一个镜头”至少区分前摄、后摄主镜头和其他后摄镜头“返回了什么”保留原始布尔值或错误码“下一步”则记录页面是否解锁自动构图或聚焦操作。没有这些上下文事后看到一个supported无法知道它来自哪个镜头、哪个构建版本也无法解释为什么另一台设备的按钮不同。页面状态建议采用单向推进unknown只出现在尚未请求权限前notQueried只出现在权限与会话前置条件尚未完成时supported与unsupported只由真实查询回写错误则单列为queryFailed或带错误码的状态。这样做能防止常见的两类问题页面重新进入时沿用上一次设备的绿色状态用户切换镜头后却没有重新查询。任何输入条件变化都应该使对应能力回到notQueried要求重新取得事实。真正落地时查询并非越频繁越好。相机服务刚启动、镜头切换中、应用退到后台或会话即将销毁时连续触发查询只会制造难以解释的中间态。工程可以给查询入口设置明确的可用条件并在右侧结果区展示最近一次查询时间。用户看到“正在查询”而非闪烁的支持状态测试人员也能把日志时间与截图对应起来。会话生命周期决定回调是否可信focusStateChange不是一次性结果它属于相机输出会话的生命周期。监听器注册过早可能拿不到有效会话注册过晚可能错过第一轮状态页面离开后不释放又会把旧会话的回调送到新页面。实现时应把“创建、监听、停止、释放”作为一个完整单元记录并在页面销毁时移除监听。回调处理只更新当前会话的短期状态不把相机对象塞进全局状态。privatefocusListener(state:FocusState):void{this.focusTimeline.push({state,observedAt:newDate().toISOString()});};asyncfunctionstartCameraSession(session:CameraSession):Promisevoid{session.on(focusStateChange,this.focusListener);awaitsession.start();}asyncfunctionstopCameraSession(session:CameraSession):Promisevoid{session.off(focusStateChange,this.focusListener);awaitsession.stop();this.focusTimeline[];}这里把时间线当作观察证据而不是“清晰度评分”。每一项至少包含状态、时间和轮次标识若 SDK 回调还提供区域或错误信息可以按最小需要保留。回调没有到达时时间线应保持空并显示“未观察”不可补写一个成功状态。回调到达但拍摄失败时两个事实都要保留不能用最终错误覆盖过程记录。焦点状态与自动构图也需要分开核对。自动构图可能调整主体在画面中的位置连续自动对焦则关注焦平面变化同一轮中两者都在工作时截图容易把构图变化误认为对焦成功。测试时应至少保存一张过程截图和一份最终文件正文只引用能支持当前论点的那一份并在图注中写清是过程还是结果。监听器的验证点监听器存在并不表示监听器有效。真机补测应在启动会话后记录“监听已注册”的时间在保持主体不动时观察是否有初始状态在改变主体距离或将焦点从近处主体切到远处背景时观察后续变化。每一次观察都要标明动作不应只留一串抽象状态。若两轮都没有收到回调结论只能是“本观察窗口没有回调”还要检查会话类型、镜头、权限和 SDK 版本不能立即写成“设备对焦不可用”。同时要避免把回调数量当作性能指标。连续自动对焦的回调频率会受设备、场景和实现影响更多事件不必然代表更好的体验。对本文的验收而言重点是事件是否来自当前会话、是否与明确动作在时间上可对应、页面是否能保持可解释的状态以及停止会话后是否不再收到旧事件。只有在有稳定采样方案和多设备数据时才适合讨论频率或延迟。页面重建是另一个容易遗漏的边界。横竖屏切换、返回前台、切换相机或路由返回都可能重建状态。准备页采用独立的左侧条件与右侧结果并不意味着旧会话可以继续使用。实现中应在销毁前解除监听、停止输出和释放相机资源重新进入后重新查询权限与能力。测试清单需要包含一次中断恢复以证明右侧不会展示来自上一轮的focusState或拍摄结果。两轮测试必须固定比较条件“第一轮清楚第二轮更清楚”不是可复核结论除非两轮的输入足够接近。后摄镜头、横屏方向、主体类型、主体距离、背景纹理、室内光线和拍摄动作都要固定。主体可以使用获得授权的固定人物或模型但不应把真实个人照片归档到文章目录。每轮测试记录开始时间、能力查询结果、预览是否可见、焦点回调顺序、拍摄是否成功和最终文件摘要文章只引用去敏后的截图与结论。若AUTO_FRAMING不支持测试仍然可以验证聚焦模式若目标聚焦模式不支持则保留设备边界并验证页面能否降级到设备默认模式或手动操作。不要为了让两项能力都出现绿色而换镜头、换主体或跳过查询。对于影像组件兼容性矩阵的价值就在于把“某设备不支持某组合”变成可计划的发布信息。拍摄文件本身也要进入证据链。文件存在只能证明写入成功不能直接证明构图或焦点质量可以通过尺寸、编码、生成时间和人工对照确认文件是本轮产物再由人工查看主体位置与清晰区域。若应用只提供内存图像而未落盘必须记录这一边界不能把预览帧截图包装成最终照片。正文中不展示含个人信息的原图文章图片只承担布局、状态或已经获授权的公开样本论点。对构图与清晰度的人工判定自动构图的人工判定应描述主体是否完整、是否仍位于预设安全区域、边缘是否出现不希望的裁切而不应只看画面是否“更有美感”。若测试用固定人物主体需要事先定义允许的头顶留白、肩部边界或全身入镜范围若使用物品主体需要定义主体轮廓是否完整。这样的规则让两轮测试和不同测试者有共同语言也避免将个人审美伪装成客观指标。对焦判定同样需要明确参照。可以选择主体上的高对比文字或纹理作为检查区域记录目标区域在最终照片中是否可辨识并把运动模糊、低光噪点和压缩伪影与焦点问题分开。自动对焦没有回调、回调已到但照片模糊、照片清晰但回调未观察是三种不同情况。工程师应分别记录不让一个笼统的“对焦成功”掩盖差异。人工判定不替代自动记录。它补充的是产品可感知结果而能力查询、回调时间和文件摘要仍由系统输出支撑。记录表中可以有“人工复核通过/不通过/无法判断”并写明原因若不同复核者意见不一致应保留争议而不是取一个看起来更乐观的结果。对公开文章只展示去敏后的判定摘要与可复核方法不放入原始人像。错误路径要能指导下一步权限拒绝、设备不支持、会话启动失败、回调超时和拍摄失败对用户来说下一步完全不同。权限拒绝应提供重新授权或手动上传设备不支持应说明当前机型限制会话失败应提供重试并保留错误码回调超时应显示仍在等待而非失败拍摄失败应允许重新取景。左侧操作区的禁用状态和右侧结果区的解释文字要配套否则截图只显示“按钮不能点”却没有证据说明为什么。对开发者而言错误信息还要有层级。系统错误码、Camera Kit 的状态、业务提示和人工处理意见不应共用一个字符串。日志可以带设备型号、镜头和会话 ID但不得写入完整证件、人物隐私或原始图像路径。文章记录的是错误类别和可复现条件不记录密钥、账号或无法公开的设备标识。复测顺序与停止条件真机到位后不需要一开始就试图覆盖所有镜头。先选后摄主镜头在固定横屏条件下走完整链路权限、能力查询、会话、第一轮观察、拍摄、停止、第二轮观察、拍摄。只有第一台设备的原始记录完整后才扩展到第二台设备或其他镜头。这样发现问题时团队能定位是流程设计问题还是特定机型差异。每轮都有明确停止条件用户拒绝权限停止在权限层并保存降级提示能力不支持停止对应自动操作但继续验证手动相机流程会话无法启动停止回调和拍摄断言并保留错误拍摄失败停止将图像质量纳入结论。停止不是测试失败而是防止后续步骤建立在不存在的前提上。文章补测时只补已经完成的层不能因为期望尽快发布而跨层填充结论。两轮一致也不等于所有设备一致。它只说明同一设备、同一镜头和固定环境下的可重复观察。后续要形成设备兼容性结论还需将相同执行卡用于不同机型并把系统版本和镜头组合纳入矩阵。本文的准备页已经为这种扩展预留了条件栏和结果栏但当前不把这种设计预留混同为已完成的矩阵验证。发布判定哪些话现在能写在当前模拟器环境我可以准确写“API 24 声明包含AUTO_FRAMING”“准备页横屏运行成功”“页面没有用静态素材伪造预览”“真机能力查询和拍摄尚未开始”。小结Camera Kit 的难点不是记住一个枚举或调用一次setFocusMode而是把设备能力、权限、会话、过程回调和最终拍摄文件连成一条可复现链路。横屏 Pad Demo 将条件放在左侧、结果放在右侧服务于截图和评审准备页如实显示notQueried与“未观察”服务于证据边界。等真机和合法测试主体到位后再把能力查询、focusStateChange、预览和拍摄结果逐项补齐这样自动构图与自动对焦才有资格从“声明可用”进入“运行可用”的阶段。附录HarmonyOS 6.1.1 新特性开发环境与真机验证准入1. 版本硬基线本批新特性统一以 HarmonyOS 6.1.1 API 24 为目标版本。项目sourceproject/build-profile.json5必须保持{ compatibleSdkVersion: 6.1.1(24), targetSdkVersion: 6.1.1(24), runtimeOS: HarmonyOS }开发者不得为了绕过构建错误把项目静默改为 API 26 或其他版本。版本变化会同时改变 API 声明、兼容设备、文章结论和文章事实范围。2. 编译环境准入在 DevEco Studio 的 SDK Manager 中必须选择与项目一致的 HarmonyOS6.1.1(API 24)SDK。仅有system-image只能启动模拟器不能证明 ArkTS 项目可以编译。至少应核对以下编译组件组件作用准入要求hms/etsArkTS/ETS API 声明与编译目录存在元数据与 Hvigor 兼容hms/nativeNative 编译支持目录存在元数据与 Hvigor 兼容hms/toolchains编译、签名和设备工具链目录存在hdc可执行hms/previewer预览与设计期支持目录存在版本与 SDK 对齐openharmony/toolchains设备安装、启动与调试hdc.exe可调用硬性判定不是“SDK Manager 显示了 API 24”而是构建已经越过 SDK 扫描并进入CompileArkTS。本项目曾遇到组件metaVersion: 3.1.0与项目自带 Hvigor 扫描器不兼容最终报00303168 SDK component missing此时不能进入特性 API 编码和文章结论阶段。3. 推荐构建链路当前已验证可用的是 DevEco Studio 内置 Hvigor 与 DevEco JBR而不是项目自带的旧/不兼容 Hvigor 组合$env:DEVECO_SDK_HOMED:\Program Files\Huawei\DevEco Studio\sdk$env:JAVA_HOMED:\Program Files\Huawei\DevEco Studio\jbr$env:Path$env:JAVA_HOME\bin;$env:PathD:\Program Files\Huawei\DevEco Studio\tools\hvigor\bin\hvigorw.bat--no-daemon--mode module-p moduleentrydefault-p productdefault assembleHap--stacktrace准入日志必须至少出现Finished :entry:defaultCompileArkTS Finished :entry:defaultPackageHap BUILD SUCCESSFUL如果失败停在 SDK 扫描、依赖解析或 ArkTS 编译之前结论只能写“环境未解锁”。不要根据 IDE 能打开项目、预览器能显示页面或旧 HAP 仍能安装推导新特性 API 可用。4. HAP 安装与启动环境安装验证至少记录设备、包名、HAP 来源和结果。当前项目基线如下项目要求/已验证值包名com.csdn.harmonyos.featuredemos项目 APIcompatibleSdkVersion6.1.1(24)、targetSdkVersion6.1.1(24)设备 API与项目兼容范围匹配当前 API 24releaseType项目、SDK、设备保持一致当前为Release设备形态本批 Demo 以横向 Pad 为主要截图形态手机需单独复核HAP 来源当前 SDK 重新构建的产物不沿用旧 HAP$hdcD:\Program Files\Huawei\DevEco Studio\sdk\default\openharmony\toolchains\hdc.exe$hdcinstall-rsourceproject\entry\build\default\outputs\default\entry-default-unsigned.hap$hdcshell aastart-a EntryAbility-b com.csdn.harmonyos.featuredemosinstall bundle successfully只证明 HAP 与设备的安装条件匹配start ability successfully只证明应用可以启动。两者均不证明 Map、Camera、Notification 听觉、AI 字幕或通行证识别已经成功。