HarmonyOS 应用开发之应用上下文Context

概述

Context 是应用中对象的上下文,其提供了应用的一些基础信息,例如resourceManager(资源管理)、applicationInfo(当前应用信息)、dir(应用文件路径)、area(文件分区)等,以及应用的一些基本方法,例如createBundleContext()、getApplicationContext()等。UIAbility组件和各种ExtensionAbility派生类组件都有各自不同的Context类。分别有基类Context、ApplicationContext、AbilityStageContext、UIAbilityContext、ExtensionContext、ServiceExtensionContext等Context。

  • 各类Context的继承关系
  • 各类Context的持有关系
  • 各类Context的获取方式

    • 获取 UIAbilityContext 。每个UIAbility中都包含了一个Context属性,提供操作应用组件、获取应用组件的配置信息等能力。

      import UIAbility from '@ohos.app.ability.UIAbility';
      import type AbilityConstant from '@ohos.app.ability.AbilityConstant';
      import type Want from '@ohos.app.ability.Want';
      export default class EntryAbility extends UIAbility {
      onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
      let uiAbilityContext = this.context;
      ...
      }
      }

说明:

页面中获取UIAbility实例的上下文信息请参见 获取UIAbility的上下文信息。

*   获取特定场景 ExtensionContext 。以ServiceExtensionContext为例,表示后台服务的上下文环境,继承自ExtensionContext,提供后台服务相关的接口能力。

import ServiceExtensionAbility from '@ohos.app.ability.ServiceExtensionAbility';
import Want from '@ohos.app.ability.Want';
export default class MyService extends ServiceExtensionAbility {
  onCreate(want: Want) {
    let serviceExtensionContext = this.context;
    ...
  }
}

*   获取 AbilityStageContext 。Module级别的Context,和基类Context相比,额外提供HapModuleInfo、Configuration等信息。

import AbilityStage from '@ohos.app.ability.AbilityStage';
export default class MyAbilityStage extends AbilityStage {
  onCreate(): void {
    let abilityStageContext = this.context;
    ...
  }
}

*   获取 ApplicationContext 。应用级别的Context。ApplicationContext在基类Context的基础上提供了订阅应用内应用组件的生命周期的变化、订阅系统内存变化和订阅应用内系统环境的变化的能力,在UIAbility、ExtensionAbility、AbilityStage中均可以获取。

import UIAbility from '@ohos.app.ability.UIAbility';
import type AbilityConstant from '@ohos.app.ability.AbilityConstant';
import type Want from '@ohos.app.ability.Want';
export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    let applicationContext = this.context.getApplicationContext();
    ...
  }
}

Context的典型使用场景

本章节通过如下典型场景来介绍Context的用法:

  • 获取应用文件路径
  • 获取和修改加密分区
  • 创建其他应用或其他Module的Context
  • 订阅进程内UIAbility生命周期变化

获取应用文件路径

基类Context 提供了获取应用文件路径的能力,ApplicationContext、AbilityStageContext、UIAbilityContext和ExtensionContext均继承该能力。应用文件路径属于应用沙箱路径,具体请参见 应用沙箱目录 。

上述各类Context获取的应用文件路径有所不同。

  • 通过ApplicationContext获取应用级别的应用文件路径,此路径是应用全局信息推荐的存放路径,这些文件会跟随应用的卸载而删除。

    属性 路径
    bundleCodeDir <路径前缀>/el1/bundle
    cacheDir <路径前缀>/<加密等级>/base/cache
    filesDir <路径前缀>/<加密等级>/base/files
    preferencesDir <路径前缀>/<加密等级>/base/preferences
    tempDir <路径前缀>/<加密等级>/base/temp
    databaseDir <路径前缀>/<加密等级>/database
    distributedFilesDir <路径前缀>/el2/distributedFiles

    示例代码如下所示。

    import common from '@ohos.app.ability.common';
    import hilog from '@ohos.hilog';
    import promptAction from '@ohos.promptAction';

    const TAG: string = '[Page_Context]';
    const DOMAIN_NUMBER: number = 0xFF00;
    @Entry
    @Component
    struct Page_Context {

    private context = getContext(this) as common.UIAbilityContext;
    
    build() {
      ...
      Button()
        .onClick(() => {
          let applicationContext = this.context.getApplicationContext();
          let cacheDir = applicationContext.cacheDir;
          let tempDir = applicationContext.tempDir;
          let filesDir = applicationContext.filesDir;
          let databaseDir = applicationContext.databaseDir;
          let bundleCodeDir = applicationContext.bundleCodeDir;
          let distributedFilesDir = applicationContext.distributedFilesDir;
          let preferencesDir = applicationContext.preferencesDir;
          // 获取应用文件路径
          let filePath = tempDir + 'test.txt';
          hilog.info(DOMAIN_NUMBER, TAG, `filePath: ${filePath}`);
          if (filePath !== null) {
            promptAction.showToast({
            message: filePath
            });
          }
        })
    }
    

    }

  • 通过AbilityStageContext、UIAbilityContext、ExtensionContext获取HAP级别的应用文件路径。此路径是HAP相关信息推荐的存放路径,这些文件会跟随HAP的卸载而删除,但不会影响应用级别路径的文件,除非该应用的HAP已全部卸载。

    属性 路径
    bundleCodeDir <路径前缀>/el1/bundle
    cacheDir <路径前缀>/<加密等级>/base/haps//cache
    filesDir <路径前缀>/<加密等级>/base/haps//files
    preferencesDir <路径前缀>/<加密等级>/base/haps//preferences
    tempDir <路径前缀>/<加密等级>/base/haps//temp
    databaseDir <路径前缀>/<加密等级>/database/
    distributedFilesDir <路径前缀>/el2/distributedFiles/

