开天辟地 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
         */
        let context = getContext(this) as common.UIAbilityContext;
        context.terminateSelf()
      })

      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/entryability/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",
    "abilities": [
      {
        "name": "com.webabcd.harmonydemo.EntryAbility", // 当前 ability 的名称(自定义标识)
        "srcEntry": "./ets/entryability/EntryAbility.ets", // 当前 ability 的代码的地址
        "description": "$string:EntryAbility_desc", // 描述
        "icon": "$media:layered_image", // 图标(入口 ability 的图标就是 app 的图标)
        "label": "$string:EntryAbility_label", // 标题(入口 ability 的标题就是 app 的标题)
        "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", // 蓝牙传输
        ]
      },
      {
        "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');
  }

  // 内存占用级别发生变化时的回调
  onMemoryLevel(level: AbilityConstant.MemoryLevel): void {
    // MEMORY_LEVEL_MODERATE - 内存占用适中
    // MEMORY_LEVEL_LOW - 内存占用低
    // MEMORY_LEVEL_CRITICAL - 内存占用高
    MyLog.d(`ability onMemoryLevel ${level}`);
  }

  // 全局的环境配置发生变化时的回调(比如系统语言,深色浅色模式等)
  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(() => {
        this.context.terminateSelf()
      })

      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 @   webabcd  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2016-03-07 背水一战 Windows 10 (1) - C# 6.0 新特性
2013-03-07 重新想象 Windows 8 Store Apps (9) - 控件之 ScrollViewer 基础
点击右上角即可分享
微信分享提示