开天辟地 HarmonyOS(鸿蒙) - 开发基础: UIAbility
开天辟地 HarmonyOS(鸿蒙) - 开发基础: UIAbility
示例如下:
pages\basic\UIAbilityDemo.ets
/*
* UIAbility - 用于为应用提供绘制界面的窗口
* 一个应用可以包含一个或多个 UIAbility,每个 UIAbility 实例都会在最近任务列表中显示为一个对应的任务窗口
* 一个 UIAbility 可以包含多个页面
*
* 关于 UIAbility 的相关配置,请参见 module.json5 配置文件中的 abilities 标签
* 关于 UIAbility 的实现及其生命周期,请参见 /ets/entryability/EntryAbility.ets 中的相关说明
*
* 在单 UIAbility 内共享数据可以使用 LocalStorage,请参见 /state/LocalStorageDemo.ets 中的相关说明
* 在多 UIAbility 中共享数据可以使用 AppStorage,请参见 /state/AppStorageDemo.ets 中的相关说明
*
* 打开新的 UIAbility 并接收返回结果,请参见本例和 UIAbilityDemo2.ets 中的相关说明
* 在一个 UIAbility 内做事件的发布和订阅,请参见 UIAbilityDemo2.ets 中的相关说明
*/
import { TitleBar } from '../TitleBar';
import { common, Want } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct UIAbilityDemo {
build() {
Column() {
TitleBar()
Tabs() {
TabContent() { MySample1() }.tabBar('基础').align(Alignment.Top)
}
.scrollable(true)
.barMode(BarMode.Scrollable)
.layoutWeight(1)
}
}
}
@Component
struct MySample1 {
@State message: string = ""
build() {
Column({ space: 10 }) {
Text(this.message)
Button("杀死当前 UIAbility").onClick(() => {
/*
* getContext(this) - 获取上下文对象
* UIAbilityContext - 上下文对象
* terminateSelf() - 杀死当前 UIAbility
*
* 注:
* 当调用 terminateSelf() 杀死当前 UIAbility 后,在最近任务列表中仍会保留其快照
* 如果不需要这个快照,则需要将 module.json5 中的 abilities 的 removeMissionAfterTerminate 设置为 true
*/
let context = getContext(this) as common.UIAbilityContext;
context.terminateSelf()
})
Button("将当前 UIAbility 移入后台").onClick(() => {
/*
* getContext(this) - 获取上下文对象
* UIAbilityContext - 上下文对象
* moveAbilityToBackground() - 将当前 UIAbility 移入后台
*/
let context = getContext(this) as common.UIAbilityContext;
context.moveAbilityToBackground()
})
Button("打开当前 hap 包内的指定的 UIAbility").onClick(() => {
let context = getContext(this) as common.UIAbilityContext;
// Want - 需要拉起的 ability 的相关信息
let want: Want = {
deviceId: '', // 空代表本设备
bundleName: 'com.webabcd.harmonydemo', // 需要打开的 ability 的 bundle 的名称
abilityName: 'com.webabcd.harmonydemo.EntryAbility2', // 需要打开的 ability 的名称(此名称是在 module.json5 中配置的)
parameters: { // 传参
'k1': 'v1',
'k2': 'v2',
}
};
// context.startAbility() - 拉起指定的 ability
context.startAbility(want).then(() => {
this.message = `startAbility 成功`
}).catch((err: BusinessError) => {
this.message = `startAbility 失败, errCode:${err.code}, errMessage:${err.message}`
});
})
Button("打开当前 hap 包内的指定的 UIAbility 并获取返回结果").onClick(() => {// UIAbilityContext
let context = getContext(this) as common.UIAbilityContext;
// Want - 需要拉起的 ability 的相关信息
let want: Want = {
deviceId: '', // 空代表本设备
bundleName: 'com.webabcd.harmonydemo', // 需要打开的 ability 的 bundle 的名称
abilityName: 'com.webabcd.harmonydemo.EntryAbility2', // 需要打开的 ability 的名称(此名称是在 module.json5 中配置的)
parameters: { // 传参
'k1': 'v1',
'k2': 'v2',
}
};
// context.startAbilityForResult() - 拉起指定的 ability 并获取返回结果
context.startAbilityForResult(want).then((data:common.AbilityResult) => {
/*
* AbilityResult - 拉起的 ability 的返回结果
* resultCode - 返回的 code
* want.parameters - 返回的数据
*/
this.message = `startAbility 成功 code:${data.resultCode}, k3:${data.want?.parameters?.k3}, k4:${data.want?.parameters?.k4}`
}).catch((err: BusinessError) => {
this.message = `startAbility 失败, errCode:${err.code}, errMessage:${err.message}`
});
})
}
}
}
\entry\src\main\module.json5
{
"module": {
"name": "entry", // 当前 module 的名称
"type": "entry", // 当前 module 的类型
"srcEntry": "./ets/MyAbilityStage.ets", // 当前 module 的对应的 AbilityStage 的代码的地址
"description": "$string:module_desc", // 当前 module 的描述
"mainElement": "com.webabcd.harmonydemo.EntryAbility", // 当前 module 的入口 ability 的名称(ability 必须是 exported 为 true 的)
"deviceTypes": [
"phone",
"tablet",
"2in1"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages", // 用于描述页面的信息(参见 /entry/src/main/resources/base/profile/main_pages.json)
"querySchemes": [ // 当前应用可以通过 canOpenLink() 判断当前设备中是否存在支持指定协议(这个协议必须在 querySchemes 中配置,最多 50 个)的应用
"webabcd"
],
"abilities": [
{
"name": "com.webabcd.harmonydemo.EntryAbility", // 当前 ability 的名称(自定义标识)
"srcEntry": "./ets/entryability/EntryAbility.ets", // 当前 ability 的代码的地址
"description": "$string:EntryAbility_desc", // 描述
"icon": "$media:layered_image", // app 的图标(需要配置 entity.system.home, action.system.home),如果不指定此字段的话则 app 的图标会使用 AppScope/app.json5 中的 icon
"label": "$string:EntryAbility_label", // app 的标题(需要配置 entity.system.home, action.system.home),如果不指定此字段的话则 app 的标题会使用 AppScope/app.json5 中的 label
"startWindowIcon": "$media:startIcon", // 启动屏上显示的图标
"startWindowBackground": "$color:start_window_background", // 启动屏的背景
"exported": true, // 用于标识当前 ability 是否可以被其他应用调用
"orientation": "portrait", // 屏幕方向
"preferMultiWindowOrientation": "landscape_auto", // 悬浮窗方向
"skills": [ { "entities": [ "entity.system.home" ], "actions": [ "action.system.home" ] } ], // 这个设置说明当前 ability 是入口 ability(主:有了这个配置则 module 的 mainElement 标签将失效)
"backgroundModes": [ // 长时任务的类型
"dataTransfer", // 数据上传下载
// "audioPlayback", // 音频、视频播放
// "audioRecording", // 录音、录屏
// "location", // 定位
// "bluetoothInteraction", // 蓝牙传输
],
"removeMissionAfterTerminate": true // 当调用 terminateSelf() 杀死当前 UIAbility 时,是否需要将其从在最近任务列表中删除(默认值为 false)
},
{
"name": "com.webabcd.harmonydemo.EntryAbility2",
"srcEntry": "./ets/entryability/EntryAbility2.ets",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
},
{
"name": "com.webabcd.harmonydemo.EntryAbility_singleton",
"srcEntry": "./ets/entryability/EntryAbility_singleton.ets",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"launchType": "singleton", // 指定当前 ability 的启动方式为 singleton 方式(详见 /basic/LaunchTypeDemo.ets 中的相关说明)
},
{
"name": "com.webabcd.harmonydemo.EntryAbility_multiton",
"srcEntry": "./ets/entryability/EntryAbility_multiton.ets",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"launchType": "multiton" // 指定当前 ability 的启动方式为 multiton 方式(详见 /basic/LaunchTypeDemo.ets 中的相关说明)
},
{
"name": "com.webabcd.harmonydemo.EntryAbility_specified",
"srcEntry": "./ets/entryability/EntryAbility_specified.ets",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"launchType": "specified" // 指定当前 ability 的启动方式为 specified 方式(详见 /basic/LaunchTypeDemo.ets 中的相关说明)
}
],
"extensionAbilities": [
{
"name": "EntryBackupAbility",
"srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
"type": "backup",
"exported": false,
"metadata": [
{
"name": "ohos.extension.backup",
"resource": "$profile:backup_config"
}
],
},
{
"name": "com.webabcd.harmonydemo.MyWorkSchedulerExtensionAbility", // 自定义标识
"srcEntry": "./ets/pages/background/MyWorkSchedulerExtensionAbility.ets", // 延迟任务对应的代码的地址
"type": "workScheduler" // 当前的 ExtensionAbility 的类型为延迟任务
}
],
"routerMap": "$profile:route_map", // 指定路由表,详见 src/main/resources/profile/route_map.json 中的配置
"requestPermissions":[
{
"name": "ohos.permission.INTERNET", // 请求 Internet 网络的权限
"reason": "$string:hello_webabcd", // 申请此权限的原因
"usedScene": {
"abilities": [ ],
"when":"always" // inuse(使用时允许使用此权限),always(始终允许使用此权限)
}
},
{
"name": "ohos.permission.KEEP_BACKGROUND_RUNNING", // 请求长时任务的权限
"reason": "$string:hello_webabcd", // 申请此权限的原因
"usedScene": {
"abilities": [ ],
"when": "always" // inuse(使用时允许使用此权限),always(始终允许使用此权限)
}
},
{
"name": "ohos.permission.PUBLISH_AGENT_REMINDER", // 请求提醒任务的权限
"reason": "$string:hello_webabcd", // 申请此权限的原因
"usedScene": {
"abilities": [ ],
"when": "always" // inuse(使用时允许使用此权限),always(始终允许使用此权限)
}
}
]
}
}
\entry\src\main\ets\entryability\EntryAbility.ets
/*
* UIAbility - 用于为应用提供绘制界面的窗口
* UIAbility 的相关配置,请参见 module.json5 配置文件中的 abilities 标签
*/
import { AbilityConstant, Configuration, UIAbility, Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { MyLog } from '../utils/MyLog';
export default class EntryAbility extends UIAbility {
// UIAbility 实例创建完成时(冷启动)
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
MyLog.d('ability onCreate');
}
// 当 UIAbility 已经启动了,之后再次启动时(热启动)
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
MyLog.d(`ability onNewWant, parameters:${JSON.stringify((want.parameters))}`);
}
// UIAbility 实例销毁时
onDestroy(): void {
MyLog.d('ability onDestroy');
}
// UIAbility 的窗口创建完成时
// 在这里需要通过 windowStage.loadContent() 加载当前 UIAbility 的首页
onWindowStageCreate(windowStage: window.WindowStage): void {
MyLog.d('ability onWindowStageCreate');
let record: Record<string, number> = {
'myNumber': 5000
};
let storage: LocalStorage = new LocalStorage(record);
// 加载当前 UIAbility 的首页
// 必须是 @Entry 组件
// 必须在 main_pages.json 文件(在 module.json5 中通过 "pages":"$profile:main_pages" 指定的)中声明
// 这里指定的 LocalStorage 对象的数据,会自动合并到当前 UIAbility 的 LocalStorage.getShared() 中
windowStage.loadContent('pages/Index', storage, (err) => {
if (err.code) {
MyLog.d(`windowStage.loadContent() failed, ${JSON.stringify(err)}`)
return;
}
MyLog.d(`windowStage.loadContent() succeeded`)
});
}
// UIAbility 的窗口销毁之前
onWindowStageWillDestroy(windowStage: window.WindowStage) {
MyLog.d('ability onWindowStageWillDestroy');
}
// UIAbility 的窗口销毁时
onWindowStageDestroy(): void {
MyLog.d('ability onWindowStageDestroy');
}
// 切换到前台时
onForeground(): void {
MyLog.d('ability onForeground');
}
// 切换到后台时
onBackground(): void {
MyLog.d('ability onBackground');
}
// 内存占用级别发生变化时的回调
// 注:在 AbilityStage 中也有此回调
onMemoryLevel(level: AbilityConstant.MemoryLevel): void {
// MEMORY_LEVEL_MODERATE - 内存占用适中
// MEMORY_LEVEL_LOW - 内存占用低
// MEMORY_LEVEL_CRITICAL - 内存占用高
MyLog.d(`ability onMemoryLevel ${level}`);
}
// 全局的环境配置发生变化时的回调(比如系统语言,深色浅色模式等)
// 注:在 AbilityStage 中也有此回调
onConfigurationUpdate(newConfig: Configuration): void {
MyLog.d(`ability onConfigurationUpdate ${JSON.stringify(newConfig)}`);
}
}
\entry\src\main\ets\entryability\EntryAbility2.ets
/*
* UIAbility - 用于为应用提供绘制界面的窗口
* UIAbility 的相关配置,请参见 module.json5 配置文件中的 abilities 标签
*/
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { MyLog } from '../utils/MyLog';
export default class EntryAbility2 extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
MyLog.d(`ability onCreate, parameters:${JSON.stringify((want.parameters))}`);
/*
* context.eventHub - 用于在当前 UIAbility 内做事件的发布和订阅
* emit() - 发布指定的事件,允许传递多个参数
*/
setInterval(() => {
this.context.eventHub.emit("my_event", "timestamp", new Date().getTime())
}, 1000)
}
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
MyLog.d(`ability onNewWant, parameters:${JSON.stringify((want.parameters))}`);
}
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.loadContent('pages/basic/UIAbilityDemo2');
}
}
\entry\src\main\ets\pages\basic\UIAbilityDemo2.ets
/*
* UIAbility - 用于为应用提供绘制界面的窗口
*
* 本例演示了如何获取上下文对象,如何返回数据给父 UIAbility,如何在一个 UIAbility 内做事件的发布和订阅
* 本页面所属的 UIAbility 请参见 /entry/src/main/ets/entryability/EntryAbility2.ets 中的代码
*/
import { MyLog, TitleBar } from '../TitleBar';
import { common } from '@kit.AbilityKit';
@Entry
@Component
struct UIAbilityDemo2 {
build() {
Column() {
TitleBar()
Tabs() {
TabContent() { MySample1() }.tabBar('基础').align(Alignment.Top)
}
.scrollable(true)
.barMode(BarMode.Scrollable)
.layoutWeight(1)
}
}
}
@Component
struct MySample1 {
@State message: string = ""
/*
* getContext(this) - 获取上下文对象
*/
context = getContext(this) as common.UIAbilityContext;
aboutToAppear(): void {
/*
* context.eventHub - 用于在当前 UIAbility 内做事件的发布和订阅
* on() - 订阅指定的事件,并接收发布事件时的参数
* off() - 取消订阅指定的事件
*/
this.context.eventHub.on('my_event', (p1: string, p2: number) => {
this.message = `监听到 my_event 事件 ${p1} ${p2}`
});
}
aboutToDisappear(): void {
this.context.eventHub.off('my_event');
}
build() {
Column({ space: 10 }) {
Text(this.message)
Button("杀死当前 UIAbility").onClick(() => {
/*
* getContext(this) - 获取上下文对象
* UIAbilityContext - 上下文对象
* terminateSelf() - 杀死当前 UIAbility
*
* 注:
* 当调用 terminateSelf() 杀死当前 UIAbility 后,在最近任务列表中仍会保留其快照
* 如果不需要这个快照,则需要将 module.json5 中的 abilities 的 removeMissionAfterTerminate 设置为 true
*/
this.context.terminateSelf()
})
Button("杀死全部 UIAbility").onClick(() => {
/*
* ApplicationContext - 应用级上下文对象
* killAllProcesses() - 杀死全部 UIAbility
* 注:杀死全部后,如果某个 UIAbility 不需要在最近任务列表中显示一个快照,则需要将 module.json5 中的 abilities 的 removeMissionAfterTerminate 设置为 true
*/
this.context.getApplicationContext().killAllProcesses()
})
Button("杀死当前 UIAbility 并返回结果给父 UIAbility").onClick(() => {
/*
* context.terminateSelfWithResult() - 杀死当前 UIAbility 并将指定的 AbilityResult 对象返回给父 UIAbility
* AbilityResult - 返回给父 UIAbility 的对象
* resultCode - 需要返回的 code
* want - 父 ability 的相关信息
* parameters - 需要返回的数据
*/
let abilityResult: common.AbilityResult = {
resultCode: 123,
want: {
bundleName: 'com.webabcd.harmonydemo', // 父 ability 的 bundle 的名称
abilityName: 'com.webabcd.harmonydemo.EntryAbility', // 父 ability 的名称
parameters: { // 传参
'k3': 'v3',
'k4': 'v4',
}
},
};
this.context.terminateSelfWithResult(abilityResult, (err) => {
MyLog.d(`terminateSelfWithResult failed, ${JSON.stringify(err)}`)
});
})
}
}
}