示例代码如下所示。

import common from '@ohos.app.ability.common';
import hilog from '@ohos.hilog';
import promptAction from '@ohos.promptAction';

const TAG: string = '[Page_Context]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_Context {

  private context = getContext(this) as common.UIAbilityContext;

  build() {
    ...
    Button()
      .onClick(() => {
        let cacheDir = this.context.cacheDir;
        let tempDir = this.context.tempDir;
        let filesDir = this.context.filesDir;
        let databaseDir = this.context.databaseDir;
        let bundleCodeDir = this.context.bundleCodeDir;
        let distributedFilesDir = this.context.distributedFilesDir;
        let preferencesDir = this.context.preferencesDir;
        // 获取应用文件路径
        let filePath = tempDir + 'test.txt';
        hilog.info(DOMAIN_NUMBER, TAG, `filePath: ${filePath}`);
        if (filePath !== null) {
          promptAction.showToast({
            message: filePath
          });
        }
      })
  }
}

获取和修改加密分区

应用文件加密是一种保护数据安全的方法,可以使得文件在未经授权访问的情况下得到保护。在不同的场景下,应用需要不同程度的文件保护。

在实际应用中,开发者需要根据不同场景的需求选择合适的加密分区,从而保护应用数据的安全。通过合理使用不同级别的加密分区,可以有效提高应用数据的安全性。关于不同分区的权限说明。

  • EL1:对于私有文件,如闹铃、壁纸等,应用可以将这些文件放到设备级加密分区(EL1)中,以保证在用户输入密码前就可以被访问。
  • EL2:对于更敏感的文件,如个人隐私信息等,应用可以将这些文件放到更高级别的加密分区(EL2)中,以保证更高的安全性。
  • EL3:对于应用中的记录步数、文件下载、音乐播放,需要在锁屏时读写和创建新文件,放在(EL3)的加密分区比较合适。
  • EL4:对于用户安全信息相关的文件,锁屏时不需要读写文件、也不能创建文件,放在(EL4)的加密分区更合适。

要实现获取和设置当前加密分区,可以通过读写Contextarea属性来实现。

import UIAbility from '@ohos.app.ability.UIAbility';
import contextConstant from '@ohos.app.ability.contextConstant';
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import Want from '@ohos.app.ability.Want';

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
    // 存储普通信息前,切换到EL1设备级加密
    this.context.area = contextConstant.AreaMode.EL1; // 切换area
    // 存储普通信息

    // 存储敏感信息前,切换到EL2用户级加密
    this.context.area = contextConstant.AreaMode.EL2; // 切换area
    // 存储敏感信息

    // 存储敏感信息前,切换到EL3用户级加密
    this.context.area = contextConstant.AreaMode.EL3; // 切换area
    // 存储敏感信息

    // 存储敏感信息前,切换到EL4用户级加密
    this.context.area = contextConstant.AreaMode.EL4; // 切换area
    // 存储敏感信息
  }
}

import contextConstant from '@ohos.app.ability.contextConstant';
import common from '@ohos.app.ability.common';
import promptAction from '@ohos.promptAction';

@Entry
@Component
struct Page_Context {

  private context = getContext(this) as common.UIAbilityContext;

