鸿蒙 韶非 UI 系列:能力调用 startAbilityForResult,跳能力拿回参,鸿蒙能力路由入门

发布时间:2026/7/22 4:02:14
鸿蒙 韶非 UI 系列:能力调用 startAbilityForResult,跳能力拿回参,鸿蒙能力路由入门 写在前面如果你写过 ArkUI 之外任何需要跨能力协作的鸿蒙应用大概率遇到过这个场景用户在「主页能力」点「设置」按钮你用context.startAbility(want)跳到「设置能力」。跳过去就完用户在设置里改了啥你拿不到。用户切回主页你问他「你在设置里改了啥」——你不知道。因为startAbility不等回参跳过去就出本能力生命周期。你查文档发现「要拿回参得用startAbilityForResult」——它跳能力后等用户操作完自动拉回本能力并给你一个AbilityResult含 resultCode want.parameters。你点进去发现Want路由载体、resultCode区分、onAbilityResult监听、terminateSelf收尾——比前端window.openpostMessage复杂十倍一脸懵。这是「单向跳」和「跳拿回参」的分水岭。鸿蒙给的能力路由答案是UIAbilityContext.startAbilityForResult——Want路由定位目标能力、resultCode表示返回结果、want.parameters携回写参、terminateSelf销毁本能力。本文就用一个真机可跑的「跳系统设置能力 拿 resultCode 回参」demo把能力调用从「听名字一脸懵」讲到「下个项目直接抄」。代码托管在 AtomGit文末有链接真机实拍截图作证。这是韶非 UI 系列第三篇接续上两篇 HTTP 网络栈 文件 IO。适合人群写过鸿蒙应用、被「跳能力拿不到回参」折磨过的同学。不适合人群还在学State的同学——出门左转看我的入门篇。一、先讲清楚能力调用到底是啥一句话能力调用是鸿蒙的能力路由机制管「跳能力、拿回参、收本能力」全流程。你之前写前端window.open(url)是浏览器宿主 API——鸿蒙不是浏览器环境没有这种。能力调用是鸿蒙专门给跨能力协作的原生机制能力对标window.open postMessage但更精细可控。核心 API 一览API作用一句话理解context.startAbility(want)单向跳能力「跳过去不等回参」context.startAbilityForResult(want)跳拿回参「跳过去等用户操作完拉回本能力」context.terminateSelf()销毁本能力「主动结束生命周期」Want路由载体「bundleName abilityName 定位目标能力」AbilityResult回参结果「resultCode0正常/-1取消 want.parameters」记住这五个往下看。二、动手一个跳系统设置能力拿回参的 demo2.1 import 拿 UIAbilityContextimportcommonfromohos.app.ability.commonimportWantfromohos.app.ability.WantEntryComponentstruct Index{privatecontext:common.UIAbilityContextgetContext(this)ascommon.UIAbilityContextStateresultLog:string尚未发起能力调用StateresultCode:number-1StatecallCount:number0// ...}三个细节import common from ohos.app.ability.common——common.UIAbilityContext是能力调用的入口getContext(this) as common.UIAbilityContext——拿 UIAbility 上下文用于调startAbility/startAbilityForResult/terminateSelfWant是能力路由载体要单独 import 装载 bundleName/abilityName/parameters2.2startAbilityForResult跳能力拿回参asynccallAbilityForResult():Promisevoid{this.callCountthis.resultLog第${this.callCount}次发起能力调用中...try{// Want 是能力路由载体bundleName abilityName 定位目标能力// 系统设置能力 bundlecom.ohos.settings, abilitySettingsAbilityconstwant:Want{bundleName:com.ohos.settings,abilityName:com.ohos.settings.MainAbility,parameters:{caller:ArkTS-demo,ts:${Date.now()}}}asWant// startAbilityForResult 跳过去,用户在目标能力里交互后返回本能力// 回调 AbilityResult:{ resultCode: number, want?: Want }constresultawaitthis.context.startAbilityForResult(want)this.resultCoderesult.resultCodeconstparamEchoresult.want?.parameters?.[echo]asstring||(目标能力没回写 echo)this.resultLog第${this.callCount}次resultCode ${result.resultCode}0正常返回-1取消\n回写参${paramEcho}}catch(e){this.resultLog第${this.callCount}次失败${e.message}this.resultCode-1}}startAbilityForResult三个关键点①Want路由载体bundleName abilityName 定位目标constwant:Want{bundleName:com.ohos.settings,// 目标能力 bundle 包名abilityName:com.ohos.settings.MainAbility,// 目标能力 ability 名parameters:{caller:ArkTS-demo,ts:${Date.now()}}// 携参给目标能力}asWantWant是鸿蒙能力路由的核心数据结构对标前端的 url query。三个字段字段作用bundleName目标能力 bundle 包名应用唯一标识abilityName目标能力 ability 名应用内能力唯一标识parameters携参给目标能力键值对ArkTS 强约束want不能是裸对象字面量必须as Want显式断言。②AbilityResult回参resultCode want.parametersconstresultawaitthis.context.startAbilityForResult(want)result.resultCode// 0正常返回, -1取消result.want?.parameters?.[echo]// 目标能力回写的参数resultCode是返回码类似前端的 window.returnValueresultCode含义0正常返回用户操作完-1取消用户没操作就退其他业务自定义目标能力写result.want?.parameters是目标能力回写的参数类似前端的 event.data。③ 异步等回await等用户操作完拉回constresultawaitthis.context.startAbilityForResult(want)// ← 这一行会等用户在目标能力里交互完拉回本能力后才继续startAbilityForResult返回PromiseAbilityResultawait它就会等用户操作完。期间本能力挂后台用户拉回时自动恢复。2.3startAbility单向跳能力asynccallAbilityNoResult():Promisevoid{this.callCountthis.resultLog第${this.callCount}次发起不等回参中...try{constwant:Want{bundleName:com.ohos.settings,abilityName:com.ohos.settings.MainAbility}asWant// startAbility 跳过去不等回参,无 AbilityResult 返回awaitthis.context.startAbility(want)this.resultLog第${this.callCount}次已发起不等回参,日志不显示 resultCode}catch(e){this.resultLog第${this.callCount}次失败${e.message}}}startAbility比startAbilityForResult简单一截——跳过去不等回参无AbilityResult返回。适合「跳设置/跳关于/跳协议」这种单向跳场景。2.4terminateSelf销毁本能力asynckillSelf():Promisevoid{this.resultLogterminateSelf 已调,能力即将销毁try{awaitthis.context.terminateSelf()}catch(e){this.resultLog销毁失败${e.message}}}terminateSelf主动销毁本能力结束生命周期。适合「登录页跳主页后销毁登录页」这种防返回场景。三、真机实拍跳系统设置能力真发出去并真拿回参我把这个 demo 装到真机上跑鸿蒙 6.1.1.125, API 24调系统设置能力com.ohos.settings下面两张都是真机实拍没有任何 P 图。初始态Want 路由载体展示 调用结果「尚未发起能力调用」 ForResult/不调回参/terminateSelf 三按钮点 ForResult 按钮跳能力后返回态调用结果「第 1 次resultCode 00正常返回 回写参(目标能力没回写 echo)」重点看第二张调用结果显示「第 1 次resultCode 00正常返回」——ForResult 真跳过去又正常返回了。回写参「(目标能力没回写 echo)」是因为系统设置能力没 echo 我传的参数——如果调自己的能力在目标能力onAbilityResult回调里写回就行。这是startAbilityForResult双向通讯的证明。四、startAbilityForResultvs 前端window.open postMessage啥差异新手最容易纠结的问题既然前端window.open那么简洁鸿蒙为啥要造能力调用维度前端window.open postMessagestartAbilityForResult运行环境浏览器宿主鸿蒙原生运行环境路由载体url queryWantbundleName abilityName parameters等回参window.openpostMessage双步await一行搞定回参类型event.data任意AbilityResultresultCode want.parameters销毁来源window.closeterminateSelf安全模型同源策略鸿蒙权限 bundle 签名一句话决策鸿蒙应用跨能力协作必须用能力调用不能用window.open不存在。鸿蒙不是浏览器这套原生机制更安全可控。五、常见坑都是血泪坑症状解法用window.open/window.postMessage编译报错「找不到 window」鸿蒙用能力调用没浏览器宿主 APIstartAbility期望拿回参拿不到 resultCode拿回参用startAbilityForResult不是startAbility裸对象字面量传want编译报错arkts-no-untyped-obj-literals显式as Want断言bundleName/abilityName写错跳能力报「找不到能力」真机装目标能力 名字完全一致resultCode当业务码混业务判断错resultCode 是返回码0/-1业务码在want.parameters忘terminateSelf防返回登录页能返回主页登录成功后调terminateSelf销毁登录能力await期间改本能力状态拉回时状态错乱await 后才改状态期间不要动六、Want路由载体的安全模型鸿蒙能力调用受安全约束——不是任意能力都能调要满足以下之一场景能调吗何时用调系统能力com.ohos.settings 等能系统能力公开跳设置/跳关于/跳协议调自有能力同 bundle能跳自家能力拿回参调其他应用能力需对方 ability export应用间协作少数场景调未导出能力不能鸿蒙安全模型这是鸿蒙安全模型的硬约束——比浏览器window.open严但比 iOS URL Scheme 松鸿蒙能力路由可控粒度更细。七、完整代码仓库本文所有代码都已托管到AtomGit欢迎 clone、提 issue、点 star仓库地址https://atomgit.com/JaneConan/arkui-ability-call仓库包含完整的「跳系统设置能力拿回参」demo 工程Index.ets主页面startAbilityForResultstartAbilityterminateSelf三姿势Want路由载体示范 AbilityResult回参处理可直接用 DevEco Studio 打开运行真机装系统设置能力必能跑八、下一步该学什么跑通这个 demo 之后你的鸿蒙能力路由就入门了。这是韶非 UI 系列第三篇后续按这个顺序往下后台任务backgroundTaskManager下一篇延迟挂起 持续后台跑告别前台才活数据持久化ohos.data.relationalStore鸿蒙 SQLite 封装结构化数据存取WebSocketohos.net.webSocket长连接、推送、实时通讯聊天应用必学媒体访问ohos.file.photoAccessHelper访问相册、扫描媒体文件应用调系统相册必学推送通知ohos.notificationManager通知栏展示、点击拉起离线触达必学写在最后startAbilityForResult的本质是**「能力路由的双向通讯」**——不是浏览器window.open是鸿蒙专门给跨能力协作的原生机制能力对标window.open postMessage但更安全可控。代价是Want路由载体多一步、resultCode区分多一步。一旦你开始用能力路由思维写跨能力协作你会发现大部分「跳能力拿回参」「跳能力拿用户操作」的需求都是startAbilityForResultWant的自然结果。代码量比window.open postMessage多两行安全可控性高九成。代码已经给你了仓库链接在上面。现在关掉这篇文章打开 DevEco Studio把 demo 跑起来亲手点 ForResult 跳能力再返回感受下双向通讯。跑通了回来评论区打个「1」我看看有多少人真的动手了。作者JaneConan仓库https://atomgit.com/JaneConan/arkui-ability-call协议Apache-2.0随便用别告我