【HarmonyOS 6】鸿蒙原生应用智能体接入
本文中的代码全部来自项目现有实现,核心逻辑集中在。
本文只讲一个很细的功能:如何在首页标题栏右上角接入智能体入口。本文中的代码全部来自项目现有实现,核心逻辑集中在 entry/src/main/ets/pages/MainMenu.ets。
功能效果
这个接入点放在首页标题栏最右侧,具备三个特点:
- 位置固定:显示在应用标题右边
- 按能力显示:只有设备支持、控制器初始化成功时才渲染
- 生命周期完整:页面进入时初始化,页面离开时移除监听

相关文件
本功能的主要实现文件只有一个:
entry/src/main/ets/pages/MainMenu.ets
也就是说,这次接入并没有拆到额外的服务层里,页面自己完成了状态声明、能力检测、组件渲染和事件解绑,结构比较直接,适合写成独立教程。
一、先引入智能体组件相关能力
首页文件顶部先引入 FunctionComponent 和 FunctionController:
import { common } from '@kit.AbilityKit'
import { BusinessError } from '@kit.BasicServicesKit'
import { FunctionComponent, FunctionController } from '@kit.AgentFrameworkKit'
这里三项分别承担不同职责:
FunctionComponent:真正显示在页面上的智能体入口组件FunctionController:负责控制组件,并监听打开、关闭等事件common.UIAbilityContext:做能力检测时需要的上下文对象
这个功能直接使用系统 Kit,不需要在项目里额外补第三方依赖。
二、页面内声明状态与控制器
在 MainMenu 页面里,和智能体相关的成员只有三个,逻辑很清晰:
@State isAgentSupport: boolean = false
private agentController: FunctionController | null = null
private agentId: string = 'your_agent_id_here'
这三个字段的作用分别是:
isAgentSupport:当前设备和环境是否支持该智能体能力agentController:智能体组件控制器agentId:接入的智能体标识
这里把真实 ID 换成了占位符。你在自己的项目里,只需要把 your_agent_id_here 替换成实际智能体 ID 即可。
三、在页面出现时初始化智能体能力
这个功能没有在页面创建时直接渲染,而是先做设备判断,再决定是否初始化:
aboutToAppear(): void {
const is2In1 = is2In1Device()
if (!is2In1) {
this.agentController = new FunctionController()
this.initAgentListeners()
this.checkAgentSupport()
} else {
this.agentController = null
this.isAgentSupport = false
hilog.info(DOMAIN, TAG, 'Agent entry disabled on 2in1 device')
}
}
这里有两个关键点:
1. 不是所有设备都直接展示
代码里明确对 2in1 做了排除处理。如果当前设备不适合该能力,就直接把入口关闭,不继续初始化。
2. 初始化顺序很重要
接入顺序是固定的:
- 创建
FunctionController - 注册监听事件
- 检查能力是否支持
这样写的好处是:只有在能力确认可用后,页面才会真正显示右上角入口,避免空白占位或者点击无响应。
四、补上打开与关闭事件监听
当前实现里还给智能体组件补了两个事件监听:
private initAgentListeners(): void {
this.agentController?.on('agentDialogOpened', this.onAgentOpenedCallback)
this.agentController?.on('agentDialogClosed', this.onAgentClosedCallback)
}
private readonly onAgentOpenedCallback = () => {
hilog.info(DOMAIN, TAG, 'agent dialog opened callback')
}
private readonly onAgentClosedCallback = () => {
hilog.info(DOMAIN, TAG, 'agent dialog closed callback')
}
这部分逻辑不复杂,但很有必要。因为智能体入口往往不是一个普通按钮,它可能会拉起对话框或服务面板。接入监听后,后续如果你要统计打开次数、补埋点、做页面联动,都可以直接在这两个回调里扩展。
当前项目里这两个回调先只做日志记录,属于非常稳妥的写法:先把链路接通,再逐步增加业务逻辑。
五、渲染前先做能力检测
是否显示入口,不是靠写死布尔值,而是通过 checkAgentSupport() 动态判断:
private async checkAgentSupport(): Promise<void> {
try {
const context = this.getUIContext()?.getHostContext() as common.UIAbilityContext | undefined
if (!context) {
this.isAgentSupport = false
hilog.warn(DOMAIN, TAG, 'UIAbilityContext is unavailable when checking agent support')
return
}
if (!this.agentController) {
this.isAgentSupport = false
return
}
this.isAgentSupport = await this.agentController.isAgentSupport(context, this.agentId)
hilog.info(DOMAIN, TAG, `Agent support: ${this.isAgentSupport}`)
} catch (error) {
const err = error as BusinessError
this.isAgentSupport = false
hilog.error(DOMAIN, TAG, `Failed to check agent support: code=${err.code}, message=${err.message}`)
}
}
这段代码建议重点理解三件事:
1. 检测依赖页面上下文
这里不是直接调用 isAgentSupport(),而是先从页面里拿到 UIAbilityContext。如果上下文拿不到,就立即返回,并把状态设为 false。
2. 检测结果直接驱动 UI
isAgentSupport 是 @State 变量,一旦检测完成,页面会自动刷新。这样就不需要你手动控制标题栏重绘。
3. 错误场景要兜底
如果检测异常,当前实现会:
- 把
isAgentSupport置为false - 记录错误日志
也就是说,接入失败时页面仍然可以正常使用,只是右上角不显示智能体入口,不会影响首页其它按钮。
六、把智能体入口放到标题栏右上角
UI 布局同样写得很直接:左边是应用标题,右边是智能体入口。关键代码如下:
Row({ space: 12 }) {
Column() {
Text('左左右右')
.fontSize(36)
.fontWeight(FontWeight.Bold)
.fontColor('#FF6B35')
}
.height(44)
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
if (this.isAgentSupport && this.agentController) {
Column() {
FunctionComponent({
agentId: this.agentId,
onError: (err: BusinessError) => {
hilog.error(DOMAIN, TAG, `Agent component error: code=${err.code}, message=${err.message}`)
},
controller: this.agentController
})
}
.padding(6)
.backgroundColor(getThemeManager().isDark() ? '#1F2A3A' : '#FFFFFF')
.borderRadius(20)
.shadow({ radius: 6, color: '#00000014', offsetY: 2 })
}
}
.width('90%')
.alignItems(VerticalAlign.Center)
.padding({ top: 30, bottom: 20 })
这一段可以拆成两个层面来看。
1. 布局层
- 左侧标题区域用了
.layoutWeight(1) - 这样右侧智能体入口就会自然被“挤”到最右边
- 外层
Row({ space: 12 })负责控制标题和入口之间的间距
所以这个右上角布局并不需要额外写 Blank(),直接用 layoutWeight(1) 就已经足够。
2. 组件层
真正的智能体接入只有一行核心:
FunctionComponent({
agentId: this.agentId,
onError: (err: BusinessError) => {
hilog.error(DOMAIN, TAG, `Agent component error: code=${err.code}, message=${err.message}`)
},
controller: this.agentController
})
这里最重要的是三个参数:
agentId:指定接入哪个智能体controller:把前面创建好的控制器传进去onError:兜底处理组件异常
外层再用一个 Column 包起来,补上 padding、圆角和阴影,右上角入口就会更像一个完整的小卡片,而不是直接把组件生硬贴在标题旁边。
七、页面离开时移除监听
这个细节很容易漏,但当前项目已经补上了:
aboutToDisappear(): void {
this.agentController?.off('agentDialogOpened')
this.agentController?.off('agentDialogClosed')
}
为什么要写这一步?原因很简单:
- 首页可能会被重复进入
- 如果监听不解绑,重复注册后可能出现多次回调
- 长期来看也不利于页面生命周期管理
所以完整接入不只是“显示出来”,还要把退出阶段的清理动作一起做完。
八、接入这类首页智能体入口的最小步骤
如果你也要在自己的 HarmonyOS 页面右上角放一个智能体入口,最小接入步骤就是下面这 5 步:
- 在页面中引入
FunctionComponent、FunctionController - 声明
isAgentSupport、agentController、agentId - 在
aboutToAppear()里创建控制器并调用checkAgentSupport() - 在标题栏右侧通过
FunctionComponent渲染入口 - 在
aboutToDisappear()里移除监听
照着当前项目这套结构接入,逻辑会比较完整,而且不会把首页写乱。
小结
首页右上角智能体接入,本质上只做了三件事:
- 先判断能不能用:通过
isAgentSupport()控制显隐 - 再把组件放到标题栏右侧:通过
layoutWeight(1)留出右侧空间 - 最后把生命周期补完整:进入时初始化,离开时解绑事件
这类功能看起来只是页面右上角多了一个入口,但真正稳定的关键,不在“放上去”,而在于能力检测、错误兜底、事件监听和退出清理都要一起做好。当前项目里的实现已经把这条链路串通了,直接按这个结构复用即可。
更多推荐



所有评论(0)