  build() {
    ...
    Button()
      .onClick(() => {
        // 存储普通信息前,切换到EL1设备级加密
        if (this.context.area === contextConstant.AreaMode.EL2) { // 获取area
          this.context.area = contextConstant.AreaMode.EL1; // 修改area
          promptAction.showToast({
            message: $r('app.string.SwitchToEL1')
          });
        }
        // 存储普通信息
      })
    
    ...

    Button()
      .onClick(() => {
        // 存储敏感信息前,切换到EL2用户级加密
        if (this.context.area === contextConstant.AreaMode.EL1) { // 获取area
          this.context.area = contextConstant.AreaMode.EL2; // 修改area
          promptAction.showToast({
            message: $r('app.string.SwitchToEL2')
          });
        }
        // 存储敏感信息
      })
    
    ...
  }
}

创建其他应用或其他Module的Context

基类Context提供创建其他应用或其他Module的Context的方法有 createBundleContext(bundleName: string) 、createModuleContext(moduleName: string) 和createModuleContext(bundleName: string, moduleName: string)接口,创建其他应用或者其他Module的Context,从而通过该Context获取相应的资源信息(例如获取其他Module的 获取应用文件路径信息)。

  • 调用createBundleContext(bundleName:string)方法,创建其他应用的Context信息。

说明:

当获取的是其他应用的Context时:

  • 申请ohos.permission.GET_BUNDLE_INFO_PRIVILEGED权限,配置方式请参见 申请应用权限 。
  • 接口为系统接口,三方应用不支持调用。

例如在桌面上显示的应用信息,包括应用名称和应用图标等,桌面应用可以通过调用上述的方法获取相应应用的Context信息从而获取到相应的应用名称、图标等资源信息。

import promptAction from '@ohos.promptAction';
import common from '@ohos.app.ability.common';

let storageEventCall = new LocalStorage();

@Entry(storageEventCall)
@Component
struct Page_ContextAbility {
  private context = getContext(this) as common.UIAbilityContext;
  build() {
    Button()
      .onClick(() => {
        let bundleName2: string = 'com.samples.stagemodelabilityinteraction';
        let bundleContext: Context = this.context.createBundleContext(bundleName2);
        let label2: string = bundleContext.applicationInfo.label;
        if (bundleContext && label2 !== null) {
          promptAction.showToast({
            message: ('成功获取Context')
          });
        }
      })
  }
}
  • 调用createModuleContext(bundleName:string, moduleName:string)方法,获取指定应用指定Module的上下文信息。获取到指定应用指定Module的Context之后,即可获取到相应应用Module的资源信息。

说明:

当获取的是其他应用的指定Module的Context时:

  • 申请ohos.permission.GET_BUNDLE_INFO_PRIVILEGED权限,配置方式请参见 申请应用权限 。

  • 接口为系统接口,三方应用不支持调用。

    import promptAction from '@ohos.promptAction';
    import common from '@ohos.app.ability.common';

    let storageEventCall = new LocalStorage();

    @Entry(storageEventCall)
    @Component
    struct Page_ContextAbility {
    private context = getContext(this) as common.UIAbilityContext;
    build() {
    Button()
    .onClick(() => {
    let bundleName2: string = 'com.samples.stagemodelabilityinteraction';
    let moduleName2: string = 'entry';
    let moduleContext = this.context.createModuleContext(bundleName2, moduleName2);
    if (moduleContext !== null) {
    promptAction.showToast({
    message: ('成功获取Context')
    });
    }
    })
    }
    }

  • 调用createModuleContext(moduleName:string)方法,获取本应用中其他Module的Context。获取到其他Module的Context之后,即可获取到相应Module的资源信息。

    mport promptAction from '@ohos.promptAction';
    import common from '@ohos.app.ability.common';

    let storageEventCall = new LocalStorage();

    @Entry(storageEventCall)
    @Component
    struct Page_ContextAbility {
    private context = getContext(this) as common.UIAbilityContext;
    build() {
    Button()
    .onClick(() => {
    let moduleName2: string = 'entry';
    let moduleContext: Context = this.context.createModuleContext(moduleName2);
    if (moduleContext !== null) {
    promptAction.showToast({
    message: ('成功获取Context')
    });
    }
    })
    }
    }

订阅进程内UIAbility生命周期变化

在应用内的DFX统计场景中,如需要统计对应页面停留时间和访问频率等信息,可以使用订阅进程内UIAbility生命周期变化功能。

通过 ApplicationContext 提供的能力,可以订阅进程内UIAbility生命周期变化。当进程内的UIAbility生命周期变化时,如创建、可见/不可见、获焦/失焦、销毁等,会触发相应的回调函数。每次注册回调函数时,都会返回一个监听生命周期的ID,此ID会自增+1。当超过监听上限数量2^63-1时,会返回-1。以 UIAbilityContext 中的使用为例进行说明。

