HarmonyOS 5 上下文的使用:AbilityContext 的使用
摘要: 本文详细介绍了鸿蒙开发中的AbilityContext核心功能与使用场景。作为UIAbility的分身,AbilityContext负责应用组件交互,具备跨Ability跳转、权限申请、结束进程等核心能力。文章通过对比ApplicationContext和UIContext,阐明其"部门经理"的定位,并给出不同场景下的获取方式(UIAbility文件/UI页面)。重点解
大家好,我是不想掉发的鸿蒙开发工程师 城中的雾,我们已经搞定了上下文的配置以及页面上的使用,但光有界面是不够的。App 得动起来,得和系统交互,得跳来跳去。这时候,光靠 UIContext 那个只管画图的小管家是不够的,我们需要权限更高、路子更野的角色。本期主要聊一聊:AbilityContext。它是 UIAbility 的“分身”,掌握着应用组件的生杀大权。
1. 它是谁?部门经理!
如果说 ApplicationContext 是公司老板,负责定战略;那 AbilityContext 就是部门经理,负责具体的业务执行。
- 生命周期:它与
UIAbility绑定。当你打开一个 App 的界面时,它就诞生了;当你把 App 从后台划掉(或者调用terminateSelf)时,它就下岗了。 - 职责:专门处理 “能力 (Ability)” 相关的交互。比如启动另一个 App、申请系统权限、连接 Service 等。
核心区别:
- router (UIContext):是在同一个 Ability 内部的页面之间切换(相当于在部门内部换座位)。
- startAbility (AbilityContext):是启动一个新的 Ability,或者跳转到其他 App(相当于去别的部门办事,或者去别的公司出差)。
2. 如何获取:找到你的经理
在 Stage 模型中,获取 AbilityContext 的方式取决于你现在的代码位置。
场景 A:在 UIAbility 文件中 (EntryAbility.ets)
通过UIAbility直接拿 this.context 即可。
import { UIAbility, Want, AbilityConstant } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 这里的 this.context 就是 AbilityContext
console.info('Ability ID:', this.context.abilityInfo.name);
}
}
场景 B:在 UI 页面中 (Index.ets)
在 UI 页面里,我们需要通过 UIContext 顺藤摸瓜找到它。
import { common } from '@kit.AbilityKit';
@Entry
@Component
struct Index {
// 1. 定义一个变量来接收
private context = getContext(this) as common.UIAbilityContext;
build() {
Button('获取经理')
.onClick(() => {
// 推荐方式 (API 11+):通过 UIContext 获取宿主
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
if (context) {
console.info('当前 Ability 名字:', context.abilityInfo.name);
}
})
}
}
3. 核心能力一:跳转 (startAbility)
在鸿蒙里,只要是“跨越”了 Ability 的跳转,都要找它。
1. 跳转到应用内的另一个 UIAbility
比如从“主页 Ability”跳转到“支付 Ability”。
let want: Want = {
deviceId: '', // 空表示本设备
bundleName: 'com.example.myapp', // 包名
abilityName: 'PayAbility' // 目标 Ability 名
};
context.startAbility(want).then(() => {
console.info('跳转支付成功');
}).catch((err: BusinessError) => {
console.error('跳转失败:', err.code);
});
2. 跳转到系统应用 (如拨号盘、浏览器)
这是最常用的场景。比如点击电话号码直接跳到拨号盘。
let want: Want = {
action: 'ohos.want.action.viewData',
entities: ['entity.system.home'],
uri: 'tel:10086'
};
context.startAbility(want);
3. 打开网页 (拉起浏览器)
let want: Want = {
action: 'ohos.want.action.viewData',
entities: ['entity.system.browsable'],
uri: '[https://developer.huawei.com](https://developer.huawei.com)'
};
context.startAbility(want);
4. 核心能力二:权限申请 (requestPermissionsFromUser)
在鸿蒙中,申请动态权限(如相机、麦克风、位置)必须使用 AbilityContext 或 UIContext(API 12+)。
虽然 UIContext 也能申请,但目前 AbilityContext 的兼容性更强。
import { abilityAccessCtrl, Permissions } from '@kit.AbilityKit';
// 定义要申请的权限列表
const permissions: Array<Permissions> = ['ohos.permission.CAMERA'];
// 使用 AtManager 检查是否已授权
let atManager = abilityAccessCtrl.createAtManager();
// ... 省略检查步骤,假设未授权 ...
// 向用户弹窗申请
context.requestPermissionsFromUser(permissions).then((data) => {
let grantStatus: Array<number> = data.authResults;
if (grantStatus.length > 0 && grantStatus[0] === 0) {
console.info('用户同意了相机权限');
} else {
console.warn('用户拒绝了');
}
});
5. 核心能力三:结束进程 (terminateSelf)
有时候我们需要代码控制退出当前 Ability(注意:不是退出 App,除非这是最后一个 Ability)。
场景:用户点击“完成”按钮,关闭当前的“设置页 Ability”,返回上一级。
// 相当于 Android 的 finish()
context.terminateSelf().then(() => {
console.info('关闭成功');
});
带结果返回 (setResult):
如果你想告诉上一个页面“我处理完了,结果是OK”,需要在 terminateSelf 之前调用 terminateSelfWithResult。
// 返回数据给上一个页面
let result: common.AbilityResult = {
resultCode: 1, // 自定义结果码
want: {
parameters: {
'pay_status': 'success'
}
}
};
context.terminateSelfWithResult(result);
6. 避坑指南:Context 混用惨案
这是新手最容易犯的错误:在 AbilityContext 里干 UIContext 的活,或者反过来。
惨案 A:用 AbilityContext 弹窗
// 错误示范
// 虽然代码提示可能有 showDialog,但在多窗口场景下,系统不知道弹在哪
context.getPromptAction().showToast(...) // 可能会报错或不显示
** 修正**:弹窗请认准 this.getUIContext().getPromptAction()。
惨案 B:用 ApplicationContext 跳转
// 错误示范
// ApplicationContext 没有 startAbility 方法(或者受限)
let appContext = context.getApplicationContext();
appContext.startAbility(...) // 报错:方法不存在
** 修正**:跳转必须用 AbilityContext。
总结:AbilityContext 业务速查表
| 需求场景 | 方法 API | 关键参数 |
|---|---|---|
| 跳内部页面 | router.pushUrl |
(找 UIContext) |
| 跳外部 App | startAbility |
Want (bundleName, abilityName) |
| 打电话/打开网页 | startAbility |
Want (uri: ‘tel:xxx’) |
| 申请权限 | requestPermissionsFromUser |
Permissions[] |
| 关闭当前页 | terminateSelf |
无 |
| 关闭并返回数据 | terminateSelfWithResult |
AbilityResult |
下一期预告:
到现在为止,我们已经在 UI 里面处理了很对上下文的使用场景。但是,如果我们把代码抽离到 utils 工具类,或者 ViewModel 里,脱离了 UI 组件的 this,我们该怎么拿到这些 Context 呢?
- 全局单例 Context 到底能不能用?
- 怎么优雅地封装一个全局 Toast 工具类?
- 下一篇,我们来聊聊 脱离 UI 怎么用 Context?
📚 充电时间
如果有想加入鸿蒙生态的大佬们,快来加入鸿蒙认证吧!初高级证书还没获取的,点这里:
如果您有任何疑问、对文章写的不满意、发现错误或者有更好的方法,欢迎在评论、私信中提出,非常感谢您的支持。
更多推荐


所有评论(0)