开天辟地 HarmonyOS(鸿蒙) - 开发基础: UIAbility

源码 https://github.com/webabcd/HarmonyDemo
作者 webabcd

开天辟地 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)}`)
        });
      })
    }
  }
}

源码 https://github.com/webabcd/HarmonyDemo
作者 webabcd

posted @ 2025-03-07 15:25  webabcd  阅读(97)  评论(0)    收藏  举报