鸿蒙 HarmonyOS 6 | AbilityDelegator.startAbility 错误处理迁移实战

张开发
2026/4/14 19:59:25 15 分钟阅读

分享文章

鸿蒙 HarmonyOS 6 | AbilityDelegator.startAbility 错误处理迁移实战
文章目录前言一、先把这次错误码变更看清楚二、测试代码会在哪些地方开始失真三、异常处理代码怎么改更稳四、升级时最值得先做的事总结前言做自动化测试时AbilityDelegator.startAbility()这类接口的稳定性直接影响测试代码的寿命。业务代码升级之后测试代码通常会跟着调一轮。测试框架自己的行为一旦变化影响会更隐蔽很多问题要等到测试跑挂了才会暴露出来。鸿蒙 6 API 20 这里有一个典型例子。AbilityDelegator.startAbility()的返回错误码在 6.0.0(20) Beta1 做了标准化调整这项变更带了版本隔离只有应用targetSdkVersion大于等于 6.0.0(20) 时才会生效。平台变更说明里写的是这项调整不涉及应用适配但测试工程里的异常处理、失败断言和错误报告分类都会受到影响。一、先把这次错误码变更看清楚这次调整的核心很直接AbilityDelegator.startAbility()过去返回的错误码与接口文档描述存在差异。现在平台把它们收回到了和 API 描述一致的编号体系里。变更说明已经给出了明确映射关系比如29360128调整为4012097199调整为160000012097187调整为160000022097179调整为160000042097208调整为16000005后面还有2097207 - 16000006、2097203 - 16000008、11 - 16000009、2097206 - 16000010、2097323 - 16000011、2097204 - 16000012、2097215 - 16000013、2097167 - 16000050、5242881 - 16000053、29360300 - 16000055、2097205 - 16200001。从接口层看调用方式没有变依旧是通过AbilityDelegatorRegistry拿到 delegator再传入Want启动目标 Ability。当前参考接口里已经给出了新的错误码集例如16000001表示指定 Ability 不存在16000002表示 Ability 类型错误16000004表示不可启动不可见组件16000005表示权限相关问题。这件事落到工程里真正会受影响的地方很集中。第一类是直接断言错误码数值的测试用例。第二类是按旧错误码走恢复逻辑的封装层。第三类是把旧错误码写进日志平台、监控告警或测试报告分类规则的那部分代码。接口名没动风险点都藏在错误处理分支里。二、测试代码会在哪些地方开始失真最先失真的通常是失败断言。很多测试代码会写成启动某个 Ability预期它因为参数错误或配置错误失败然后断言error.code 某个旧值。这种写法在旧 targetSdkVersion 下可以成立targetSdkVersion 切到 6.0.0(20) 之后断言值会整体漂移。接口调用还是失败测试结果会从可预期失败变成断言失败。第二个高频问题出在工具层封装。很多团队会在测试基建里封一个startAbilitySafe或launchAbility里面按错误码分配置问题、权限问题、系统问题再决定是直接报错、重试、补权限还是重启测试环境。这类代码如果继续按旧错误值分类后面的策略就会跑偏。比如过去用29360128判断参数错误升级后这个值已经换成401恢复分支也要跟着改。第三个问题更隐蔽出在测试报告。很多自动化测试平台会把错误码聚合成趋势图和统计面板。升级前后的同一种错误会以新旧两组编号同时出现。接口行为已经统一报表会先乱一段时间。这个问题不影响单条测试执行但会影响长期趋势判断和故障归类。三、异常处理代码怎么改更稳这类升级里更稳的做法是做两层收口。第一层直接按新错误码写主逻辑。第二层保留一个兼容映射把旧编号统一转到新编号再往上层抛。这样后面的分类、日志和重试策略都能只认一套编号。先看面向 API 20 主线的写法。AbilityDelegator.startAbility()还是 Promise 形式异常里拿BusinessError处理即可。下面这段代码保留了常见的几类判断适合直接落到测试工程里。当前参考接口里16000001、16000002、16000004、16000005这些语义都已经能对上新的 Ability Kit 错误码说明。import{abilityDelegatorRegistry}fromkit.TestKit;importtype{Want}fromkit.AbilityKit;importtype{BusinessError}fromkit.BasicServicesKit;exportasyncfunctionstartAbilityWithHandledError(want:Want):Promisevoid{constdelegatorabilityDelegatorRegistry.getAbilityDelegator();try{awaitdelegator.startAbility(want);console.info(Ability 启动成功);}catch(err){consterrorerrasBusinessError;switch(error.code){case401:console.error(参数错误请检查 want 结构和必填字段);break;case16000001:console.error(目标 Ability 不存在请检查 bundleName 和 abilityName);break;case16000002:console.error(Ability 类型错误请检查目标组件类型);break;case16000004:console.error(目标组件不可见无法启动);break;case16000005:console.error(权限校验失败请检查测试进程权限);break;default:console.error(启动失败code${error.code}, message${error.message});break;}throwerror;}}如果项目里还要兼容旧 targetSdkVersion建议把旧编号到新编号的转换收在一个小适配层里。不要把映射逻辑散落到每个测试用例里后面维护会很累。变更说明给出的旧新编号关系正适合做成统一映射表。exportclassStartAbilityErrorCodeAdapter{privatestaticreadonlylegacyToStandardnewMapnumber,number([[29360128,401],[2097199,16000001],[2097187,16000002],[2097179,16000004],[2097208,16000005],[2097207,16000006],[2097203,16000008],[11,16000009],[2097206,16000010],[2097323,16000011],[2097204,16000012],[2097215,16000013],[2097167,16000050],[5242881,16000053],[29360300,16000055],[2097205,16200001],]);staticnormalize(code:number):number{returnthis.legacyToStandard.get(code)??code;}}有了这层之后上层逻辑就能只认标准编号import{abilityDelegatorRegistry}fromkit.TestKit;importtype{Want}fromkit.AbilityKit;importtype{BusinessError}fromkit.BasicServicesKit;exportasyncfunctionrobustStartAbility(want:Want):Promisevoid{constdelegatorabilityDelegatorRegistry.getAbilityDelegator();try{awaitdelegator.startAbility(want);}catch(err){consterrorerrasBusinessError;constnormalizedCodeStartAbilityErrorCodeAdapter.normalize(error.code);if(normalizedCode401||normalizedCode16000001||normalizedCode16000004){console.error(配置类错误code${normalizedCode});}elseif(normalizedCode16000005||normalizedCode16000006){console.error(权限类错误code${normalizedCode});}elseif(normalizedCode16000050normalizedCode16000055){console.error(系统类错误code${normalizedCode});}else{console.error(未知错误code${normalizedCode}, rawCode${error.code});}throwerror;}}这种写法的好处很直接。旧环境里抛旧值先规范化新环境里直接抛新值也能走同一套分类逻辑。测试报告、重试策略、日志平台都能跟着一起收口。四、升级时最值得先做的事这类接口变更真正麻烦的地方不在代码改动量而在遗漏。一个测试仓库里直接写startAbility()的地方也许不多围绕它做二次封装、错误断言、报表分类、失败重试的地方通常更多。升级时最值得先做的事是先把所有和旧错误码绑定的逻辑找出来再开始替换。实践里更稳的顺序通常是这样。先把旧错误码映射表补进基础库让底层能统一收口。然后把用例里的硬编码断言逐步换成标准编号。最后再看监控、日志和测试报告这类外围系统把新旧编号统一到同一套展示规则里。这样做测试不会一夜之间大面积飘红团队也更容易看清哪些问题来自接口升级哪些问题来自业务代码本身。还有一个细节值得单独拎出来。平台变更页明确说这次调整做了版本隔离只在targetSdkVersion 6.0.0(20)时生效。同一份测试代码在不同 targetSdkVersion 下看到的错误码可能不同。测试基础库如果不显式处理这个条件后面多分支维护会越来越难。把兼容逻辑往下收是这次迁移里最省事的一步。总结AbilityDelegator.startAbility()这次变更核心就是把返回错误码收回到和 API 描述一致的标准编号体系里生效条件是targetSdkVersion 6.0.0(20)。业务接口名没变影响点集中在测试代码的异常处理、失败断言和报告分类上。工程里更稳的处理办法也很明确。主路径按新错误码写兼容层把旧编号统一映射到新编号再让上层逻辑只认一套标准值。这样做完之后测试代码会更短错误报告也更容易看懂。

更多文章