import type AbilityConstant from '@ohos.app.ability.AbilityConstant';
import type AbilityLifecycleCallback from '@ohos.app.ability.AbilityLifecycleCallback';
import hilog from '@ohos.hilog';
import UIAbility from '@ohos.app.ability.UIAbility';
import type Want from '@ohos.app.ability.Want';
import type window from '@ohos.window';

const TAG: string = '[LifecycleAbility]';
const DOMAIN_NUMBER: number = 0xFF00;

export default class LifecycleAbility extends UIAbility {
  // 定义生命周期ID
  lifecycleId: number = -1;

  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    // 定义生命周期回调对象
    let abilityLifecycleCallback: AbilityLifecycleCallback = {
      // 当UIAbility创建时被调用
      onAbilityCreate(uiAbility) {
        hilog.info(DOMAIN_NUMBER, TAG, `onAbilityCreate uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
      },
      // 当窗口创建时被调用
      onWindowStageCreate(uiAbility, windowStage: window.WindowStage) {
        hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageCreate uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
        hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageCreate windowStage: ${JSON.stringify(windowStage)}`);
      },
      // 当窗口处于活动状态时被调用
      onWindowStageActive(uiAbility, windowStage: window.WindowStage) {
        hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageActive uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
        hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageActive windowStage: ${JSON.stringify(windowStage)}`);
      },
      // 当窗口处于非活动状态时被调用
      onWindowStageInactive(uiAbility, windowStage: window.WindowStage) {
        hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageInactive uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
        hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageInactive windowStage: ${JSON.stringify(windowStage)}`);
      },
      // 当窗口被销毁时被调用
      onWindowStageDestroy(uiAbility, windowStage: window.WindowStage) {
        hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageDestroy uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
        hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageDestroy windowStage: ${JSON.stringify(windowStage)}`);
      },
      // 当UIAbility被销毁时被调用
      onAbilityDestroy(uiAbility) {
        hilog.info(DOMAIN_NUMBER, TAG, `onAbilityDestroy uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
      },
      // 当UIAbility从后台转到前台时触发回调
      onAbilityForeground(uiAbility) {
        hilog.info(DOMAIN_NUMBER, TAG, `onAbilityForeground uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
      },
      // 当UIAbility从前台转到后台时触发回调
      onAbilityBackground(uiAbility) {
        hilog.info(DOMAIN_NUMBER, TAG, `onAbilityBackground uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
      },
      // 当UIAbility迁移时被调用
      onAbilityContinue(uiAbility) {
        hilog.info(DOMAIN_NUMBER, TAG, `onAbilityContinue uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
      }
    };
    // 获取应用上下文
    let applicationContext = this.context.getApplicationContext();
    // 注册应用内生命周期回调
    this.lifecycleId = applicationContext.on('abilityLifecycle', abilityLifecycleCallback);
    hilog.info(DOMAIN_NUMBER, TAG, `register callback number: ${this.lifecycleId}`);
  }

  ...

  onDestroy() : void {
    // 获取应用上下文
    let applicationContext = this.context.getApplicationContext();
    // 取消应用内生命周期回调
    applicationContext.off('abilityLifecycle', this.lifecycleId);
  }
};

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ......

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ......

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ......

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题

2.性能优化方向

3.架构方向

4.鸿蒙开发系统底层方向

5.鸿蒙音视频开发方向

6.鸿蒙车载开发方向

7.鸿蒙南向开发方向

相关推荐
鲜枣课堂1 小时前
5G-A如何与AI融合发展?华为MBBF2024给出解答
人工智能·5g·华为
似水流年QC1 小时前
初探鸿蒙:从概念到实践
华为·harmonyos
晓源よ1 小时前
huawei初级网络工程师综合实验
华为
申耀的科技观察1 小时前
【观察】华为持续投入开源开放“结硕果”,openEuler走出操作系统“创新路”...
华为·开源
华为云PaaS服务小智1 小时前
华为大咖说 | 浅谈智能运维技术
运维·华为·华为云
悟空码字1 小时前
支付宝与华为终端联手,移动支付即将进入“碰时代”
华为·鸿蒙·支付宝
HMS Core2 小时前
融合虚拟与现实,AR Engine为用户提供沉浸式交互体验
华为·ar·harmonyos
dawn12 小时前
鸿蒙ArkTS中的获取网络数据
华为·harmonyos
桃花键神12 小时前
鸿蒙5.0时代:原生鸿蒙应用市场引领开发者服务新篇章
华为·harmonyos
鸿蒙自习室12 小时前
鸿蒙多线程开发——并发模型对比(Actor与内存共享)
华为·harmonyos