1# 应用上下文Context 2 3 4## 概述 5 6[Context](../reference/apis/js-apis-inner-application-context.md)是应用中对象的上下文,其提供了应用的一些基础信息,例如resourceManager(资源管理)、applicationInfo(当前应用信息)、dir(应用开发路径)、area(文件分区)等,以及应用的一些基本方法,例如createBundleContext()、getApplicationContext()等。UIAbility组件和各种ExtensionAbility派生类组件都有各自不同的Context类。分别有基类Context、ApplicationContext、AbilityStageContext、UIAbilityContext、ExtensionContext、ServiceExtensionContext等Context。 7 8- 各类Context的继承关系 9 ![context-inheritance](figures/context-inheritance.png) 10 11- 各类Context的持有关系 12 ![context-holding](figures/context-holding.png) 13 14- 各类Context的获取方式 15 - 获取[UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md)。每个UIAbility中都包含了一个Context属性,提供操作应用组件、获取应用组件的配置信息等能力。 16 17 ```ts 18 import UIAbility from '@ohos.app.ability.UIAbility'; 19 export default class EntryAbility extends UIAbility { 20 onCreate(want, launchParam) { 21 let uiAbilityContext = this.context; 22 ... 23 } 24 } 25 ``` 26 27 > **说明:** 28 > 29 > 页面中获取UIAbility实例的上下文信息请参见[获取UIAbility的上下文信息](uiability-usage.md#获取uiability的上下文信息)。 30 - 获取特定场景[ExtensionContext](../reference/apis/js-apis-inner-application-extensionContext.md)。以ServiceExtensionContext为例,表示后台服务的上下文环境,继承自ExtensionContext,提供后台服务相关的接口能力。 31 32 ```ts 33 import ServiceExtensionAbility from '@ohos.app.ability.ServiceExtensionAbility'; 34 export default class MyService extends ServiceExtensionAbility { 35 onCreate(want) { 36 let serviceExtensionContext = this.context; 37 ... 38 } 39 } 40 ``` 41 - 获取[AbilityStageContext](../reference/apis/js-apis-inner-application-abilityStageContext.md)。Module级别的Context,和基类Context相比,额外提供HapModuleInfo、Configuration等信息。 42 43 ```ts 44 import AbilityStage from '@ohos.app.ability.AbilityStage'; 45 export default class MyAbilityStage extends AbilityStage { 46 onCreate() { 47 let abilityStageContext = this.context; 48 ... 49 } 50 } 51 ``` 52 - 获取[ApplicationContext](../reference/apis/js-apis-inner-application-applicationContext.md)。应用级别的Context。ApplicationContext在基类Context的基础上提供了订阅应用内应用组件的生命周期的变化、订阅系统内存变化和订阅应用内系统环境的变化的能力,在UIAbility、ExtensionAbility、AbilityStage中均可以获取。 53 54 ```ts 55 import UIAbility from '@ohos.app.ability.UIAbility'; 56 export default class EntryAbility extends UIAbility { 57 onCreate(want, launchParam) { 58 let applicationContext = this.context.getApplicationContext(); 59 ... 60 } 61 } 62 ``` 63 64 65## Context的典型使用场景 66 67 68本章节通过如下典型场景来介绍Context的用法: 69 70 71- [获取应用开发路径](#获取应用开发路径) 72- [获取和修改加密分区](#获取和修改加密分区) 73- [创建其他应用或其他Module的Context](#创建其他应用或其他module的context) 74- [订阅进程内UIAbility生命周期变化](#订阅进程内uiability生命周期变化) 75 76 77### 获取应用开发路径 78 79从Context中获取的应用开发路径如下表所示。 80 81**表1** 应用开发路径说明 82 83| 属性名称 | 参数类型 | 可读 | 可写 | 说明 | 84| -------- | -------- | -------- | -------- | -------- | 85| bundleCodeDir | string | 是 | 否 | 安装文件路径。应用在内部存储上的安装路径。 | 86| cacheDir | string | 是 | 否 | 缓存文件路径。应用在内部存储上的缓存路径。<br/>对应于“设置 > 应用管理”,找到对应应用的“存储”中的缓存内容。 | 87| filesDir | string | 是 | 否 | 通用文件路径。应用在内部存储上的文件路径。<br/>本目录下存放的文件可能会被应用迁移或者备份的时候同步到其他目录中。 | 88| preferencesDir | string | 是 | 是 | 首选项文件路径。指示应用程序首选项目录。 | 89| tempDir | string | 是 | 否 | 临时文件路径。<br/>在应用卸载后,系统会删除存储在此目录中的文件。 | 90| databaseDir | string | 是 | 否 | 数据库路径。获取本地数据库存储路径。 | 91| distributedFilesDir | string | 是 | 否 | 分布式文件路径。 | 92 93获取路径的能力是基类Context中提供的能力,因此在ApplicationContext、AbilityStageContext、UIAbilityContext和ExtensionContext中均可以获取,在各类Context中获取到的路径会有一些差别,具体差别如下图所示。 94 95**图1** Context中获取的应用开发路径 96![context-dir](figures/context-dir.png) 97 98- 通过ApplicationContext获取的应用级别路径。应用全局信息建议存放的路径,存放在此路径的文件内容仅在应用卸载时会被删除。 99 | 属性 | 路径 | 100 | -------- | -------- | 101 | bundleCodeDir | {路径前缀}/el1/bundle/ | 102 | cacheDir | {路径前缀}/{加密等级}/base/cache/ | 103 | filesDir | {路径前缀}/{加密等级}/base/files/ | 104 | preferencesDir | {路径前缀}/{加密等级}/base/preferences/ | 105 | tempDir | {路径前缀}/{加密等级}/base/temp/ | 106 | databaseDir | {路径前缀}/{加密等级}/database/ | 107 | distributedFilesDir | {路径前缀}/el2/distributedFiles/ | 108 109- 通过AbilityStageContext、UIAbilityContext、ExtensionContext获取的HAP级别路径。HAP对应的信息建议存放的路径,存放在此路径的文件内容会跟随HAP的卸载而删除,不会影响应用级别路径的文件内容,除非该应用的HAP已全部卸载。 110 | 属性 | 路径 | 111 | -------- | -------- | 112 | bundleCodeDir | {路径前缀}/el1/bundle/ | 113 | cacheDir | {路径前缀}/{加密等级}/base/**haps/{moduleName}**/cache/ | 114 | filesDir | {路径前缀}/{加密等级}/base/**haps/{moduleName}**/files/ | 115 | preferencesDir | {路径前缀}/{加密等级}/base/**haps/{moduleName}**/preferences/ | 116 | tempDir | {路径前缀}/{加密等级}/base/**haps/{moduleName}**/temp/ | 117 | databaseDir | {路径前缀}/{加密等级}/database/**{moduleName}**/ | 118 | distributedFilesDir | {路径前缀}/el2/distributedFiles/**{moduleName}**/ | 119 120获取应用开发路径的示例代码如下所示。 121 122 123```ts 124import UIAbility from '@ohos.app.ability.UIAbility'; 125 126export default class EntryAbility extends UIAbility { 127 onCreate(want, launchParam) { 128 let cacheDir = this.context.cacheDir; 129 let tempDir = this.context.tempDir; 130 let filesDir = this.context.filesDir; 131 let databaseDir = this.context.databaseDir; 132 let bundleCodeDir = this.context.bundleCodeDir; 133 let distributedFilesDir = this.context.distributedFilesDir; 134 let preferencesDir = this.context.preferencesDir; 135 ... 136 } 137} 138``` 139 140> **说明:** 141> 142> 示例代码获取到的是应用开发路径的沙箱路径。其对应的绝对路径,在创建或者修改文件之后,可以在`hdc shell`中,通过`find / -name <文件名称>`命令查找获取。 143 144### 获取和修改加密分区 145 146应用文件加密是一种保护数据安全的方法,可以使得文件在未经授权访问的情况下得到保护。在不同的场景下,应用需要不同程度的文件保护。对于私有文件,如闹铃、壁纸等,应用需要将这些文件放到设备级加密分区(EL1)中,以保证在用户输入密码前就可以被访问;对于更敏感的文件,如个人隐私信息等,应用需要将这些文件放到更高级别的加密分区(EL2)中,以保证更高的安全性。 147 148在实际应用中,开发者需要根据不同场景的需求选择合适的加密分区,从而保护应用数据的安全。通过合理使用EL1和EL2加密分区,可以有效提高应用数据的安全性。 149 150> **说明:** 151> 152> - AreaMode.EL1:设备级加密区,设备开机后可访问的数据区。 153> 154> - AreaMode.EL2:用户级加密区,设备开机,首次输入密码后才能够访问的数据区。 155 156要实现获取和设置当前加密分区,可以通过读写[Context的area属性](../reference/apis/js-apis-inner-application-context.md)来实现。 157 158```ts 159import UIAbility from '@ohos.app.ability.UIAbility'; 160 161export default class EntryAbility extends UIAbility { 162 onCreate(want, launchParam) { 163 // 存储普通信息前,切换到EL1设备机加密 164 if (this.context.area === 1) { // 获取area 165 this.context.area = 0; // 修改area 166 } 167 // 存储普通信息 168 169 // 存储敏感信息前,切换到EL2用户级加密 170 if (this.context.area === 0) { // 获取area 171 this.context.area = 1; // 修改area 172 } 173 // 存储敏感信息 174 } 175} 176``` 177 178 179### 创建其他应用或其他Module的Context 180 181基类Context提供创建其他应用或其他Module的Context的方法有[createBundleContext(bundleName: string)](../reference/apis/js-apis-inner-application-context.md#contextcreatebundlecontext)、[createModuleContext(moduleName: string)](../reference/apis/js-apis-inner-application-context.md#contextcreatemodulecontext)和[createModuleContext(bundleName: string, moduleName: string)](../reference/apis/js-apis-inner-application-context.md#contextcreatemodulecontext-1)接口,创建其他应用或者其他Module的Context,从而通过该Context获取相应的资源信息(例如获取其他Module的[获取应用开发路径](#获取应用开发路径)信息)。 182 183- 调用createBundleContext(bundleName:string)方法,创建其他应用的Context信息。 184 > **说明:** 185 > 当获取的是其他应用的Context时: 186 > 187 > - 申请`ohos.permission.GET_BUNDLE_INFO_PRIVILEGED`权限,配置方式请参见[访问控制授权申请](../security/accesstoken-guidelines.md#配置文件权限声明)。 188 > 189 > - 接口为系统接口,三方应用不支持调用。 190 191 例如在桌面上显示的应用信息,包括应用名称和应用图标等,桌面应用可以通过调用上述的方法获取相应应用的Context信息从而获取到相应的应用名称、图标等资源信息。 192 193 ```ts 194 import UIAbility from '@ohos.app.ability.UIAbility'; 195 196 export default class EntryAbility extends UIAbility { 197 onCreate(want, launchParam) { 198 let bundleName2 = 'com.example.application'; 199 let context2 = this.context.createBundleContext(bundleName2); 200 let label2 = context2.applicationInfo.label; 201 ... 202 } 203 } 204 ``` 205 206- 调用createModuleContext(bundleName:string, moduleName:string)方法,获取指定应用指定Module的上下文信息。获取到指定应用指定Module的Context之后,即可获取到相应应用Module的资源信息。 207 > **说明:** 208 > 209 > 当获取的是其他应用的指定Module的Context时: 210 > 211 > - 申请`ohos.permission.GET_BUNDLE_INFO_PRIVILEGED`权限,配置方式请参见[配置文件权限声明](../security/accesstoken-guidelines.md#配置文件权限声明)。 212 > 213 > - 接口为系统接口,三方应用不支持调用。 214 215 ```ts 216 import UIAbility from '@ohos.app.ability.UIAbility'; 217 218 export default class EntryAbility extends UIAbility { 219 onCreate(want, launchParam) { 220 let bundleName2 = 'com.example.application'; 221 let moduleName2 = 'module1'; 222 let context2 = this.context.createModuleContext(bundleName2, moduleName2); 223 ... 224 } 225 } 226 ``` 227 228- 调用createModuleContext(moduleName:string)方法,获取本应用中其他Module的Context。获取到其他Module的Context之后,即可获取到相应Module的资源信息。 229 230 ```ts 231 import UIAbility from '@ohos.app.ability.UIAbility'; 232 233 export default class EntryAbility extends UIAbility { 234 onCreate(want, launchParam) { 235 let moduleName2 = 'module1'; 236 let context2 = this.context.createModuleContext(moduleName2); 237 ... 238 } 239 } 240 ``` 241 242 243### 订阅进程内UIAbility生命周期变化 244 245在应用内的DFX统计场景中,如需要统计对应页面停留时间和访问频率等信息,可以使用订阅进程内UIAbility生命周期变化功能。 246 247通过[ApplicationContext](../reference/apis/js-apis-inner-application-applicationContext.md)提供的能力,可以订阅进程内UIAbility生命周期变化。当进程内的UIAbility生命周期变化时,如创建、可见/不可见、获焦/失焦、销毁等,会触发相应的回调函数。每次注册回调函数时,都会返回一个监听生命周期的ID,此ID会自增+1。当超过监听上限数量2^63-1时,会返回-1。以[UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md)中的使用为例进行说明。 248 249 250```ts 251import UIAbility from '@ohos.app.ability.UIAbility'; 252import window from '@ohos.window'; 253 254const TAG: string = '[Example].[Entry].[EntryAbility]'; 255 256export default class EntryAbility extends UIAbility { 257 // 定义生命周期ID 258 lifecycleId: number; 259 260 onCreate(want, launchParam) { 261 // 定义生命周期回调对象 262 let abilityLifecycleCallback = { 263 // 当UIAbility创建时被调用 264 onAbilityCreate(uiAbility) { 265 console.info(TAG, `onAbilityCreate uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); 266 }, 267 // 当窗口创建时被调用 268 onWindowStageCreate(uiAbility, windowStage: window.WindowStage) { 269 console.info(TAG, `onWindowStageCreate uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); 270 console.info(TAG, `onWindowStageCreate windowStage: ${JSON.stringify(windowStage)}`); 271 }, 272 // 当窗口处于活动状态时被调用 273 onWindowStageActive(uiAbility, windowStage: window.WindowStage) { 274 console.info(TAG, `onWindowStageActive uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); 275 console.info(TAG, `onWindowStageActive windowStage: ${JSON.stringify(windowStage)}`); 276 }, 277 // 当窗口处于非活动状态时被调用 278 onWindowStageInactive(uiAbility, windowStage: window.WindowStage) { 279 console.info(TAG, `onWindowStageInactive uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); 280 console.info(TAG, `onWindowStageInactive windowStage: ${JSON.stringify(windowStage)}`); 281 }, 282 // 当窗口被销毁时被调用 283 onWindowStageDestroy(uiAbility, windowStage: window.WindowStage) { 284 console.info(TAG, `onWindowStageDestroy uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); 285 console.info(TAG, `onWindowStageDestroy windowStage: ${JSON.stringify(windowStage)}`); 286 }, 287 // 当UIAbility被销毁时被调用 288 onAbilityDestroy(uiAbility) { 289 console.info(TAG, `onAbilityDestroy uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); 290 }, 291 // 当UIAbility从后台转到前台时触发回调 292 onAbilityForeground(uiAbility) { 293 console.info(TAG, `onAbilityForeground uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); 294 }, 295 // 当UIAbility从前台转到后台时触发回调 296 onAbilityBackground(uiAbility) { 297 console.info(TAG, `onAbilityBackground uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); 298 }, 299 // 当UIAbility迁移时被调用 300 onAbilityContinue(uiAbility) { 301 console.info(TAG, `onAbilityContinue uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); 302 } 303 } 304 // 获取应用上下文 305 let applicationContext = this.context.getApplicationContext(); 306 // 注册应用内生命周期回调 307 this.lifecycleId = applicationContext.on('abilityLifecycle', abilityLifecycleCallback); 308 console.info(TAG, `register callback number: ${this.lifecycleId}`); 309 } 310 311 ... 312 313 onDestroy() { 314 // 获取应用上下文 315 let applicationContext = this.context.getApplicationContext(); 316 // 取消应用内生命周期回调 317 applicationContext.off('abilityLifecycle', this.lifecycleId); 318 } 319} 320``` 321