未验证 提交 0b482aed 编写于 作者: O openharmony_ci 提交者: Gitee

!12090 应用模型文档新增

Merge pull request !12090 from zengyawen/master
...@@ -12,9 +12,28 @@ ...@@ -12,9 +12,28 @@
- [使用ArkTS语言开发(FA模型)](quick-start/start-with-ets-fa.md) - [使用ArkTS语言开发(FA模型)](quick-start/start-with-ets-fa.md)
- [使用JS语言开发(FA模型)](quick-start/start-with-js-fa.md) - [使用JS语言开发(FA模型)](quick-start/start-with-js-fa.md)
- 开发基础知识 - 开发基础知识
- [应用包结构说明(FA模型)](quick-start/package-structure.md) - 应用程序包基础知识
- [应用包结构说明(Stage模型)](quick-start/stage-structure.md) - [应用程序包概述](quick-start/application-package-overview.md)
- [SysCap说明](quick-start/syscap.md) - 应用程序包结构
- [Stage模型应用程序包结构](quick-start/application-package-structure-stage.md)
- [FA模型应用程序包结构](quick-start/application-package-structure-fa.md)
- [HAR包结构](quick-start/har-structure.md)
- 应用程序包多HAP机制
- [多HAP机制设计目标](quick-start/multi-hap-objective.md)
- [多HAP构建视图](quick-start/multi-hap-build-view.md)
- [多HAP发布部署流程](quick-start/multi-hap-release-deployment.md)
- [多HAP使用规则](quick-start/multi-hap-rules.md)
- [多HAP运行机制及数据通信方式](quick-start/multi-hap-principles.md)
- [应用程序包安装和卸载流程](quick-start/application-package-install-uninstall.md)
- 应用配置文件(Stage模型)
- [应用配置文件概述(Stage模型)](quick-start/application-configuration-file-overview-stage.md)
- [app.json5配置文件](quick-start/app-configuration-file.md)
- [module.json5配置文件](quick-start/module-configuration-file.md)
- 应用配置文件(FA模型)
- [应用配置文件概述(FA模型)](quick-start/application-configuration-file-overview-fa.md)
- [app对象内部结构](quick-start/app-structure.md)
- [deviceConfig内部结构](quick-start/deviceconfig-structure.md)
- [module对象内部结构](quick-start/module-structure.md)
- [资源分类与访问](quick-start/resource-categories-and-access.md) - [资源分类与访问](quick-start/resource-categories-and-access.md)
- 学习ArkTS语言 - 学习ArkTS语言
- [初识ArkTS语言](quick-start/arkts-get-started.md) - [初识ArkTS语言](quick-start/arkts-get-started.md)
...@@ -28,9 +47,9 @@ ...@@ -28,9 +47,9 @@
- [渲染控制](quick-start/arkts-rendering-control.md) - [渲染控制](quick-start/arkts-rendering-control.md)
- [使用限制与扩展](quick-start/arkts-restrictions-and-extensions.md) - [使用限制与扩展](quick-start/arkts-restrictions-and-extensions.md)
- 开发 - 开发
- [Ability开发](ability/Readme-CN.md) - [应用模型](application-models/Readme-CN.md)
- [UI开发](ui/Readme-CN.md) - [UI开发](ui/Readme-CN.md)
- [公共事件与通知](notification/Readme-CN.md) - [通知](notification/Readme-CN.md)
- [窗口管理](windowmanager/Readme-CN.md) - [窗口管理](windowmanager/Readme-CN.md)
- [WebGL](webgl/Readme-CN.md) - [WebGL](webgl/Readme-CN.md)
- [媒体](media/Readme-CN.md) - [媒体](media/Readme-CN.md)
...@@ -54,11 +73,14 @@ ...@@ -54,11 +73,14 @@
- [示例代码](https://gitee.com/openharmony/applications_app_samples/blob/master/README_zh.md) - [示例代码](https://gitee.com/openharmony/applications_app_samples/blob/master/README_zh.md)
- [Codelabs](https://gitee.com/openharmony/codelabs/blob/master/README.md) - [Codelabs](https://gitee.com/openharmony/codelabs/blob/master/README.md)
- API参考 - API参考
- [系统能力SystemCapability使用指南](reference/syscap.md)
- [系统能力SystemCapability列表](reference/syscap-list.md)
- [组件参考(基于TS扩展的声明式开发范式)](reference/arkui-ts/Readme-CN.md) - [组件参考(基于TS扩展的声明式开发范式)](reference/arkui-ts/Readme-CN.md)
- [组件参考(基于JS扩展的类Web开发范式)](reference/arkui-js/Readme-CN.md) - [组件参考(基于JS扩展的类Web开发范式)](reference/arkui-js/Readme-CN.md)
- [JS服务卡片UI组件参考](reference/js-service-widget-ui/Readme-CN.md) - [JS服务卡片UI组件参考](reference/js-service-widget-ui/Readme-CN.md)
- 接口 - 接口
- [JS及TS API参考](reference/apis/Readme-CN.md) - [ArkTS及JS API参考](reference/apis/Readme-CN.md)
- [错误码参考](reference/errorcodes/Readme-CN.md)
- Native API - Native API
- [Native API参考](reference/native-apis/Readme-CN.md) - [Native API参考](reference/native-apis/Readme-CN.md)
- [标准库](reference/native-lib/third_party_libc/musl.md) - [标准库](reference/native-lib/third_party_libc/musl.md)
......
...@@ -18,13 +18,13 @@ ...@@ -18,13 +18,13 @@
首先,提供了支撑OpenHarmony应用的两个重要框架: 首先,提供了支撑OpenHarmony应用的两个重要框架:
- 应用程序的框架:[Ability开发](ability/Readme-CN.md) - 应用程序的框架:[应用模型](application-models/Readme-CN.md)
- UI的框架:[UI开发](ui/Readme-CN.md) - UI的框架:[UI开发](ui/Readme-CN.md)
所有应用都应该在这两个框架的基础之上进行功能的开发。 所有应用都应该在这两个框架的基础之上进行功能的开发。
在此基础上,还提供了如下功能的开发指导: 在此基础上,还提供了如下功能的开发指导:
- [公共事件与通知](notification/Readme-CN.md) - [通知](notification/Readme-CN.md)
- [窗口管理](windowmanager/Readme-CN.md) - [窗口管理](windowmanager/Readme-CN.md)
- [WebGL](webgl/Readme-CN.md) - [WebGL](webgl/Readme-CN.md)
- [媒体](media/Readme-CN.md) - [媒体](media/Readme-CN.md)
......
...@@ -18,13 +18,13 @@ ...@@ -18,13 +18,13 @@
首先,提供了支撑OpenHarmony应用的两个重要框架: 首先,提供了支撑OpenHarmony应用的两个重要框架:
- 应用程序的框架:[Ability开发](ability/fa-brief.md) - 应用程序的框架:[应用模型](application-models/application-model-composition.md)
- UI的框架:[UI开发](ui/arkui-overview.md) - UI的框架:[UI开发](ui/arkui-overview.md)
所有应用都应该在这两个框架的基础之上进行功能的开发。 所有应用都应该在这两个框架的基础之上进行功能的开发。
在此基础上,还提供了如下功能的开发指导: 在此基础上,还提供了如下功能的开发指导:
- [公共事件与通知](notification/notification-brief.md) - [通知](notification/notification-overview.md)
- [窗口管理](windowmanager/window-overview.md) - [窗口管理](windowmanager/window-overview.md)
- [WebGL](webgl/webgl-overview.md) - [WebGL](webgl/webgl-overview.md)
- [媒体](media/audio-overview.md) - [媒体](media/audio-overview.md)
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
- [设备使用信息统计](device-usage-statistics/device-usage-statistics-overview.md) - [设备使用信息统计](device-usage-statistics/device-usage-statistics-overview.md)
- [DFX](dfx/hiappevent-overview.md) - [DFX](dfx/hiappevent-overview.md)
- [国际化](internationalization/international-overview.md) - [国际化](internationalization/international-overview.md)
- [应用测试](application-test/Readme-CN.md) - [应用测试](application-test/arkxtest-guidelines.md)
- [IDL工具规格及使用说明书](IDL/idl-guidelines.md) - [IDL工具规格及使用说明书](IDL/idl-guidelines.md)
- [Native API的相关指导](napi/napi-guidelines.md) - [Native API的相关指导](napi/napi-guidelines.md)
......
# 应用模型
- 应用模型概述
- [OpenHarmony应用模型的构成要素](application-model-composition.md)
- [OpenHarmony应用模型解读](application-model-description.md)
- Stage模型开发指导
- [Stage模型开发概述](stage-model-development-overview.md)
- Stage模型应用组件
- [应用/组件级配置](application-component-configuration-stage.md)
- UIAbility组件
- [UIAbility组件概述](uiability-overview.md)
- [UIAbility组件生命周期](uiability-lifecycle.md)
- [UIAbility组件启动模式](uiability-launch-type.md)
- [UIAbility组件基本用法](uiability-usage.md)
- [UIAbility组件与UI的数据同步](uiability-data-sync-with-ui.md)
- [UIAbility组件间交互(设备内)](uiability-intra-device-interaction.md)
- ExtensionAbility组件
- [ExtensionAbility组件概述](extensionability-overview.md)
- [ServiceExtensionAbility](serviceextensionability.md)
- [DataShareExtensionAbility(仅对系统应用开放)](datashareextensionability.md)
- [FormExtensionAbility(服务卡片)](widget-development-stage.md)
- [AbilityStage组件容器](abilitystage.md)
- [应用上下文Context](application-context-stage.md)
- 信息传递载体Want
- [Want概述](want-overview.md)
- [显式Want与隐式Want匹配规则](explicit-implicit-want-mappings.md)
- [常见action与entities](actions-entities.md)
- [使用显式Want启动Ability](ability-startup-with-explicit-want.md)
- [使用隐式Want打开网址](ability-startup-with-implicit-want.md)
- [应用间使用Want分享数据](data-share-via-want.md)
- [组件启动规则](component-startup-rules.md)
- 应用组件跨设备交互(流转)
- [流转概述](inter-device-interaction-hop-overview.md)
- [跨端迁移(仅对系统应用开放)](hop-cross-device-migration.md)
- [多端协同(仅对系统应用开放)](hop-multi-device-collaboration.md)
- 进程间通信
- [进程模型](process-model-stage.md)
- 公共事件
- [公共事件简介](common-event-overview.md)
- [公共事件订阅](common-event-subscription.md)
- [公共事件发布](common-event-publish.md)
- [公共事件取消订阅](common-event-unsubscription.md)
- [后台服务](background-services.md)
- 线程间通信
- [线程模型](thread-model-stage.md)
- [使用Emitter进行线程间通信](itc-with-emitter.md)
- [使用Worker进行线程间通信](itc-with-worker.md)
- 任务管理
- [任务管理场景介绍](mission-management-overview.md)
- [任务管理与启动模式](mission-management-launch-type.md)
- [页面栈及任务链](page-mission-stack.md)
- FA模型开发指导
- [FA模型开发概述](fa-model-development-overview.md)
- FA模型应用组件
- [应用/组件级配置](application-component-configuration-fa.md)
- PageAbility组件开发指导
- [PageAbility组件概述](pageability-overview.md)
- [PageAbility组件配置](pageability-configuration.md)
- [PageAbility的生命周期](pageability-lifecycle.md)
- [PageAbility的启动模式](pageability-launch-type.md)
- [创建PageAbility](create-pageability.md)
- [启动本地PageAbility](start-local-pageability.md)
- [停止PageAbility](stop-pageability.md)
- [启动远程PageAbility(仅对系统应用开放)](start-remote-pageability.md)
- [启动指定页面](start-page.md)
- [窗口属性](window-properties.md)
- [申请授权](request-permissions.md)
- [跳转规则](redirection-rules.md)
- ServiceAbility组件开发指导
- [ServiceAbility组件概述](serviceability-overview.md)
- [ServiceAbility组件配置](serviceability-configuration.md)
- [ServiceAbility的生命周期](serviceability-lifecycle.md)
- [创建ServiceAbility](create-serviceability.md)
- [启动ServiceAbility](start-serviceability.md)
- [连接ServiceAbility](connect-serviceability.md)
- DataAbility组件开发指导
- [DataAbility组件概述](dataability-overview.md)
- [DataAbility组件配置](dataability-configuration.md)
- [DataAbility的生命周期](dataability-lifecycle.md)
- [创建DataAbility](create-dataability.md)
- [启动DataAbility](start-dataability.md)
- [访问DataAbility](access-dataability.md)
- [DataAbility权限控制](dataability-permission-control.md)
- [服务卡片开发指导](widget-development-fa.md)
- [FA模型的Context](application-context-fa.md)
- [信息传递载体Want](want-fa.md)
- 进程间通信
- [进程模型](process-model-fa.md)
- [公共事件](common-event-fa.md)
- [后台服务](rpc.md)
- 线程间通信
- [线程模型](thread-model-fa.md)
- [线程间通信](itc-fa-overview.md)
- [任务管理](mission-management-fa.md)
- FA模型与Stage模型应用组件互通指导
- [FA模型与Stage模型应用组件互通综述](fa-stage-interaction-overview.md)
- [FA模型启动Stage模型UIAbility](start-uiability-from-fa.md)
- [FA模型绑定Stage模型ServiceExtensionAbility](bind-serviceextensionability-from-fa.md)
- [FA模型访问Stage模型DataShareExtensionAbility](access-datashareextensionability-from-fa.md)
- [Stage模型启动FA模型PageAbility](start-pageability-from-stage.md)
- [Stage模型绑定FA模型ServiceAbility](bind-serviceability-from-stage.md)
- FA模型切换Stage模型指导
- [模型切换概述](model-switch-overview.md)
- 配置文件切换
- [配置文件的差异](configuration-file-diff.md)
- [app和deviceConfig的切换](app-deviceconfig-switch.md)
- [module的切换](module-switch.md)
- 组件切换
- [PageAbility切换](pageability-switch.md)
- [ServiceAbility切换](serviceability-switch.md)
- [DataAbility切换](dataability-switch.md)
- [卡片切换](widget-switch.md)
- API切换
- [API切换概述](api-switch-overview.md)
- [Context接口切换](context-switch.md)
- [featureAbility接口切换](featureability-switch.md)
- [particleAbility接口切换](particleability-switch.md)
- [LifecycleForm接口切换](lifecycleform-switch.md)
- [LifecycleApp接口切换](lifecycleapp-switch.md)
- [LifecycleService接口切换](lifecycleservice-switch.md)
- [LifecycleData接口切换](lifecycledata-switch.md)
- [DataAbilityHelper接口切换](dataabilityhelper-switch.md)
- [mediaLibrary接口切换](medialibrary-switch.md)
- [request接口切换](request-switch.md)
- [resourceManager接口切换](resourcemanager-switch.md)
- [window接口切换](window-switch.md)
- [Storage接口切换](storage-switch.md)
# 使用显式Want启动Ability
在应用使用场景中,当用户点击某个按钮时,应用经常需要拉起指定UIAbility组件来完成某些特定任务。下面介绍如何通过显式Want拉起应用内一个指定UIAbility组件。
## 开发步骤
1. Stage模型工程内,创建一个Ability(此示例内命名为callerAbility)与相应Page(此示例中名为Index.ets),并在callerAbility.ts文件内的onWindowStageCreate函数内通过windowStage.loadContent()方法将两者绑定。
```ts
// ...
// callerAbility.ts
onWindowStageCreate(windowStage) {
// Main window is created, set main page for this ability
console.info('[Demo] EntryAbility onWindowStageCreate')
// Bind callerAbility with a paged named Index
windowStage.loadContent('pages/Index')
}
// ...
```
2. 同上方法再创建一个Ability,此示例内命名为“calleeAbility”。
3. 在callerAbility的“Index.ets”页面内新增一个按钮。
```ts
// ...
build() {
Row() {
Column() {
Text('hello')
.fontSize(50)
.fontWeight(FontWeight.Bold)
// A new button with will call explicitStartAbility() when clicked.
Button("CLICKME")
.onClick(this.explicitStartAbility) // explicitStartAbility见下面示例代码
// ...
}
.width('100%')
}
.height('100%')
}
// ...
```
4. 补充相对应的onClick方法,并使用**显式Want**在方法内启动calleeAbility。bundleName字段可在工程AppScope>app.json5文件内获取;abilityName可在对应模块内的“yourModuleName > src > main > module.json5”文件查看。
```ts
import common from '@ohos.app.ability.common';
// ...
async explicitStartAbility() {
try {
// Explicit want with abilityName specified.
let want = {
deviceId: "",
bundleName: "com.example.myapplication",
abilityName: "calleeAbility"
};
let context = getContext(this) as common.UIAbilityContext;
await context.startAbility(want);
console.info(`explicit start ability succeed`);
} catch (error) {
console.info(`explicit start ability failed with ${error.code}`);
}
}
// ...
```
5. 至此,当您点击CLICKME按钮时,应看到页面的跳转。
<img src="figures/startAbilityWtExplicitWant.PNG" alt="startAbilityWtExplicitWant" style="zoom: 80%;" />
# 使用隐式Want打开网址
## 前提条件
设备上安装了一个或多个浏览器。
浏览器应用中通过module.json5配置如下:
```json
"skills": [
{
"entities": [
"entity.system.browsable"
// ...
],
"actions": [
"ohos.want.action.viewData"
// ...
],
"uris": [
{
"scheme": "https",
"host": "www.test.com",
"port": "8080",
// prefix matching
"pathStartWith": "query",
"type": "text/*"
},
{
"scheme": "http",
// ...
}
// ...
]
},
]
```
## 开发步骤
1. 在自定义函数implicitStartAbility内使用**隐式Want**启动Ability。
```ts
async implicitStartAbility() {
try {
let want = {
// uncomment line below if wish to implicitly query only in the specific bundle.
// bundleName: "com.example.myapplication",
"action": "ohos.want.action.viewData",
// entities can be omitted.
"entities": [ "entity.system.browsable" ],
"uri": "https://www.test.com:8080/query/student",
"type": "text/plain"
}
let context = getContext(this) as common.UIAbilityContext;
await context.startAbility(want)
console.info(`explicit start ability succeed`)
} catch (error) {
console.info(`explicit start ability failed with ${error.code}`)
}
let context = getContext(this) as common.UIAbilityContext;
await context.startAbility(want)
console.info(`explicit start ability succeed`)
} catch (error) {
console.info(`explicit start ability failed with ${error.code}`)
}
}
```
匹配过程如下:
1. want内action不为空,且被skills内action包括,匹配成功。
2. want内entities不为空,且被skills内entities包括,匹配成功。
3. skills内uris拼接为https://www.test.com:8080/query\* (\*为通配符)包含want内uri,匹配成功。
4. want内type不为空,且被skills内type包含,匹配成功。
2. 当有多个匹配应用时,会被应用选择器展示给用户进行选择。<img src="figures/stage-want1.png" alt="stage-want1" style="zoom:50%;" />
# AbilityStage组件容器
AbilityStage是一个[Module](../quick-start/application-package-structure-stage.md)级别的组件容器,应用的HAP在首次加载时会创建一个AbilityStage实例,可以对该Module进行初始化等操作。
AbilityStage与Module一一对应,即一个Module拥有一个AbilityStage。
DevEco Studio默认工程中未自动生成AbilityStage,如需要使用AbilityStage的能力,可以手动新建一个AbilityStage文件,具体步骤如下。
1. 在工程Module对应的ets目录下,右键选择“New &gt; Directory”,新建一个目录并命名为myabilitystage。
2. 在myabilitystage目录,右键选择“New &gt; ts File”,新建一个TS文件并命名为MyAbilityStage.ts。
3. 打开MyAbilityStage.ts文件,导入AbilityStage的依赖包,自定义类继承AbilityStage并加上需要的生命周期回调,示例中增加了一个onCreate()生命周期回调。
```ts
import AbilityStage from '@ohos.app.ability.AbilityStage';
export default class MyAbilityStage extends AbilityStage {
onCreate() {
// 应用的HAP在首次加载的时,为该Module初始化操作
}
onAcceptWant(want) {
// 仅specified模式下触发
return "MyAbilityStage";
}
}
```
[AbilityStage](../reference/apis/js-apis-application-abilitystage.md)拥有[onCreate()](../reference/apis/js-apis-application-abilitystage.md#abilitystageoncreate)生命周期回调和[onAcceptWant()](../reference/apis/js-apis-application-abilitystage.md#abilitystageonacceptwant)[onConfigurationUpdated()](../reference/apis/js-apis-application-abilitystage.md#abilitystageonconfigurationupdated)[onMemoryLevel()](../reference/apis/js-apis-application-abilitystage.md#abilitystageonmemorylevel)事件回调。
- [onCreate()](../reference/apis/js-apis-application-abilitystage.md#abilitystageoncreate)生命周期回调:在开始加载对应Module的第一个UIAbility实例之前会先创建AbilityStage,并在AbilityStage创建完成之后执行其onCreate()生命周期回调。AbilityStage模块提供在Module加载的时候,通知开发者,可以在此进行该Module的初始化(如资源预加载,线程创建等)能力。
- [onAcceptWant()](../reference/apis/js-apis-application-abilitystage.md#abilitystageonacceptwant)事件回调:UIAbility[指定实例模式(specified)](uiability-launch-type.md#specified启动模式)启动时候触发的事件回调,具体使用请参见[UIAbility启动模式综述](uiability-launch-type.md)
- [onConfigurationUpdated()](../reference/apis/js-apis-application-abilitystage.md#abilitystageonconfigurationupdated)事件回调:当系统全局配置发生变更时触发的事件,系统语言、深浅色等,配置项目前均定义在[Configuration](../reference/apis/js-apis-configuration.md)类中。
- [onMemoryLevel()](../reference/apis/js-apis-application-abilitystage.md#abilitystageonmemorylevel)事件回调:当系统调整内存时触发的事件。
应用被切换到后台时,系统会将在后台的应用保留在缓存中。即使应用处于缓存中,也会影响系统整体性能。当系统资源不足时,系统会通过多种方式从应用中回收内存,必要时会完全停止应用,从而释放内存用于执行关键任务。为了进一步保持系统内存的平衡,避免系统停止用户的应用进程,可以在AbilityStage中的onMemoryLevel()生命周期回调中订阅系统内存的变化情况,释放不必要的资源。
```ts
import AbilityStage from '@ohos.app.ability.AbilityStage';
export default class MyAbilityStage extends AbilityStage {
onMemoryLevel(level) {
// 根据系统可用内存的变化情况,释放不必要的内存
}
}
```
# 访问DataAbility
访问DataAbility需导入基础依赖包,以及获取与DataAbility子模块通信的URI字符串。
其中,基础依赖包包括:
- @ohos.ability.featureAbility
- @ohos.data.dataAbility
- @ohos.data.rdb
访问DataAbility的示例代码如下:
1. 创建工具接口类对象。
```ts
// 作为参数传递的URI,与config中定义的URI的区别是多了一个"/",有三个"/"
import featureAbility from '@ohos.ability.featureAbility'
import ohos_data_ability from '@ohos.data.dataAbility'
import ohos_data_rdb from '@ohos.data.rdb'
let urivar = "dataability:///com.ix.DataAbility"
let DAHelper = featureAbility.acquireDataAbilityHelper(urivar);
```
2. 构建数据库相关的RDB数据。
```ts
let valuesBucket = {"name": "gaolu"}
let da = new ohos_data_ability.DataAbilityPredicates()
let valArray =new Array("value1");
let cars = new Array({"batchInsert1" : "value1",});
```
注:关于DataAbilityPredicates的详细内容,请参考[DataAbility谓词](../reference/apis/js-apis-data-ability.md)
3. 调用insert方法向指定的DataAbility子模块插入数据。
```ts
// callback方式调用:
DAHelper.insert(
urivar,
valuesBucket,
(error, data) => {
console.info("DAHelper insert result: " + data)
}
);
```
```ts
// promise方式调用(await需要在async方法中使用):
let datainsert = await DAHelper.insert(urivar, valuesBucket).then((data) => {
console.info("insert success.");
}).catch((error) => {
console.error("insert failed.");
});
```
4. 调用delete方法删除DataAbility子模块中指定的数据。
```ts
// callback方式调用:
DAHelper.delete(
urivar,
da,
(error, data) => {
console.info("DAHelper delete result: " + data)
}
);
```
```ts
// promise方式调用(await需要在async方法中使用):
let datadelete = await DAHelper.delete(
urivar,
da,
);
```
5. 调用update方法更新指定DataAbility子模块中的数据。
```ts
// callback方式调用:
DAHelper.update(
urivar,
valuesBucket,
da,
(error, data) => {
console.info("DAHelper update result: " + data)
}
);
```
```ts
// promise方式调用(await需要在async方法中使用):
let dataupdate = await DAHelper.update(
urivar,
valuesBucket,
da,
);
```
6. 调用query方法在指定的DataAbility子模块中查找数据。
```ts
// callback方式调用:
DAHelper.query(
urivar,
valArray,
da,
(error, data) => {
console.info("DAHelper query result: " + data)
}
);
```
```ts
// promise方式调用(await需要在async方法中使用):
let dataquery = await DAHelper.query(
urivar,
valArray,
da
);
```
7. 调用batchInsert方法向指定的DataAbility子模块批量插入数据。
```ts
// callback方式调用:
DAHelper.batchInsert(
urivar,
cars,
(error, data) => {
console.info("DAHelper batchInsert result: " + data)
}
);
```
```ts
// promise方式调用(await需要在async方法中使用):
let databatchInsert = await DAHelper.batchInsert(
urivar,
cars
);
```
8. 调用executeBatch方法向指定的DataAbility子模块进行数据的批量处理。
```ts
// callback方式调用:
DAHelper.executeBatch(
urivar,
[
{
uri: urivar,
type: featureAbility.DataAbilityOperationType.TYPE_INSERT,
valuesBucket: {"executeBatch" : "value1",},
predicates: da,
expectedCount:0,
predicatesBackReferences: null,
interrupted:true,
}
],
(error, data) => {
console.info("DAHelper executeBatch result: " + data)
}
);
```
```ts
// promise方式调用(await需要在async方法中使用):
let dataexecuteBatch = await DAHelper.executeBatch(
urivar,
[
{
uri: urivar,
type: featureAbility.DataAbilityOperationType.TYPE_INSERT,
valuesBucket:
{
"executeBatch" : "value1",
},
predicates: da,
expectedCount:0,
predicatesBackReferences: null,
interrupted:true,
}
]
);
```
DataAbility的客户端的接口是由工具接口类对象DataAbilityHelper向外提供,相关接口可参考[DataAbilityHelper模块](../reference/apis/js-apis-dataAbilityHelper.md)
# FA模型访问Stage模型DataShareExtensionAbility
## 概述
无论FA模型还是Stage模型,数据读写功能都包含客户端和服务端两部分。
- FA模型中,客户端是由DataAbilityHelper提供对外接口,服务端是由DataAbility提供数据库的读写服务。
- Stage模型中,客户端是由DataShareHelper提供对外接口,服务端是由DataShareExtensionAbility提供数据库的读写服务。
服务端由FA模型升级到Stage模型后,会导致FA模型的客户端在API 9(含)之后的版本上无法访问服务端。
为了解决上述问题,OpenHarmony在框架侧提供了一个解决方案,让开发者平滑过渡到API 9(含)之后的版本。
## 基本原理
一种兼容方法是DataAbilityHelper根据传入的URI的前缀是DataAbility还是DataShare来决定是否调DataShareHelper的接口。但是这种方法需要开发者修改原客户端代码的URI,做不到无感知切换。
因此DataAbilityHelper不能仅依赖URI的前缀决定访问DataAbility还是DataShareExtensionAbility,OpenHarmony采用的方法是:
1. 先按照传入的URI拉起DataAbility;如果拉起失败,再将传入的URI的前缀转换成DataShare再去尝试拉起DataShareExtensionAbility。
2. 如果URI无对应的DataAbility和DataShareExtensionAbility,则拉起失败;反之,必定会拉起DataAbility或者DataShareExtensionAbility。
## 约束与限制
1. 由DataAbility切换到DataShareExtensionAbility时,只能修改URI的前缀,不能修改URI的其他部分。![FAvsStage-uri](figures/FAvsStage-uri.png)
2. DataShareHelper并没有实现原DataAbilityHelper对外API接口的所有功能,因此有部分接口是无法兼容的,具体如表1所示。
**表1** FA模型访问stage模型DataShareExtensionAbility接口支持情况
| 接口 | DataAbilityHelper是否提供 | DataShareHelper是否提供 | 是否兼容 |
| -------- | -------- | -------- | -------- |
| on | 是 | 是 | 是 |
| off | 是 | 是 | 是 |
| notifyChange | 是 | 是 | 是 |
| insert | 是 | 是 | 是 |
| delete | 是 | 是 | 是 |
| query | 是 | 是 | 是 |
| update | 是 | 是 | 是 |
| batchInsert | 是 | 是 | 是 |
| getType | 是 | 否 | 否 |
| getFileTypes | 是 | 否 | 否 |
| normalizeUri | 是 | 是 | 是 |
| denormalizeUri | 是 | 是 | 是 |
| openFile | 是 | 否 | 否 |
| call | 是 | 否 | 否 |
| executeBatch | 是 | 否 | 否 |
# 常见action与entities
**[action](../reference/apis/js-apis-ability-wantConstant.md#wantconstantaction)**:表示调用方要执行的通用操作(如查看、分享、应用详情)。在隐式Want中,您可定义该字段,配合uri或parameters来表示对数据要执行的操作。如打开,查看该uri数据。例如,当uri为一段网址,action为ohos.want.action.viewData则表示匹配可查看该网址的Ability。在Want内声明action字段表示希望被调用方应用支持声明的操作。在被调用方应用配置文件skills字段内声明actions表示该应用支持声明操作。
**常见action**
- ACTION_HOME:启动应用入口组件的动作,需要和ENTITY_HOME配合使用;系统桌面应用图标就是显式的入口组件,点击也是启动入口组件;入口组件可以配置多个。
- ACTION_CHOOSE:选择本地资源数据,例如联系人、相册等;系统一般对不同类型的数据有对应的Picker应用,例如联系人和图库。
- ACTION_VIEW_DATA:查看数据,当使用网址uri时,则表示显示该网址对应的内容。
- ACTION_VIEW_MULTIPLE_DATA:发送多个数据记录的操作。
**[entities](../reference/apis/js-apis-ability-wantConstant.md#wantconstantentity)**:表示目标Ability的类别信息(如浏览器、视频播放器),在隐式Want中是对action的补充。在隐式Want中,开发者可定义该字段,来过滤匹配应用的类别,例如必须是浏览器。在Want内声明entities字段表示希望被调用方应用属于声明的类别。在被调用方应用配置文件skills字段内声明entites表示该应用支持的类别。
**常用entities**
- ENTITY_DEFAULT:默认类别无实际意义。
- ENTITY_HOME:主屏幕有图标点击入口类别。
- ENTITY_BROWSABLE:指示浏览器类别。
# API切换概述
FA模型和Stage模型由于线程模型和进程模型的差异,部分接口仅在FA模型下才能使用,针对这部分接口在SDK的接口中有FAModelOnly的标记,用于提醒开发者这部分接口仅能在FA模型下使用。因此在切换到Stage模型时,需要将应用中用到的FAModelOnly接口替换成Stage模型下对应的接口。下面是startAbility的接口切换示例,全量接口列表请查看后续章节:
![api-switch-overview](figures/api-switch-overview.png)
startAbility接口由FA模型切换到Stage模型的示例:
- FA模型示例
```ts
import fa from '@ohos.ability.featureAbility';
let parameter = {
"want": {
bundleName: "ohos.samples.demo",
abilityName: "ohos.samples.demo.MainAbility"
}
}
fa.startAbility(parameter).then((data) => {
console.info('startAbility success');
}).catch((error) => {
console.error('startAbility failed.');
})
```
- Stage示例示例
```ts
// context为Ability对象的成员,在非Ability对象内部调用需要
// 将Context对象传递过去
let wantInfo = {
bundleName: "ohos.samples.demo",
abilityName: "ohos.samples.demo.MainAbility"
};
this.context.startAbility(wantInfo).then((data) => {
console.info('startAbility success.');
}).catch((error) => {
console.error('startAbility failed.');
})
```
# app和deviceConfig的切换
为了便于开发者维护应用级别的属性配置,Stage模型将config.json中的app和deviceConfig标签提取到了app.json5中进行配置,并对部分标签名称进行了修改,具体差异见下表。
**表1** 配置文件app标签差异对比
| 配置项 | FA模型配置文件config.json中app标签 | Stage模型配置文件app.json5中app标签 |
| -------- | -------- | -------- |
| 应用的版本号 | "version": {<br/> "code": 1,<br/>} | "versionCode":&nbsp;1&nbsp;, |
| 标识版本号的文字描述,用于向用户展示 | "version": {<br/> "name": "1.0.0",<br/>} | "versionName"&nbsp;:&nbsp;"1.0.0"&nbsp;, |
| 标识应用可兼容的最低版本号 | "version": {<br/> "minCompatibleVersionCode": 1,<br/>} | "minCompatibleVersionCode"&nbsp;:&nbsp;1&nbsp;, |
| 运行应用所需要的最低API版本 | "apiVersion": {<br/> "compatible": 7,<br/>} | "minAPIVersion"&nbsp;:&nbsp;7&nbsp;, |
| 应用运行所需的目标API版本 | "apiVersion": {<br/> "target": 8,<br/>} | "targetApiVersion"&nbsp;:&nbsp;8&nbsp;, |
| 应用运行所需的目标API版本的类型 | "apiVersion": {<br/> "releaseType": Release,<br/>} | "apiReleaseType":&nbsp;"Release"&nbsp;, |
app.json5中对原先config.json中的[deviceConfig](../quick-start/deviceconfig-structure.md)标签进行了重构,将deviceConfig下的标签的设备信息整合到了[app.json5](../quick-start/app-configuration-file.md)的app标签下,具体差异见下表
**表2** 配置文件deviceConfig标签差异对比
| FA中deviceConfig标签 | 描述 | stage模型中 | 差异比对 |
| -------- | -------- | -------- | -------- |
| deviceConfig标签 | deviceConfig标签配置了设备信息 | / | Stage模型中没有该标签,直接在app标签下配置设备信息 |
| process | 标识应用或者Ability的进程名。如果在deviceConfig标签下配置了process标签,则该应用的所有Ability都运行在这个进程中。如果在abilities标签下也为某个Ability配置了process标签,则该Ability就运行在这个进程中。 | / | Stage模型不支持配置进程名称 |
| keepAlive | 标识应用是否始终保持运行状态,仅支持系统应用配置,三方应用配置不生效。 | / | Stage模型不支持系统应用模型管控方式变更 |
| supportBackup | 标识应用是否支持备份和恢复。 | / | Stage模型不支持 |
| compressNativeLibs | 标识libs库是否以压缩存储的方式打包到HAP包。 | / | Stage模型不支持 |
| network | 标识网络安全性配置。 | / | Stage模型不支持 |
# 应用/组件级配置
开发者在开发应用时,需要配置应用的一些标签,例如应用的包名、图标等标识特征的属性。这一章节描述了开发者在开发应用时需要配置的一些关键标签。
- **应用包名配置**
应用包名需在config.json文件中app标签下配置bundleName字段,该字段用于指定应用的包名,需保证唯一性。包名是由字母、数字、下划线(_)和点号(.)组成的字符串,必须以字母开头。支持的字符串长度为7~127字节。包名通常采用反向域名形式表示(例如,"com.example.myapplication")。建议第一级为域名后缀"com",第二级为厂商/个人名,也可以采用多级。应用名称配置可以参考[app标签说明](../quick-start/app-structure.md)
- **应用图标和标签配置**
FA模型不支持直接配置应用图标和标签,会以符合规则的PageAbility的图标和标签作为应用图标和标签。PageAbility的图标和标签配置请参见[PageAbility组件配置](pageability-configuration.md)。需在config.json文件的abilities标签下配置icon字段,标签值为资源文件的索引。图标需要在配置IDE的资源文件中,路径为/resource/base/media。取值示例:$media:ability_icon。标签值为资源文件的索引,标识Ability对用户显示的名称。取值可以是Ability名称,也可以是对该名称的资源索引,以支持多语言。如果在该Ability的skills属性中,actions的取值包含 "action.system.home",entities取值中包含"entity.system.home",则该Ability的icon和label将同时作为应用的icon和label。如果存在多个符合条件的Ability,则取位置靠前的Ability的icon和label作为应用的icon和label。应用图标和标签配置可以参考[ablities标签说明](../quick-start/module-structure.md)
```json
"abilities": [
"icon": "$media:icon",
"label": "$string:MainAbility_label",
"skills": [
{
"entities": ["entity.system.home"],
"actions": ["action.system.home"]
}
]
// ...
}
```
- **应用版本声明配置**
应用版本声明配置需在config.json中的app标签下配置version字段,以说明应用当前的版本号和版本名称以及应用能够兼容的最低历史版本号。应用版本配置说明可以参考[version标签说明](../quick-start/module-structure.md)
- **Module支持的设备类型配置**
Module支持的设备类型需要在config.json文件中配置deviceType字段,如果deviceType标签中添加了某种设备,则表明当前的module支持在改设备上运行。具体的deviceType配置规则可以参考[deviceType标签说明](../quick-start/module-structure.md)
- **组件权限申请配置**
组件权限申请配置需在confog.json中的module标签下配置reqPermission字段。来声明需要申请权限的名称,申请权限的原因以及权限使用的场景。组件权限申请可以参考[reqPermission标签说明](../quick-start/module-structure.md)
\ No newline at end of file
# 应用/组件级配置
在开发应用时,需要配置应用的一些标签,例如应用的包名、图标等标识特征的属性。本文描述了在开发应用需要配置的一些关键标签。图标和标签通常一起配置,可以分为应用图标、应用标签和入口图标、入口标签,分别对应[app.json5配置文件](../quick-start/app-configuration-file.md)[module.json5配置文件](../quick-start/module-configuration-file.md)文件中的icon和label标签。应用图标和标签是在设置应用中使用,例如设置应用中的应用列表。入口图标是应用安装完成后在设备桌面上显示出来的,如图一所示。入口图标是以[UIAbility](uiability-overview.md)为粒度,支持同一个应用存在多个入口图标和标签,点击后进入对应的UIAbility界面。
**图1** 应用图标和标签  
![application-component-configuration-stage](figures/application-component-configuration-stage.png)
- **应用包名配置**
应用需要在工程的AppScope目录下的[app.json5配置文件](../quick-start/app-configuration-file.md)中配置bundleName标签,该标签用于标识应用的唯一性。推荐采用反域名形式命名(如com.example.demo,建议第一级为域名后缀com,第二级为厂商/个人名,第三级为应用名,也可以多级)。
- **应用图标和标签配置**
应用图标需要在工程的AppScope目录下的[app.json5配置文件](../quick-start/app-configuration-file.md)中配置icon标签。应用图标需配置为图片的资源索引,配置完成后,该图片即为应用的图标。应用图标通常用于显示在应用列表中,例如设置中的应用列表。
应用标签需要在工程的AppScope模块下的[app.json5配置文件](../quick-start/app-configuration-file.md)中配置label标签。标识应用对用户显示的名称,需要配置为字符串资源的索引。
Stage模型的应用支持单独配置应用图标和标签,在[app.json5配置文件](../quick-start/app-configuration-file.md)中配置。应用图标和标签是在设置应用中使用,例如设置应用中的应用列表,会显示出对应的图标和标签。在app字段下面分别有icon和label字段,根据对应的规则进行配置。
```json
{
"app": {
"icon": "$media:app_icon",
"label": "$string:app_name"
// ...
}
}
```
- **入口图标和标签配置**
入口图标和标签需要在[app.json5配置文件](../quick-start/app-configuration-file.md)中配置,在abilities标签下面分别有icon和label标签。例如希望在桌面上显示该UIAbility的图标和标签,则需要在skills标签下面的entities中添加"entity.system.home"、actions中添加"action.system.home"。同一个应用有多个UIAbility配置上述字段时,桌面上会显示出多个图标和标签,分别对应各自的UIAbility。
```json
{
"module": {
// ...
"abilities": [
{
// $开头的为资源值
"icon": "$media:icon",
"label": "$string:EntryAbility_label",
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
}
]
}
}
```
- **应用版本声明配置**
应用版本声明需要在工程的AppScope目录下的[app.json5配置文件](../quick-start/app-configuration-file.md)中配置versionCode标签和versionName标签。versionCode用于标识应用的版本号,该标签值为32位非负整数。此数字仅用于确定某个版本是否比另一个版本更新,数值越大表示版本越高。versionName标签标识版本号的文字描述。
- **Module支持的设备类型配置**
Module支持的设备类型需要在[module.json5配置文件](../quick-start/module-configuration-file.md)中配置deviceTypes标签,如果deviceTypes标签中添加了某种设备,则表明当前的Module支持在该设备上运行。
- **Module权限配置**
Module访问系统或其他应用受保护部分所需的权限信息需要在[module.json5配置文件](../quick-start/module-configuration-file.md)中配置requestPermission标签。该标签用于声明需要申请权限的名称、申请权限的原因以及权限使用的场景。
\ No newline at end of file
# FA模型的Context
FA模型下只有一个Context。Context中的所有功能都是通过方法来提供的,它提供了一些featureAbility中不存在的方法,相当于featureAbility的一个扩展和补全。
## 接口说明
FA模型下使用Context,需要通过featureAbility下的接口getContext来获取,而在此之前,需要先导入对应的包:
```ts
import featureAbility from "@ohos.ability.featureAbility";
```
然后使用如下方式获取对应的Context对象:
```ts
let context = featureAbility.getContext()
```
最终返回的对象为Context,其对应的接口说明请参见[接口文档](../reference/apis/js-apis-Context.md)
## 开发步骤
1. 查询Bundle信息。
```ts
import featureAbility from '@ohos.ability.featureAbility'
export default {
onCreate() {
// 获取context并调用相关方法
let context = featureAbility.getContext();
context.getBundleName((data, bundleName)=>{
console.info("ability bundleName:" + bundleName)
});
console.info('Application onCreate')
},
onDestroy() {
console.info('Application onDestroy')
},
}
```
2. 设置当前featureAbility的显示方向。
```ts
import featureAbility from '@ohos.ability.featureAbility'
import bundle from '@ohos.bundle';
export default {
onCreate() {
// 获取context并调用相关方法
let context = featureAbility.getContext();
context.setDisplayOrientation(bundle.DisplayOrientation.LANDSCAPE).then(() => {
console.info("Set display orientation.")
})
console.info('Application onCreate')
},
onDestroy() {
console.info('Application onDestroy')
},
}
```
# 应用上下文Context
## 概述
[Context](../reference/apis/js-apis-application-context.md)是应用中对象的上下文,其提供了应用的一些基础信息,例如resourceManager(资源管理)、applicationInfo(当前应用信息)、dir(应用开发路径)、area(文件分区)等,以及应用的一些基本方法,例如createBundleContext()、getApplicationContext()等。UIAbility组件和各种ExtensionAbility派生类组件都有各自不同的Context类。分别有基类Context、ApplicationContext、AbilityStageContext、UIAbilityContext、ExtensionContext、ServiceExtensionContext等Context。
- 各类Context的继承关系
<img src="figures/context-inheritance.png" alt="context-inheritance" style="zoom: 50%;" />
- 各类Context的持有关系
<img src="figures/context-holding.png" alt="context-holding" style="zoom:50%;" />
- 各类Context的获取方式
- 获取[UIAbilityContext](../reference/apis/js-apis-ability-context.md)。每个UIAbility中都包含了一个Context属性,提供操作Ability、获取Ability的配置信息、应用向用户申请授权等能力。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
let uiAbilityContext = this.context;
// ...
}
}
```
- 获取特定场景[ExtensionContext](../reference/apis/js-apis-extension-context.md)。以ServiceExtensionContext为例,表示后台服务的上下文环境,继承自ExtensionContext,提供后台服务相关的接口能力。
```ts
import ServiceExtensionAbility from '@ohos.app.ability.ServiceExtensionAbility';
export default class MyService extends ServiceExtensionAbility {
onCreate(want) {
let serviceExtensionContext = this.context;
// ...
}
}
```
- 获取[AbilityStageContext](../reference/apis/js-apis-abilitystagecontext.md)。Module级别的Context,和基类Context相比,额外提供HapModuleInfo、Configuration等信息。
```ts
import AbilityStage from "@ohos.app.ability.AbilityStage";
export default class MyAbilityStage extends AbilityStage {
onCreate() {
let abilityStageContext = this.context;
// ...
}
}
```
- 获取[ApplicationContext](../reference/apis/js-apis-application-applicationContext.md)。应用级别的Context。ApplicationContext在基类Context的基础上提供了订阅应用内Ability的生命周期的变化、订阅系统内存变化和订阅应用内系统环境的变化的能力,在UIAbility、ExtensionAbility、AbilityStage中均可以获取。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
let applicationContext = this.context.getApplicationContext();
// ...
}
}
```
## Context的典型使用场景
本章节通过如下典型场景来介绍Context的用法:
- [获取应用开发路径](#获取应用开发路径)
- [获取和修改加密分区](#获取和修改加密分区)
- [创建其他应用或其他Module的Context](#创建其他应用或其他module的context)
- [订阅进程内Ability生命周期变化](#订阅进程内ability生命周期变化)
- [通过AbilityContext向用户申请授权](#通过uiabilitycontext向用户申请授权)
### 获取应用开发路径
从Context中获取的应用开发路径如下表所示。
**表1** 应用开发路径说明
| 属性名称 | 参数类型 | 可读 | 可写 | 说明 |
| -------- | -------- | -------- | -------- | -------- |
| cacheDir | string | 是 | 否 | 应用在内部存储上的缓存路径。<br/>对应于"设置&nbsp;&gt;&nbsp;应用管理",找到对应应用的"存储"中的缓存内容。 |
| tempDir | string | 是 | 否 | 应用的临时文件路径。<br/>在应用卸载后,系统会删除存储在此目录中的文件。 |
| filesDir | string | 是 | 否 | 应用在内部存储上的文件路径。<br/>本目录下存放的文件可能会被应用迁移或者备份的时候同步到其他目录中。 |
| databaseDir | string | 是 | 否 | 获取本地数据库存储路径。 |
| bundleCodeDir | string | 是 | 否 | 应用在内部存储上的安装路径。 |
| distributedFilesDir | string | 是 | 否 | 应用的分布式文件路径。 |
| preferencesDir | string | 是 | 是 | 指示应用程序首选项目录。 |
获取路径的能力是基类Context中提供的能力,因此在ApplicationContext、AbilityStageContext、UIAbilityContext和ExtensionContext中均可以获取,在各类Context中获取到的路径会有一些差别,具体差别如下图所示。
**图1** Context中获取的应用开发路径
<img src="figures/context-dir.png" alt="context-dir" style="zoom: 50%;" />
- 通过ApplicationContext获取的应用级别路径。应用全局信息建议存放的路径,存放在此路径的文件内容仅在应用卸载时会被删除。
| 属性 | 路径 |
| -------- | -------- |
| bundleCodeDir | {路径前缀}/el1/bundle/ |
| cacheDir | {路径前缀}/{加密等级}/base/cache/ |
| filesDir | {路径前缀}/{加密等级}/base/files/ |
| preferencesDir | {路径前缀}/{加密等级}/base/preferences/ |
| tempDir | {路径前缀}/{加密等级}/base/temp/ |
| databaseDir | {路径前缀}/{加密等级}/database/ |
| distributedFilesDir | {路径前缀}/el2/distributedFiles/ |
- 通过AbilityStageContext、UIAbilityContext、ExtensionContext获取的HAP级别路径。HAP对应的信息建议存放的路径,存放在此路径的文件内容会跟随HAP的卸载而删除,不会影响应用级别路径的文件内容,除非该应用的HAP已全部卸载。
| 属性 | 路径 |
| -------- | -------- |
| bundleCodeDir | {路径前缀}/el1/bundle/ |
| cacheDir | {路径前缀}/{加密等级}/base/**haps/{moduleName}/**cache/ |
| filesDir | {路径前缀}/{加密等级}/base/**haps/{moduleName}/**files/ |
| preferencesDir | {路径前缀}/{加密等级}/base/**haps/{moduleName}/**preferences/ |
| tempDir | {路径前缀}/{加密等级}/base/**haps/{moduleName}/**temp/ |
| databaseDir | {路径前缀}/{加密等级}/database/**{moduleName}/** |
| distributedFilesDir | {路径前缀}/el2/distributedFiles/**{moduleName}/** |
获取应用开发路径的示例代码如下所示。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
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;
// ...
}
}
```
### 获取和修改加密分区
上一个场景中,引入了加密等级的概念,通过对[Context的area属性](../reference/apis/js-apis-application-context.md)的读写来实现获取和设置当前加密分区,支持如下两种加密等级:
- AreaMode.EL1:设备级加密区,设备开机后可访问的数据区。
- AreaMode.EL2:用户级加密区,设备开机,首次输入密码后才能够访问的数据区。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
// 存储普通信息前,切换到EL1设备机加密
if (this.context.area === 1) { // 获取area
this.context.area = 0; // 修改area
}
// 存储普通信息
// 存储敏感信息前,切换到EL2用户级加密
if (this.context.area === 0) { // 获取area
this.context.area = 1; // 修改area
}
// 存储敏感信息
}
}
```
### 创建其他应用或其他Module的Context
基类Context提供创建其他应用或其他Module的Context的方法有[createBundleContext(bundleName:string)](../reference/apis/js-apis-application-context.md#contextcreatebundlecontext)[createModuleContext(moduleName:string)](../reference/apis/js-apis-application-context.md#contextcreatemodulecontext)[createModuleContext(bundleName:string, moduleName:string)](../reference/apis/js-apis-application-context.md#contextcreatemodulecontext-1)接口,创建其他应用或者其他Module的Context,从而通过该Context获取相应的资源信息(例如获取其他Module的[获取应用开发路径](#获取应用开发路径)信息)。
- 调用createBundleContext(bundleName:string)方法,创建其他应用的Context信息。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 当获取的是其他应用的Context时:
>
> - 申请`ohos.permission.GET_BUNDLE_INFO_PRIVILEGED`权限,配置方式请参阅[访问控制授权申请指导](../security/accesstoken-guidelines.md#stage模型)。
>
> - 接口为系统接口,三方应用不支持调用。
例如在桌面上显示的应用信息,包括应用名称和应用图标等,桌面应用可以通过调用上述的方法获取相应应用的Context信息从而获取到相应的应用名称、图标等资源信息。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
let bundleName2 = "com.example.application";
let context2 = this.context.createBundleContext(bundleName2);
let label2 = context2.applicationInfo.label;
// ...
}
}
```
- 调用createModuleContext(bundleName:string, moduleName:string)方法,获取指定应用指定Module的上下文信息。获取到指定应用指定Module的Context之后,即可获取到相应应用Module的资源信息。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 当获取的是其他应用的指定Module的Context时:
>
> - 申请`ohos.permission.GET_BUNDLE_INFO_PRIVILEGED`权限,配置方式请参阅[访问控制授权申请指导](../security/accesstoken-guidelines.md#stage模型)。
>
> - 接口为系统接口,三方应用不支持调用。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
let bundleName2 = "com.example.application";
let moduleName2 = "module1";
let context2 = this.context.createModuleContext(bundleName2, moduleName2);
// ...
}
}
```
- 调用createModuleContext(moduleName:string)方法,获取本应用中其他Module的Context。获取到其他Module的Context之后,即可获取到相应Module的资源信息。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
let moduleName2 = "module1";
let context2 = this.context.createModuleContext(moduleName2);
// ...
}
}
```
### 订阅进程内Ability生命周期变化
在应用内的DFX统计场景,如需要统计对应页面停留时间和访问频率等信息,可以使用订阅进程内Ability生命周期变化功能。
在进程内Ability生命周期变化时,如创建、可见/不可见、获焦/失焦、销毁等,会触发进入相应的回调,其中返回的此次注册监听生命周期的ID(每次注册该ID会自增+1,当超过监听上限数量2^63-1时,返回-1),以在[UIAbilityContext](../reference/apis/js-apis-ability-context.md)中使用为例进行说明。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
import Window from '@ohos.window';
const TAG: string = "[Example].[Entry].[EntryAbility]";
export default class EntryAbility extends UIAbility {
lifecycleId: number;
onCreate(want, launchParam) {
let abilityLifecycleCallback = {
onAbilityCreate(ability) {
console.info(TAG, "onAbilityCreate ability:" + JSON.stringify(ability));
},
onWindowStageCreate(ability, windowStage) {
console.info(TAG, "onWindowStageCreate ability:" + JSON.stringify(ability));
console.info(TAG, "onWindowStageCreate windowStage:" + JSON.stringify(windowStage));
},
onWindowStageActive(ability, windowStage) {
console.info(TAG, "onWindowStageActive ability:" + JSON.stringify(ability));
console.info(TAG, "onWindowStageActive windowStage:" + JSON.stringify(windowStage));
},
onWindowStageInactive(ability, windowStage) {
console.info(TAG, "onWindowStageInactive ability:" + JSON.stringify(ability));
console.info(TAG, "onWindowStageInactive windowStage:" + JSON.stringify(windowStage));
},
onWindowStageDestroy(ability, windowStage) {
console.info(TAG, "onWindowStageDestroy ability:" + JSON.stringify(ability));
console.info(TAG, "onWindowStageDestroy windowStage:" + JSON.stringify(windowStage));
},
onAbilityDestroy(ability) {
console.info(TAG, "onAbilityDestroy ability:" + JSON.stringify(ability));
},
onAbilityForeground(ability) {
console.info(TAG, "onAbilityForeground ability:" + JSON.stringify(ability));
},
onAbilityBackground(ability) {
console.info(TAG, "onAbilityBackground ability:" + JSON.stringify(ability));
},
onAbilityContinue(ability) {
console.info(TAG, "onAbilityContinue ability:" + JSON.stringify(ability));
}
}
// 1. 通过context属性获取applicationContext
let applicationContext = this.context.getApplicationContext();
// 2. 通过applicationContext注册监听应用内生命周期
this.lifecycleId = applicationContext.on("abilityLifecycle", abilityLifecycleCallback);
console.info(TAG, "register callback number: " + JSON.stringify(this.lifecycleId));
}
onDestroy() {
let applicationContext = this.context.getApplicationContext();
applicationContext.off("abilityLifecycle", this.lifecycleId, (error, data) => {
console.info(TAG, "unregister callback success, err: " + JSON.stringify(error));
});
}
}
```
### 通过UIAbilityContext向用户申请授权
每个Ability中都包含了一个Context属性。Ability功能主要是处理生命周期,其余操作Ability的方法(例如startAbility()、connectServiceExtensionAbility()、terminateSelf()等)都是在对应的Context中实现的,同时Context也提供了获取Ability的配置信息、向用户申请授权等能力,如何获取Context请参见[获取UIAbility的上下文信息](uiability-usage.md#获取uiability的上下文信息)
应用需要获取用户的隐私信息或使用系统能力时,例如获取位置信息、访问日历、使用相机拍摄照片或录制视频等,需要向用户申请授权,示意效果如下图所示。具体使用请参见[访问控制授权申请指导](../security/accesstoken-guidelines.md)
**图2** 向用户申请日历访问授权
<img src="figures/application-context-stage.png" alt="application-context-stage" style="zoom:50%;" />
\ No newline at end of file
# OpenHarmony应用模型的构成要素
应用模型是OpenHarmony为开发者提供的应用程序所需能力的抽象提炼,它提供了应用程序必备的组件和运行机制。有了应用模型,开发者可以基于一套统一的模型进行应用开发,使应用开发更简单、高效。
OpenHarmony应用模型的构成要素包括:
1. 应用组件
应用组件是应用的基本组成单位,是应用的运行入口。用户启动、使用和退出应用过程中,应用组件会在不同的状态间切换,这些状态称为应用组件的生命周期。应用组件提供生命周期的回调函数,开发者通过应用组件的生命周期回调感知应用的[状态变化](uiability-lifecycle.md)。应用开发者在编写应用时,首先需要编写的就是应用组件,同时还需编写应用组件的生命周期回调函数,并在应用配置文件中配置相关信息。这样,操作系统在运行期间通过配置文件创建应用组件的实例,并调度它的生命周期回调函数,从而执行开发者的代码。
2. 应用进程模型
应用进程模型定义应用进程的创建和销毁方式,以及进程间的通信方式。
3. 应用线程模型
应用线程模型定义应用进程内线程的创建和销毁方式、主线程和UI线程的创建方式、线程间的通信方式。
4. 应用任务管理模型
应用任务管理模型定义任务(Mission)的创建和销毁方式,以及任务与组件间的关系。所谓任务,即用户使用一个应用组件实例的记录。每次用户启动一个新的应用组件实例,都会生成一个新的任务。例如,用户启动一个视频应用,此时在“最近任务”界面,将会看到视频应用这个任务,当用户点击这个任务时,系统会把该任务切换到前台,如果这个视频应用中的视频编辑功能也是通过应用组件编写的,那么在用户启动视频编辑功能时,会创建视频编辑的应用组件实例,在“最近任务”界面中,将会展示视频应用、视频编辑两个任务。
5. 应用配置文件
应用配置文件中包含应用配置信息、应用组件信息、权限信息、开发者自定义信息等,这些信息在编译构建、分发和运行阶段分别提供给编译工具、应用市场和操作系统使用。
# OpenHarmony应用模型解读
## OpenHarmony应用模型概况
随着系统的演进发展,OpenHarmony先后提供了两种应用模型:
- FA(Feature Ability)模型:OpenHarmony API 7开始支持的模型,已经不再主推。
- Stage模型:OpenHarmony API 9开始新增的模型,是目前主推且会长期演进的模型。在该模型中,由于提供了AbilityStage、WindowStage等类作为应用组件和Window窗口的“舞台”,因此称这种应用模型为Stage模型。
Stage模型之所以成为主推模型,源于其设计思想。Stage模型的设计基于如下4个出发点。
1. **为复杂应用而设计**
- 多个应用组件共享同一个ArkTS引擎(运行ArkTS语言的虚拟机)实例,应用组件之间可以方便的共享对象和状态,同时减少复杂应用运行对内存的占用。
- 采用面向对象的开发方式,使得复杂应用代码可读性高、易维护性好、可扩展性强。
2. **原生支持应用组件级的[跨端迁移](hop-cross-device-migration.md)和[多端协同](hop-multi-device-collaboration.md)**
Stage模型实现了应用组件与UI解耦:
- 在跨端迁移场景下,系统在多设备的应用组件之间迁移数据/状态后,UI便可利用ArkUI的声明式特点,通过应用组件中保存的数据/状态恢复用户界面,便捷实现跨端迁移。
- 在多端协同场景下,应用组件具备组件间通信的RPC调用能力,天然支持跨设备应用组件的交互。
3. **支持多设备和多窗口形态**
应用组件管理和窗口管理在架构层面解耦:
- 便于系统对应用组件进行裁剪(无屏设备可裁剪窗口)。
- 便于系统扩展窗口形态。
- 在多设备(如桌面设备和移动设备)上,应用组件可使用同一套生命周期。
4. **平衡应用能力和系统管控成本**
Stage模型重新定义应用能力的边界,平衡应用能力和系统管控成本。
- 提供特定场景(如卡片、输入法)的应用组件,以便满足更多的使用场景。
- 规范化后台进程管理:为保障用户体验,Stage模型对后台应用进程进行了有序治理,应用程序不能随意驻留在后台,同时应用后台行为受到严格管理,防止恶意应用行为。
## 通过对比认识FA模型与Stage模型
**Stage模型与FA模型最大的区别在于**:Stage模型中,多个应用组件共享同一个ArkTS引擎实例;而FA模型中,每个应用组件独享一个ArkTS引擎实例。因此在Stage模型中,应用组件之间可以方便的共享对象和状态,同时减少复杂应用运行对内存的占用。Stage模型作为主推的应用模型,开发者通过它能够更加便利地开发出分布式场景下的复杂应用。
可通过如下对比表格了解两种模型的整体概况。
**表1** FA模型与Stage模型差异概览
| 项目 | FA模型 | Stage模型 |
| -------- | -------- | -------- |
| **应用组件** | 1.&nbsp;组件分类<br/>&nbsp;&nbsp;&nbsp;-&nbsp;PageAbility组件:包含UI界面,提供展示UI的能力。详细介绍请参见[PageAbility组件概述](pageability-overview.md)。<br/>&nbsp;&nbsp;&nbsp;-&nbsp;ServiceAbility组件:提供后台服务的能力,无UI界面。详细介绍请参见[ServiceAbility组件概述](serviceability-overview.md)。<br/>&nbsp;&nbsp;&nbsp;-&nbsp;DataAbility组件:提供数据分享的能力,无UI界面。详细介绍请参见[DataAbility组件概述](dataability-overview.md)。<br/>2.&nbsp;开发方式<br/>&nbsp;&nbsp;&nbsp;通过导出匿名对象、固定入口文件的方式指定应用组件。开发者无法进行派生,不利于扩展能力。 | 1.&nbsp;组件分类<br/>&nbsp;&nbsp;&nbsp;-&nbsp;UIAbility组件:包含UI界面,提供展示UI的能力,主要用于和用户交互。详细介绍请参见[UIAbility组件概述](uiability-overview.md)。<br/>&nbsp;&nbsp;&nbsp;-&nbsp;ExtensionAbility组件:提供特定场景(如卡片、输入法)的扩展能力,满足更多的使用场景。详细介绍请参见[ExtensionAbility组件概述](extensionability-overview.md)。<br/>2.&nbsp;开发方式<br/>&nbsp;&nbsp;&nbsp;采用面向对象的方式,将应用组件以类接口的形式开放给开发者,可以进行派生,利于扩展能力。 |
| **进程模型** | 有两类进程:<br/>1.&nbsp;主进程<br/>2.&nbsp;渲染进程<br/>详细介绍请参见[进程模型](process-model-fa.md)。 | 有三类进程:<br/>1.&nbsp;主进程<br/>2.&nbsp;ExtensionAbility进程<br/>3.&nbsp;渲染进程<br/>详细介绍请参见[进程模型](process-model-stage.md)。 |
| **线程模型** | 1.&nbsp;ArkTS引擎实例的创建<br/>&nbsp;&nbsp;&nbsp;一个进程可以运行多个应用组件实例,每个应用组件实例运行在一个单独的ArkTS引擎实例中。<br/>2.&nbsp;线程模型<br/>&nbsp;&nbsp;&nbsp;每个ArkTS引擎实例都在一个单独线程(非主线程)上创建,主线程没有ArkTS引擎实例。<br/>3.&nbsp;进程内对象共享:不支持。<br/>详细介绍请参见[线程模型](thread-model-fa.md)。 | 1.&nbsp;ArkTS引擎实例的创建<br/>&nbsp;&nbsp;&nbsp;一个进程可以运行多个应用组件实例,所有应用组件实例共享一个ArkTS引擎实例。<br/>2.&nbsp;线程模型<br/>&nbsp;&nbsp;&nbsp;ArkTS引擎实例在主线程上创建。<br/>3.&nbsp;进程内对象共享:支持。<br/>详细介绍请参见[线程模型](thread-model-stage.md)。 |
| **任务管理模型** | -&nbsp;每个PageAbility组件实例创建一个任务。<br/>-&nbsp;任务会持久化存储,直到超过最大任务个数(根据产品配置自定义)或者用户主动删除任务。<br/>-&nbsp;PageAbility组件之间不会形成栈的结构。<br/>详细介绍请参见[任务管理场景介绍](mission-management-overview.md)。 | -&nbsp;每个UIAbility组件实例创建一个任务。<br/>-&nbsp;任务会持久化存储,直到超过最大任务个数(根据产品配置自定义)或者用户主动删除任务。<br/>-&nbsp;UIAbility组件之间不会形成栈的结构。<br/>详细介绍请参见[任务管理场景介绍](mission-management-overview.md)。 |
| **应用配置文件** | 使用config.json描述应用信息、HAP信息和应用组件信息。<br/>详细介绍请参见[应用配置文件概述(FA模型)](../quick-start/application-configuration-file-overview-fa.md)。 | 使用app.json5描述应用信息,module.json5描述HAP信息、应用组件信息。<br/>详细介绍请参见[应用配置文件概述(Stage模型)](../quick-start/application-configuration-file-overview-stage.md)。 |
# 后台服务
Stage模型提供了ServiceExtensionAbility来提供后台服务的能力,支持系统应用实现一个后台服务并对外提供相应的能力;系统应用A实现了一个后台服务,三方应用B可以通过连接系统应用A的后台服务与其进行进程间通信。
ServiceExtensionAbility的详细介绍请参见[后台服务开发指导](serviceextensionability.md)
# Stage模型绑定FA模型ServiceAbility
本小节介绍Stage模型的两种应用组件如何绑定FA模型ServiceAbility组件。
## UIAbility关联访问ServiceAbility
UIAbility关联访问ServiceAbility和UIAbility关联访问ServiceExtensionAbility的方式完全相同。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
export default class MainAbility extends UIAbility {
onCreate(want, launchParam) {
console.info("MainAbility onCreate");
}
onDestroy() {
console.info("MainAbility onDestroy")
}
onWindowStageCreate(windowStage) {
console.info("MainAbility onWindowStageCreate")
let want = {
bundleName: "com.ohos.fa",
abilityName: "ServiceAbility",
};
let options = {
onConnect:function (elementName, proxy) {
console.info("onConnect called.");
},
onDisconnect:function (elementName) {
console.info("onDisconnect called.");
},
onFailed:function (code) {
console.info("onFailed code is: " + code);
}
};
let connectionId = this.context.connectServiceExtensionAbility(want, options);
}
onWindowStageDestroy() {
console.info("MainAbility onWindowStageDestroy")
}
onForeground() {
console.info("MainAbility onForeground")
}
onBackground() {
console.info("MainAbility onBackground")
}
}
```
## ExtensionAbility关联访问ServiceAbility
下面以ServiceExtensionAbility为例来说明ExtensionAbility关联访问ServiceAbility。ServiceExtensionAbility关联访问ServiceAbility和ServiceExtensionAbility关联访问ServiceExtensionAbility的方式完全相同。
```ts
import Extension from '@ohos.app.ability.ServiceExtensionAbility'
export default class ServiceExtension extends Extension {
onCreate(want) {
console.info("ServiceExtension onCreate")
}
onDestroy() {
console.info("ServiceExtension onDestroy")
}
onRequest(want, startId) {
console.info("ServiceExtension onRequest")
let wantFA = {
bundleName: "com.ohos.fa",
abilityName: "ServiceAbility",
};
let options = {
onConnect:function (elementName, proxy) {
console.info("onConnect called.");
},
onDisconnect:function (elementName) {
console.info("onDisconnect called.");
},
onFailed:function (code) {
console.info("onFailed code is: " + code);
}
};
let connectionId = this.context.connectServiceExtensionAbility(wantFA, options);
}
}
```
# FA模型绑定Stage模型ServiceExtensionAbility
本文介绍FA模型的三种应用组件如何绑定Stage模型的ServiceExtensionAbility组件。
## PageAbility关联访问ServiceExtensionAbility
PageAbility关联访问ServiceExtensionAbility和PageAbility关联访问ServiceAbility的方式完全相同。
```ts
import featureAbility from '@ohos.ability.featureAbility';
let want = {
bundleName: "com.ohos.stage",
abilityName: "com.ohos.stage.ServiceExtensionAbility"
};
let faConnect = {
onConnect:function (elementName, proxy) {
console.info("Faconnection onConnect called.");
},
onDisconnect:function (elementName) {
console.info("Faconnection onDisconnect called.");
},
onFailed:function (code) {
console.info("Faconnection onFailed code is: " + code);
}
};
let connectionId = featureAbility.connectAbility(want, faConnect);
```
## ServiceAbility/DataAbility关联访问ServiceExtensionAbility
ServiceAbility/DataAbility关联访问ServiceExtensionAbility和ServiceAbility/DataAbility关联访问ServiceAbility的方式完全相同。
```ts
import particleAbility from '@ohos.ability.particleAbility';
let want = {
bundleName: "com.ohos.stage",
abilityName: "com.ohos.stage.ServiceExtensionAbility"
};
let faConnect = {
onConnect:function (elementName, proxy) {
console.info("Faconnection onConnect called.");
},
onDisconnect:function (elementName) {
console.info("Faconnection onDisconnect called.");
},
onFailed:function (code) {
console.info("Faconnection onFailed code is: " + code);
}
};
let connectionId = particleAbility.connectAbility(want, faConnect);
```
# 公共事件
请参见Stage模型的"[公共事件](common-event-overview.md)"。
# 公共事件简介
OpenHarmony通过CES(Common Event Service,公共事件服务)为应用程序提供订阅、发布、退订公共事件的能力。
公共事件从系统角度可分为:系统公共事件和自定义公共事件。
- 系统公共事件:CES内部定义的公共事件,只有系统应用和系统服务才能发布,例如HAP安装,更新,卸载等公共事件。目前支持的系统公共事件详见[系统公共事件列表](../reference/apis/js-apis-commonEvent.md#support)
- 自定义公共事件:应用自定义一些公共事件用来实现跨进程的事件通信能力。
公共事件按发送方式可分为:无序公共事件、有序公共事件和粘性公共事件。
- 无序公共事件:CES转发公共事件时,不考虑订阅者是否接收到,按订阅者订阅先后顺序转发。
- 有序公共事件:CES转发公共事件时,按订阅者订阅先后顺序,在接收到前一个订阅者回复后,再转发下一个订阅者。
- 粘性公共事件:能够让订阅者收到在订阅前已经发送的公共事件就是粘性公共事件。普通的公共事件只能在订阅后发送才能收到,而粘性公共事件的特殊性就是可以先发送后订阅。发送粘性事件必须是系统应用或系统服务,且需要申请`ohos.permission.COMMONEVENT_STICKY`权限,配置方式请参阅[访问控制授权申请指导](../security/accesstoken-guidelines.md#stage模型)
每个应用都可以按需订阅公共事件,订阅成功,当公共事件发布时,系统会将其发送给对应的应用。这些公共事件可能来自系统、其他应用和应用自身。
**图1** 公共事件示意图
![common-event](figures/common-event.png)
# 公共事件发布
## 场景介绍
当需要发布某个自定义公共事件时,可以通过publish()方法发布事件。发布的公共事件可以携带数据,供订阅者解析并进行下一步处理。
> ![icon-notice.gif](public_sys-resources/icon-notice.gif) **须知:**
> 已发出的粘性公共事件后来订阅者也可以接收到,其他公共事件都需要先订阅再接收,订阅参考[公共事件订阅章节](common-event-subscription.md)。
## 接口说明
详细接口见[接口文档](../reference/apis/js-apis-commonEvent.md#commoneventpublish)
| 接口名 | 接口描述 |
| -------- | -------- |
| publish(event:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback) | 发布公共事件。 |
| publish(event:&nbsp;string,&nbsp;options:&nbsp;[CommonEventPublishData](../reference/apis/js-apis-commonEvent.md#commoneventpublishdata),&nbsp;callback:&nbsp;AsyncCallback) | 指定发布信息并发布公共事件。 |
## 发布不携带信息的公共事件
不携带信息的公共事件,只能发布无序公共事件。
1. 导入CommonEvent模块。
```ts
import commonEvent from '@ohos.commonEventManager';
```
2. 传入需要发布的事件名称和回调函数,发布事件。
```ts
// 发布公共事件
commonEvent.publish("usual.event.SCREEN_OFF", (err) => {
if (err) {
console.error(`[CommonEvent] PublishCallBack err=${JSON.stringify(err)}`);
} else {
console.info(`[CommonEvent] Publish success`);
}
})
```
## 发布携带信息的公共事件
携带信息的公共事件,可以发布为无序公共事件、有序公共事件和粘性事件,可以通过参数[CommonEventPublishData](../reference/apis/js-apis-commonEvent.md#commoneventpublishdata)的isOrdered、isSticky的字段进行设置。
1. 导入CommonEvent模块。
```ts
import commonEvent from '@ohos.commonEventManager';
```
2. 传入需要发布的事件名称和回调函数,发布事件。
```ts
// 公共事件相关信息
let options = {
code: 1, // 公共事件的初始代码
data: "initial data", // 公共事件的初始数据
}
```
3. 传入需要发布的事件名称、需要发布的指定信息和回调函数,发布事件。
```ts
// 发布公共事件
commonEvent.publish("usual.event.SCREEN_OFF", options, (err) => {
if (err) {
console.error('[CommonEvent] PublishCallBack err=' + JSON.stringify(err));
} else {
console.info('[CommonEvent] Publish success')
}
})
```
# 公共事件订阅
## 场景介绍
当需要订阅某个公共事件,获取该公共事件传递的参数时,需要创建一个订阅者对象,用于作为订阅公共事件的载体,订阅公共事件并获取公共事件传递而来的参数。订阅部分系统公共事件需要先[申请权限](../security/accesstoken-guidelines.md),订阅这些事件所需要的权限请见[公共事件权限列表](../reference/apis/js-apis-commonEvent.md#support)
## 接口说明
详细接口见[接口文档](../reference/apis/js-apis-commonEvent.md#commoneventcreatesubscriber)
| 接口名 | 接口描述 |
| -------- | -------- |
| createSubscriber(subscribeInfo:&nbsp;[CommonEventSubscribeInfo](../reference/apis/js-apis-commonEvent.md#commoneventsubscribeinfo),&nbsp;callback:&nbsp;AsyncCallback&lt;[CommonEventData](../reference/apis/js-apis-commonEvent.md#commoneventdata)&gt;):&nbsp;void | 创建订阅者对象(callback) |
| createSubscriber(subscribeInfo:&nbsp;CommonEventSubscribeInfo):&nbsp;Promise&lt;CommonEventSubscriber&gt; | 创建订阅者对象(promise) |
| subscribe(subscriber:&nbsp;CommonEventSubscriber,&nbsp;callback:&nbsp;AsyncCallback):&nbsp;void | 订阅公共事件 |
## 开发步骤
1. 导入CommonEvent模块。
```ts
import commonEvent from '@ohos.commonEventManager';
```
2. 创建订阅者信息,详细的订阅者信息数据类型及包含的参数请见[CommonEventSubscribeInfo](../reference/apis/js-apis-commonEvent.md#commoneventsubscribeinfo)文档介绍。
```ts
// 用于保存创建成功的订阅者对象,后续使用其完成订阅及退订的动作
let subscriber = null;
// 订阅者信息
let subscribeInfo = {
events: ["usual.event.SCREEN_OFF"], // 订阅灭屏公共事件
}
```
3. 创建订阅者,保存返回的订阅者对象subscriber,用于执行后续的订阅、退订等操作。
```ts
// 创建订阅者回调
commonEvent.createSubscriber(subscribeInfo, (err, data) => {
if (err) {
console.error(`[CommonEvent] CreateSubscriberCallBack err=${JSON.stringify(err)}`);
} else {
console.info(`[CommonEvent] CreateSubscriber success`);
subscriber = data;
// 订阅公共事件回调
}
})
```
4. 创建订阅回调函数,订阅回调函数会在接收到事件时触发。订阅回调函数返回的data内包含了公共事件的名称、发布者携带的数据等信息,公共事件数据的详细参数和数据类型请见[CommonEventData](../reference/apis/js-apis-commonEvent.md#commoneventdata)文档介绍。
```ts
// 订阅公共事件回调
if (subscriber !== null) {
commonEvent.subscribe(subscriber, (err, data) => {
if (err) {
console.error(`[CommonEvent] SubscribeCallBack err=${JSON.stringify(err)}`);
} else {
console.info(`[CommonEvent] SubscribeCallBack data=${JSON.stringify(data)}`);
}
})
} else {
console.error(`[CommonEvent] Need create subscriber`);
}
```
# 公共事件取消订阅
## 场景介绍
订阅者完成业务需要时,需要主动取消订阅,订阅者通过下面方法取消订阅事件。
## 接口说明
| 接口名 | 接口描述 |
| -------- | -------- |
| unsubscribe(subscriber:&nbsp;CommonEventSubscriber,&nbsp;callback?:&nbsp;AsyncCallback) | 取消订阅公共事件 |
## 开发步骤
1. 导入CommonEvent模块。
```ts
import commonEvent from '@ohos.commonEventManager';
```
2. 根据[事件订阅章节](common-event-subscription.md)的步骤来订阅某个事件。
3. 调用CommonEvent中的unsubscribe方法取消订阅某事件。
```ts
// subscriber为订阅事件时创建的订阅者对象
if (subscriber !== null) {
commonEvent.unsubscribe(subscriber, (err) => {
if (err) {
console.error(`[CommonEvent] UnsubscribeCallBack err=${JSON.stringify(err)}`)
} else {
console.info(`[CommonEvent] Unsubscribe`)
subscriber = null
}
})
}
```
# 组件启动规则
启动组件是指一切启动或连接Ability的行为:
- 启动Ability,如使用startAbility()、startServiceExtensionAbility()、startAbilityByCall()等相关接口。
- 连接Ability,如使用connectAbility()、connectServiceExtensionAbility()、acquireDataAbilityHelper()、createDataShareHelper()等相关接口。
在OpenHarmony中,为了保证用户具有更好的使用体验,对以下几种易影响用户体验与系统安全的行为做了限制:
- 后台应用任意弹框,如各种广告弹窗,影响用户使用。
- 后台应用相互唤醒,不合理的占用系统资源,导致系统功耗增加或系统卡顿。
- 前台应用任意跳转至其他应用,如随意跳转到其他应用的支付Ability,存在安全风险。
鉴于此,OpenHarmony制订了一套组件启动规则,主要包括:
- 应用位于后台时,启动组件需鉴权。
- 跨应用启动visible为false的组件,需鉴权。
- 跨应用启动FA模型的ServiceAbility组件或DataAbility组件,对端应用需配置关联启动。
- 使用startAbilityByCall接口,需鉴权(使用方式参考:[Call调用开发指南](hop-multi-device-collaboration.md#通过跨设备call调用实现多端协同)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 1. 组件启动管控自OpenHarmony v3.2 Release版本开始落地。
>
> 2. 与原本的启动规则不同,新的组件启动规则较为严格,开发者需熟知启动规则,避免业务功能异常。
## 相关概念说明
为方便开发者理解管控规则,此处对所涉及的相关概念进行解释。
- **应用APL(Ability Privilege Level)**,表示应用的权限申请优先级的定义,不同APL等级的应用所能申请的权限不同,APL分为3个等级:
- 操作系统核心能力APL="system_core" (APL = 3)
- 系统基础服务APL="system_basic" (APL = 2)
- 三方应用程序APL="normal" (APL = 1)
- **注:三方应用默认都是APL="normal"**
- **BACKGROUND校验**
- 对发起端应用进程的状态进行判断,若应用进程获焦或所属的Ability位于前台则判定为前台应用,否则为后台应用
- 若发起端为后台应用,则需校验START_ABILITIES_FROM_BACKGROUND权限
- **VISIBLE校验**
- 只针对跨应用启动的场景
- 若目标组件visible配置为false,则需校验START_INVISIBLE_ABILITY权限
- **CALL校验**
- 只针对startAbilityByCall接口
- 需校验ABILITY_BACKGROUND_COMMUNICATION权限
- **关联启动(AssociateWakeUp)**
- 只有系统预置应用才允许配置AssociateWakeUp字段,其余应用AssociateWakeUp默认为**false**
- 只针对跨应用场景
- 只针对目标组件为**FA**模型的**ServiceAbility****DataAbility**生效
- 目标应用的AssociateWakeUp为**ture**,其提供的ServiceAbility与DataAbility才允许被其他应用访问
- **相关权限**
```json
{
"name": "ohos.permission.START_ABILITIES_FROM_BACKGROUND",
"grantMode": "system_grant",
"availableLevel": "system_basic", // APL等级至少为system_basic才可申请
"since": 9,
"deprecated": "",
"provisionEnable": true, // 支持ACL方式申请权限
"distributedSceneEnable": false
},
{
"name": "ohos.permission.START_INVISIBLE_ABILITY",
"grantMode": "system_grant",
"availableLevel": "system_core", // APL等级至少为system_core才可申请
"since": 9,
"deprecated": "",
"provisionEnable": true, // 支持ACL方式申请权限
"distributedSceneEnable": false
},
{
"name": "ohos.permission.ABILITY_BACKGROUND_COMMUNICATION",
"grantMode": "system_grant",
"availableLevel": "system_basic", // APL等级至少为system_basic才可申请
"since": 9,
"deprecated": "",
"provisionEnable": true, // 支持ACL方式申请权限
"distributedSceneEnable": false
}
```
## 同设备组件启动管控
不同场景下的管控规则不同,可分为如下三种场景:
- 启动一般组件:(FA模型)PageAbility,(Stage模型)UIAbility、ServiceExtensionAbility、DataShareExtensionAbility。
- 启动FA模型的ServiceAbility或DataAbility。
- 通过startAbilityByCall接口启动(Stage模型)UIAbility。
![startup-rule](figures/startup-rule.png)
## 分布式跨设备组件启动管控
不同场景下的管控规则不同,可分为如下三种场景:
- 启动一般组件:(FA模型)PageAbility,(Stage模型)UIAbility、ServiceExtensionAbility。
- 启动FA模型的ServiceAbility。
- 通过startAbilityByCall接口启动(Stage模型)UIAbility。
![component-startup-rules](figures/component-startup-rules.jpg)
# 配置文件的差异
FA模型应用在[config.json文件](../quick-start/application-configuration-file-overview-fa.md)中描述应用的基本信息,一个应用工程中可以创建多个Module,每个Module中都有一份config.json文件。config.json由app、deviceConfig和module三部分组成,app标签用于配置应用级别的属性,如果一个应用有多个Module,需要由开发者保证各个config.json文件中app标签配置的一致性。
Stage模型应用在[app.json5](../quick-start/app-configuration-file.md)[module.json](../quick-start/module-configuration-file.md)文件中描述应用的基本信息,和FA模型应用类似,一个Stage模型应用工程中同样可以创建多个[Module],但是一个应用工程中仅存在一份app.json5,用于配置应用级别的属性,对每个Module都生效;每个Module中都有一份module.json5配置文件,用于配置Module级别的属性,仅对当前Module生效。
**图1** 配置文件差异
![comparison-of-configuration-file](figures/comparison-of-configuration-file.png)
# 连接ServiceAbility
如果ServiceAbility需要与PageAbility或其他应用的ServiceAbility进行交互,则须创建用于连接的Connection。ServiceAbility支持其他Ability通过connectAbility()方法与其进行连接。PageAbility的connectAbility方法定义在featureAbility中,ServiceAbility的connectAbility方法定义在particleAbility中。连接ServiceAbility的规则详见[组件启动规则](component-startup-rules.md)章节。在使用connectAbility()处理回调时,需要传入目标Service的Want与IAbilityConnection的实例。IAbilityConnection提供了以下方法供开发者实现。
**表1** IAbilityConnection接口说明
| 接口名 | 描述 |
| -------- | -------- |
| onConnect() | 用于处理连接Service成功的回调。 |
| onDisconnect() | 用来处理Service异常死亡的回调。 |
| onFailed() | 用来处理连接Service失败的回调。 |
PageAbility创建连接本地ServiceAbility回调实例的代码以及连接本地ServiceAbility的示例代码如下:
```ts
import rpc from "@ohos.rpc"
import prompt from '@system.prompt'
import featureAbility from '@ohos.ability.featureAbility'
let option = {
onConnect: function onConnectCallback(element, proxy) {
console.info(`onConnectLocalService onConnectDone`)
if (proxy === null) {
prompt.showToast({
message: "Connect service failed"
})
return
}
let data = rpc.MessageParcel.create()
let reply = rpc.MessageParcel.create()
let option = new rpc.MessageOption()
data.writeInterfaceToken("connect.test.token")
proxy.sendRequest(0, data, reply, option)
prompt.showToast({
message: "Connect service success"
})
},
onDisconnect: function onDisconnectCallback(element) {
console.info(`onConnectLocalService onDisconnectDone element:${element}`)
prompt.showToast({
message: "Disconnect service success"
})
},
onFailed: function onFailedCallback(code) {
console.info(`onConnectLocalService onFailed errCode:${code}`)
prompt.showToast({
message: "Connect local service onFailed"
})
}
}
let request = {
bundleName: "com.example.myapplication",
abilityName: "com.example.myapplication.ServiceAbility",
}
let connId = featureAbility.connectAbility(request, option)
```
同时,Service侧也需要在onConnect()时返回IRemoteObject,从而定义与Service进行通信的接口。onConnect()需要返回一个IRemoteObject对象。OpenHarmony提供了IRemoteObject的默认实现,开发者可以通过继承rpc.RemoteObject来创建自定义的实现类。
Service侧把自身的实例返回给调用侧的示例代码如下:
```ts
import rpc from "@ohos.rpc"
class FirstServiceAbilityStub extends rpc.RemoteObject {
constructor(des: any) {
if (typeof des === 'string') {
super(des)
} else {
return
}
}
onRemoteRequest(code: number, data: any, reply: any, option: any) {
console.info(`onRemoteRequest called`)
if (code === 1) {
let string = data.readString()
console.info(`string=${string}`)
let result = Array.from(string).sort().join('')
console.info(`result=${result}`)
reply.writeString(result)
} else {
console.info(`unknown request code`)
}
return true
}
}
```
# Context接口切换
| FA接口 | Stage模型接口对应d.ts文件 | Stage对应接口或字段 |
| -------- | -------- | -------- |
| [getOrCreateLocalDir(callback:AsyncCallback&lt;string&gt;):void;](../reference/apis/js-apis-Context.md#contextgetorcreatelocaldir7)<br/>[getOrCreateLocalDir():Promise&lt;string&gt;;](../reference/apis/js-apis-Context.md#contextgetorcreatelocaldir7-1) | Stage模型无对应接口 | Stage模型应用在应用根目录下没有操作权限,不提供对应接口 |
| [verifyPermission(permission:string,options:PermissionOptions,callback:AsyncCallback&lt;number&gt;):void;](../reference/apis/js-apis-Context.md#contextverifypermission7)<br/>[verifyPermission(permission:string,callback:AsyncCallback&lt;number&gt;):void;](../reference/apis/js-apis-Context.md#contextverifypermission7-1)<br/>[verifyPermission(permission:string,options?:PermissionOptions):Promise&lt;number&gt;;](../reference/apis/js-apis-Context.md#contextverifypermission7-2) | \@ohos.abilityAccessCtrl.d.ts | [verifyAccessTokenSync(tokenID: number, permissionName: Permissions): GrantStatus;](../reference/apis/js-apis-abilityAccessCtrl.md#verifyaccesstokensync9)<br/>[verifyAccessToken(tokenID: number, permissionName: Permissions): Promise&lt;GrantStatus&gt;;](../reference/apis/js-apis-abilityAccessCtrl.md#verifyaccesstoken9) |
| [requestPermissionsFromUser(permissions:Array&lt;string&gt;,requestCode:number,resultCallback:AsyncCallback&lt;PermissionRequestResult&gt;):void;](../reference/apis/js-apis-Context.md#contextrequestpermissionsfromuser7)<br/>[requestPermissionsFromUser(permissions:Array&lt;string&gt;,requestCode:number):Promise&lt;PermissionRequestResult&gt;;](../reference/apis/js-apis-Context.md#contextrequestpermissionsfromuser7-1) | application\UIAbilityContext.d.ts | [requestPermissionsFromUser(permissions: Array&lt;string&gt;, requestCallback: AsyncCallback&lt;PermissionRequestResult&gt;) : void;](../reference/apis/js-apis-ability-context.md#abilitycontextrequestpermissionsfromuser)<br/>[requestPermissionsFromUser(permissions: Array&lt;string&gt;) : Promise&lt;PermissionRequestResult&gt;;](../reference/apis/js-apis-ability-context.md#abilitycontextrequestpermissionsfromuser-1) |
| [getApplicationInfo(callback:AsyncCallback&lt;ApplicationInfo&gt;):void;](../reference/apis/js-apis-Context.md#contextgetapplicationinfo7)<br/>[getApplicationInfo():Promise&lt;ApplicationInfo&gt;;](../reference/apis/js-apis-Context.md#contextgetapplicationinfo7-1) | application\Context.d.ts | [applicationInfo: ApplicationInfo;](../reference/apis/js-apis-application-context.md#属性) |
| [getBundleName(callback : AsyncCallback&lt;string&gt;): void;](../reference/apis/js-apis-Context.md#contextgetbundlename7)<br/>[getBundleName(): Promise&lt;string&gt;;](../reference/apis/js-apis-Context.md#contextgetbundlename7-1) | application\UIAbilityContext.d.ts | [abilityInfo.bundleName: string;](../reference/apis/js-apis-ability-context.md#属性) |
| [getDisplayOrientation(callback : AsyncCallback&lt;bundle.DisplayOrientation&gt;): void;](../reference/apis/js-apis-Context.md#contextgetdisplayorientation7)<br/>[getDisplayOrientation(): Promise&lt;bundle.DisplayOrientation&gt;;](../reference/apis/js-apis-Context.md#contextgetdisplayorientation7-1) | \@ohos.screen.d.ts | [readonly orientation: Orientation;](../reference/apis/js-apis-screen.md#orientation) |
| [setDisplayOrientation(orientation:bundle.DisplayOrientation, callback:AsyncCallback&lt;void&gt;):void;](../reference/apis/js-apis-Context.md#contextsetdisplayorientation7)<br/>[setDisplayOrientation(orientation:bundle.DisplayOrientation):Promise&lt;void&gt;;](../reference/apis/js-apis-Context.md#contextsetdisplayorientation7-1) | \@ohos.screen.d.ts | [setOrientation(orientation: Orientation, callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-screen.md#setorientation)<br/>[setOrientation(orientation: Orientation): Promise&lt;void&gt;;](../reference/apis/js-apis-screen.md#setorientation-1) |
| [setShowOnLockScreen(show:boolean, callback:AsyncCallback&lt;void&gt;):void;](../reference/apis/js-apis-Context.md#contextsetshowonlockscreen7)<br/>[setShowOnLockScreen(show:boolean):Promise&lt;void&gt;;](../reference/apis/js-apis-Context.md#contextsetshowonlockscreen7-1) | \@ohos.window.d.ts | [setShowOnLockScreen(showOnLockScreen: boolean): void;](../reference/apis/js-apis-window.md#setshowonlockscreen9) |
| [setWakeUpScreen(wakeUp:boolean, callback:AsyncCallback&lt;void&gt;):void;](../reference/apis/js-apis-Context.md#contextsetwakeupscreen7)<br/>[setWakeUpScreen(wakeUp:boolean):Promise&lt;void&gt;;](../reference/apis/js-apis-Context.md#contextsetwakeupscreen7-1) | \@ohos.window.d.ts | [setWakeUpScreen(wakeUp: boolean): void;](../reference/apis/js-apis-window.md#setwakeupscreen9) |
| [getProcessInfo(callback:AsyncCallback&lt;ProcessInfo&gt;):void;](../reference/apis/js-apis-Context.md#contextgetprocessinfo7)<br/>[getProcessInfo():Promise&lt;ProcessInfo&gt;;](../reference/apis/js-apis-Context.md#contextgetprocessinfo7-1) | \@ohos.app.ability.abilityManager.d.ts | [getAbilityRunningInfos(callback: AsyncCallback&lt;Array&lt;AbilityRunningInfo&gt;&gt;): void;](../reference/apis/js-apis-application-abilityManager.md#getabilityrunninginfos)<br/>[getAbilityRunningInfos(): Promise&lt;Array&lt;AbilityRunningInfo&gt;&gt;;](../reference/apis/js-apis-application-abilityManager.md#getabilityrunninginfos-1) |
| [getElementName(callback:AsyncCallback&lt;ElementName&gt;):void;](../reference/apis/js-apis-Context.md#contextgetelementname7)<br/>[getElementName():Promise&lt;ElementName&gt;;](../reference/apis/js-apis-Context.md#contextgetelementname7-1) | application\UIAbilityContext.d.ts | [abilityInfo.name: string;](../reference/apis/js-apis-ability-context.md#属性)<br/>[abilityInfo.bundleName: string;](../reference/apis/js-apis-ability-context.md#属性) |
| [getProcessName(callback:AsyncCallback&lt;string&gt;):void;](../reference/apis/js-apis-Context.md#contextgetprocessname7)<br/>[getProcessName():Promise&lt;string&gt;;](../reference/apis/js-apis-Context.md#contextgetprocessname7-1) | \@ohos.app.ability.abilityManager.d.ts | [getAbilityRunningInfos(callback: AsyncCallback&lt;Array&lt;AbilityRunningInfo&gt;&gt;): void;](../reference/apis/js-apis-application-abilityManager.md#getabilityrunninginfos)<br/>[getAbilityRunningInfos(): Promise&lt;Array&lt;AbilityRunningInfo&gt;&gt;;](../reference/apis/js-apis-application-abilityManager.md#getabilityrunninginfos-1) |
| [getCallingBundle(callback:AsyncCallback&lt;string&gt;):void;](../reference/apis/js-apis-Context.md#contextgetcallingbundle7)<br/>[getCallingBundle():Promise&lt;string&gt;;](../reference/apis/js-apis-Context.md#contextgetcallingbundle7-1) | Stage模型无对应接口 | Stage模型应用可以使用Want.parameters的ohos.aafwk.param.callerUid参数,获取调用方的应用信息 |
| [getFilesDir(callback:AsyncCallback&lt;string&gt;):void;](../reference/apis/js-apis-Context.md#contextgetfilesdir)<br/>[getFilesDir():Promise&lt;string&gt;;](../reference/apis/js-apis-Context.md#contextgetfilesdir-1) | application\Context.d.ts | [filesDir: string;](../reference/apis/js-apis-application-context.md#属性) |
| [getCacheDir(callback:AsyncCallback&lt;string&gt;):void;](../reference/apis/js-apis-Context.md#contextgetcachedir)<br/>[getCacheDir():Promise&lt;string&gt;;](../reference/apis/js-apis-Context.md#contextgetcachedir-1) | application\Context.d.ts | [cacheDir: string;](../reference/apis/js-apis-application-context.md#属性) |
| [getOrCreateDistributedDir(callback:AsyncCallback&lt;string&gt;):void;](../reference/apis/js-apis-Context.md#contextgetorcreatedistributeddir7)<br/>[getOrCreateDistributedDir():Promise&lt;string&gt;;](../reference/apis/js-apis-Context.md#contextgetorcreatedistributeddir7-1) | application\Context.d.ts | [distributedFilesDir: string;](../reference/apis/js-apis-application-context.md#属性) |
| [getAppType(callback:AsyncCallback&lt;string&gt;):void;](../reference/apis/js-apis-Context.md#contextgetapptype7)<br/>[getAppType():Promise&lt;string&gt;;](../reference/apis/js-apis-Context.md#contextgetapptype7-1) | application\UIAbilityContext.d.ts | 通过abilityInfo字段的type属性获取<br/>[abilityInfo.type: bundleManager.AbilityType;](../reference/apis/js-apis-ability-context.md#属性) |
| [getHapModuleInfo(callback:AsyncCallback&lt;HapModuleInfo&gt;):void;](../reference/apis/js-apis-Context.md#contextgethapmoduleinfo7)<br/>[getHapModuleInfo():Promise&lt;HapModuleInfo&gt;;](../reference/apis/js-apis-Context.md#contextgethapmoduleinfo7-1) | application\UIAbilityContext.d.ts | [currentHapModuleInfo: HapModuleInfo;](../reference/apis/js-apis-ability-context.md#属性) |
| [getAppVersionInfo(callback:AsyncCallback&lt;AppVersionInfo&gt;):void;](../reference/apis/js-apis-Context.md#contextgetappversioninfo7)<br/>[getAppVersionInfo():Promise&lt;AppVersionInfo&gt;;](../reference/apis/js-apis-Context.md#contextgetappversioninfo7-1) | bundle\bundleInfo.d.ts | [readonly name: string;](../reference/apis/js-apis-bundleManager-bundleInfo.md#bundleinfo-1)<br/>[readonly versionCode: number;](../reference/apis/js-apis-bundleManager-bundleInfo.md#bundleinfo-1)<br/>[readonly versionName: string;](../reference/apis/js-apis-bundleManager-bundleInfo.md#bundleinfo-1) |
| [getApplicationContext():Context;](../reference/apis/js-apis-Context.md#contextgetapplicationcontext7) | application\Context.d.ts | [getApplicationContext(): ApplicationContext;](../reference/apis/js-apis-application-context.md#contextgetapplicationcontext) |
| [getAbilityInfo(callback:AsyncCallback&lt;AbilityInfo&gt;):void;](../reference/apis/js-apis-Context.md#contextgetabilityinfo7)<br/>[getAbilityInfo():Promise&lt;AbilityInfo&gt;;](../reference/apis/js-apis-Context.md#contextgetabilityinfo7-1) | application\UIAbilityContext.d.ts | [abilityInfo: AbilityInfo;](../reference/apis/js-apis-ability-context.md#属性) |
| [isUpdatingConfigurations(callback:AsyncCallback&lt;boolean&gt;):void;](../reference/apis/js-apis-Context.md#contextisupdatingconfigurations7)<br/>[isUpdatingConfigurations():Promise&lt;boolean&gt;;](../reference/apis/js-apis-Context.md#contextisupdatingconfigurations7-1) | Stage模型无对应接口 | OpenHarmony在系统环境变化时,应用不会重启,调用onConfigurationUpdated接口通知应用,该接口在FA模型是空实现接口,Stage模型不提供对应接口 |
| [printDrawnCompleted(callback:AsyncCallback&lt;void&gt;):void;](../reference/apis/js-apis-Context.md#contextprintdrawncompleted7)<br/>[printDrawnCompleted():Promise&lt;void&gt;;](../reference/apis/js-apis-Context.md#contextprintdrawncompleted7-1) | Stage模型无对应接口 | 该接口在FA模型是空实现接口,不影响应用功能,Stage模型不提供对应接口 |
# 创建DataAbility
实现DataAbility中Insert、Query、Update、Delete接口的业务内容。保证能够满足数据库存储业务的基本需求。BatchInsert与ExecuteBatch接口已经在系统中实现遍历逻辑,依赖Insert、Query、Update、Delete接口逻辑,来实现数据的批量处理。
创建DataAbility的代码示例如下:
```ts
import featureAbility from '@ohos.ability.featureAbility'
import dataAbility from '@ohos.data.dataAbility'
import dataRdb from '@ohos.data.rdb'
const TABLE_NAME = 'book'
const STORE_CONFIG = { name: 'book.db' }
const SQL_CREATE_TABLE = 'CREATE TABLE IF NOT EXISTS book(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, introduction TEXT NOT NULL)'
let rdbStore: dataRdb.RdbStore = undefined
export default {
onInitialized(abilityInfo) {
console.info('DataAbility onInitialized, abilityInfo:' + abilityInfo.bundleName)
let context = featureAbility.getContext()
dataRdb.getRdbStore(context, STORE_CONFIG, 1, (err, store) => {
console.info('DataAbility getRdbStore callback')
store.executeSql(SQL_CREATE_TABLE, [])
rdbStore = store
});
},
insert(uri, valueBucket, callback) {
console.info('DataAbility insert start')
rdbStore.insert(TABLE_NAME, valueBucket, callback)
},
batchInsert(uri, valueBuckets, callback) {
console.info('DataAbility batch insert start')
for (let i = 0;i < valueBuckets.length; i++) {
console.info('DataAbility batch insert i=' + i)
if (i < valueBuckets.length - 1) {
rdbStore.insert(TABLE_NAME, valueBuckets[i], (err: any, num: number) => {
console.info('DataAbility batch insert ret=' + num)
})
} else {
rdbStore.insert(TABLE_NAME, valueBuckets[i], callback)
}
}
},
query(uri, columns, predicates, callback) {
console.info('DataAbility query start')
let rdbPredicates = dataAbility.createRdbPredicates(TABLE_NAME, predicates)
rdbStore.query(rdbPredicates, columns, callback)
},
update(uri, valueBucket, predicates, callback) {
console.info('DataAbilityupdate start')
let rdbPredicates = dataAbility.createRdbPredicates(TABLE_NAME, predicates)
rdbStore.update(valueBucket, rdbPredicates, callback)
},
delete(uri, predicates, callback) {
console.info('DataAbilitydelete start')
let rdbPredicates = dataAbility.createRdbPredicates(TABLE_NAME, predicates)
rdbStore.delete(rdbPredicates, callback)
}
};
```
# 创建PageAbility
开发者需要重写app.js/app.ets中的生命周期回调函数,开发者通过DevEco Studio开发平台创建PageAbility时,DevEco Studio会在app.js/app.ets中默认生成onCreate()和onDestroy()方法,其他方法需要开发者自行实现。接口说明参见前述章节,创建PageAbility示例如下:
```ts
export default {
onCreate() {
console.info('Application onCreate')
},
onDestroy() {
console.info('Application onDestroy')
},
onShow() {
console.info('Application onShow')
},
onHide() {
console.info('Application onHide')
},
onActive() {
console.info('Application onActive')
},
onInactive() {
console.info('Application onInactive')
},
onNewWant() {
console.info('Application onNewWant')
},
}
```
PageAbility创建成功后,其abilities相关的配置项在config.json中体现,一个名字为MainAbility的config.json配置文件示例如下:
```json
{
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"orientation": "unspecified",
"visible": true,
"srcPath": "MainAbility",
"name": ".MainAbility",
"srcLanguage": "ets",
"icon": "$media:icon",
"description": "$string:MainAbility_desc",
"formsEnabled": false,
"label": "$string:MainAbility_label",
"type": "page",
"launchType": "singleton"
}
]
}
```
FA模型中,可以通过featureAbility的getContext接口获取应用上下文,进而使用上下文提供的能力。
**表1** featureAbility接口说明
| 接口名 | 接口描述 |
| -------- | -------- |
| getContext() | 获取应用上下文。 |
通过getContext获取应用上下文并获取分布式目录的示例如下:
```ts
import featureAbility from '@ohos.ability.featureAbility'
import fileIo from '@ohos.fileio'
(async () => {
let dir: string
try {
console.info('Begin to getOrCreateDistributedDir')
dir = await featureAbility.getContext().getOrCreateDistributedDir()
console.info('distribute dir is ' + dir)
} catch (error) {
console.error('getOrCreateDistributedDir failed with ' + error)
}
let fd: number;
let path = dir + "/a.txt";
fd = fileIo.openSync(path, 0o2 | 0o100, 0o666);
fileIo.close(fd);
})()
```
# 创建ServiceAbility
1. 创建ServiceAbility。
重写ServiceAbility的生命周期方法,添加其他Ability请求与ServiceAbility交互时的处理方法。
```ts
import rpc from "@ohos.rpc"
class FirstServiceAbilityStub extends rpc.RemoteObject {
constructor(des: any) {
if (typeof des === 'string') {
super(des)
} else {
return
}
}
}
export default {
onStart() {
console.info('ServiceAbility onStart')
},
onStop() {
console.info('ServiceAbility onStop')
},
onCommand(want, startId) {
console.info('ServiceAbility onCommand')
},
onConnect(want) {
console.info('ServiceAbility onConnect' + want)
return new FirstServiceAbilityStub('test')
},
onDisconnect(want) {
console.info('ServiceAbility onDisconnect' + want)
}
}
```
2. 注册ServiceAbility。
ServiceAbility需要在应用配置文件config.json中进行注册,注册类型type需要设置为service。"visible"属性表示ServiceAbility是否可以被其他应用调用,true表示可以被其他应用调用,false表示不能被其他应用调用(仅应用内可以调用)。若ServiceAbility需要被其他应用调用,注册ServiceAbility时需要设置"visible"为true,同时需要设置支持关联启动。ServiceAbility的启动规则详见[组件启动规则](component-startup-rules.md)章节。
```json
{
"module": {
"abilities": [
{
"name": ".ServiceAbility",
"srcLanguage": "ets",
"srcPath": "ServiceAbility",
"icon": "$media:icon",
"description": "hap sample empty service",
"type": "service",
"visible": true
}
]
}
}
```
# 应用间使用Want分享数据
在应用使用场景中,用户经常需要将一个应用内的数据(如文字、图片等)分享至另一个应用内继续操作。下面以PDF文件分享为例,介绍应用间使用Want分享数据的方法。
## 前提条件
1. 数据分享涉及2个UIAbility组件(分享方和被分享方)和1个系统部件(应用选择框)。当分享方通过startAbility接口发起数据分享后,将拉起应用选择框。其将**隐式匹配并展示**所有支持接受分享数据类型的应用,由用户主动选取,并由系统拉起点击应用完成数据的分享。
2. 在本章节中,将继续以按钮形式来触发分享,实际开发场景中并不局限于此,此章节着重讲解分享时Want的配置。
3. 本章节涉及的action:
- ACTION_SELECT (ohos.want.action.select):指示显示应用程序选择框的操作。用于拉起应用选择框。
- ACTION_SEND_DATA (ohos.want.action.sendData):指示发送单个数据记录的操作。用于传递数据至分享方。
## 开发步骤
- 分享方
1. Stage模型下经常会遇到需要分享文件的场景,在这种场景下我们需要使用[文件描述符(FD)](../reference/apis/js-apis-fileio.md#fileioopensync)来传递文件。此示例中,默认已获取分享文件的路径。
```ts
import fileIO from '@ohos.fileio';
// let path = ...
// file open where path is a variable contains the file path.
let fileFd = fileIO.openSync(path, 0o102, 0o666);
```
2. 在前提条件中介绍了分享的流程。分享方需先拉起应用选择框,并将数据分享给应用选择框,并由应用选择框代理传递至被分享方,完成分享。因此分享方的Want需使用2层嵌套,在第1层中使用隐式Want并配合“ohos.want.action.select”action拉起应用选择框,并在自定义字段parameters内声明一个完整的want作为第2层,其中声明传递给被分享方的数据。
```ts
import wantConstant from '@ohos.app.ability.wantConstant';
// let path = ...
// let fileFd = ...
// let fileSize = ...
let want = {
// This action is used to implicitly match the application selctor.
action: wantConstant.Action.ACTION_SELECT,
// This is the custom parameter in the first layer of want
// which is intended to add info to application selector.
parameters: {
// The MIME type of pdf
"ability.picker.type": "application/pdf",
"ability.picker.fileNames": [path],
"ability.picker.fileSizes": [fileSize],
// This a nested want which will be directly send to the user selected application.
"ability.want.params.INTENT": {
"action": "ohos.want.action.sendData",
"type": "application/pdf",
"parameters": {
"keyFd": {"type": "FD", "value": fileFd}
}
}
}
}
```
以上代码中使用Want自定义字段paramters,其中第一层paramters中的“ability.picker.\*”字段用于传递展示信息给应用选择器,具体字段表示为:
- "ability.picker.type":应用选择器根据该字段渲染相应的文件类型图标。
- "ability.picker.fileNames":应用选择器根据该字段展示文件名。
- "ability.picker.fileSizes":应用选择器根据该字段展示文件大小。以字节为单位。
- "ability.picker.fileNames"与"ability.picker.fileSizes"为数组,其有一一对应关系。
例如:当"ability.picker.type"为“application/pdf”,"ability.picker.fileNames"为“["接口文档.pdf"]”,"ability.picker.fileSizes"为“[350 \* 1024]”时,应用选择器将以下形式展示。
<img src="figures/stage-want2.png" alt="stage-want2" style="zoom:50%;" />
示例代码中“ability.want.params.INTENT”字段是一个嵌套Want,内部所含action、type等字段将由应用选择器进行隐式匹配,具体隐式匹配规则可参考[隐式Want匹配原理详解](explicit-implicit-want-mappings.md#隐式want匹配原理详解)。当用户选择具体应用后,“ability.want.params.INTENT”字段的嵌套Want将传递至所选应用。
- 被分享方:
1. 上文中提到,应用选择器通过“ability.want.params.INTENT”字段进行隐式匹配。因此被分享方Ability配置文件内(stage模型下的module.json5)skills字段需配置如下。
```ts
"skills": [
{
"entities": [
// ...
],
"actions": [
"ohos.want.action.sendData"
// ...
],
"uris": [
{
"type": "application/pdf"
},
// ...
]
},
]
```
其中"actions"字段和“uris”内“type”字段分别与“ability.want.params.INTENT”内“action”,“type”字段匹配。
注意:当前文件传递不支持uri方式传递,仅支持FD方式,但隐式匹配中,Want内的“type”字段需与被分享方配置文件skills内“uris”字段下的“type”字段匹配,因此skills内的“uris”字段建议只声明“type”字段,增加“host”,“port”等字段在上述示例中将匹配失败。因为应用选择框通过“ability.want.params.INTENT”发起隐式匹配,所以在“ability.want.params.INTENT”字段内增加uri字段,且与skills内的“uris”字段匹配时,仍可匹配成功且传递额外数据。
2. 应用选择器拉起被分享方后,系统将调用其“onCreate”接口,并传入“ability.want.params.INTENT”至其入参want内。
```ts
onCreate(want, launchParam) {
// note when keyFd is undefined, app crash will happen.
if (want["parameters"]["keyFd"] !== undefined) {
// receive file descriptor
let fd = want["parameters"]["keyFd"].value;
// ...
}
}
```
# DataAbility组件配置
## URI介绍
DataAbility的提供方和使用方都通过URI(Uniform Resource Identifier)来标识一个具体的数据,例如数据库中的某个表或磁盘上的某个文件。OpenHarmony的URI仍基于URI通用标准,格式如下:
![fa-dataability-uri](figures/fa-dataability-uri.png)
- scheme:协议方案名,固定为"dataability",代表Data Ability所使用的协议类型。
- authority:设备ID。如果为跨设备场景,则为目标设备的ID;如果为本地设备场景,则不需要填写。
- path:资源的路径信息,代表特定资源的位置信息。
- query:查询参数。
- fragment:可以用于指示要访问的子资源。
URI示例:
- 跨设备场景:dataability://_device_id_/_com.domainname.dataability.persondata_/_person_/_10_
- 本地设备:dataability:///_com.domainname.dataability.persondata_/_person_/_1_
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 本地设备的"device_id"字段为空,因此在"dataability:"后面有三个"/"。
## 部分配置项介绍
与PageAbility类似,DataAbility的相关配置在config.json配置文件的"module"对象的"abilities"对象中,与PageAbility的区别在于"type"属性及"uri"属性。
**表1** DataAbility的部分配置项说明
| Json重要字段 | 备注说明 |
| -------- | -------- |
| "name" | Ability名称。 |
| "type" | UIAbility类型,DataAbility的类型为"data"。 |
| "uri" | 通信使用的URI。 |
| "visible" | 对其他应用是否可见,设置为true时,DataAbility才能与其他应用进行通信传输数据。 |
config.json配置样例
```json
"abilities": [{
"srcPath": "DataAbility",
"name": ".DataAbility",
"icon": "$media:icon",
"srcLanguage": "ets",
"description": "$string:description_dataability",
"type": "data",
"visible": true,
"uri": "dataability://ohos.samples.etsdataability.DataAbility"
}]
```
DataAbility支持的配置项及详细说明详见[module对象内部结构](../quick-start/module-structure.md)
# DataAbility的生命周期
应用开发者可以根据业务场景重写生命周期相关接口。DataAbility生命周期接口说明见下表。
**表1** DataAbility相关生命周期API功能介绍
| 接口名 | 描述 |
| -------- | -------- |
| onInitialized?(info:&nbsp;AbilityInfo):&nbsp;void | 在Ability初始化调用,通过此回调方法执行RDB等初始化操作。 |
| update?(uri:&nbsp;string,&nbsp;valueBucket:&nbsp;rdb.ValuesBucket,&nbsp;predicates:&nbsp;dataAbility.DataAbilityPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void | 更新数据库中的数据。 |
| query?(uri:&nbsp;string,&nbsp;columns:&nbsp;Array&lt;string&gt;,&nbsp;predicates:&nbsp;dataAbility.DataAbilityPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;ResultSet&gt;):&nbsp;void | 查询数据库中的数据。 |
| delete?(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataAbility.DataAbilityPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void | 删除一条或多条数据。 |
| normalizeUri?(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void | 对URI进行规范化。一个规范化的URI可以支持跨设备使用、持久化、备份和还原等,当上下文改变时仍然可以引用到相同的数据项。 |
| batchInsert?(uri:&nbsp;string,&nbsp;valueBuckets:&nbsp;Array&lt;rdb.ValuesBucket&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void | 向数据库中插入多条数据。 |
| denormalizeUri?(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void | 将一个由normalizeUri生产的规范化URI转换成非规范化的URI。 |
| insert?(uri:&nbsp;string,&nbsp;valueBucket:&nbsp;rdb.ValuesBucket,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void | 向数据中插入一条数据。 |
| openFile?(uri:&nbsp;string,&nbsp;mode:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void | 打开一个文件。 |
| getFileTypes?(uri:&nbsp;string,&nbsp;mimeTypeFilter:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;Array&lt;string&gt;&gt;):&nbsp;void | 获取文件的MIME类型。 |
| getType?(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void | 获取URI指定数据相匹配的MIME类型。 |
| executeBatch?(ops:&nbsp;Array&lt;DataAbilityOperation&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;Array&lt;DataAbilityResult&gt;&gt;):&nbsp;void | 批量操作数据库中的数据。 |
| call?(method:&nbsp;string,&nbsp;arg:&nbsp;string,&nbsp;extras:&nbsp;PacMap,&nbsp;callback:&nbsp;AsyncCallback&lt;PacMap&gt;):&nbsp;void | 自定义方法。 |
# DataAbility组件概述
DataAbility,即"使用Data模板的Ability",主要用于对外部提供统一的数据访问抽象,不提供用户交互界面。DataAbility可由PageAbility、ServiceAbility或其他应用启动,即使用户切换到其他应用,DataAbility仍将在后台继续运行。
使用DataAbility有助于应用管理其自身和其他应用存储数据的访问,并提供与其他应用共享数据的方法。DataAbility既可用于同设备不同应用的数据共享,也支持跨设备不同应用的数据共享。
数据的存放形式多样,可以是数据库,也可以是磁盘上的文件。DataAbility对外提供对数据的增、删、改、查,以及打开文件等接口,这些接口的具体实现由开发者提供。
# DataAbility权限控制
DataAbility提供数据服务,并不是所有的Ability都有权限读写它,DataAbility有一套权限控制机制来保证数据安全。分为静态权限控制和动态权限控制两部分。
## 静态权限控制
DataAbility作为服务端,在被拉起的时候,会根据config.json里面配置的权限来进行校验,有"readPermission"、"writePermission"和"Permission"三个配置项,可以不配或者为空。示例如下:
```json
"abilities": [{
"srcPath": "DataAbility",
"name": ".DataAbility",
"icon": "$media:icon",
"srcLanguage": "ets",
"description": "$string:description_dataability",
"type": "data",
"visible": true,
"uri": "dataability://ohos.samples.etsdataability.DataAbility",
"readPermission":"ohos.permission.READ_CONTACTS",
"writePermission":"ohos.permission.WRITE_CONTACTS"
}]
```
客户端在拉起DataAbility的时候,需要校验客户端是否有权限拉起该DataAbility。客户端的权限配置在config.json配置文件的"module"对象的"reqPermissions"对象中,示例如下:
```json
{
"module": {
"reqPermissions":{
{
"name":"ohos.permission.READ_CONTACTS"
},
{
"name":"ohos.permission.WRITE_CONTACTS"
}
}
}
}
```
## 动态权限控制
静态权限校验只能控制某个DataAbility是否能被另一个Ability或应用拉起,无法精确校验每个读写接口的权限,因为拉起DataAbility的时候,还不知道应用是否需要读写它的数据。
动态权限控制是校验每个数据操作的接口是否有对应的权限。客户端调用数据操作接口所需的权限如下表所示。
**表1** 接口对应的读写权限配置
| 需要配置读权限的接口 | 需要配置写权限的接口 | 据实际操作配置读写权限的接口 |
| -------- | -------- | -------- |
| query、normalizeUri、denormalizeUri、openfile(传入mode有'r') | insert、batchInsert、delete、update、openfile(传入mode有'w') | executeBatch |
对于需要配置读权限的接口,服务端需要配置readPermission,客户端必须申请相应的读权限才能调用相关的接口。
对于需要配置写权限的接口,服务端需要配置writePermission,客户端必须申请相应的写权限才能调用相关的接口。
# DataAbility切换
FA模型中的DataAbility对应Stage模型中的DataShareExtensionAbility。
与ServiceExtensionAbility类似,Stage模型下的DataShareExtensionAbility为系统API,只有系统应用才可以创建。因此,FA模型的DataAbility的切换,对于系统应用和三方应用策略有所不同。下面分别介绍这两种场景。
## 系统应用DataAbility切换至DataShareExtensionAbility
迁移步骤和PageAbility基本一致。
1. 在Stage应用中创建DataShareExtensionAbility。
2. 将FA应用中DataAbility的业务代码迁移到新创建的DataShareExtensionAbility中。
DataAbility和DataShareExtensionAbility生命周期对比见下表。
| FA的DataAbility | Stage的DataShareExtensionAbility | 对比描述 |
| -------- | -------- | -------- |
| onInitialized?(info:&nbsp;AbilityInfo):&nbsp;void | onCreate?(want:&nbsp;Want,&nbsp;callback:<br/>AsyncCallback&lt;void&gt;):&nbsp;void | 两者调用时机一致,函数名即入参都不一样,Stage模型下增加了入参want以便开发者在创建时获取参数。 |
| update?(uri:&nbsp;string,&nbsp;valueBucket:&nbsp;rdb.ValuesBucket,&nbsp;predicates:&nbsp;dataAbility.DataAbilityPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void | update?(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataSharePredicates.DataSharePredicates,&nbsp;value:&nbsp;ValuesBucket,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void | 两者意义和调用时机一致,参数顺序和参数类型略有不同,需要简单改造。 |
| query?(uri:&nbsp;string,&nbsp;columns:&nbsp;Array&lt;string&gt;,&nbsp;predicates:&nbsp;dataAbility.DataAbilityPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;ResultSet&gt;):&nbsp;void | query?(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataSharePredicates.DataSharePredicates,&nbsp;columns:&nbsp;Array&lt;string&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;Object&gt;):&nbsp;void; | 两者意义和调用时机一致,参数顺序和参数类型略有不同,需要简单改造。 |
| delete?(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataAbility.DataAbilityPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void | delete?(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataSharePredicates.DataSharePredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;): | 两者意义和调用时机一致,参数类型略有不同,需要简单改造。 |
| normalizeUri?(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void | normalizeUri?(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void | 两者意义和调用时机一致,参数也一致。 |
| batchInsert?(uri:&nbsp;string,&nbsp;valueBuckets:&nbsp;Array&lt;rdb.ValuesBucket&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void | batchInsert?(uri:&nbsp;string,&nbsp;values:&nbsp;Array&lt;ValuesBucket&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void | 两者意义和调用时机一致,参数类型略有不同,需要简单改造。 |
| denormalizeUri?(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void | denormalizeUri?(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void | 两者意义和调用时机一致,参数也一致。 |
| insert?(uri:&nbsp;string,&nbsp;valueBucket:&nbsp;rdb.ValuesBucket,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void | insert?(uri:&nbsp;string,&nbsp;value:&nbsp;ValuesBucket,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void | 两者意义和调用时机一致,参数类型略有不同,需要简单改造。 |
| openFile?(uri:&nbsp;string,&nbsp;mode:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void | NA | Stage模型不支持uri跨进程访问,建议通过[want携带FD和文件信息](../application-models/data-share-via-want.md)进行跨进程文件访问 |
| getFileTypes?(uri:&nbsp;string,&nbsp;mimeTypeFilter:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;Array&lt;string&gt;&gt;):&nbsp;void | NA | Stage模型不支持uri跨进程访问,建议通过[want携带FD和文件信息](../application-models/data-share-via-want.md)进行跨进程文件访问 |
| getType?(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void | NA | Stage模型不支持uri跨进程访问,建议通过[want携带FD和文件信息](../application-models/data-share-via-want.md)进行跨进程文件访问 |
| executeBatch?(ops:&nbsp;Array&lt;DataAbilityOperation&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;Array&lt;DataAbilityResult&gt;&gt;):&nbsp;void | NA | DataShareExtensonAbility不提供该接口,开发者需根据业务功能重新实现。 |
| call?(method:&nbsp;string,&nbsp;arg:&nbsp;string,&nbsp;extras:&nbsp;PacMap,&nbsp;callback:&nbsp;AsyncCallback&lt;PacMap&gt;):&nbsp;void | NA | DataShareExtensonAbility不提供该接口,开发者需根据业务功能重新实现。 |
## 三方应用DataAbility改造为公共模块
Stage模型三方应用不能对其他三方提供数据,应用需要根据具体业务选择切换方案。
| DataAbility业务类型 | 切换DataShareExtension策略 |
| -------- | -------- |
| 对三方提供数据 | 需根据业务场景匹配到系统对应的场景化[ExtensionAbility](../reference/apis/js-apis-bundleManager.md#extensionabilitytype)。 |
| 应用内使用的数据 | 对应用内其他组件提供数据,建议提取公共模块。 |
# DataAbilityHelper接口切换
| FA模型接口 | Stage模型接口对应d.ts文件 | Stage模型对应接口 |
| -------- | -------- | -------- |
| [openFile(uri:&nbsp;string,&nbsp;mode:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperopenfile)<br/>[openFile(uri:&nbsp;string,&nbsp;mode:&nbsp;string):&nbsp;Promise&lt;number&gt;;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperopenfile-1) | \@ohos.data.fileAccess.d.ts | [openFile(uri:&nbsp;string,&nbsp;flags:&nbsp;OPENFLAGS)&nbsp;:&nbsp;Promise&lt;number&gt;;](../reference/apis/js-apis-fileAccess.md#fileaccesshelperopenfile)<br/>[openFile(uri:&nbsp;string,&nbsp;flags:&nbsp;OPENFLAGS,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;)&nbsp;:&nbsp;void;](../reference/apis/js-apis-fileAccess.md#fileaccesshelperopenfile) |
| [on(type:&nbsp;'dataChange',&nbsp;uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperon) | \@ohos.data.dataShare.d.ts | [on(type:&nbsp;'dataChange',&nbsp;uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-data-dataShare.md#ondatachange) |
| [off(type:&nbsp;'dataChange',&nbsp;uri:&nbsp;string,&nbsp;callback?:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperoff) | \@ohos.data.dataShare.d.ts | [off(type:&nbsp;'dataChange',&nbsp;uri:&nbsp;string,&nbsp;callback?:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-data-dataShare.md#offdatachange) |
| [getType(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelpergettype)<br/>[getType(uri:&nbsp;string):&nbsp;Promise&lt;string&gt;;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelpergettype-1) | Stage模型无对应接口 | Stage模型不支持uri跨进程访问,建议通过[want携带fd和文件信息](data-share-via-want.md#开发步骤)进行跨进程文件访问 |
| [getFileTypes(uri:&nbsp;string,&nbsp;mimeTypeFilter:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;Array&lt;string&gt;&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelpergetfiletypes)<br/>[getFileTypes(uri:&nbsp;string,&nbsp;mimeTypeFilter:&nbsp;string):&nbsp;Promise&lt;Array&lt;string&gt;&gt;;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelpergetfiletypes-1) | Stage模型无对应接口 | Stage模型不支持uri跨进程访问,建议通过[want携带fd和文件信息](data-share-via-want.md#开发步骤)进行跨进程文件访问 |
| [normalizeUri(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelpernormalizeuri)<br/>[normalizeUri(uri:&nbsp;string):&nbsp;Promise&lt;string&gt;;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelpernormalizeuri-1) | \@ohos.data.dataShare.d.ts | [normalizeUri(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void;](../reference/apis/js-apis-data-dataShare.md#normalizeuri)<br/>[normalizeUri(uri:&nbsp;string):&nbsp;Promise&lt;string&gt;;](../reference/apis/js-apis-data-dataShare.md#normalizeuri-1) |
| [denormalizeUri(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperdenormalizeuri)<br/>[denormalizeUri(uri:&nbsp;string):&nbsp;Promise&lt;string&gt;;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperdenormalizeuri-1) | \@ohos.data.dataShare.d.ts | [denormalizeUri(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void;](../reference/apis/js-apis-data-dataShare.md#denormalizeuri)<br/>[denormalizeUri(uri:&nbsp;string):&nbsp;Promise&lt;string&gt;;](../reference/apis/js-apis-data-dataShare.md#denormalizeuri-1) |
| [notifyChange(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelpernotifychange)<br/>[notifyChange(uri:&nbsp;string):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelpernotifychange-1) | \@ohos.data.dataShare.d.ts | [notifyChange(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-data-dataShare.md#notifychange)<br/>[notifyChange(uri:&nbsp;string):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-data-dataShare.md#notifychange-1) |
| [insert(uri:&nbsp;string,&nbsp;valuesBucket:&nbsp;rdb.ValuesBucket,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperinsert)<br/>[insert(uri:&nbsp;string,&nbsp;valuesBucket:&nbsp;rdb.ValuesBucket):&nbsp;Promise&lt;number&gt;;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperinsert-1) | \@ohos.data.dataShare.d.ts | [insert(uri:&nbsp;string,&nbsp;value:&nbsp;ValuesBucket,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-data-dataShare.md#insert)<br/>[insert(uri:&nbsp;string,&nbsp;value:&nbsp;ValuesBucket):&nbsp;Promise&lt;number&gt;;](../reference/apis/js-apis-data-dataShare.md#insert-1) |
| [batchInsert(uri:&nbsp;string,&nbsp;valuesBuckets:&nbsp;Array&lt;rdb.ValuesBucket&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperbatchinsert)<br/>[batchInsert(uri:&nbsp;string,&nbsp;valuesBuckets:&nbsp;Array&lt;rdb.ValuesBucket&gt;):&nbsp;Promise&lt;number&gt;;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperbatchinsert-1) | \@ohos.data.dataShare.d.ts | [batchInsert(uri:&nbsp;string,&nbsp;values:&nbsp;Array&lt;ValuesBucket&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-data-dataShare.md#batchinsert)<br/>[batchInsert(uri:&nbsp;string,&nbsp;values:&nbsp;Array&lt;ValuesBucket&gt;):&nbsp;Promise&lt;number&gt;;](../reference/apis/js-apis-data-dataShare.md#batchinsert-1) |
| [delete(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataAbility.DataAbilityPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperdelete)<br/>[delete(uri:&nbsp;string,&nbsp;predicates?:&nbsp;dataAbility.DataAbilityPredicates):&nbsp;Promise&lt;number&gt;;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperdelete-1)<br/>[delete(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperdelete) | \@ohos.data.dataShare.d.ts | [delete(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataSharePredicates.DataSharePredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-data-dataShare.md#delete)<br/>[delete(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataSharePredicates.DataSharePredicates):&nbsp;Promise&lt;number&gt;;](../reference/apis/js-apis-data-dataShare.md#delete-1) |
| [update(uri:&nbsp;string,&nbsp;valuesBucket:&nbsp;rdb.ValuesBucket,&nbsp;predicates:&nbsp;dataAbility.DataAbilityPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperupdate)<br/>[update(uri:&nbsp;string,&nbsp;valuesBucket:&nbsp;rdb.ValuesBucket,&nbsp;predicates?:&nbsp;dataAbility.DataAbilityPredicates):&nbsp;Promise&lt;number&gt;;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperupdate-1)<br/>[update(uri:&nbsp;string,&nbsp;valuesBucket:&nbsp;rdb.ValuesBucket,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperupdate) | \@ohos.data.dataShare.d.ts | [update(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataSharePredicates.DataSharePredicates,&nbsp;value:&nbsp;ValuesBucket,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-data-dataShare.md#update)<br/>[update(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataSharePredicates.DataSharePredicates,&nbsp;value:&nbsp;ValuesBucket):&nbsp;Promise&lt;number&gt;;](../reference/apis/js-apis-data-dataShare.md#update-1) |
| [query(uri:&nbsp;string,&nbsp;columns:&nbsp;Array&lt;string&gt;,&nbsp;predicates:&nbsp;dataAbility.DataAbilityPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;ResultSet&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperquery)<br/>[query(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;ResultSet&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperquery)<br/>[query(uri:&nbsp;string,&nbsp;columns:&nbsp;Array&lt;string&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;ResultSet&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperquery)<br/>[query(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataAbility.DataAbilityPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;ResultSet&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperquery)<br/>[query(uri:&nbsp;string,&nbsp;columns?:&nbsp;Array&lt;string&gt;,&nbsp;predicates?:&nbsp;dataAbility.DataAbilityPredicates):&nbsp;Promise&lt;ResultSet&gt;;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperquery-1) | \@ohos.data.dataShare.d.ts | [query(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataSharePredicates.DataSharePredicates,&nbsp;columns:&nbsp;Array&lt;string&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;DataShareResultSet&gt;):&nbsp;void;](../reference/apis/js-apis-data-dataShare.md#query)<br/>[query(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataSharePredicates.DataSharePredicates,&nbsp;columns:&nbsp;Array&lt;string&gt;):&nbsp;Promise&lt;DataShareResultSet&gt;;](../reference/apis/js-apis-data-dataShare.md#query-1) |
| [call(uri:&nbsp;string,&nbsp;method:&nbsp;string,&nbsp;arg:&nbsp;string,&nbsp;extras:&nbsp;PacMap,&nbsp;callback:&nbsp;AsyncCallback&lt;PacMap&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelpercall-1)<br/>[call(uri:&nbsp;string,&nbsp;method:&nbsp;string,&nbsp;arg:&nbsp;string,&nbsp;extras:&nbsp;PacMap):&nbsp;Promise&lt;PacMap&gt;;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelpercall) | Stage模型无对应接口 | 暂时未提供对应接口 |
| [executeBatch(uri:&nbsp;string,&nbsp;operations:&nbsp;Array&lt;DataAbilityOperation&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;Array&lt;DataAbilityResult&gt;&gt;):&nbsp;void;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperexecutebatch)<br/>[executeBatch(uri:&nbsp;string,&nbsp;operations:&nbsp;Array&lt;DataAbilityOperation&gt;):&nbsp;Promise&lt;Array&lt;DataAbilityResult&gt;&gt;;](../reference/apis/js-apis-dataAbilityHelper.md#dataabilityhelperexecutebatch-1) | Stage模型无对应接口 | 暂时未提供对应接口 |
# DataShareExtensionAbility(仅对系统应用开放)
DataShareExtensionAbility提供了数据分享的能力,系统应用可以实现一个DataShareExtensionAbility,也可以访问系统中已有的DataShareExtensionAbility,针对三方应用仅开放访问系统中已有DataShareExtensionAbility的能力,详细介绍请参见[数据共享开发指导](../database/database-datashare-guidelines.md)
# 显式Want与隐式Want匹配规则
在启动目标Ability时,会通过显式Want和隐式Want进行目标Ability的匹配,这里说的匹配规则就是调用方Want中设置的参数如何与目标Ability声明的配置文件进行匹配。
- **显式Want匹配原理**
| 名称 | 类型 | 匹配项 | 必选 | 规则 |
| -------- | -------- | -------- | -------- | -------- |
| deviceId | string | 是 | 否 | 留空将仅匹配本设备内Ability。 |
| bundleName | string | 是 | 是 | 如果指定abilityName,而不指定bundleName,则匹配失败。 |
| moduleName | string | 是 | 否 | 留空时当同一个应用内存在多个模块且模块间存在重名Ability,将默认匹配第一个。 |
| abilityName | string | 是 | 是 | 该字段必须设置表示显式匹配。 |
| uri | string | 否 | 否 | 系统匹配时将忽略该参数,但仍可作为参数传递给目标Ability。 |
| type | string | 否 | 否 | 系统匹配时将忽略该参数,但仍可作为参数传递给目标Ability。 |
| action | string | 否 | 否 | 系统匹配时将忽略该参数,但仍可作为参数传递给目标Ability。 |
| entities | Array&lt;string&gt; | 否 | 否 | 系统匹配时将忽略该参数,但仍可作为参数传递给目标Ability。 |
| flags | number | 否 | 否 | 不参与匹配,直接传递给系统处理,一般用来设置运行态信息,例如URI数据授权等。 |
| parameters | {[key:&nbsp;string]:&nbsp;any} | 否 | 否 | 不参与匹配,应用自定义数据将直接传递给目标Ability。 |
- **隐式Want匹配原理**
| 名称 | 类型 | 匹配项 | 必选 | 规则 |
| -------- | -------- | -------- | -------- | -------- |
| deviceId | string | 是 | 否 | 跨设备目前不支持隐式调用。 |
| abilityName | string | 否 | 否 | 该字段必须留空表示隐式匹配。 |
| bundleName | string | 是 | 否 | -&nbsp;声明bundleName时,隐式搜索将仅限于对应应用包内。<br/>-&nbsp;声明bundleName与moduleName时,隐式搜索将仅限于对应应用的对应Module内。<br/>-&nbsp;单独声明moduleName时,该字段无效。<br/>-&nbsp;同时声明bundleName与moduleName时,隐式搜索将仅限于对应应用包内的对应模块内。<br/>这些字段将用来隐式匹配,具体规则可参考[隐式Want匹配原理详解](#隐式want匹配原理详解)。 |
| moduleName | string | 是 | 否 |
| uri | string | 是 | 否 |
| type | string | 是 | 否 |
| action | string | 是 | 否 |
| entities | Array&lt;string&gt; | 是 | 否 |
| flags | number | 否 | 否 | 不参与匹配,直接传递给系统处理,一般用来设置运行态信息,例如URI数据授权等。 |
| parameters | {[key:&nbsp;string]:&nbsp;any} | 否 | 否 | 不参与匹配,应用自定义数据将直接传递给目标Ability。 |
## 隐式Want匹配原理详解
从隐式Want的定义,可得知:
- 调用方传入的want参数,表明调用方需要执行的操作,并提供相关数据以及其他应用类型限制。
- 待匹配Ability的skills配置,声明其具备的能力([module.json5配置文件](../quick-start/module-configuration-file.md)中的[skills标签](../quick-start/module-configuration-file.md#skills标签)参数)。
系统将调用方传入的want参数(包含action、entities、uri和type属性)与已安装待匹配的应用Ability的skills配置(包含actions、entities、uris和type属性)依次进行匹配。当四个属性匹配均通过,则此应用才会被应用选择器展示给用户进行选择。
### want参数的action匹配规则
将调用方传入的want参数的action与待匹配Ability的skills配置中的actions进行匹配。
- 调用方传入的want参数的action不为空,待匹配Ability的skills配置中的actions为空,则action匹配失败。
- 调用方传入的want参数的action为空,待匹配Ability的skills配置中的actions不为空,则action匹配成功。
- 调用方传入的want参数的action不为空,待匹配Ability的skills配置中的actions不为空且包含调用方传入的want参数的action,则action匹配成功。
- 调用方传入的want参数的action不为空,待匹配Ability的skills配置中的actions不为空且不包含调用方传入的want参数的action,则action匹配失败。
**图1** want参数的action匹配规则  <img src="figures/want-action.png" alt="want-action" style="zoom:80%;" />
### want参数的entities匹配规则
将调用方传入的want参数的entities与待匹配Ability的skills配置中的entities进行匹配。
- 调用方传入的want参数的entities为空,待匹配Ability的skills配置中的entities不为空,则entities匹配成功。
- 调用方传入的want参数的entities为空,待匹配Ability的skills配置中的entities为空,则entities匹配成功。
- 调用方传入的want参数的entities不为空,待匹配Ability的skills配置中的entities为空,则entities匹配失败。
- 调用方传入的want参数的entities不为空,待匹配Ability的skills配置中的entities不为空且包含调用方传入的want参数的entities,则entities匹配成功。
- 调用方传入的want参数的entities不为空,待匹配Ability的skills配置中的entities不为空且不完全包含调用方传入的want参数的entities,则entities匹配失败。
**图2** want参数的entities匹配规则
<img src="figures/want-entities.png" alt="want-entities" style="zoom:80%;" />
### want参数的uri和type匹配规则
调用方传入的want参数中设置uri和type参数发起组件启动请求,系统会遍历当前系统已安装的组件列表,并逐个匹配待匹配Ability的skills配置中的uris数组,如果待匹配Ability的skills配置中的uris数组中只要有一个可以匹配调用方传入的want参数中设置的uri和type即为匹配成功。
**图3** want参数中uri和type皆不为空时的匹配规则
<img src="figures/want-uri-type1.png" alt="want-uri-type1" style="zoom: 80%;" />
实际应用中,uri和type共存在四种情况,下面将讲解四种情况的具体匹配规则:
- 调用方传入的want参数的uri和type都为空。
1. 如果待匹配Ability的skills配置中的uris数组为空,匹配成功。
2. 如果待匹配Ability的skills配置中的uris数组中存在uri的scheme和type都为空的元素,匹配成功。
3. 除以上两种情况,其他情况均为匹配失败。
- 调用方传入的want参数的uri不为空,type为空。
1. 如果待匹配Ability的skills配置中的uris数组为空,匹配失败。
2. 如果待匹配Ability的skills配置中的uris数组存在一条数据[uri匹配](#uri匹配规则)成功且type为空,则匹配成功,否则匹配失败。
- 调用方传入的want参数的uri为空,type不为空。
1. 如果待匹配Ability的skills配置中的uris数组为空,匹配失败。
2. 如果待匹配Ability的skills配置中的uris数组存在一条数据uri的scheme为空且[type匹配](#type匹配规则)成功,则匹配成功,否则匹配失败。
- 调用方传入的want参数的uri和type都不为空,如图3所示。
1. 如果待匹配Ability的skills配置中的uris数组为空,匹配失败。
2. 如果待匹配Ability的skills配置中的uris数组存在一条数据[uri匹配](#uri匹配规则)[type匹配](#type匹配规则)需要均匹配成功,则匹配成功,否则匹配失败。
下图为了简化描述,称want中传入的uri为w_uri,称want中传入的type为w_type, 待匹配Ability的skills配置中uris为s_uris,其中每个元素为s_uri;按自上而下顺序匹配。
**图4** want参数中uri和type的具体匹配规则
<img src="figures/want-uri-type2.png" alt="want-uri-type2" style="zoom:80%;" />
### uri匹配规则
这里为了简化描述,称want中传入的uri为w_uri,待匹配Ability的skills配置中uri为s_uri,具体的匹配规则如下:
- 如果s_uri的scheme为空,当w_uri为空时匹配成功,否则匹配失败;
- 如果s_uri的host为空,当w_uri和s_uri的scheme相同时匹配成功,否则匹配失败;
- 如果s_uri的path、pathStartWith和pathRegex都为空,当w_uri和s_uri完全相同时匹配成功,否则匹配失败;
- 如果s_uri的path不为空,当w_uri和s_uri**全路径表达式**相同时匹配成功,否则继续进行pathStartWith的匹配;
- 如果s_uri的pathStartWith不为空,当w_uri包含s_uri**前缀表达式**时匹配成功,否则继续进行pathRegex的匹配;
- 如果s_uri的pathRegex不为空,当w_uri满足s_uri**正则表达式**时匹配成功,否则匹配失败;
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 待匹配Ability的skills配置的uris中scheme、host、port、path、pathStartWith和pathRegex属性拼接,如果依次声明了path、pathStartWith和pathRegex属性时,uris将分别拼接为如下三种表达式:
>
> - **全路径表达式**:scheme://host:port/path
>
> - **前缀表达式**:scheme://host:port/pathStartWith
>
> - **正则表达式**:scheme://host:port/pathRegex
### type匹配规则
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 此小节所述的type匹配规则的适用性需建立在want参数内type不为空的基础上。当want参数内type为空时请参考[want参数的uri和type匹配规则](#want参数的uri和type匹配规则)。
这里为了简化描述,称want中传入的uri为w_type,待匹配Ability的skills数组中uris的type数据为s_type,具体的匹配规则如下:
- 如果s_type为空,则匹配失败。
- 如果s_type或者w_type为通配符"\*/\*",则匹配成功。
- 如果s_type最后一个字符为通配符'\*',如"prefixType/\*",则当w_type包含"prefixType/"时匹配成功,否则匹配失败。
- 如果w_type最后一个字符为通配符'\*',如"prefixType/\*",则当s_type包含"prefixType/"时匹配成功,否则匹配失败。
# ExtensionAbility组件概述
ExtensionAbility组件是基于特定场景(例如服务卡片、输入法等)提供的应用组件,以便满足更多的使用场景。
每一个具体场景对应一个[ExtensionAbilityType](../reference/apis/js-apis-bundleManager.md#extensionabilitytype),各类型的ExtensionAbility组件均由相应的系统服务统一管理,例如InputMethodExtensionAbility组件由输入法管理服务统一管理。当前支持的ExtensionAbility类型有:
- [FormExtensionAbility](../reference/apis/js-apis-formextension.md):FORM类型的ExtensionAbility组件,用于提供服务卡片场景相关能力。
- [WorkSchedulerExtensionAbility](../reference/apis/js-apis-resourceschedule-workScheduler.md):WORK_SCHEDULER类型的ExtensionAbility组件,用于提供延迟任务注册、取消、查询的能力。
- [InputMethodExtensionAbility](../reference/apis/js-apis-inputmethod.md):INPUT_METHOD类型的ExtensionAbility组件,提供对输入法框架的管理,包括隐藏输入法、查询已安装的输入法列表和显示输入法选择对话框。
- [ServiceExtensionAbility](../reference/apis/js-apis-service-extension-ability.md):SERVICE类型的ExtensionAbility组件,用于提供后台服务场景相关能力。
- [AccessibilityExtensionAbility](../reference/apis/js-apis-application-AccessibilityExtensionAbility.md):ACCESSIBILITY类型的ExtensionAbility组件,用于提供辅助功能业务的能力。
- [DataShareExtensionAbility](../reference/apis/js-apis-application-DataShareExtensionAbility.md):DATA_SHARE类型的ExtensionAbility组件,用于提供支持数据共享业务的能力。
- [StaticSubscriberExtensionAbility](../reference/apis/js-apis-application-staticSubscriberExtensionAbility.md):STATIC_SUBSCRIBER类型的ExtensionAbility组件,用于提供静态广播的能力。
- [WindowExtensionAbility](../reference/apis/js-apis-application-WindowExtensionAbility.md):WINDOW类型的ExtensionAbility组件,用于提供界面组合扩展能力,允许系统应用进行跨应用的界面拉起和嵌入。
- [EnterpriseAdminExtensionAbility](../reference/apis/js-apis-EnterpriseAdminExtensionAbility.md):ENTERPRISE_ADMIN类型的ExtensionAbility组件,用于提供企业管理时处理管理事件的能力,比如设备上应用安装事件、锁屏密码输入错误次数过多事件等。
## 使用指定类型的ExtensionAbility组件
所有类型的ExtensionAbility组件均不能被应用直接启动,而是由相应的系统管理服务拉起,以确保其生命周期受系统管控,使用时拉起,使用完销毁。ExtensionAbility组件的调用方无需关心目标ExtensionAbility组件的生命周期。
[InputMethodExtensionAbility](../reference/apis/js-apis-inputmethod.md)组件为例进行说明,如下图所示,调用方应用发起对InputMethodExtensionAbility组件的调用,此时将先调用输入法管理服务,由输入法管理服务拉起[InputMethodExtensionAbility](../reference/apis/js-apis-inputmethod.md)组件,返回给调用方,同时开始管理其生命周期。
**图1** 使用InputMethodExtensionAbility组件
![ExtensionAbility-start](figures/ExtensionAbility-start.png)
## 实现指定类型的ExtensionAbility组件
以实现卡片[FormExtensionAbility](../reference/apis/js-apis-formextension.md)为例进行说明。卡片框架提供了[FormExtensionAbility](../reference/apis/js-apis-formextension.md)基类,开发者通过派生此基类(如MyFormExtensionAbility),实现回调(如创建卡片的onCreate()回调、更新卡片的onUpdateForm()回调等)来实现具体卡片功能,具体见开发指导见[服务卡片FormExtensionAbility](widget-development-stage.md)
卡片FormExtensionAbility实现方不用关心使用方何时去请求添加、删除卡片,FormExtensionAbility实例及其所在的ExtensionAbility进程的整个生命周期,都是由卡片管理系统服务FormManagerService进行调度管理。
![form_extension](figures/form_extension.png)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 同一应用内的所有同类型的ExtensionAbility运行在同一独立进程(除ServiceExtensionAbility、DataShareExtensionAbility外),跟UIAbility组件不在同一进程,Stage模型的进程模型请参见[进程模型](process-model-stage.md)。
>
> 例如一个应用有1个UIAbility组件、1个ServiceExtensionAbility、1个DataShareExtensionAbility、2个FormExtensionAbility、1个ImeExtensionAbility。则该应用在运行时,有三个进程:
>
> - UIAbility、ServiceExtensionAbility、DataShareExtensionAbility运行在同一个进程。
>
> - FormExtensionAbility运行在一个独立进程。
>
> - ImeExtensionAbility运行在一个独立进程。
# FA模型开发概述
基于FA模型开发应用时,在应用模型部分,涉及如下开发过程。
**表1** FA模型开发流程
| 任务 | 简介 | 相关指导 |
| -------- | -------- | -------- |
| 应用组件开发 | 本章节介绍了如何使用FA模型的PageAbility、ServiceAbility、DataAbility以及服务卡片进行应用开发。 | [应用/组件级配置](application-component-configuration-fa.md)<br/>[PageAbility开发指导](pageability-overview.md)<br/>[ServiceAbility开发指导](serviceability-overview.md)<br/>[DataAbility开发指导](dataability-overview.md)<br/>[服务卡片开发指导](widget-development-fa.md)<br/>[FA模型的Context](application-context-fa.md)<br/>[信息传递载体Want](want-fa.md) |
| 应用配置文件 | 本章节介绍了FA模型的配置文件中所有的字段以及各个字段的说明。 | [app对象内部结构](../quick-start/app-structure.md)<br/>[deviceConfig内部结构](../quick-start/deviceconfig-structure.md)<br/>[module对象内部结构](../quick-start/module-structure.md) |
| 进程间通信 | 本章节介绍了FA模型的进程模型以及几种常用的进程间通信方式。 | [公共事件](common-event-fa.md)<br/>[RPC通信](rpc.md) |
| 线程间通信 | 本章节介绍了FA模型的线程模型以及几种常用的线程间通信方式。 | [线程间通信](itc-fa-overview.md) |
| 任务管理 | 本章节介绍了FA模型中任务管理的基本概念和典型场景。 | [任务管理](mission-management-fa.md) |
# FA模型与Stage模型应用组件互通综述
API 8及以前的接口基于FA模型提供;从API 9开始,OpenHarmony主推Stage模型。FA模型与Stage模型是两套不同的应用模型,他们拥有各自的组件。FA模型提供三种应用组件,分别是PageAbility、ServiceAbility和DataAbility。Stage模型提供了两种应用组件,分别是UIAbility和ExtensionAbility。
由于FA模型与Stage模型不能在应用内混合开发(见下图),当一个设备(系统)内包含两种模型应用时(下图中"场景三"),可能涉及两种模型应用组件间的互通,本文将介绍相关互通指导。
**图1** FA模型与Stage模型应用组件共存场景  
![coexistence-of-FAandStage](figures/coexistence-of-FAandStage.png)
FA模型与Stage模型应用组件互通场景及开发者关注点请参考下表。
**表1** FA模型与Stage模型应用组件互通概览
| 互通场景 | 开发者关注点 |
| -------- | -------- |
| [FA模型启动Stage模型UIAbility](start-uiability-from-fa.md) | 只需要把want中的bundleName和abilityName替换成Stage模型UIAbility的bundleName和abilityName。 |
| [FA模型绑定Stage模型ServiceExtensionAbility](bind-serviceextensionability-from-fa.md) | 只需要把want中的bundleName和abilityName替换成Stage模型ServiceExtensionAbility的bundleName和abilityName。 |
| [FA模型访问Stage模型DataShareExtensionAbility](access-datashareextensionability-from-fa.md) | 无需做代码修改。但需了解DataShareHelper和DataAbilityHelper对外接口的兼容情况。 |
| [Stage模型启动FA模型PageAbility](start-pageability-from-stage.md) | 只需要把want中的bundleName和abilityName替换成FA模型PageAbility的bundleName和abilityName。 |
| [Stage模型绑定FA模型ServiceAbility](bind-serviceability-from-stage.md) | 只需要把want中的bundleName和abilityName替换成FA模型ServiceAbility的bundleName和abilityName。 |
| Stage模型访问FA模型DataAbility | 不支持此种访问。 |
# featureAbility接口切换
| FA模型接口 | Stage模型接口对应d.ts文件 | Stage模型对应接口 |
| -------- | -------- | -------- |
| [getWant(callback:&nbsp;AsyncCallback&lt;Want&gt;):&nbsp;void;](../reference/apis/js-apis-featureAbility.md#featureabilitygetwant)<br/>[getWant():&nbsp;Promise&lt;Want&gt;;](../reference/apis/js-apis-featureAbility.md#featureabilitygetwant-1) | \@ohos.app.ability.UIAbility.d.ts | [launchWant:&nbsp;Want;](../reference/apis/js-apis-application-ability.md#属性) |
| [startAbility(parameter:&nbsp;StartAbilityParameter,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-featureAbility.md#featureabilitystartability)<br/>[startAbility(parameter:&nbsp;StartAbilityParameter):&nbsp;Promise&lt;number&gt;;](../reference/apis/js-apis-featureAbility.md#featureabilitystartability-1) | application\UIAbilityContext.d.ts | [startAbility(want:&nbsp;Want,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-ability-context.md#abilitycontextstartability)<br/>[startAbility(want:&nbsp;Want,&nbsp;options:&nbsp;StartOptions,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-ability-context.md#abilitycontextstartability-1)<br/>[startAbility(want:&nbsp;Want,&nbsp;options?:&nbsp;StartOptions):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-ability-context.md#abilitycontextstartability-2) |
| [getContext():&nbsp;Context;](../reference/apis/js-apis-featureAbility.md#featureabilitygetcontext) | \@ohos.app.ability.UIAbility.d.ts | [context:&nbsp;UIAbilityContext;](../reference/apis/js-apis-application-ability.md#属性) |
| [startAbilityForResult(parameter:&nbsp;StartAbilityParameter,&nbsp;callback:&nbsp;AsyncCallback&lt;AbilityResult&gt;):&nbsp;void;](../reference/apis/js-apis-featureAbility.md#featureabilitystartabilityforresult7)<br/>[startAbilityForResult(parameter:&nbsp;StartAbilityParameter):&nbsp;Promise&lt;AbilityResult&gt;;](../reference/apis/js-apis-featureAbility.md#featureabilitystartabilityforresult7-1) | application\UIAbilityContext.d.ts | [startAbilityForResult(want:&nbsp;Want,&nbsp;callback:&nbsp;AsyncCallback&lt;AbilityResult&gt;):&nbsp;void;](../reference/apis/js-apis-ability-context.md#abilitycontextstartabilityforresult)<br/>[startAbilityForResult(want:&nbsp;Want,&nbsp;options:&nbsp;StartOptions,&nbsp;callback:&nbsp;AsyncCallback&lt;AbilityResult&gt;):&nbsp;void;](../reference/apis/js-apis-ability-context.md#abilitycontextstartabilityforresult-1)<br/>[startAbilityForResult(want:&nbsp;Want,&nbsp;options?:&nbsp;StartOptions):&nbsp;Promise&lt;AbilityResult&gt;;](../reference/apis/js-apis-ability-context.md#abilitycontextstartabilityforresult-2) |
| [terminateSelfWithResult(parameter:&nbsp;AbilityResult,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-featureAbility.md#featureabilityterminateselfwithresult7)<br/>[terminateSelfWithResult(parameter:&nbsp;AbilityResult):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-featureAbility.md#featureabilityterminateselfwithresult7-1) | application\UIAbilityContext.d.ts | [terminateSelfWithResult(parameter:&nbsp;AbilityResult,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-ability-context.md#abilitycontextterminateselfwithresult)<br/>[terminateSelfWithResult(parameter:&nbsp;AbilityResult):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-ability-context.md#abilitycontextterminateselfwithresult-1) |
| [terminateSelf(callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-featureAbility.md#featureabilityterminateself7)<br/>[terminateSelf():&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-featureAbility.md#featureabilityterminateself7-1) | application\UIAbilityContext.d.ts | [terminateSelf(callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-ability-context.md#abilitycontextterminateself)<br/>[terminateSelf():&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-ability-context.md#abilitycontextterminateself-1) |
| [acquireDataAbilityHelper(uri:&nbsp;string):&nbsp;DataAbilityHelper;](../reference/apis/js-apis-featureAbility.md#featureabilityacquiredataabilityhelper7) | \@ohos.data.dataShare.d.ts<br/>\@ohos.data.fileAccess.d.ts | [createDataShareHelper(context:&nbsp;Context,&nbsp;uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;DataShareHelper&gt;):&nbsp;void;](../reference/apis/js-apis-data-dataShare.md#datasharecreatedatasharehelper)<br/>[createDataShareHelper(context:&nbsp;Context,&nbsp;uri:&nbsp;string):&nbsp;Promise&lt;DataShareHelper&gt;;](../reference/apis/js-apis-data-dataShare.md#datasharecreatedatasharehelper-1)<br/>[createFileAccessHelper(context:&nbsp;Context):&nbsp;FileAccessHelper;](../reference/apis/js-apis-fileAccess.md#fileaccesscreatefileaccesshelper-1)<br/>[createFileAccessHelper(context:&nbsp;Context,&nbsp;wants:&nbsp;Array&lt;Want&gt;):&nbsp;FileAccessHelper;](../reference/apis/js-apis-fileAccess.md#fileaccesscreatefileaccesshelper) |
| [hasWindowFocus(callback:&nbsp;AsyncCallback&lt;boolean&gt;):&nbsp;void;](../reference/apis/js-apis-featureAbility.md#featureabilityhaswindowfocus7)<br/>[hasWindowFocus():&nbsp;Promise&lt;boolean&gt;;](../reference/apis/js-apis-featureAbility.md#featureabilityhaswindowfocus7-1) | \@ohos.window.d.ts | [on(eventType:&nbsp;'windowStageEvent',&nbsp;callback:&nbsp;Callback&lt;WindowStageEventType&gt;):&nbsp;void;](../reference/apis/js-apis-window.md#onwindowstageevent9)<br/>监听[Active](../reference/apis/js-apis-window.md#windowstageeventtype9)获焦状态 |
| [connectAbility(request:&nbsp;Want,&nbsp;options:ConnectOptions&nbsp;):&nbsp;number;](../reference/apis/js-apis-featureAbility.md#featureabilityconnectability7) | application\UIAbilityContext.d.ts | [connectServiceExtensionAbility(want:&nbsp;Want,&nbsp;options:&nbsp;ConnectOptions):&nbsp;number;](../reference/apis/js-apis-ability-context.md#abilitycontextconnectserviceextensionability) |
| [disconnectAbility(connection:&nbsp;number,&nbsp;callback:AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-featureAbility.md#featureabilitydisconnectability7)<br/>[disconnectAbility(connection:&nbsp;number):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-featureAbility.md#featureabilitydisconnectability7-1) | application\UIAbilityContext.d.ts | [disconnectAbility(connection:&nbsp;number,&nbsp;callback:AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-ability-context.md#abilitycontextdisconnectserviceextensionability-1)<br/>[disconnectAbility(connection:&nbsp;number):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-ability-context.md#abilitycontextdisconnectserviceextensionability) |
| [getWindow(callback:&nbsp;AsyncCallback&lt;window.Window&gt;):&nbsp;void;](../reference/apis/js-apis-featureAbility.md#featureabilitygetwindow7)<br/>[getWindow():&nbsp;Promise&lt;window.Window&gt;;](../reference/apis/js-apis-featureAbility.md#featureabilitygetwindow7-1) | \@ohos.window.d.ts | [getLastWindow(ctx:&nbsp;BaseContext,&nbsp;callback:&nbsp;AsyncCallback&lt;Window&gt;):&nbsp;void;](../reference/apis/js-apis-window.md#windowgetlastwindow9)<br/>[getLastWindow(ctx:&nbsp;BaseContext):&nbsp;Promise&lt;Window&gt;;](../reference/apis/js-apis-window.md#windowgetlastwindow9-1) |
# 跨端迁移(仅对系统应用开放)
## 功能描述
跨端迁移的主要工作是实现将应用当前任务(包括页面控件状态变量等)迁移到目标设备,能在目标设备上接续。主要功能包括:
- 支持用户自定义数据存储及恢复。
- 支持页面路由信息和页面控件状态数据的存储及恢复。
- 支持应用兼容性检测。
## 跨端迁移流程
跨端迁移流程如下图所示。
**图1** 跨端迁移流程图  
![hop-cross-device-migration](figures/hop-cross-device-migration.png)
## 约束限制
- 由于“跨端迁移任务管理”能力尚未具备,开发者当前只能开发具备跨端迁移能力的应用,但不能发起迁移。
- 跨端迁移要求在同UIAbility之间进行,也就是需要相同的bundleName、abilityName和签名。
## 最佳实践
为了获得最佳体验,使用wantParam传输的数据建议在100KB以下。
## 接口说明
跨端迁移主要接口如下。详细接口介绍请参见[API参考](../reference/apis/js-apis-application-ability.md)
**表1** 跨端迁移接口
| **接口名** | **描述** |
| -------- | -------- |
| onContinue(wantParam&nbsp;:&nbsp;{[key:&nbsp;string]:&nbsp;any}):&nbsp;OnContinueResult | 迁移发起端在该回调中保存迁移所需要的数据,同时返回是否同意迁移:<br/>-&nbsp;AGREE:表示同意。<br/>-&nbsp;REJECT:表示拒绝。<br/>-&nbsp;MISMATCH:表示版本不匹配。 |
| onCreate(want:&nbsp;Want,&nbsp;param:&nbsp;AbilityConstant.LaunchParam):&nbsp;void; | 多实例应用迁移接收端在该回调中完成数据恢复,并触发页面恢复。 |
| onNewWant(want:&nbsp;Want,&nbsp;launchParams:&nbsp;AbilityConstant.LaunchParam):&nbsp;void; | 单实例应用迁移接收端在该回调中完成数据恢复,并触发页面恢复。 |
## 开发步骤
1. 在module.json5配置数据同步权限,示例代码如下。
```json
{
"module": {
"requestPermissions":[
{
"name" : "ohos.permission.DISTRIBUTED_DATASYNC",
}
]
}
}
```
2. 在配置文件中配置跨端迁移相关标签字段。
- 配置应用支持迁移
在module.json5中配置continuable标签:true表示支持迁移,false表示不支持,默认为false。配置为false的UIAbility将被系统识别为无法迁移。
```json
{
"module": {
// ...
"abilities": [
{
// ...
"continuable": true,
}
]
}
}
```
- 根据需要配置应用启动模式类型,配置详情请参照[UIAbility组件启动模式](uiability-launch-type.md)
3. 申请数据同步权限,弹框示例代码。
```ts
requestPermission() {
let context = this.context
let permissions: Array<string> = ['ohos.permission.DISTRIBUTED_DATASYNC']
context.requestPermissionsFromUser(permissions).then((data) => {
console.info("Succeed to request permission from user with data: "+ JSON.stringify(data))
}).catch((error) => {
console.info("Failed to request permission from user with error: "+ JSON.stringify(error))
})
}
```
4. 在发起端UIAbility中实现[onContinue()](../reference/apis/js-apis-application-ability.md#abilityoncontinue)接口。
当应用触发迁移时,[onContinue()](../reference/apis/js-apis-application-ability.md#abilityoncontinue)接口在发起端被调用,开发者可以在该接口中保存迁移数据,实现应用兼容性检测,决定是否支持此次迁移。
- 保存迁移数据:开发者可以将要迁移的数据通过键值对的方式保存在wantParam中。
- 应用兼容性检测:开发者可以通过从wantParam中获取目标应用的版本号与本应用版本号做兼容性校验。
- 迁移决策:开发者可以通过onContinue接口的返回值决定是否支持此次迁移,返回值信息见[接口说明](#接口说明)
示例如下:
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
onContinue(wantParam : {[key: string]: any}) {
console.info(`onContinue version = ${wantParam.version}, targetDevice: ${wantParam.targetDevice}`)
let workInput = AppStorage.Get<string>('ContinueWork');
// set user input data into want params
wantParam["work"] = workInput // set user input data into want params
console.info(`onContinue input = ${wantParam["input"]}`);
return AbilityConstant.OnContinueResult.AGREE
}
```
5. 在目标端设备UIAbility中实现onCreate()/onNewWant()接口,恢复迁移数据。
- 多实例场景onCreate实现示例
- 目标端设备上,在onCreate中根据launchReason判断该次启动是否为迁移LaunchReason.CONTINUATION。
- 开发者可以从want中获取保存的迁移数据。
- 完成数据恢复后,开发者需要调用restoreWindowStage来触发页面恢复。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import distributedObject from '@ohos.data.distributedDataObject';
export default class EntryAbility extends UIAbility {
storage : LocalStorage;
onCreate(want, launchParam) {
console.info(`EntryAbility onCreate ${AbilityConstant.LaunchReason.CONTINUATION}`)
if (launchParam.launchReason == AbilityConstant.LaunchReason.CONTINUATION) {
// get user data from want params
let workInput = want.parameters.work
console.info(`work input ${workInput}`)
AppStorage.SetOrCreate<string>('ContinueWork', workInput)
this.storage = new LocalStorage();
this.context.restoreWindowStage(this.storage);
}
}
}
```
- 如果是单实例应用,则采用同样的代码实现onNewWant()接口即可。
# 多端协同(仅对系统应用开放)
## 功能描述
多端协同主要包括如下场景:
- [通过跨设备启动UIAbility和ServiceExtensionAbility组件实现多端协同(无返回数据)](#通过跨设备启动uiability和serviceextensionability组件实现多端协同无返回数据)
- [通过跨设备启动UIAbility组件实现多端协同(获取返回数据)](#通过跨设备启动uiability组件实现多端协同获取返回数据)
- [通过跨设备连接ServiceExtensionAbility组件实现多端协同](#通过跨设备连接serviceextensionability组件实现多端协同)
- [通过跨设备Call调用实现多端协同](#通过跨设备call调用实现多端协同)
## 多端协同流程
多端协同流程如下图所示。
**图1** 多端协同流程图  
![hop-multi-device-collaboration](figures/hop-multi-device-collaboration.png)
## 约束限制
- 由于“多端协同任务管理”能力尚未具备,开发者当前只能通过开发系统应用获取设备列表,不支持三方应用接入。
- 多端协同需遵循[分布式跨设备组件启动规则](component-startup-rules.md#分布式跨设备组件启动管控)
- 为了获得最佳体验,使用want传输的数据建议在100KB以下。
## 通过跨设备启动UIAbility和ServiceExtensionAbility组件实现多端协同(无返回数据)
在设备A上通过发起端应用提供的启动按钮,启动设备B上指定的UIAbility。
### 接口说明
**表1** 跨设备启动API接口功能介绍
| **接口名** | **描述** |
| -------- | -------- |
| startAbility(want:&nbsp;Want,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void; | 启动UIAbility和ServiceExtensionAbility(callback形式)。 |
### 开发步骤
1. 申请`ohos.permission.DISTRIBUTED_DATASYNC`权限,配置方式请参阅[访问控制授权申请指导](../security/accesstoken-guidelines.md#stage模型)
2. 申请数据同步权限,弹框示例代码。
```ts
requestPermission() {
let context = this.context
let permissions: Array<string> = ['ohos.permission.DISTRIBUTED_DATASYNC']
context.requestPermissionsFromUser(permissions).then((data) => {
console.info("Succeed to request permission from user with data: "+ JSON.stringify(data))
}).catch((error) => {
console.info("Failed to request permission from user with error: "+ JSON.stringify(error))
})
}
```
3. 获取目标设备的设备ID。
```ts
import deviceManager from '@ohos.distributedHardware.deviceManager';
let dmClass;
function initDmClass() {
// 其中createDeviceManager接口为系统API
deviceManager.createDeviceManager('ohos.samples.demo', (err, dm) => {
if (err) {
// ...
return
}
dmClass = dm
})
}
function getRemoteDeviceId() {
if (typeof dmClass === 'object' && dmClass !== null) {
let list = dmClass.getTrustedDeviceListSync()
if (typeof (list) === 'undefined' || typeof (list.length) === 'undefined') {
console.info('EntryAbility onButtonClick getRemoteDeviceId err: list is null')
return;
}
return list[0].deviceId
} else {
console.info('EntryAbility onButtonClick getRemoteDeviceId err: dmClass is null')
}
}
```
4. 设置目标组件参数,调用startAbility()接口,启动UIAbility或ServiceExtensionAbility。
```ts
let want = {
deviceId: getRemoteDeviceId(),
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'module1', // moduleName非必选
}
// context为发起端UIAbility的AbilityContext
this.context.startAbility(want).then(() => {
// ...
}).catch((err) => {
// ...
})
```
## 通过跨设备启动UIAbility组件实现多端协同(获取返回数据)
在设备A上通过应用提供的启动按钮,启动设备B上指定的UIAbility,当设备B上的UIAbility退出后,会将返回值发回设备A上的发起端应用。
### 接口说明
**表2** 跨设备启动,返回结果数据API接口功能描述
| 接口名 | 描述 |
| -------- | -------- |
| startAbilityForResult(want:&nbsp;Want,&nbsp;callback:&nbsp;AsyncCallback&lt;AbilityResult&gt;):&nbsp;void; | 启动UIAbility并在该Ability退出的时候返回执行结果(callback形式)。 |
| terminateSelfWithResult(parameter:&nbsp;AbilityResult,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void; | 停止UIAbility,配合startAbilityForResult使用,返回给接口调用方AbilityResult信息(callback形式)。 |
| terminateSelfWithResult(parameter:&nbsp;AbilityResult):&nbsp;Promise&lt;void&gt;; | 停止UIAbility,配合startAbilityForResult使用,返回给接口调用方AbilityResult信息(promise形式)。 |
### 开发步骤
1. 申请`ohos.permission.DISTRIBUTED_DATASYNC`权限,配置方式请参阅[访问控制授权申请指导](../security/accesstoken-guidelines.md#stage模型)
2. 申请数据同步权限,弹框示例代码。
```ts
requestPermission() {
let context = this.context
let permissions: Array<string> = ['ohos.permission.DISTRIBUTED_DATASYNC']
context.requestPermissionsFromUser(permissions).then((data) => {
console.info("Succeed to request permission from user with data: "+ JSON.stringify(data))
}).catch((error) => {
console.info("Failed to request permission from user with error: "+ JSON.stringify(error))
})
}
```
3. 在发起端设置目标组件参数,调用startAbilityForResult()接口启动目标端UIAbility,异步回调中的data用于接收目标端UIAbility停止自身后返回给调用方UIAbility的信息。getRemoteDeviceId方法参照[通过跨设备启动uiability和serviceextensionability组件实现多端协同无返回数据](#通过跨设备启动uiability和serviceextensionability组件实现多端协同无返回数据)
```ts
let want = {
deviceId: getRemoteDeviceId(),
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'module1', // moduleName非必选
}
// context为发起端UIAbility的AbilityContext
this.context.startAbilityForResult(want).then((data) => {
// ...
}).catch((err) => {
// ...
})
```
4. 在目标端UIAbility任务完成后,调用terminateSelfWithResult()方法,将数据返回给发起端的UIAbility。
```ts
const RESULT_CODE: number = 1001;
let abilityResult = {
resultCode: RESULT_CODE,
want: {
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'module1',
},
}
// context为目标端UIAbility的AbilityContext
this.context.terminateSelfWithResult(abilityResult, (err) => {
// ...
});
```
5. 发起端UIAbility接收到目标端UIAbility返回的信息,对其进行处理。
```ts
const RESULT_CODE: number = 1001;
// ...
// context为调用方UIAbility的AbilityContext
this.context.startAbilityForResult(want).then((data) => {
if (data?.resultCode === RESULT_CODE) {
// 解析目标端UIAbility返回的信息
let info = data.want?.parameters?.info
// ...
}
}).catch((err) => {
// ...
})
```
## 通过跨设备连接ServiceExtensionAbility组件实现多端协同
系统应用可以通过[connectServiceExtensionAbility()](../reference/apis/js-apis-ability-context.md#abilitycontextconnectserviceextensionability)跨设备连接一个服务,实现跨设备远程调用。比如:分布式游戏场景,平板作为遥控器,智慧屏作为显示器。
### 接口说明
**表3** 跨设备连接API接口功能介绍
| 接口名 | 描述 |
| -------- | -------- |
| connectServiceExtensionAbility(want:&nbsp;Want,&nbsp;options:&nbsp;ConnectOptions):&nbsp;number; | 连接ServiceExtensionAbility。 |
| disconnectServiceExtensionAbility(connection:&nbsp;number,&nbsp;callback:AsyncCallback&lt;void&gt;):&nbsp;void; | 断开连接(callback形式)。 |
| disconnectServiceExtensionAbility(connection:&nbsp;number):&nbsp;Promise&lt;void&gt;; | 断开连接(promise形式)。 |
### 开发步骤
1. 在module.json5配置数据同步权限,示例代码如下。
```json
{
"module": {
"requestPermissions":[
{
"name" : "ohos.permission.DISTRIBUTED_DATASYNC",
}
]
}
}
```
2. 申请数据同步权限,弹框示例代码。
```ts
requestPermission() {
let context = this.context
let permissions: Array<string> = ['ohos.permission.DISTRIBUTED_DATASYNC']
context.requestPermissionsFromUser(permissions).then((data) => {
console.info("Succeed to request permission from user with data: "+ JSON.stringify(data))
}).catch((error) => {
console.info("Failed to request permission from user with error: "+ JSON.stringify(error))
})
}
```
3. 如果已有后台服务,请直接进入下一步;如果没有,则[实现一个后台服务](serviceextensionability.md#实现一个后台服务仅对系统应用开放)
4. 连接一个后台服务。
- 实现IAbilityConnection接口。IAbilityConnection提供了以下方法供开发者实现:onConnect()是用来处理连接Service成功的回调,onDisconnect()是用来处理Service异常终止的回调,onFailed()是用来处理连接Service失败的回调。
- 设置目标组件参数,包括目标设备ID、包名、ability名。
- 调用connectServiceExtensionAbility发起连接。
- 连接成功,收到目标设备返回的服务句柄。
- 进行跨设备调用,获得目标端服务返回的结果。
```ts
import rpc from '@ohos.rpc';
const REQUEST_CODE = 99;
let want = {
"deviceId": getRemoteDeviceId(),
"bundleName": "com.example.myapplication",
"abilityName": "ServiceExtAbility"
};
let options = {
onConnect(elementName, remote) {
console.info('onConnect callback');
if (remote === null) {
console.info(`onConnect remote is null`);
return;
}
let option = new rpc.MessageOption();
let data = new rpc.MessageParcel();
let reply = new rpc.MessageParcel();
data.writeInt(1);
data.writeInt(99); // 开发者可发送data到目标端应用进行相应操作
// @param code 表示客户端发送的服务请求代码。
// @param data 表示客户端发送的{@link MessageParcel}对象。
// @param reply 表示远程服务发送的响应消息对象。
// @param options 指示操作是同步的还是异步的。
//
// @return 如果操作成功返回{@code true}; 否则返回 {@code false}。
remote.sendRequest(REQUEST_CODE, data, reply, option).then((ret) => {
let msg = reply.readInt(); // 在成功连接的情况下,会收到来自目标端返回的信息(100)
console.info(`sendRequest ret:${ret} msg:${msg}`);
}).catch((error) => {
console.info('sendRequest failed');
});
},
onDisconnect(elementName) {
console.info('onDisconnect callback')
},
onFailed(code) {
console.info('onFailed callback')
}
}
// 建立连接后返回的Id需要保存下来,在解绑服务时需要作为参数传入
let connectionId = this.context.connectServiceExtensionAbility(want, options);
```
getRemoteDeviceId方法参照[通过跨设备启动uiability和serviceextensionability组件实现多端协同无返回数据](#通过跨设备启动uiability和serviceextensionability组件实现多端协同无返回数据)。
5. 断开连接。调用disconnectServiceExtensionAbility()断开与后台服务的连接。
```ts
let connectionId = 1 // 在通过connectServiceExtensionAbility绑定服务时返回的Id
this.context.disconnectServiceExtensionAbility(connectionId).then((data) => {
console.info('disconnectServiceExtensionAbility success');
}).catch((error) => {
console.error('disconnectServiceExtensionAbility failed');
})
```
## 通过跨设备Call调用实现多端协同
跨设备Call调用的基本原理与设备内Call调用相同,请参见[通过Call调用实现UIAbility交互(仅对系统应用开放)](uiability-intra-device-interaction.md#通过call调用实现uiability交互仅对系统应用开放)
下面介绍跨设备Call调用实现多端协同的方法。
### 接口说明
**表4** Call API接口功能介绍
| 接口名 | 描述 |
| -------- | -------- |
| startAbilityByCall(want:&nbsp;Want):&nbsp;Promise&lt;Caller&gt;; | 启动指定UIAbility至前台或后台,同时获取其Caller通信接口,调用方可使用Caller与被启动的Ability进行通信。 |
| on(method:&nbsp;string,&nbsp;callback:&nbsp;CalleeCallBack):&nbsp;void | 通用组件Callee注册method对应的callback方法。 |
| off(method:&nbsp;string):&nbsp;void | 通用组件Callee解注册method的callback方法。 |
| call(method:&nbsp;string,&nbsp;data:&nbsp;rpc.Sequenceable):&nbsp;Promise&lt;void&gt; | 向通用组件Callee发送约定序列化数据。 |
| callWithResult(method:&nbsp;string,&nbsp;data:&nbsp;rpc.Sequenceable):&nbsp;Promise&lt;rpc.MessageParcel&gt; | 向通用组件Callee发送约定序列化数据,&nbsp;并将Callee返回的约定序列化数据带回。 |
| release():&nbsp;void | 释放通用组件的Caller通信接口。 |
| on(type:&nbsp;"release",&nbsp;callback:&nbsp;OnReleaseCallback):&nbsp;void | 注册通用组件通信断开监听通知。 |
### 开发步骤
1. 在module.json5配置数据同步权限,示例代码如下。
```json
{
"module": {
"requestPermissions":[
{
"name" : "ohos.permission.DISTRIBUTED_DATASYNC",
}
]
}
}
```
2. 申请数据同步权限,弹框示例代码。
```ts
requestPermission() {
let context = this.context
let permissions: Array<string> = ['ohos.permission.DISTRIBUTED_DATASYNC']
context.requestPermissionsFromUser(permissions).then((data) => {
console.info("Succeed to request permission from user with data: "+ JSON.stringify(data))
}).catch((error) => {
console.info("Failed to request permission from user with error: "+ JSON.stringify(error))
})
}
```
3. 创建被调用端UIAbility。
被调用端UIAbility需要实现指定方法的数据接收回调函数、数据的序列化及反序列化方法。在需要接收数据期间,通过on接口注册监听,无需接收数据时通过off接口解除监听。
1. 配置UIAbility的启动模式。
配置module.json5,将CalleeAbility配置为单实例"singleton"。
| Json字段 | 字段说明 |
| -------- | -------- |
| “launchType” | Ability的启动模式,设置为"singleton"类型。 |
UIAbility配置标签示例如下:
```json
"abilities":[{
"name": ".CalleeAbility",
"srcEntrance": "./ets/CalleeAbility/CalleeAbility.ts",
"launchType": "singleton",
"description": "$string:CalleeAbility_desc",
"icon": "$media:icon",
"label": "$string:CalleeAbility_label",
"visible": true
}]
```
2. 导入UIAbility模块。
```ts
import Ability from '@ohos.app.ability.UIAbility'
```
3. 定义约定的序列化数据。
调用端及被调用端发送接收的数据格式需协商一致,如下示例约定数据由number和string组成。
```ts
export default class MySequenceable {
num: number = 0
str: string = ""
constructor(num, string) {
this.num = num
this.str = string
}
marshalling(messageParcel) {
messageParcel.writeInt(this.num)
messageParcel.writeString(this.str)
return true
}
unmarshalling(messageParcel) {
this.num = messageParcel.readInt()
this.str = messageParcel.readString()
return true
}
}
```
4. 实现Callee.on监听及Callee.off解除监听。
如下示例在Ability的onCreate注册MSG_SEND_METHOD监听,在onDestroy取消监听,收到序列化数据后作相应处理并返回。应用开发者根据实际业务需要做相应处理。
```ts
const TAG: string = '[CalleeAbility]'
const MSG_SEND_METHOD: string = 'CallSendMsg'
function sendMsgCallback(data) {
console.info('CalleeSortFunc called')
// 获取Caller发送的序列化数据
let receivedData = new MySequenceable(0, '')
data.readSequenceable(receivedData)
console.info(`receiveData[${receivedData.num}, ${receivedData.str}]`)
// 作相应处理
// 返回序列化数据result给Caller
return new MySequenceable(receivedData.num + 1, `send ${receivedData.str} succeed`)
}
export default class CalleeAbility extends Ability {
onCreate(want, launchParam) {
try {
this.callee.on(MSG_SEND_METHOD, sendMsgCallback)
} catch (error) {
console.info(`${MSG_SEND_METHOD} register failed with error ${JSON.stringify(error)}`)
}
}
onDestroy() {
try {
this.callee.off(MSG_SEND_METHOD)
} catch (error) {
console.error(TAG, `${MSG_SEND_METHOD} unregister failed with error ${JSON.stringify(error)}`)
}
}
}
```
4. 获取Caller接口,访问被调用端UIAbility。
1. 导入UIAbility模块。
```ts
import Ability from '@ohos.app.ability.UIAbility'
```
2. 获取Caller通信接口。
Ability的context属性实现了startAbilityByCall方法,用于获取指定通用组件的Caller通信接口。如下示例通过this.context获取Ability实例的context属性,使用startAbilityByCall拉起Callee被调用端并获取Caller通信接口,注册Caller的onRelease监听。应用开发者根据实际业务需要做相应处理。
```ts
async onButtonGetRemoteCaller() {
var caller = undefined
var context = this.context
context.startAbilityByCall({
deviceId: getRemoteDeviceId(),
bundleName: 'com.samples.CallApplication',
abilityName: 'CalleeAbility'
}).then((data) => {
if (data != null) {
caller = data
console.info('get remote caller success')
// 注册caller的release监听
caller.onRelease((msg) => {
console.info(`remote caller onRelease is called ${msg}`)
})
console.info('remote caller register OnRelease succeed')
}
}).catch((error) => {
console.error(`get remote caller failed with ${error}`)
})
}
```
getRemoteDeviceId方法参照[通过跨设备启动uiability和serviceextensionability组件实现多端协同无返回数据](#通过跨设备启动uiability和serviceextensionability组件实现多端协同无返回数据)。
5. 向被调用端UIAbility发送约定序列化数据。
1. 向被调用端发送Sequenceable数据有两种方式,一种是不带返回值,一种是获取被调用端返回的数据,method以及序列化数据需要与被调用端协商一致。如下示例调用Call接口,向Callee被调用端发送数据。
```ts
const MSG_SEND_METHOD: string = 'CallSendMsg'
async onButtonCall() {
try {
let msg = new MySequenceable(1, 'origin_Msg')
await this.caller.call(MSG_SEND_METHOD, msg)
} catch (error) {
console.info(`caller call failed with ${error}`)
}
}
```
2. 如下示例调用CallWithResult接口,向Callee被调用端发送待处理的数据originMsg,并将’CallSendMsg’方法处理完毕的数据赋值给backMsg。
```ts
const MSG_SEND_METHOD: string = 'CallSendMsg'
originMsg: string = ''
backMsg: string = ''
async onButtonCallWithResult(originMsg, backMsg) {
try {
let msg = new MySequenceable(1, originMsg)
const data = await this.caller.callWithResult(MSG_SEND_METHOD, msg)
console.info('caller callWithResult succeed')
let result = new MySequenceable(0, '')
data.readSequenceable(result)
backMsg(result.str)
console.info(`caller result is [${result.num}, ${result.str}]`)
} catch (error) {
console.info(`caller callWithResult failed with ${error}`)
}
}
```
6. 释放Caller通信接口。
Caller不再使用后,应用开发者可以通过release接口释放Caller。
```ts
releaseCall() {
try {
this.caller.release()
this.caller = undefined
console.info('caller release succeed')
} catch (error) {
console.info(`caller release failed with ${error}`)
}
}
```
# 流转概述
## 场景介绍
随着全场景多设备的生活方式不断深入,用户拥有的设备越来越多,不同设备都能在适合的场景下提供良好的体验,例如手表可以提供及时的信息查看能力,电视可以带来沉浸的观影体验。但是,每个设备也有使用场景的局限,例如在电视上输入文本相对移动设备来说是非常糟糕的体验。当多个设备通过分布式操作系统能够相互感知、进而整合成一个超级终端时,设备与设备之间就可以取长补短、相互帮助,为用户提供更加自然流畅的分布式体验。
在OpenHarmony中,将跨多设备的分布式操作统称为**流转**;根据使用场景的不同,流转又分为[跨端迁移](hop-cross-device-migration.md)[多端协同](hop-multi-device-collaboration.md)两种具体场景。要实现应用跨设备流转,需使用应用组件的跨设备交互相关能力,这些能力目前仅对系统应用开放。
## 基本概念
- **流转**
在OpenHarmony中泛指跨多设备的分布式操作。流转能力打破设备界限,多设备联动,使用户应用程序可分可合、可流转,实现如邮件跨设备编辑、多设备协同健身、多屏游戏等分布式业务。流转为开发者提供更广的使用场景和更新的产品视角,强化产品优势,实现体验升级。流转按照使用场景可分为**跨端迁移****多端协同**
- **跨端迁移**
在用户使用设备的过程中,当使用情境发生变化时(例如从室内走到户外或者周围有更合适的设备等),之前使用的设备可能已经不适合继续当前的任务,此时,用户可以选择新的设备来继续当前的任务,原设备退出任务,这就是跨端迁移场景。常见的跨端迁移场景实例:在平板上播放的视频,迁移到智慧屏继续播放,从而获得更佳的观看体验;平板上的视频应用退出。在应用开发层面,跨端迁移指在A端运行的UIAbility迁移到B端上,完成迁移后, B端UIAbility继续任务,而A端UIAbility退出。
- **多端协同**
用户拥有的多个设备,可以作为一个整体,为用户提供比单设备更加高效、沉浸的体验,这就是多端协同场景。常见的多端协同场景实例:平板侧应用A做答题板,智慧屏侧应用B做直播,为用户提供更优的上网课体验。在应用开发层面,多端协同指多端上的不同UIAbility/ServiceExtensionAbility同时运行、或者交替运行实现完整的业务;或者多端上的相同UIAbility/ServiceExtensionAbility同时运行实现完整的业务。
## 流转架构
OpenHarmony流转提供了一组API库,可让用户应用程序更轻松、快捷地完成流转体验。OpenHarmony流转架构有如下优势:
- 支持远程服务调用等能力,可轻松设计业务。
- 支持多个应用同时进行流转。
- 支持不同形态设备,如平板、智慧屏、手表等。
流转架构如下图所示。
**图1** 流转架构图
<img src="figures/hop-structure.png" alt="hop-structure" style="zoom:80%;" />
- 跨端迁移任务管理:在迁移发起端,接受用户迁移的意图,提供迁移流转入口,迁移结果显示等能力。(该能力尚未构建。)
- 多端协同任务管理:在协同发起端,接受用户应用程序注册,提供协同入口、状态显示、退出流转等管理能力。(该能力尚未构建。)
- 分布式组件管理服务:提供远程服务启动、远程服务连接、远程迁移等能力,并通过不同能力组合,支撑用户应用程序完成跨端迁移或多端协同的业务体验。
- 分布式安全:提供E2E的加密通道,为用户应用程序提供安全的跨端传输机制,保证“正确的人,通过正确的设备,正确地使用数据”。
- 分布式软总线:使用基于平板、智能穿戴、智慧屏等分布式设备的统一通信基座,为设备之间的互联互通提供统一的分布式通信能力。
# 线程间通信
请参见Stage模型的"[线程间通信](thread-model-stage.md)"。
# 使用Emitter进行线程间通信
[Emitter](../reference/apis/js-apis-emitter.md)主要提供线程间发送和处理事件的能力,包括对持续订阅事件或单次订阅事件的处理、取消订阅事件、发送事件到事件队列等。
Emitter的开发步骤如下:
1. 订阅事件
```ts
import emitter from "@ohos.events.emitter";
// 定义一个eventId为1的事件
let event = {
eventId: 1
};
// 收到eventId为1的事件后执行该回调
let callback = (eventData) => {
console.info('event callback');
};
// 订阅eventId为1的事件
emitter.on(event, callback);
```
2. 发送事件
```ts
import emitter from "@ohos.events.emitter";
// 定义一个eventId为1的事件,事件优先级为Low
let event = {
eventId: 1,
priority: emitter.EventPriority.LOW
};
let eventData = {
data: {
"content": "c",
"id": 1,
"isEmpty": false,
}
};
// 发送eventId为1的事件,事件内容为eventData
emitter.emit(event, eventData);
```
# 使用Worker进行线程间通信
[Worker](../reference/apis/js-apis-worker.md)是与主线程并行的独立线程。创建Worker的线程被称为宿主线程,Worker工作的线程被称为Worker线程。创建Worker时传入的脚本文件在Worker线程中执行,通常在Worker线程中处理耗时的操作,需要注意的是,Worker中不能直接更新Page。
Worker的开发步骤如下:
1. 在工程的[模块级build-profile.json5](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-building-configuration-0000001218440654#section6887184182020)文件的buildOption属性中添加配置信息。
```ts
"buildOption": {
"sourceOption": {
"workers": [
"./src/main/ets/workers/worker.ts"
]
}
}
```
2. 根据build-profile.json5中的配置创建对应的worker.js文件。
```ts
import worker from '@ohos.worker';
let parent = worker.workerPort;
// 处理来自主线程的消息
parent.onmessage = function(message) {
console.info("onmessage: " + message)
// 发送消息到主线程
parent.postMessage("message from worker thread.")
}
```
3. 主线程中使用如下方式初始化和使用worker。
- Stage模型:
```ts
import worker from '@ohos.worker';
let wk = new worker.ThreadWorker("entry/ets/workers/worker.ts");
// 发送消息到worker线程
wk.postMessage("message from main thread.")
// 处理来自worker线程的消息
wk.onmessage = function(message) {
console.info("message from worker: " + message)
// 根据业务按需停止worker线程
wk.terminate()
}
```
- FA模型:
```ts
import worker from '@ohos.worker';
let wk = new worker.ThreadWorker("../workers/worker.js");
// 发送消息到worker线程
wk.postMessage("message from main thread.")
// 处理来自worker线程的消息
wk.onmessage = function(message) {
console.info("message from worker: " + message)
// 根据业务按需停止worker线程
wk.terminate()
}
```
**说明:**
- build-profile.json5中配置的worker.ts的相对路径都为`./src/main/ets/workers/worker.ts`时,在Stage模型下创建worker需要传入路径`entry/ets/workers/worker.ts`;在FA模型下创建worker需要传入路径`../workers/worker.js`
- 主线程与Worker线程间支持的数据类型参考[序列化支持类型](../reference/apis/js-apis-worker.md#%E5%BA%8F%E5%88%97%E5%8C%96%E6%94%AF%E6%8C%81%E7%B1%BB%E5%9E%8B)
# LifecycleApp接口切换
| FA模型接口 | Stage模型接口对应d.ts文件 | Stage模型对应接口 |
| -------- | -------- | -------- |
| onShow?():&nbsp;void; | \@ohos.window.d.ts | [on(eventType:&nbsp;'windowStageEvent',&nbsp;callback:&nbsp;Callback&lt;WindowStageEventType&gt;):&nbsp;void;](../reference/apis/js-apis-window.md#onwindowstageevent9)<br/>监听[FOREGROUND](../reference/apis/js-apis-window.md#windowstageeventtype9)切到前台状态 |
| onHide?():&nbsp;void; | \@ohos.window.d.ts | [on(eventType:&nbsp;'windowStageEvent',&nbsp;callback:&nbsp;Callback&lt;WindowStageEventType&gt;):&nbsp;void;](../reference/apis/js-apis-window.md#onwindowstageevent9)<br/>监听[BACKGROUND](../reference/apis/js-apis-window.md#windowstageeventtype9)切到后台状态 |
| onDestroy?():&nbsp;void; | \@ohos.app.ability.UIAbility.d.ts | [onDestroy():&nbsp;void;](../reference/apis/js-apis-application-ability.md#abilityondestroy) |
| onCreate?():&nbsp;void; | \@ohos.app.ability.UIAbility.d.ts | [onCreate(want:&nbsp;Want,&nbsp;param:&nbsp;AbilityConstant.LaunchParam):&nbsp;void;](../reference/apis/js-apis-application-ability.md#abilityoncreate) |
| onWindowDisplayModeChanged?(isShownInMultiWindow:&nbsp;boolean,&nbsp;newConfig:&nbsp;resourceManager.Configuration):&nbsp;void; | Stage模型无对应接口 | 暂时未提供对应接口 |
| onStartContinuation?():&nbsp;boolean; | Stage模型无对应接口 | Stage模型上,应用无需感知迁移是否成功(由应用发起迁移请求时感知),onStartContinuation废弃 |
| onSaveData?(data:&nbsp;Object):&nbsp;boolean; | \@ohos.app.ability.UIAbility.d.ts | [onContinue(wantParam&nbsp;:&nbsp;{[key:&nbsp;string]:&nbsp;any}):&nbsp;AbilityConstant.OnContinueResult;](../reference/apis/js-apis-application-ability.md#abilityoncontinue) |
| onCompleteContinuation?(result:&nbsp;number):&nbsp;void; | application\ContinueCallback.d.ts | [onContinueDone(result:&nbsp;number):&nbsp;void;](../reference/apis/js-apis-distributedMissionManager.md#continuecallback) |
| onRestoreData?(data:&nbsp;Object):&nbsp;void; | \@ohos.app.ability.UIAbility.d.ts | [onCreate(want:&nbsp;Want,&nbsp;param:&nbsp;AbilityConstant.LaunchParam):&nbsp;void;](../reference/apis/js-apis-application-ability.md#abilityoncreate)<br/>[onNewWant(want:&nbsp;Want,&nbsp;launchParams:&nbsp;AbilityConstant.LaunchParam):&nbsp;void;](../reference/apis/js-apis-application-ability.md#abilityonnewwant)<br/>标准实例模式Ability迁移目标端在onCreate回调中完成数据恢复,单实例应用迁移目标端在onCreate回调中完成数据恢复,回调中通过判断launchParam.launchReason可获取迁移启动的场景,从而可以从Want中获取迁移前保存的数据 |
| onRemoteTerminated?():&nbsp;void; | application\ContinueCallback.d.ts | [onContinueDone(result:&nbsp;number):&nbsp;void;](../reference/apis/js-apis-distributedMissionManager.md#continuecallback) |
| onSaveAbilityState?(outState:&nbsp;PacMap):&nbsp;void; | \@ohos.app.ability.UIAbility.d.ts | [onSaveState(reason:&nbsp;AbilityConstant.StateType,&nbsp;wantParam&nbsp;:&nbsp;{[key:&nbsp;string]:&nbsp;any}):&nbsp;AbilityConstant.OnSaveResult;](../reference/apis/js-apis-application-ability.md#abilityonsavestate) |
| onRestoreAbilityState?(inState:&nbsp;PacMap):&nbsp;void; | \@ohos.app.ability.UIAbility.d.ts | [onCreate(want:&nbsp;Want,&nbsp;param:&nbsp;AbilityConstant.LaunchParam):&nbsp;void;](../reference/apis/js-apis-application-ability.md#abilityoncreate)<br/>应用重启后会触发Ability的onCreate方法,通过判断launchParam.launchReason可获取自恢复的场景,从而可以从Want中获取重启前保存的数据 |
| onInactive?():&nbsp;void; | \@ohos.app.ability.UIAbility.d.ts | [onBackground():&nbsp;void;](../reference/apis/js-apis-application-ability.md#abilityonbackground) |
| onActive?():&nbsp;void; | \@ohos.app.ability.UIAbility.d.ts | [onForeground():&nbsp;void;](../reference/apis/js-apis-application-ability.md#abilityonforeground) |
| onNewWant?(want:&nbsp;Want):&nbsp;void; | \@ohos.app.ability.UIAbility.d.ts | [onNewWant(want:&nbsp;Want,&nbsp;launchParams:&nbsp;AbilityConstant.LaunchParam):&nbsp;void;](../reference/apis/js-apis-application-ability.md#abilityonnewwant) |
| onMemoryLevel?(level:&nbsp;number):&nbsp;void | \@ohos.app.ability.UIAbility.d.ts | [onMemoryLevel(level:&nbsp;AbilityConstant.MemoryLevel):&nbsp;void;](../reference/apis/js-apis-application-ability.md#abilityonmemorylevel) |
# LifecycleData接口切换
| FA模型接口 | Stage模型接口对应d.ts文件 | Stage模型对应接口 |
| -------- | -------- | -------- |
| update?(uri:&nbsp;string,&nbsp;valueBucket:&nbsp;rdb.ValuesBucket,&nbsp;predicates:&nbsp;dataAbility.DataAbilityPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void; | \@ohos.application.DataShareExtensionAbility.d.ts | [update?(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataSharePredicates.DataSharePredicates,&nbsp;valueBucket:&nbsp;ValuesBucket,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-application-DataShareExtensionAbility.md#update) |
| query?(uri:&nbsp;string,&nbsp;columns:&nbsp;Array&lt;string&gt;,&nbsp;predicates:&nbsp;dataAbility.DataAbilityPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;ResultSet&gt;):&nbsp;void; | \@ohos.application.DataShareExtensionAbility.d.ts | [query?(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataSharePredicates.DataSharePredicates,&nbsp;columns:&nbsp;Array&lt;string&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;Object&gt;):&nbsp;void;](../reference/apis/js-apis-application-DataShareExtensionAbility.md#query) |
| delete?(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataAbility.DataAbilityPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void; | \@ohos.application.DataShareExtensionAbility.d.ts | [delete?(uri:&nbsp;string,&nbsp;predicates:&nbsp;dataSharePredicates.DataSharePredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-application-DataShareExtensionAbility.md#delete) |
| normalizeUri?(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void; | \@ohos.application.DataShareExtensionAbility.d.ts | [normalizeUri?(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void;](../reference/apis/js-apis-application-DataShareExtensionAbility.md#normalizeuri) |
| batchInsert?(uri:&nbsp;string,&nbsp;valueBuckets:&nbsp;Array&lt;rdb.ValuesBucket&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void; | \@ohos.application.DataShareExtensionAbility.d.ts | [batchInsert?(uri:&nbsp;string,&nbsp;valueBuckets:&nbsp;Array&lt;ValuesBucket&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-application-DataShareExtensionAbility.md#batchinsert) |
| denormalizeUri?(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void; | \@ohos.application.DataShareExtensionAbility.d.ts | [denormalizeUri?(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void;](../reference/apis/js-apis-application-DataShareExtensionAbility.md#denormalizeuri) |
| insert?(uri:&nbsp;string,&nbsp;valueBucket:&nbsp;rdb.ValuesBucket,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void; | \@ohos.application.DataShareExtensionAbility.d.ts | [insert?(uri:&nbsp;string,&nbsp;valueBucket:&nbsp;ValuesBucket,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-application-DataShareExtensionAbility.md#insert) |
| openFile?(uri:&nbsp;string,&nbsp;mode:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void; | Stage模型无对应接口 | Stage模型不支持uri跨进程访问,建议通过[want携带fd和文件信息](data-share-via-want.md#开发步骤)进行跨进程文件访问 |
| getFileTypes?(uri:&nbsp;string,&nbsp;mimeTypeFilter:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;Array&lt;string&gt;&gt;):&nbsp;void; | Stage模型无对应接口 | Stage模型不支持uri跨进程访问,建议通过[want携带fd和文件信息](data-share-via-want.md#开发步骤)进行跨进程文件访问 |
| onInitialized?(info:&nbsp;AbilityInfo):&nbsp;void; | \@ohos.application.DataShareExtensionAbility.d.ts | [onCreate?(want:&nbsp;Want,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-application-DataShareExtensionAbility.md#oncreate) |
| getType?(uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void; | Stage模型无对应接口 | Stage模型不支持uri跨进程访问,建议通过[want携带fd和文件信息](data-share-via-want.md#开发步骤)进行跨进程文件访问 |
| executeBatch?(ops:&nbsp;Array&lt;DataAbilityOperation&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;Array&lt;DataAbilityResult&gt;&gt;):&nbsp;void; | Stage模型无对应接口 | 暂时未提供对应接口 |
| call?(method:&nbsp;string,&nbsp;arg:&nbsp;string,&nbsp;extras:&nbsp;PacMap,&nbsp;callback:&nbsp;AsyncCallback&lt;PacMap&gt;):&nbsp;void; | Stage模型无对应接口 | 暂时未提供对应接口 |
# LifecycleForm接口切换
| FA模型接口 | Stage模型接口对应d.ts文件 | Stage模型对应接口 |
| -------- | -------- | -------- |
| onCreate?(want:&nbsp;Want):&nbsp;formBindingData.FormBindingData; | \@ohos.app.form.FormExtensionAbility.d.ts | [onAddForm(want:&nbsp;Want):&nbsp;formBindingData.FormBindingData;](../reference/apis/js-apis-app-form-formextensionability.md#onaddform) |
| onCastToNormal?(formId:&nbsp;string):&nbsp;void; | \@ohos.app.form.FormExtensionAbility.d.ts | [onCastToNormalForm(formId:&nbsp;string):&nbsp;void;](../reference/apis/js-apis-app-form-formextensionability.md#oncasttonormalform) |
| onUpdate?(formId:&nbsp;string):&nbsp;void; | \@ohos.app.form.FormExtensionAbility.d.ts | [onUpdateForm(formId:&nbsp;string):&nbsp;void;](../reference/apis/js-apis-app-form-formextensionability.md#onupdateform) |
| onVisibilityChange?(newStatus:&nbsp;{&nbsp;[key:&nbsp;string]:&nbsp;number&nbsp;}):&nbsp;void; | \@ohos.app.form.FormExtensionAbility.d.ts | [onChangeFormVisibility(newStatus:&nbsp;{&nbsp;[key:&nbsp;string]:&nbsp;number&nbsp;}):&nbsp;void;](../reference/apis/js-apis-app-form-formextensionability.md#onchangeformvisibility) |
| onEvent?(formId:&nbsp;string,&nbsp;message:&nbsp;string):&nbsp;void; | \@ohos.app.form.FormExtensionAbility.d.ts | [onFormEvent(formId:&nbsp;string,&nbsp;message:&nbsp;string):&nbsp;void;](../reference/apis/js-apis-app-form-formextensionability.md#onformevent) |
| onDestroy?(formId:&nbsp;string):&nbsp;void; | \@ohos.app.form.FormExtensionAbility.d.ts | [onRemoveForm(formId:&nbsp;string):&nbsp;void;](../reference/apis/js-apis-app-form-formextensionability.md#onremoveform) |
| onAcquireFormState?(want:&nbsp;Want):&nbsp;formInfo.FormState; | \@ohos.app.form.FormExtensionAbility.d.ts | [onAcquireFormState?(want:&nbsp;Want):&nbsp;formInfo.FormState;](../reference/apis/js-apis-app-form-formextensionability.md#onacquireformstate) |
| onShare?(formId:&nbsp;string):&nbsp;{[key:&nbsp;string]:&nbsp;any}; | \@ohos.app.form.FormExtensionAbility.d.ts | [onShareForm?(formId:&nbsp;string):&nbsp;{&nbsp;[key:&nbsp;string]:&nbsp;any&nbsp;};](../reference/apis/js-apis-app-form-formextensionability.md#onshareform) |
# LifecycleService接口切换
| FA模型接口 | Stage模型接口对应d.ts文件 | Stage模型对应接口 |
| -------- | -------- | -------- |
| onStart?():&nbsp;void; | \@ohos.app.ability.ServiceExtensionAbility.d.ts | [onCreate(want:&nbsp;Want):&nbsp;void;](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md#serviceextensionabilityoncreate) |
| onCommand?(want:&nbsp;Want,&nbsp;startId:&nbsp;number):&nbsp;void; | \@ohos.app.ability.ServiceExtensionAbility.d.ts | [onRequest(want:&nbsp;Want,&nbsp;startId:&nbsp;number):&nbsp;void;](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md#serviceextensionabilityonrequest) | |
| onStop?():&nbsp;void; | \@ohos.app.ability.ServiceExtensionAbility.d.ts | [onDestroy():&nbsp;void;](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md#serviceextensionabilityondestroy) | |
| onConnect?(want:&nbsp;Want):&nbsp;rpc.RemoteObject; | \@ohos.app.ability.ServiceExtensionAbility.d.ts | [onConnect(want:&nbsp;Want):&nbsp;rpc.RemoteObject;](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md#serviceextensionabilityonconnect) | |
| onDisconnect?(want:&nbsp;Want):&nbsp;void; | \@ohos.app.ability.ServiceExtensionAbility.d.ts | [onDisconnect(want:&nbsp;Want):&nbsp;void;](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md#serviceextensionabilityondisconnect) | |
| onReconnect?(want:&nbsp;Want):&nbsp;void; | \@ohos.app.ability.ServiceExtensionAbility.d.ts | [onReconnect(want:&nbsp;Want):&nbsp;void;](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md#serviceextensionabilityonreconnect) | |
# mediaLibrary接口切换
| FA模型接口 | Stage模型接口对应d.ts文件 | Stage模型对应接口 |
| -------- | -------- | -------- |
| [getMediaLibrary():&nbsp;MediaLibrary;](../reference/apis/js-apis-medialibrary.md#medialibrarygetmedialibrary) | \@ohos.multimedia.mediaLibrary.d.ts | [getMediaLibrary(context: Context): MediaLibrary;](../reference/apis/js-apis-medialibrary.md#medialibrarygetmedialibrary8) |
# 任务管理
请参见Stage模型的"[任务管理](mission-management-overview.md)"。
# 任务管理与启动模式
如前文所述,一个UIAbility实例对应一个任务。UIAbility实例个数与UIAbility配置的启动模式有关。在FA模型下,通过config.json配置文件中的“launchType”属性配置;在Stage模型下,通过[module.json5配置文件](../quick-start/module-configuration-file.md)中的“launchType”属性配置。
下面介绍了任务管理如何实现以下三种启动模式UIAbility组件的管理:
- singleton:单实例模式,应用在运行时只存在一个该UIAbility实例。
**图1** 任务与singleton模式
![mission-and-singleton](figures/mission-and-singleton.png)
- standard:多实例模式,每次调用startAbility()方法,都会在应用进程中创建一个该Ability的实例。
**图2** 任务与standard模式
![mission-and-standard](figures/mission-and-standard.png)
- specified:指定实例模式,由[AbilityStage](abilitystage.md)的([onAcceptWant](../reference/apis/js-apis-application-abilitystage.md#abilitystageonacceptwant))决定是否创建新的实例。
**图3** 任务与specified模式
![mission-and-specified](figures/mission-and-specified.png)
每个UIAbility实例都对应了一个最近任务列表中看到的Mission(任务)。
每个UIAbility实例对应的Mission都保留有该UIAbility实例的快照(Snapshot),UIAbility实例销毁后,Mission信息(包括Ability信息和任务快照)依然会保留,直到用户删除该任务。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> specified模式只在Stage模型上支持,FA模型不支持。
# 任务管理场景介绍
任务管理相关的基本概念如下:
- AbilityRecord:系统服务侧管理一个UIAbility实例的最小单元,对应一个应用侧的UIAbility组件实例。
- MissionRecord:任务管理的最小单元。一个MissionRecord中仅有一个AbilityRecord,即一个UIAbility组件实例对应一个单独的任务。
- MissionList:一个从桌面开始启动的任务列表,记录了任务之间的启动关系,上一个任务由下一个任务启动,最底部的任务由桌面启动,这里称之为任务链。
- MissionListManager:系统任务管理模块,内部维护了当前所有的任务链,与最近任务列表保持一致。
**图1** 任务管理示意图  
![mission-list-manager](figures/mission-list-manager.png)
任务的管理由系统应用(如桌面应用)负责,三方应用无法管理任务。用户通过最近任务列表进行任务的相关交互。当创建任务后,用户可以对最近任务列表进行如下操作:
- 删除一个指定的任务。
- 加锁或解锁一个指定的任务(加锁后的任务在清理所有任务时不会被清理)。
- 清理最近任务列表中的所有任务。
- 将一个指定的任务切换到前台。
一个UIAbility实例对应一个单独的任务,因此应用调用startAbility()方法启动一个UIAbility时,就是创建了一个任务。
桌面应用调用[missionManager](../reference/apis/js-apis-missionManager.md)的接口管理任务,需要申请`ohos.permission.MANAGE_MISSIONS`权限,配置方式请参阅[访问控制授权申请指导](../security/accesstoken-guidelines.md#stage模型)
利用missionManager进行任务管理(监听任务变化、获取任务信息、获取任务快照、清理任务、任务加锁/解锁等),示例代码如下:
```ts
import missionManager from '@ohos.app.ability.missionManager'
let listener = {
// 任务创建
onMissionCreated: function (mission) {
console.info("--------onMissionCreated-------")
},
// 任务销毁
onMissionDestroyed: function (mission) {
console.info("--------onMissionDestroyed-------")
},
// 任务快照变化
onMissionSnapshotChanged: function (mission) {
console.info("--------onMissionSnapshotChanged-------")
},
// 任务被移动到前台
onMissionMovedToFront: function (mission) {
console.info("--------onMissionMovedToFront-------")
},
// 任务图标变化
onMissionIconUpdated: function (mission, icon) {
console.info("--------onMissionIconUpdated-------")
},
// 任务名称变化
onMissionLabelUpdated: function (mission) {
console.info("--------onMissionLabelUpdated-------")
},
// 任务实例被关闭
onMissionClosed: function (mission) {
console.info("--------onMissionClosed-------")
}
};
// 1.注册任务变化通知
let listenerId = missionManager.on('mission', listener);
// 2.获取系统最近20个任务
missionManager.getMissionInfos("", 20, (error, missions) => {
console.info("getMissionInfos is called, error.code = " + error.code);
console.info("size = " + missions.length);
console.info("missions = " + JSON.stringify(missions));
});
// 3.获取单个任务的详细信息()
let missionId = 11; // 11只是示例,实际是从系统中获取的任务id,下面类似
let mission = missionManager.getMissionInfo("", missionId).catch(function (err) {
console.info(err);
});
// 4.获取任务快照
missionManager.getMissionSnapShot("", missionId, (error, snapshot) => {
console.info("getMissionSnapShot is called, error.code = " + error.code);
console.info("bundleName = " + snapshot.ability.bundleName);
})
// 5.获取低分辨任务快照
missionManager.getLowResolutionMissionSnapShot("", missionId, (error, snapshot) => {
console.info("getLowResolutionMissionSnapShot is called, error.code = " + error.code);
console.info("bundleName = " + snapshot.ability.bundleName);
})
// 6.加锁/解锁任务
missionManager.lockMission(missionId).then(() => {
console.info("lockMission is called ");
});
missionManager.unlockMission(missionId).then(() => {
console.info("unlockMission is called ");
});
// 7.把任务切到前台
missionManager.moveMissionToFront(missionId).then(() => {
console.info("moveMissionToFront is called ");
});
// 8.删除单个任务
missionManager.clearMission(missionId).then(() => {
console.info("clearMission is called ");
});
// 9.删除全部任务
missionManager.clearAllMissions().catch(function (err) {
console.info(err);
});
// 10.解注册任务变化通知
missionManager.off('mission', listenerId, (error) => {
console.info("unregisterMissionListener");
})
```
# 模型切换概述
本文介绍如何将一个FA模型开发的声明式范式应用切换到Stage模型,您需要完成如下动作:
- 工程切换:新建一个Stage模型的应用工程。
![model-switch-overview1](figures/model-switch-overview1.png)
- [配置文件切换](configuration-file-diff.md):config.json切换为app.json5和module.json5。
![model-switch-overview2](figures/model-switch-overview2.png)
- [组件切换](pageability-switch.md):PageAbility/ServiceAbility/DataAbility切换为UIAbility和ExtensionAbility(图片仅展示了FA模型的PageAbility切换成Stage模型的UIAbility:下图左侧为FA模型,app.ets为FA模型的PageAbility组件;下图右侧为Stage模型,EntryAbility.ts为Stage模型的UIAbility组件)。
![model-switch-overview3](figures/model-switch-overview3.png)
- [卡片切换](widget-switch.md):将FA模型的FormAbility切换为Stage模型的FormExtensionAbility(下图中的**Service Widget**在FA中为FormAbility,在Stage中为FormExtensionAbility)。
![model-switch-overview4](figures/model-switch-overview4.png)
![model-switch-overview5](figures/model-switch-overview5.png)
- [API切换](api-switch-overview.md):将FA模型应用中使用到的FAModelOnly接口切换为Stage模型下的推荐接口和写法。
![model-switch-overview6](figures/model-switch-overview6.png)
# module的切换
从FA模型切换到Stage模型时,开发者需要将config.json文件module标签下的配置迁移到module.json5配置文件module标签下,具体差异见下列表格。
### **表1** FA模型module标签与Stage模型module标签差异对比
| FA标签 | 标签说明 | 对应的Stage标签 | 差异说明 |
| -------- | -------- | -------- | -------- |
| mainAbility | 服务中心图标露出的ability,常驻进程拉起时会启动mainAbility。 | mainElement | 标签名称变更,Stage模型不在使用.符号。 |
| package | 标识HAP的包结构名称,在应用内保证唯一性。 | / | Stage模型使用name来保证应用唯一性。 |
| name | 标识HAP的类名 | / | FA模型中实际未使能,Stage模型没有与之对应的标签。 |
| supportedModes | 标识应用支持的运行模式,当前只定义了驾驶模式(drive) | / | Stage模型已废弃。 |
| distro对象中的moduleName | 标识当前HAP的名称<br/>**distro对象**中的moduleName | name | 标签变更。 |
| distro对象中的moduleType | 标识当前HAP的类型,包括两种类型:entry和feature。另外,如果表示HAR包类型,请设置为har | type | 标签变更。 |
| distro对象中的installationFree | 标识当前HAP是否支持免安装特性 | installationFree | 标签变更。 |
| distro对象中的deliveryWithInstall | 标识当前HAP是否支持随应用安装 | deliveryWithInstall | 标签变更。 |
| metaData | 标识HAP的元信息 | metadata | 具体差异如[表2](#表2 FA模型metaData和Stage中metadata对比)。 |
| abilities | 标识当前模块内的所有Ability | abilities | 具体差异如[表5](#表5 FA模型和Stage中abilities差异对比)。 |
| js | 标识基于ArkUI框架开发的JS模块集合,其中的每个元素代表一个JS模块的信息 | pages | Stage模型在module标签下保留该对象中的pages,window配置与pages的下一级。 |
| shortcuts | 标识应用的快捷方式信息 | shortcut_config.json文件 | 在开发视图的resources/base/profile下面定义配置文件shortcut_config.json。 |
| reqPermissions | 标识应用运行时向系统申请的权限 | requestPermissions | 标签名称变更。 |
| colorMode | 标识应用自身的颜色模式 | / | Stage模型不支持。 |
| distroFilter | 标识应用的分发规则 | distroFilter_config.json文件 | Stage模型在开发视图的resources/base/profile下面定义配置文件distroFilter_config.json。 |
| reqCapabilities | 标识运行应用程序所需的设备能力 | / | Stage模型不支持。 |
| commonEvents | 公共事件 | common_event_config.json文件 | Stage模型在开发视图的resources/base/profile下面定义配置文件common_event_config.json。 |
| entryTheme | 此标签标识OpenHarmony内部主题的关键字 | / | Stage模型不支持。 |
### 表2 FA模型metaData和Stage中metadata对比
| FA标签 | 标签说明 | 对应的Stage模型标签 | 差异对比 |
| -------- | -------- | -------- | -------- |
| parameters | 标识调用Ability时所有调用参数的元信息 | / | Stage模型不支持。 |
| results | 标识Ability返回值的元信息 | / | Stage模型不支持。 |
| customizeData | 该标签标识父级组件的自定义元信息,Parameters和results在application不可配 | metadata | 具体差异见[表3](#表3 FA模型metaData的customizeData和Stage中metadata对比)。 |
### 表3 FA模型metaData的customizeData和Stage中metadata对比
| FA标签 | 标签说明 | 对应的Stage模型标签 | 差异对比 |
| -------- | -------- | -------- | -------- |
| name | 标识数据项的键名称。字符串最大长度为255字节 | name | 无。 |
| value | 标识数据项的值。字符串最大长度为255字节。 | value | 无。 |
| extra | 标识当前custom数据的格式,取值为表示extra的资源值。 | resource | 标签变更。具体实例见[表4](#表4 FA模型metaData和Stage中metadata示例)。 |
### 表4 FA模型metaData和Stage中metadata示例
| FA模型示例 | Stage模型示例 |
| -------- | -------- |
| “meteData”: {<br/> "customizeDate": [{<br/> "name": "label",<br/> "value": "string",<br/> "extra": "$string:label",<br/> }]<br/>} | “meteData”: [{<br/> "name": "label",<br/> "value": "string",<br/> "resource": "$string:label",<br/>}] |
### 表5 FA模型和Stage中abilities差异对比
| FA模型的abilities对象标签 | 描述 | Stage模型中abilities对象标签 | 差异对比 |
| -------- | -------- | -------- | -------- |
| process | 运行应用程序或Ability的进程名称 | / | Stage模型不支持abilities中配置,在module标签下配置process |
| uri | 标识Ability的统一资源标识符 | / | Stage模型不支持 |
| deviceCapability | 标识Ability运行时要求设备具有的能力,采用字符串数组的格式表示 | / | Stage模型不支持 |
| metaData | 该标签标识ability的元信息。 | metadata | 具体差异如[表2](#表2 FA模型metaData和Stage中metadata对比) |
| type | 标识Ability的类型 | / | Stage模型不支持 |
| grantPermission | 指定是否可以向Ability内任何数据授予权限 | / | abilities内不支持; |
| readPermission | 标识读取Ability的数据所需的权限。该标签仅适用于data类型的Ability | / | abilities内不支持;在extensionAbilities标签中支持 |
| writePermission | 标识向Ability写数据所需的权限 | / | abilities内不支持;在extensionAbilities标签中支持 |
| configChanges | 标识Ability关注的系统配置集合 | / | Stage模型不支持 |
| mission | 标识Ability指定的任务栈 | / | Stage模型不支持 |
| targetAbility | 标识当前Ability重用的目标Ability | / | Stage模型不支持 |
| multiUserShared | 标识Ability是否支持多用户状态进行共享,该标签仅适用于data类型的Ability | / | Stage模型不支持 |
| supportPipMode | 标识Ability是否支持用户进入PIP模式(用于在页面最上层悬浮小窗口,俗称"画中画",常见于视频播放等场景) | / | Stage模型不支持 |
| formsEnabled | 标识Ability是否支持卡片(forms)功能 | / | Stage模型不支持 |
| forms | 标识服务卡片的属性。该标签仅当formsEnabled为"true"时,才能生效 | form_config.json文件 | Stage模型在开发视图的resources/base/profile下面定义配置文件form_config.json |
| srcLanguage | Ability开发语言的类型 | / | Stage模型不支持 |
| srcPath | 该标签标识Ability对应的JS组件代码路径 | srcEntrance | 该标签标识ability所对应的js代码路径。 |
| uriPermission | 标识该Ability有权访问的应用程序数据 | / | Stage模型不支持 |
# 页面栈及任务链
## 页面栈
单个UIAbility组件可以实现多个页面,并在多个页面之间跳转,这种UIAbility组件内部的页面跳转关系称为“页面栈”,由ArkUI框架统一管理,如下图中的UIAbility1的Page1-&gt;Page2-&gt;Page3和UIAbility2的PageA-&gt;PageB-&gt;PageC。
**图1** 页面栈示意图  
![mission-record](figures/mission-record.png)
- 页面栈的形成(下面2/3/5/6步骤为页面跳转,由ArkUI管理)
1. 点击桌面图标([startAbility](../reference/apis/js-apis-ability-context.md#abilitycontextstartability))启动UIAbility1,UIAbility1的初始页面为Page1。
2. 点击Page1页面按钮([Navigator](../reference/arkui-ts/ts-container-navigator.md))跳转到Page2页面。
3. 点击Page2页面按钮([Navigator](../reference/arkui-ts/ts-container-navigator.md))跳转到Page3页面。
4. 点击Page3页面按钮([startAbility](../reference/apis/js-apis-ability-context.md#abilitycontextstartability))跳转到UIAbility2,UIAbility2的初始页面为PageA。
5. 点击PageA页面按钮([Navigator](../reference/arkui-ts/ts-container-navigator.md))跳转到PageB页面。
6. 点击PageB页面按钮([Navigator](../reference/arkui-ts/ts-container-navigator.md))跳转到PageC页面。
- 页面栈的返回(下面1/2/4/5步骤为页面跳转,由ArkUI管理)
1. 在UIAbility2的PageC页面点击**返回键**回到UIAbility2的PageB页面。
2. 在UIAbility2的PageB页面点击**返回键**回到UIAbility2的PageA页面。
3. 在UIAbility2的PageA页面点击**返回键**跳转到UIAbility1的Page3页面。
4. 在UIAbility1的Page3页面点击**返回键**回到UIAbility1的Page2页面。
5. 在UIAbility1的Page2页面点击**返回键**回到UIAbility1的Page1页面。
6. 在UIAbility1的Page1页面点击**返回键**回到桌面。
## 任务链
上文介绍了页面栈的返回,如果Ability2页面栈一层层通过返回键返回到最底层,再次点击返回键时,会返回到Ability1。因为在MissionList中记录了任务(Mission)之间的启动关系,即如果Ability1通过startAbility启动Ability2,则会形成一个MissionList任务链:Ability1-&gt;Ability2,当Ability2页面栈返回到首页时,再次点击返回键,会返回到Ability1的页面。
MissionList任务链记录了任务之间的拉起关系,但是这个任务链可能会断开,有以下几种情况会导致任务链的断开:
- 进入任务列表,把任务链中间某个任务移动到前台。
![mission-chain1](figures/mission-chain1.png)
- 进入任务列表,把任务链中间某个任务清理掉。
![mission-chain2](figures/mission-chain2.png)
- 单实例UIAbility的任务,被不同的任务反复拉起(AbilityB为单例)。
![mission-chain3](figures/mission-chain3.png)
# PageAbility组件配置
PageAbility的相关配置在config.json配置文件的"module"对象的"abilities"对象中,"icon"属性表示Ability图标资源文件的索引,"lable"属性表示Ability对用户显示的名称,"skills"属性表示Ability能够接收的want的特征。
**表1** PageAbility部分配置项说明
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| icon | 表示Ability图标资源文件的索引。取值示例:$media:ability_icon。如果在该Ability的skills属性中,actions的取值包含&nbsp;"action.system.home",entities取值中包含"entity.system.home",则该Ability的icon将同时作为应用的icon。如果存在多个符合条件的Ability,则取位置靠前的Ability的icon作为应用的icon。<br/>说明:应用的"icon"和"label"是用户可感知配置项,需要区别于当前所有已有的应用"icon"或"label"(至少有一个不同)。 | 字符串 | 可缺省,缺省值为空。 |
| label | 表示Ability对用户显示的名称。取值可以是Ability名称,也可以是对该名称的资源索引,以支持多语言。如果在该Ability的skills属性中,actions的取值包含&nbsp;"action.system.home",entities取值中包含"entity.system.home",则该Ability的label将同时作为应用的label。如果存在多个符合条件的Ability,则取位置靠前的Ability的label作为应用的label。<br/>说明:&nbsp;应用的"icon"和"label"是用户可感知配置项,需要区别于当前所有已有的应用"icon"或"label"(至少有一个不同)。该标签为资源文件中定义的字符串的引用,或以"{}"包括的字符串。该标签最大长度为255字节。 | 字符串 | 可缺省,缺省值为空。 |
| skills | 表示Ability能够接收的want的特征。 | 对象数组 | 可缺省,缺省值为空。 |
# PageAbility的启动模式
启动模式对应PageAbility被启动时的行为,支持单实例模式、标准模式两种启动模式。
**表1** PageAbility的启动模式
| 启动模式 | 描述 | 说明 |
| -------- | -------- | -------- |
| singleton | 单实例模式 | 每次调用startAbility方法时,如果应用进程中该类型的Ability实例已经存在,则复用已有的实例,系统中只存在唯一一个实例。表现为在最近任务列表中只有一个Ability实例。<br/>典型场景:当用户打开视频播放应用并观看视频,回到桌面后,再次打开视频播放应用,应用仍为回到桌面之前正在观看的视频。 |
| standard | 标准模式 | 缺省启动模式。每次调用startAbility方法时,都会在应用进程中创建一个新的Ability实例。表现为在最近任务列表中可以看到有多个该类型的Ability实例。<br/>典型场景:当用户打开文档应用,选择新建文档的时候,每次点击新建文档,都会创建一个新的文档任务,在最近任务列表中可以看到多个新建的文档任务。 |
应用开发者可在config.json配置文件中通过“launchType”配置启动模式。示例如下:
```json
{
"module": {
// ...
"abilities": [
{
// singleton: 单实例模式
// standard: 标准模式
"launchType": "standard",
// ...
}
]
}
}
```
启动PageAbility时,对于标准启动模式(多实例启动模式)以及单实例启动模式首次启动,[PageAbility生命周期回调](pageability-lifecycle.md#table13118194914476)均会被触发。单实例非首次启动时不会再触发onCreate()接口,而是触发onNewWant(),onNewWant()的说明如下表2所示。
**表2** 单实例启动模式特有的回调函数说明
| 接口名 | 接口描述 |
| -------- | -------- |
| onNewWant(want:&nbsp;Want) | 单实例启动模式,PageAbility非首次启动时调用onNewWant方法,开发者可以在该方法中获取want,进而根据want做进一步处理。例如,单实例PageAbility迁移场景,指定页面拉起PageAbility场景。 |
# PageAbility的生命周期
PageAbility生命周期是PageAbility被调度到INACTIVE、ACTIVE、BACKGROUND等各个状态的统称。PageAbility生命周期流转及状态说明见如下图1、表1所示。
**图1** PageAbility生命周期流转
![page-ability-lifecycle](figures/page-ability-lifecycle.png)
**表1** PageAbility生命周期状态说明
| 生命周期状态 | 生命周期状态说明 |
| -------- | -------- |
| UNINITIALIZED | 未初始状态,为临时状态,PageAbility被创建后会由UNINITIALIZED状态进入INITIAL状态。 |
| INITIAL | 初始化状态,也表示停止状态,表示当前PageAbility未运行,PageAbility被启动后由INITIAL态进入INACTIVE状态。 |
| INACTIVE | 失去焦点状态,表示当前窗口已显示但是无焦点状态。 |
| ACTIVE | 前台激活状态,表示当前窗口已显示,并获取焦点。 |
| BACKGROUND | 后台状态,表示当前PageAbility退到后台,PageAbility在被销毁后由BACKGROUND状态进入INITIAL状态,或者重新被激活后由BACKGROUND状态进入ACTIVE状态。 |
应用开发者可以在app.js/app.ets中重写生命周期相关回调函数,PageAbility生命周期相关回调函数见下表。
**表2** PageAbility生命周期回调接口说明
| 接口名 | 接口描述 |
| -------- | -------- |
| onCreate() | Ability第一次启动创建Ability时调用onCreate方法,开发者可以在该方法里做一些应用初始化工作。 |
| onDestroy() | 应用退出,销毁Ability对象前调用onDestroy方法,开发者可以在该方法里做一些回收资源、清空缓存等应用退出前的准备工作。 |
| onActive() | Ability切换到前台,并且已经获取焦点时调用onActive方法。 |
| onInactive() | Ability失去焦点时调用onInactive方法,Ability在进入后台状态时会先失去焦点,再进入后台。 |
| onShow() | Ability由后台不可见状态切换到前台可见状态调用onShow方法,此时用户在屏幕可以看到该Ability。 |
| onHide() | Ability由前台切换到后台不可见状态时调用onHide方法,此时用户在屏幕看不到该Ability。 |
PageAbility生命周期回调与生命周期状态的关系如下图所示。
**图2** PageAbility生命周期回调与生命周期状态的关系
![fa-pageAbility-lifecycle](figures/fa-pageAbility-lifecycle.png)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 1、PageAbility的生命周期回调均为同步接口。
>
> 2、目前app.js环境中仅支持onCreate和onDestroy回调,app.ets环境支持全量生命周期回调。
# PageAbility组件概述
PageAbility是包含UI界面、提供展示UI能力的应用组件,主要用于与用户交互。
开发者通过DevEco Studio开发平台创建PageAbility时,DevEco Studio会自动创建相关模板代码。PageAbility相关能力通过单独的featureAbility实现,生命周期相关回调则通过app.js/app.ets中各个回调函数实现。
# PageAbility切换
FA模型中PageAbility对应Stage模型中的UIAbility。切换步骤如下。
1. 在Stage应用中[创建UIAbility](uiability-usage.md)
2. 将FA应用中PageAbility的代码迁移到新创建的UIAbility中。
FA应用中PageAbility和Stage应用中的UIAbility生命周期基本一致,两者的生命周期详细对比见下表。
| FA的PageAbility | Stage的UIAbility | 对应关系描述 |
| -------- | -------- | -------- |
| onCreate():&nbsp;void | onCreate(want:&nbsp;Want,&nbsp;param:&nbsp;AbilityConstant.LaunchParam):&nbsp;void | 两者的意义和调用时机一致,Stage模型在回调中新增了参数,方便开发者在创建的时候获取启动相关的数据。 |
| NA | onWindowStageCreate(windowStage:&nbsp;window.WindowStage):&nbsp;void | Stage模型新增,窗口创建时由系统回调。 |
| onActive():&nbsp;void | on(eventType:&nbsp;'windowStageEvent',&nbsp;callback:&nbsp;Callback&lt;WindowStageEventType&gt;):&nbsp;void;<br/>WindowStageEventType.ACTIVE | 两者的意义和调用时机一致。Stage模型下移动到了窗口对象中。 |
| onShow():&nbsp;void | onForeground():&nbsp;void | 两者的意义和调用时机一致,参数也一致。 |
| onNewWant(want:&nbsp;Want):&nbsp;void | onNewWant(want:&nbsp;Want,&nbsp;launchParams:&nbsp;AbilityConstant.LaunchParam):&nbsp;void | 两者的意义和调用时机一致,Stage模型多了LaunchParam参数来告知应用启动原因。 |
| onInactive():&nbsp;void | on(eventType:&nbsp;'windowStageEvent',&nbsp;callback:&nbsp;Callback&lt;WindowStageEventType&gt;):&nbsp;void;<br/>WindowStageEventType.INACTIVE | 两者的意义和调用时机一致。Stage模型下移动到了窗口对象中。 |
| onHide():&nbsp;void | onBackground():&nbsp;void | 两者的意义和调用时机一致,参数也一致。 |
| NA | onWindowStageDestroy():&nbsp;void | Stage模型新增,窗口销毁时由系统回调。 |
| onDestroy():&nbsp;void | onDestroy():&nbsp;void | 两者的意义和调用时机一致,参数也一致。 |
![pageability-switch](figures/pageability-switch.png)
3. 对迁移过来的代码进行调整,主要有以下两部分。
1、指定加载页面的方式不同。
- 在FA模型中,通过在config.json中设置页面信息来配置需要加载的页面。
- 在Stage模型中,则是通过在onWindowStageCreate回调中调用windowStage.loadContent实现对页面的加载。
例如,开发者希望Ability启动后加载"pages/Index"页面,在FA模型中,开发者需要在config.json中加入如下代码:
```json
"pages" : [
"pages/Index"
]
```
在Stage模型中,则在MainAbility中实现如下接口:
```ts
import Window from '@ohos.window'
onWindowStageCreate(windowStage: Window.WindowStage) {
// Main window is created, set main page for this ability
windowStage.loadContent('pages/Index', (err, data) => {
if (err.code) {
console.error("loadContent failed")
return;
}
});
}
```
# particleAbility接口切换
| FA模型接口 | Stage模型接口对应d.ts文件 | Stage模型对应接口 |
| -------- | -------- | -------- |
| [startAbility(parameter:&nbsp;StartAbilityParameter,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void;](../reference/apis/js-apis-particleAbility.md#particleabilitystartability)<br/>[startAbility(parameter:&nbsp;StartAbilityParameter):&nbsp;Promise&lt;number&gt;;](../reference/apis/js-apis-particleAbility.md#particleabilitystartability-1) | application\ServiceExtensionContext.d.ts | [startAbility(want:&nbsp;Want,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextstartability)<br/>[startAbility(want:&nbsp;Want,&nbsp;options:&nbsp;StartOptions,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextstartability-2)<br/>[startAbility(want:&nbsp;Want,&nbsp;options?:&nbsp;StartOptions):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextstartability-1)<br/>[startServiceExtensionAbility(want:&nbsp;Want,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextstartserviceextensionability)<br/>[startServiceExtensionAbility(want:&nbsp;Want):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextstartserviceextensionability-1) |
| [terminateSelf(callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-particleAbility.md#particleabilityterminateself)<br/>[terminateSelf():&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-particleAbility.md#particleabilityterminateself-1) | application\ServiceExtensionContext.d.ts | [terminateSelf(callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextterminateself)<br/>[terminateSelf():&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextterminateself-1) |
| [connectAbility(request:&nbsp;Want,&nbsp;options:ConnectOptions&nbsp;):&nbsp;number;](../reference/apis/js-apis-particleAbility.md#particleabilityconnectability) | application\ServiceExtensionContext.d.ts | [connectAbility(want:&nbsp;Want,&nbsp;options:&nbsp;ConnectOptions):&nbsp;number;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextconnectserviceextensionability)<br/>[connectServiceExtensionAbility(want:&nbsp;Want,&nbsp;options:&nbsp;ConnectOptions):&nbsp;number;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextconnectserviceextensionability) |
| [disconnectAbility(connection:&nbsp;number,&nbsp;callback:AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-particleAbility.md#particleabilitydisconnectability)<br/>[disconnectAbility(connection:&nbsp;number):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-particleAbility.md#particleabilitydisconnectability-1) | application\ServiceExtensionContext.d.ts | [disconnectAbility(connection:&nbsp;number,&nbsp;callback:AsyncCallback&lt;void&gt;):&nbsp;void;&nbsp;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextdisconnectserviceextensionability)<br/>[disconnectAbility(connection:&nbsp;number):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextdisconnectserviceextensionability-1)<br/>[disconnectServiceExtensionAbility(connection:&nbsp;number,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextdisconnectserviceextensionability)<br/>[disconnectServiceExtensionAbility(connection:&nbsp;number):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextdisconnectserviceextensionability-1) |
| [acquireDataAbilityHelper(uri:&nbsp;string):&nbsp;DataAbilityHelper;](../reference/apis/js-apis-particleAbility.md#particleabilityacquiredataabilityhelper) | \@ohos.data.dataShare.d.ts<br/>[\@ohos.data.fileAccess.d.ts | [createDataShareHelper(context:&nbsp;Context,&nbsp;uri:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;DataShareHelper&gt;):&nbsp;void;](../reference/apis/js-apis-data-dataShare.md#datasharecreatedatasharehelper)<br/>[createDataShareHelper(context:&nbsp;Context,&nbsp;uri:&nbsp;string):&nbsp;Promise&lt;DataShareHelper&gt;;](../reference/apis/js-apis-data-dataShare.md#datasharecreatedatasharehelper-1)<br/>[createFileAccessHelper(context:&nbsp;Context):&nbsp;FileAccessHelper;](../reference/apis/js-apis-fileAccess.md#fileaccesscreatefileaccesshelper-1)<br/>[createFileAccessHelper(context:&nbsp;Context,&nbsp;wants:&nbsp;Array&lt;Want&gt;):&nbsp;FileAccessHelper;](../reference/apis/js-apis-fileAccess.md#fileaccesscreatefileaccesshelper) |
| [startBackgroundRunning(id:&nbsp;number,&nbsp;request:&nbsp;NotificationRequest,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-particleAbility.md#particleabilitystartbackgroundrunning)<br/>[startBackgroundRunning(id:&nbsp;number,&nbsp;request:&nbsp;NotificationRequest):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-particleAbility.md#particleabilitystartbackgroundrunning-1) | \@ohos.resourceschedule.backgroundTaskManager.d.ts | [startBackgroundRunning(context:&nbsp;Context,&nbsp;bgMode:&nbsp;BackgroundMode,&nbsp;wantAgent:&nbsp;WantAgent,&nbsp;callback:&nbsp;AsyncCallback):&nbsp;void;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstartbackgroundrunningcallback)<br/>[startBackgroundRunning(context:&nbsp;Context,&nbsp;bgMode:&nbsp;BackgroundMode,&nbsp;wantAgent:&nbsp;WantAgent):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstartbackgroundrunningpromise) |
| [cancelBackgroundRunning(callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-particleAbility.md#particleabilitycancelbackgroundrunning)<br/>[cancelBackgroundRunning():&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-particleAbility.md#particleabilitycancelbackgroundrunning-1) | \@ohos.resourceschedule.backgroundTaskManager.d.ts | [stopBackgroundRunning(context:&nbsp;Context,&nbsp;callback:&nbsp;AsyncCallback):&nbsp;void;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstopbackgroundrunningcallback)<br/>[stopBackgroundRunning(context:&nbsp;Context):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstopbackgroundrunningpromise) |
# 进程模型
OpenHarmony的进程模型如下图所示:
- 应用中(同一包名)的所有PageAbility、ServiceAbility、DataAbility、FormAbility运行在同一个独立进程中,即图中绿色部分的“Main Process”。
- WebView拥有独立的渲染进程,即图中黄色部分的“Render Process”。
**图1** 进程模型示意图
![process-model-fa](figures/process-model-fa.png)
基于OpenHarmony的进程模型,应用间存在多个进程的情况,因此系统提供了如下两种进程间通信机制:
- [公共事件机制](common-event-fa.md):多用于一对多的通信场景,公共事件发布者可能存在多个订阅者同时接收事件。
- [后台服务机制](rpc.md):当前主要通过[ServiceAbility](serviceability-overview.md)的能力实现。
# 进程模型
OpenHarmony的进程模型如下图所示:
- 应用中(同一包名)的所有UIAbility、ServiceExtensionAbility、DataShareExtensionAbility运行在同一个独立进程中,即图中绿色部分的“Main Process”。
- 应用中(同一包名)的同一类型ExtensionAbility(除ServiceExtensionAbility和DataShareExtensionAbility外)运行在一个独立进程中,即图中蓝色部分的“FormExtensionAbility Process”、“InputMethodExtensionAbility Process”、其他ExtensionAbility Process。
- WebView拥有独立的渲染进程,即图中黄色部分的“Render Process”。
**图1** 进程模型示意图
![process-model](figures/process-model.png)
在上述模型基础上,对于系统应用可以通过申请多进程权限(如下图所示),为指定HAP配置一个自定义进程名,该HAP中的UIAbility、DataShareExtensionAbility、ServiceExtensionAbility就会运行在自定义进程中。不同的HAP可以通过配置不同的进程名运行在不同进程中。
**图2** 多进程示意图
![multi-process](figures/multi-process.png)
基于OpenHarmony的进程模型,系统中应用间和应用内都会存在多个进程的情况,因此系统提供了如下两种进程间通信机制:
- [公共事件机制](common-event-overview.md):多用于一对多的通信场景,公共事件发布者可能存在多个订阅者同时接收事件。
- [后台服务机制](background-services.md):当前主要通过[ServiceExtensionAbility](serviceextensionability.md)的能力实现。
# 跳转规则
一般情况下,应用中的界面跳转由用户触发,应用本身通过startAbility启动跳转其他界面。
PageAbility作为可见Ability,可以通过startAbility启动有界面的且对外可见的Ability。
应用可通过在config.json中设置"abilities"中的"visible"属性设置Ability是否可由其他应用的组件启动,"visible"属性的具体参数和意义如下表所示。
**表1** visible属性说明
| 属性名称 | 描述 | 是否可缺省 |
| -------- | -------- | -------- |
| visible | 表示Ability是否可以被其他应用调用。<br/>true:该Ability可以被任何应用调用。<br/>false:该Ability只能被同一应用的其他组件调用。 | 可缺省,缺省时默认属性值为"false"。 |
如果需设置当前Ability可由任何应用访问,对应config.json文件的示例代码如下所示:
```ts
{
"module": {
// ...
"abilities": [
{
"visible": "true",
// ...
}
]
}
}
```
如果应用中的Ability包含skills过滤器,建议此属性设置为"true",以允许其他应用通过[隐式调用](explicit-implicit-want-mappings.md#隐式want匹配原理详解)启动该Ability。如果此属性设为"false",其他应用尝试启动该Ability时系统会返回PERMISSION_DENIED。这种情况下系统应用可以通过申请[START_INVISIBLE_ABILITY](../security/permission-list.md)权限启动visible为false的组件,例如系统桌面、语音助手、搜索助手等。
# 申请授权
应用需要获取用户的隐私信息或使用系统能力时,例如获取位置信息、使用相机拍摄照片或录制视频等,需要向用户申请授权。
在开发过程中,首先需要明确涉及的敏感权限并在config.json中声明需要的权限,同时通过接口requestPermissionsFromUser以动态弹窗的方式向用户申请授权。
在config.json声明需要的权限,在module下添加"reqPermissions",并写入对应权限。
如申请访问日历权限,需要申请`ohos.permission.READ_CALENDAR`权限,配置方式请参阅[访问控制授权申请指导](../security/accesstoken-guidelines.md#stage模型)
对应config.json文件的示例代码如下所示:
```json
{
"module": {
// ...
"reqPermissions": [
{
"name": "ohos.permission.READ_CALENDAR"
// ...
}
]
}
}
```
通过动态弹窗向用户申请授权:
```ts
import featureAbility from '@ohos.ability.featureAbility';
let context = featureAbility.getContext();
let permissions: Array<string> = ['ohos.permission.READ_CALENDAR']
context.requestPermissionsFromUser(permissions, 1).then((data) => {
console.info("Succeed to request permission from user with data: " + JSON.stringify(data))
}).catch((error) => {
console.info("Failed to request permission from user with error: " + JSON.stringify(error))
})
```
# request接口切换
| FA模型接口 | Stage模型接口对应d.ts文件 | Stage模型对应接口 |
| -------- | -------- | -------- |
| [download(config:&nbsp;DownloadConfig,&nbsp;callback:&nbsp;AsyncCallback&lt;DownloadTask&gt;):&nbsp;void;](../reference/apis//js-apis-request.md#requestdownload-1)<br/>[download(config:&nbsp;DownloadConfig):&nbsp;Promise&lt;DownloadTask&gt;;](../reference/apis/js-apis-request.md#requestdownload) | \@ohos.request.d.ts | [downloadFile(context:&nbsp;BaseContext,&nbsp;config:&nbsp;DownloadConfig,&nbsp;callback:&nbsp;AsyncCallback&lt;DownloadTask&gt;):&nbsp;void;](../reference/apis/js-apis-request.md#requestdownloadfile9-1)<br/>[downloadFile(context:&nbsp;BaseContext,&nbsp;config:&nbsp;DownloadConfig):&nbsp;Promise&lt;DownloadTask&gt;;](../reference/apis/js-apis-request.md#requestdownloadfile9) |
| [upload(config:&nbsp;UploadConfig,&nbsp;callback:&nbsp;AsyncCallback&lt;UploadTask&gt;):&nbsp;void;](../reference/apis/js-apis-request.md#requestupload-1)<br/>[upload(config:&nbsp;UploadConfig):&nbsp;Promise&lt;UploadTask&gt;;](../reference/apis/js-apis-request.md#requestupload) | \@ohos.request.d.ts | [uploadFile(context:&nbsp;BaseContext,&nbsp;config:&nbsp;UploadConfig,&nbsp;callback:&nbsp;AsyncCallback&lt;UploadTask&gt;):&nbsp;void;](../reference/apis/js-apis-request.md#requestuploadfile9-1)<br/>[uploadFile(context:&nbsp;BaseContext,&nbsp;config:&nbsp;UploadConfig):&nbsp;Promise&lt;UploadTask&gt;;](../reference/apis/js-apis-request.md#requestuploadfile9) |
# resourceManager接口切换
| FA模型接口 | Stage模型接口对应d.ts文件 | Stage模型对应字段 |
| -------- | -------- | -------- |
| [getResourceManager(callback:&nbsp;AsyncCallback&lt;ResourceManager&gt;):&nbsp;void;](../reference/apis/js-apis-resource-manager.md#resourcemanagergetresourcemanager)<br/>[getResourceManager(bundleName:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;ResourceManager&gt;):&nbsp;void;](../reference/apis/js-apis-resource-manager.md#resourcemanagergetresourcemanager-1)<br/>[getResourceManager():&nbsp;Promise&lt;ResourceManager&gt;;](../reference/apis/js-apis-resource-manager.md#resourcemanagergetresourcemanager-2)<br/>[getResourceManager(bundleName:&nbsp;string):&nbsp;Promise&lt;ResourceManager&gt;;](../reference/apis/js-apis-resource-manager.md#resourcemanagergetresourcemanager-3) | application\Context.d.ts | [resourceManager:&nbsp;resmgr.ResourceManager;](../reference/apis/js-apis-application-context.md#属性) |
# 后台服务
请参见Stage模型的"[后台服务](background-services.md)"。
# ServiceAbility组件配置
与PageAbility类似,ServiceAbility的相关配置在config.json配置文件的"module"对象的"abilities"对象中,与PageAbility的区别在于"type"属性及"backgroundModes"属性。
**表1** ServiceAbility部分配置项说明
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| type | 表示Ability的类型。取值为"service"时表示该Ability是基于Service模板开发的Ability。 | 字符串 | 否 |
| backgroundModes | 表示后台服务的类型,可以为一个服务配置多个后台服务类型。该标签仅适用于service类型的Ability。取值范围如下:<br/>dataTransfer:通过网络/对端设备进行数据下载、备份、分享、传输等业务。<br/>audioPlayback:音频输出业务。<br/>audioRecording:音频输入业务。<br/>pictureInPicture:画中画、小窗口播放视频业务。<br/>voip:音视频电话、VOIP业务。<br/>location:定位、导航业务。<br/>bluetoothInteraction:蓝牙扫描、连接、传输业务。<br/>wifiInteraction:WLAN扫描、连接、传输业务。<br/>screenFetch:录屏、截屏业务。<br/>multiDeviceConnection:多设备互联业务。 | 字符串数组 | 可缺省,缺省值为空。 |
ServiceAbility支持的配置项及详细说明详见[module对象内部结构](../quick-start/module-structure.md)
# ServiceAbility的生命周期
开发者可以根据业务场景重写生命周期相关接口。ServiceAbility生命周期接口说明见下表。
**表1** ServiceAbility生命周期接口说明
| 接口名 | 描述 |
| -------- | -------- |
| onStart():&nbsp;void | 该方法在创建ServiceAbility的时候调用,用于Service的初始化,在ServiceAbility的整个生命周期只会调用一次。 |
| onCommand(want:&nbsp;Want,&nbsp;startId:&nbsp;number):&nbsp;void | 在Service创建完成之后调用,该方法在客户端每次启动该Service时都会调用,开发者可以在该方法中做一些调用统计、初始化类的操作。 |
| onConnect(want:&nbsp;Want):&nbsp;rpc.RemoteObject | 在连接ServiceAbility时调用。 |
| onDisconnect(want:&nbsp;Want):&nbsp;void | 在与已连接的ServiceAbility断开连接时调用。 |
| onStop():&nbsp;void | 在ServiceAbility销毁时调用。开发者应通过实现此方法来清理资源,如关闭线程、注册的侦听器等。 |
# ServiceAbility组件概述
ServiceAbility,即"基于Service模板的Ability",主要用于后台运行任务(如执行音乐播放、文件下载等),不提供用户交互界面。ServiceAbility可由其他应用或PageAbility启动,即使用户切换到其他应用,ServiceAbility仍将在后台继续运行。
# ServiceAbility切换
FA模型中的ServiceAbility对应Stage模型中的ServiceExtensionAbility。Stage模型下的ServiceExtensionAbility为系统API,只有系统应用才可以创建。因此,FA模型的ServiceAbility的切换,对于系统应用和三方应用策略有所不同。下面分别介绍这两种场景。
## 系统应用ServiceAbility切换
目前系统提供了ServiceExtensionAbility供系统应用使用。切换步骤和PageAbility基本一致。
1. 在Stage应用中[创建ServiceExtensionAbility](serviceextensionability.md)
2. 将FA应用中ServiceAbility的业务代码迁移到新创建的ServiceExtensionAbility中。
ServiceAbility和ServiceExtensionAbility生命周期对比见下表。
| FA的ServiceAbility | Stage的ServiceExtensionAbility | 对比描述 |
| -------- | -------- | -------- |
| onStart():&nbsp;void | onCreate(want:&nbsp;Want):&nbsp;void | 两者调用时机一致,Stage模型下增加了入参want以便开发者在创建时获取参数。 |
| onCommand(want:&nbsp;Want,&nbsp;startId:&nbsp;number):&nbsp;void | onRequest(want:&nbsp;Want,&nbsp;startId:&nbsp;number):&nbsp;void | 两者意义和调用时机一致,参数也一致。 |
| onConnect(want:&nbsp;Want):&nbsp;rpc.RemoteObject | onConnect(want:&nbsp;Want):&nbsp;rpc.RemoteObject | 两者意义和调用时机一致,参数也一致。 |
| onDisconnect(want:&nbsp;Want):&nbsp;void | onDisconnect(want:&nbsp;Want):&nbsp;void | 两者意义和调用时机一致,参数也一致。 |
| onReconnect(want:&nbsp;Want):&nbsp;void | onReconnect(want:&nbsp;Want):&nbsp;void | 两者意义和调用时机一致,参数也一致。 |
| onStop():&nbsp;void | onDestroy():&nbsp;void | 两者意义和调用时机一致,参数也一致。 |
## 三方应用ServiceAbility切换
Stage模型下三方应用不能对其他三方提供服务,应用可以根据具体业务选择切换方案。
| 业务类型 | 切换策略 |
| -------- | -------- |
| 对其他三方应用提供服务 | 需根据业务场景匹配到系统对应的场景化[ExtensionAbility](extensionability-overview.md)。 |
| 应用内:前台运行时公共使用 | 可以将该组件代码抽取成公共模块供其他组件使用。 |
| 应用内:进入后台时继续运行 | 可以将此服务切换为[后台任务](serviceextensionability.md),可参考如下示例。 |
# ServiceExtensionAbility
[ServiceExtensionAbility](../reference/apis/js-apis-service-extension-ability.md)是SERVICE类型的ExtensionAbility组件,提供后台服务相关扩展能力。
[ServiceExtensionAbility](../reference/apis/js-apis-service-extension-ability.md)可以被其他组件启动或连接,并根据调用者的请求信息在后台处理相关事务。[ServiceExtensionAbility](../reference/apis/js-apis-service-extension-ability.md)支持以启动和连接两种形式运行,系统应用可以调用[startServiceExtensionAbility()](../reference/apis/js-apis-ability-context.md#abilitycontextstartserviceextensionability)方法启动后台服务,也可以调用[connectServiceExtensionAbility()](../reference/apis/js-apis-ability-context.md#abilitycontextconnectserviceextensionability)方法连接后台服务,而三方应用只能调用[connectServiceExtensionAbility()](../reference/apis/js-apis-ability-context.md#abilitycontextconnectserviceextensionability)方法连接后台服务。启动和连接后台服务的差别:
- 启动:AbilityA启动ServiceB,启动后AbilityA和ServiceB为弱关联,AbilityA退出后,ServiceB可以继续存在。
- 连接:AbilityA绑定ServiceB,绑定后AbilityA和ServiceB为强关联,AbilityA退出后,ServiceB也一起退出。
每个类型的ExtensionAbility都有自己的Context,ServiceExtensionAbility通过[ServiceExtensionContext](../reference/apis/js-apis-service-extension-context.md)提供相关能力。本文描述中称被启动的ServiceExtensionAbility为服务端,称启动ServiceExtensionAbility的组件为客户端。
本章节将从如下场景来介绍ServiceExtensionAbility的基本使用。
- [实现一个后台服务(仅对系统应用开放)](#实现一个后台服务仅对系统应用开放)
- [启动一个后台服务(仅对系统应用开放)](#启动一个后台服务仅对系统应用开放)
- [连接一个后台服务](#连接一个后台服务)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 1. OpenHarmony当前不支持三方应用实现ServiceExtensionAbility。如果三方开发者想要实现后台处理相关事务的功能,可以使用后台任务,具体请参见[后台任务](../task-management/Readme-CN.md)。
>
> 2. 三方应用的UIAbility组件可以通过Context连接系统提供的ServiceExtensionAbility。
>
> 3. 三方应用需要在前台获焦的情况下才能连接系统提供的ServiceExtensionAbility。
## 实现一个后台服务(仅对系统应用开放)
[ServiceExtensionAbility](../reference/apis/js-apis-service-extension-ability.md)提供了onCreate()、onRequest()、onConnect()、onDisconnect()和onDestory()生命周期回调,根据需要重写对应的回调方法。下图展示了ServiceExtensionAbility的生命周期。
**图1** ServiceExtensionAbility生命周期
![ServiceExtensionAbility-lifecycle](figures/ServiceExtensionAbility-lifecycle.png)
- **onCreate**
服务被首次创建时触发该回调,开发者可以在此进行一些初始化的操作,例如注册公共事件监听等。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 如果服务已创建,再次启动该ServiceExtensionAbility不会触发onCreate()回调。
- **onRequest**
当另一个组件调用startServiceExtensionAbility()方法启动该服务组件时,触发该回调。执行此方法后,服务会启动并在后台运行。
- **onConnect**
当另一个组件调用connectServiceExtensionAbility()方法与该服务连接时,触发该回调。开发者在此方法中,返回一个远端代理对象(IRemoteObject),客户端拿到这个对象后可以通过这个对象与服务端进行RPC通信。
- **onDisconnect**
其他组件调用disconnectServiceExtensionAbility()方法时,如果没有任何其他组件连接该服务,触发该回调。
- **onDestroy**
当不再使用服务且准备将其销毁该实例时,触发该回调。开发者可以在该回调中清理资源,如注销监听等。
## 开发步骤
开发者在实现一个后台服务时,需要在DevEco Studio工程中手动新建一个ServiceExtensionAbility,具体步骤如下。
1. 在工程Module对应的ets目录下,右键选择“New &gt; Directory”,新建一个目录并命名为serviceextability。
2. 在serviceextability目录,右键选择“New &gt; ts File”,新建一个TS文件并命名为ServiceExtAbility.ts。
3. 打开ServiceExtAbility.ts文件,导入[RPC通信模块](../reference/apis/js-apis-rpc.md),重载onRemoteMessageRequest()方法,接收客户端传递过来的消息,并将处理的结果返回给客户端。REQUEST_VALUE用于校验客户端发送的服务请求码。
```ts
import rpc from '@ohos.rpc';
const REQUEST_CODE = 99;
class StubTest extends rpc.RemoteObject {
constructor(des) {
super(des);
}
// 接收客户端传递过来的消息处理,以及将处理的结果返回给客户端
onRemoteMessageRequest(code, data, reply, option) {
if (code === REQUEST_CODE) {
// 接收客户端传递过来的数据
// 客户端使用多次调用data.writeInt()写入多个数据时,服务端可以通过多次调用data.readInt()方法接收对应的数据
let optFir = data.readInt();
let optSec = data.readInt();
// 服务端将数据的处理结果返回给客户端
// 示例中为接收了两个数据,并将两个数据的求和返回给客户端
reply.writeInt(optFir + optSec);
}
return true;
}
// 以同步或异步方式向客户端发送消息
sendRequest(code, data, reply, options) {
return null;
}
}
```
4. 在ServiceExtAbility.ts文件中,增加导入ServiceExtensionAbility的依赖包,自定义类继承ServiceExtensionAbility并加上需要的生命周期回调。
```ts
import ServiceExtensionAbility from '@ohos.app.ability.ServiceExtensionAbility';
import rpc from '@ohos.rpc';
const TAG: string = "[Example].[Entry].[ServiceExtAbility]";
const REQUEST_CODE = 99;
class StubTest extends rpc.RemoteObject {
// ...
}
export default class ServiceExtAbility extends ServiceExtensionAbility {
onCreate(want) {
console.info(TAG, `onCreate, want: ${want.abilityName}`);
}
onRequest(want, startId) {
console.info(TAG, `onRequest, want: ${want.abilityName}`);
}
onConnect(want) {
console.info(TAG, `onConnect, want: ${want.abilityName}`);
return new StubTest("test");
}
onDisconnect(want) {
console.info(TAG, `onDisconnect, want: ${want.abilityName}`);
}
onDestroy() {
console.info(TAG, `onDestroy`);
}
}
```
5. 在工程Module对应的[module.json5配置文件](../quick-start/module-configuration-file.md)中注册ServiceExtensionAbility,type标签需要设置为“service”,srcEntrance标签表示当前ExtensionAbility组件所对应的代码路径。
```json
{
"module": {
// ...
"extensionAbilities": [
{
"name": "ServiceExtAbility",
"icon": "$media:icon",
"description": "service",
"type": "service",
"visible": true,
"srcEntrance": "./ets/serviceextability/ServiceExtAbility.ts"
}
]
}
}
```
## 启动一个后台服务(仅对系统应用开放)
系统应用通过[startServiceExtensionAbility()](../reference/apis/js-apis-ability-context.md#abilitycontextstartserviceextensionability)方法启动一个后台服务,服务的[onRequest()](../reference/apis/js-apis-service-extension-ability.md#serviceextensionabilityonrequest)回调就会被调用,并在该回调方法中接收到调用者传递过来的want对象。后台服务启动后,其生命周期独立于客户端,即使客户端已经销毁,该后台服务仍可继续运行。因此,后台服务需要在其工作完成时通过调用ServiceExtensionContext的[terminateSelf()](../reference/apis/js-apis-service-extension-context.md#serviceextensioncontextterminateself)来自行停止,或者由另一个组件调用[stopServiceExtensionAbility()](../reference/apis/js-apis-ability-context.md#abilitycontextstopserviceextensionability)来将其停止。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> ServiceExtensionContext的[startServiceExtensionAbility()](../reference/apis/js-apis-ability-context.md#abilitycontextstartserviceextensionability)、[stopServiceExtensionAbility()](../reference/apis/js-apis-ability-context.md#abilitycontextstopserviceextensionability)和[terminateSelf()](../reference/apis/js-apis-service-extension-context.md#serviceextensioncontextterminateself)为系统接口,三方应用不支持调用。
1. 在系统应用中启动一个新的ServiceExtensionAbility。示例中的context的获取方式参见[获取UIAbility的Context属性](uiability-usage.md#获取uiability的上下文信息)
```ts
let want = {
"deviceId": "",
"bundleName": "com.example.myapplication",
"abilityName": "ServiceExtAbility"
};
this.context.startServiceExtensionAbility(want).then(() => {
console.info('startServiceExtensionAbility success');
}).catch((error) => {
console.info('startServiceExtensionAbility failed');
})
```
2. 在系统应用中停止一个已启动的ServiceExtensionAbility。
```ts
let want = {
"deviceId": "",
"bundleName": "com.example.myapplication",
"abilityName": "ServiceExtAbility"
};
this.context.stopServiceExtensionAbility(want).then(() => {
console.info('stopServiceExtensionAbility success');
}).catch((error) => {
console.info('stopServiceExtensionAbility failed');
})
```
3. 已启动的ServiceExtensionAbility停止自身。
```ts
// this是当前ServiceExtensionAbility
this.context.terminateSelf().then(() => {
console.info('terminateSelf success');
}).catch((error) => {
console.info('terminateSelf failed');
})
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 后台服务可以在后台长期运行,为了避免资源浪费,需要对后台服务的生命周期进行管理。即一个后台服务完成了请求方的任务,需要及时销毁。销毁已启动的后台服务有两种方式:
>
> - 后台服务自身调用[terminateSelf()](../reference/apis/js-apis-service-extension-context.md#serviceextensioncontextterminateself)方法来自行停止。
>
> - 由其他组件调用[stopServiceExtensionAbility()](../reference/apis/js-apis-ability-context.md#abilitycontextstopserviceextensionability)方法来停止。
>
> 调用[terminateSelf()](../reference/apis/js-apis-service-extension-context.md#serviceextensioncontextterminateself)或[stopServiceExtensionAbility()](../reference/apis/js-apis-ability-context.md#abilitycontextstopserviceextensionability)方法之后,系统将销毁后台服务。
## 连接一个后台服务
系统应用或者三方应用可以通过[connectServiceExtensionAbility()](../reference/apis/js-apis-ability-context.md#abilitycontextconnectserviceextensionability)连接一个服务(在Want对象中指定启动的目标服务),服务的[onConnect()](../reference/apis/js-apis-service-extension-ability.md#serviceextensionabilityonconnect)就会被调用,并在该回调方法中接收到调用者传递过来的Want对象,从而建立长连接。
ServiceExtensionAbility服务组件在[onConnect()](../reference/apis/js-apis-service-extension-ability.md#serviceextensionabilityonconnect)中返回IRemoteObject对象,开发者通过该IRemoteObject定义通信接口,用于客户端与服务端进行RPC交互。多个客户端可以同时连接到同一个后台服务,客户端完成与服务的交互后,客户端需要通过调用[disconnectServiceExtensionAbility()](../reference/apis/js-apis-ability-context.md#abilitycontextdisconnectserviceextensionability)来断开连接。如果所有连接到某个后台服务的客户端均已断开连接,则系统会销毁该服务。
- 使用connectServiceExtensionAbility()建立与后台服务的连接。示例中的context的获取方式参见[获取UIAbility的Context属性](uiability-usage.md#获取uiability的上下文信息)
```ts
import rpc from '@ohos.rpc';
const REQUEST_CODE = 99;
let want = {
"deviceId": "",
"bundleName": "com.example.myapplication",
"abilityName": "ServiceExtAbility"
};
let options = {
onConnect(elementName, remote) {
console.info('onConnect callback');
if (remote === null) {
console.info(`onConnect remote is null`);
return;
}
let option = new rpc.MessageOption();
let data = new rpc.MessageParcel();
let reply = new rpc.MessageParcel();
data.writeInt(100);
data.writeInt(200);
// @param code 表示客户端发送的服务请求代码。
// @param data 表示客户端发送的{@link MessageParcel}对象。
// @param reply 表示远程服务发送的响应消息对象。
// @param options 指示操作是同步的还是异步的。
//
// @return 如果操作成功返回{@code true}; 否则返回 {@code false}。
remote.sendRequest(REQUEST_CODE, data, reply, option).then((ret) => {
let msg = reply.readInt();
console.info(`sendRequest ret:${ret} msg:${msg}`);
}).catch((error) => {
console.info('sendRequest failed');
});
},
onDisconnect(elementName) {
console.info('onDisconnect callback')
},
onFailed(code) {
console.info('onFailed callback')
}
}
// 建立连接后返回的Id需要保存下来,在解绑服务时需要作为参数传入
let connectionId = this.context.connectServiceExtensionAbility(want, options);
```
- 使用disconnectServiceExtensionAbility()断开与后台服务的连接。
```ts
let connectionId = 1 // 在通过connectServiceExtensionAbility绑定服务时返回的Id
this.context.disconnectServiceExtensionAbility(connectionId).then((data) => {
console.info('disconnectServiceExtensionAbility success');
}).catch((error) => {
console.error('disconnectServiceExtensionAbility failed');
})
```
## 相关示例
针对ServiceExtensionAbility开发,有以下相关示例可供参考:
[ServiceExtAbility:StageExtAbility的创建与使用(ArkTS)(API9)(Full SDK)](https://gitee.com/openharmony/applications_app_samples/tree/master/ability/ServiceExtAbility)
# Stage模型开发概述
## 基本概念
下图展示了Stage模型中的基本概念。
**图1** Stage模型概念图  
![stage-concepts](figures/stage-concepts.png)
- [UIAbility组件](uiability-overview.md)[ExtensionAbility组件](extensionability-overview.md)
Stage模型提供UIAbility和ExtensionAbility两种类型的组件,这两种组件都有具体的类承载,支持面向对象的开发方式。他们是Ability抽象概念在Stage模型上的具体实现。他们是Ability管理服务调度的单元,其生命周期都是由Ability管理服务进行调度的。
- UIAbility组件是一种包含UI界面的应用组件,主要用于和用户交互。例如,图库类应用可以在UIAbility组件中展示图片瀑布流,在用户选择某个图片后,在新的页面中展示图片的详细内容。同时用户可以通过返回键返回到瀑布流页面。UIAbility的生命周期只包含创建/销毁/前台/后台等状态,与显示相关的状态通过WindowStage的事件暴露给开发者。
- ExtensionAbility组件是一种面向特定场景的应用组件。开发者并不直接从ExtensionAbility派生,而是需要使用ExtensionAbility的派生类。目前ExtensionAbility有用于卡片场景的FormExtensionAbility,用于输入法场景的InputMethodExtensionAbility,用于闲时任务场景的WorkSchedulerExtensionAbility等多种派生类,这些派生类都是基于特定场景提供的。例如,用户在桌面创建应用的卡片,需要应用开发者从FormExtensionAbility派生,实现其中的回调函数,并在配置文件中配置该能力。ExtensionAbility派生类实例由用户触发创建,并由系统管理生命周期。在Stage模型上,普通应用开发者不能开发自定义服务,而需要根据自身的业务场景通过ExtensionAbility的派生类来实现。
- [WindowStage](../windowmanager/application-window-stage.md)
每个UIAbility类实例都会与一个WindowStage类实例绑定,该类提供了应用进程内窗口管理器的作用。它包含一个主窗口。也就是说UIAbility通过WindowStage持有了一个窗口,该窗口为ArkUI提供了绘制区域。
- [Context](application-context-stage.md)
在Stage模型上,Context及其派生类向开发者提供在运行期可以调用的各种能力。UIAbility组件和各种ExtensionAbility派生类都有各自不同的Context类,他们都继承自基类Context,但是各自又根据所属组件,提供不同的能力。
- [AbilityStage](abilitystage.md)
每个Entry类型或者Feature类型的HAP在运行期都有一个AbilityStage类实例,当HAP中的代码首次被加载到进程中的时候,系统会先创建AbilityStage实例。每个在该HAP中定义的UIAbility类,在实例化后都会与该实例产生关联。开发者可以使用AbilityStage获取该HAP中UIAbility实例的运行时信息。
## 开发流程
基于Stage模型开发应用时,在应用模型部分,涉及如下开发过程。
**表1** Stage模型开发流程
| 任务 | 简介 | 相关指导 |
| -------- | -------- | -------- |
| 应用组件开发 | 本章节介绍了如何使用Stage模型的UIAbility组件和ExtensionAbility组件开发应用。 | -&nbsp;[应用/组件级配置](application-component-configuration-stage.md)<br/>-&nbsp;[UIAbility组件](uiability-overview.md)<br/>-&nbsp;[ExtensionAbility组件](extensionability-overview.md)<br/>-&nbsp;[AbilityStage组件容器](abilitystage.md)<br/>-&nbsp;[应用上下文Context](application-context-stage.md)<br/>-&nbsp;[组件启动规则](component-startup-rules.md) |
| 应用配置文件 | 本章节介绍了Stage模型的配置文件中所有的字段以及各个字段的说明。 | -&nbsp;[app.json5配置文件](../quick-start/app-configuration-file.md)<br/>-&nbsp;[module.json5配置文件](../quick-start/module-configuration-file.md) |
| 进程间通信 | 本章节介绍了Stage模型的进程模型以及几种常用的进程间通信方式。 | -&nbsp;[公共事件](common-event-overview.md)<br/>-&nbsp;[后台服务](background-services.md) |
| 线程间通信 | 本章节介绍了Stage模型的线程模型以及几种常用的线程间通信方式。 | -&nbsp;[Emitter](itc-with-emitter.md)<br/>-&nbsp;[Worker](itc-with-worker.md) |
| 任务管理 | 本章节介绍了Stage模型中任务管理的基本概念和典型场景。 | -&nbsp;[任务管理场景介绍](mission-management-overview.md)<br/>-&nbsp;[任务管理与启动模式](mission-management-launch-type.md)<br/>-&nbsp;[页面栈和任务链](page-mission-stack.md) |
# 启动DataAbility
启动DataAbility会获取一个工具接口类对象(DataAbilityHelper)。启动DataAbility的示例代码如下:
```ts
// 作为参数传递的URI,与config中定义的URI的区别是多了一个"/",有三个"/",具体原因详见。
import featureAbility from '@ohos.ability.featureAbility'
let urivar = "dataability:///com.ix.DataAbility"
let DAHelper = featureAbility.acquireDataAbilityHelper(urivar);
```
# 启动本地PageAbility
PageAbility相关的能力通过featureAbility提供,启动本地Ability通过featureAbility中的startAbility接口实现。
**表1** featureAbility接口说明
| 接口名 | 接口描述 |
| -------- | -------- |
| startAbility(parameter:&nbsp;StartAbilityParameter) | 启动Ability。 |
| startAbilityForResult(parameter:&nbsp;StartAbilityParameter) | 启动Ability,并在该Ability被销毁时返回执行结果。 |
如下示例通过startAbility显式启动PageAbility。启动Ability的参数包含want,关于want的说明详见[对象间信息传递载体Want](want-fa.md),相应的,隐式启动与显式启动也不在此赘述。
```ts
import featureAbility from '@ohos.ability.featureAbility'
(async () => {
try {
console.info('Begin to start ability')
let param = {
want: {
bundleName: "com.example.myapplication",
moduleName: "entry",
abilityName: "com.example.myapplication.MainAbility"
}
}
await featureAbility.startAbility(param)
console.info(`Start ability succeed`)
}
catch (error) {
console.error('Start ability failed with ' + error)
}
})()
```
# 启动指定页面
当PageAbility的启动模式设置为单例时(具体设置方法和典型场景示例见[PageAbility的启动模式](pageability-launch-type.md),缺省情况下是单实例模式),若PageAbility已被拉起,再次启动PageAbility会触发onNewWant回调(即非首次拉起)。应用开发者可以通过want传递启动参数,例如开发者希望指定页面启动PageAbility,可以通过want中的parameters参数传递pages信息,具体示例代码如下:
调用方PageAbility的app.ets中或者page中,使用startAbility再次拉起PageAbility,通过want中的uri参数传递页面信息:
```ts
import featureAbility from '@ohos.ability.featureAbility';
async function restartAbility() {
let wantInfo = {
bundleName: "com.sample.MyApplication",
abilityName: "MainAbility",
parameters: {
page: "pages/second"
}
};
featureAbility.startAbility({
want: wantInfo
}).then((data) => {
console.info('restartAbility success.');
});
}
```
在目标端PageAbility的onNewWant回调中获取包含页面信息的want参数:
```ts
export default {
onNewWant(want) {
globalThis.newWant = want
}
}
```
在目标端页面的自定义组件中获取包含页面信息的want参数并根据uri做路由处理:
```ts
import router from '@ohos.router'
@Entry
@Component
struct Index {
@State message: string = 'Router Page'
newWant = undefined
onPageShow() {
console.info('Index onPageShow')
let newWant = globalThis.newWant
if (newWant.hasOwnProperty("page")) {
router.push({ url: newWant.page });
globalThis.newWant = undefined
}
}
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}
```
当PageAbility的启动模式设置为标准模式或为首次启动单例模式的PageAbility时(具体设置方法和典型场景示例见[PageAbility的启动模式](pageability-launch-type.md)),在调用方PageAbility中,通过want中的parameters参数传递要启动的指定页面的pages信息,调用startAbility()方法启动PageAbility。被调用方可以在onCreate中使用featrueAbility的getWant方法获取want,再通过调用router.push实现启动指定页面。
调用方的页面中实现按钮点击触发startAbility方法启动目标端PageAbility,startAbility方法的入参want中携带指定页面信息,示例代码如下:
```ts
import featureAbility from '@ohos.ability.featureAbility'
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() {
// ...
Button("startAbility")
.onClick(() => {
featureAbility.startAbility({
want: {
bundleName: "com.exm.myapplication",
abilityName: "com.exm.myapplication.MainAbility",
parameters: { page: "pages/page1" }
}
}).then((data) => {
console.info("startAbility finish");
}).catch((err) => {
console.info("startAbility failed errcode:" + err.code)
})
})
// ...
Button("page2")
.onClick(() => {
featureAbility.startAbility({
want: {
bundleName: "com.exm.myapplication",
abilityName: "com.exm.myapplication.MainAbility",
parameters: { page: "pages/page2" }
}
}).then((data) => {
console.info("startAbility finish");
}).catch((err) => {
console.info("startAbility failed errcode:" + err.code)
})
})
// ...
}
}
```
目标端PageAbility的onCreate生命周期回调中通过featrueAbility的getWant方法获取want,并对参数进行解析,实现指定页面拉起:
```ts
import featureAbility from '@ohos.ability.featureAbility';
import router from '@ohos.router';
export default {
onCreate() {
featureAbility.getWant().then((want) => {
if (want.parameters.page) {
router.push({
url: want.parameters.page
})
}
})
},
onDestroy() {
// ...
},
}
```
# Stage模型启动FA模型PageAbility
本小节介绍Stage模型的两种应用组件如何启动FA模型的PageAbility组件。
## UIAbility启动PageAbility
UIAbility启动PageAbility和UIAbility启动UIAbility的方式完全相同。
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
export default class MainAbility extends UIAbility {
onCreate(want, launchParam) {
console.info("MainAbility onCreate")
}
onDestroy() {
console.info("MainAbility onDestroy")
}
onWindowStageCreate(windowStage) {
console.info("MainAbility onWindowStageCreate")
windowStage.loadContent('pages/Index', (err, data) => {
// ...
});
let want = {
bundleName: "com.ohos.fa",
abilityName: "MainAbility",
};
this.context.startAbility(want).then(() => {
console.info('Start Ability successfully.');
}).catch((error) => {
console.error("Ability failed: " + JSON.stringify(error));
});
}
onWindowStageDestroy() {
console.info("MainAbility onWindowStageDestroy")
}
onForeground() {
console.info("MainAbility onForeground")
}
onBackground() {
console.info("MainAbility onBackground")
}
}
```
## UIAbility访问PageAbility(startAbilityForResult)
startAbilityForResult和startAbility的区别是当PageAbility销毁的时候会返回执行结果。
UIAbility通过startAbilityForResult启动PageABility和UIAbility通过startAbilityForResult启动UIAbility的代码一样,没有任何区别。
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
export default class MainAbility extends UIAbility {
onCreate(want, launchParam) {
console.info("MainAbility onCreate")
}
onDestroy() {
console.info("MainAbility onDestroy")
}
onWindowStageCreate(windowStage) {
console.info("MainAbility onWindowStageCreate")
windowStage.loadContent('pages/Index', (err, data) => {
// ...
});
let want = {
bundleName: "com.ohos.fa",
abilityName: "MainAbility",
};
this.context.startAbilityForResult(want).then((result) => {
console.info('Ability verify result: ' + JSON.stringify(result));
}).catch((error) => {
console.error("Ability failed: " + JSON.stringify(error));
});
}
onWindowStageDestroy() {
console.info("MainAbility onWindowStageDestroy")
}
onForeground() {
console.info("MainAbility onForeground")
}
onBackground() {
console.info("MainAbility onBackground")
}
}
```
## ExtensionAbility启动PageAbility
下面以ServiceExtensionAbility为例来说明ExtensionAbility启动PageAbility。ServiceExtensionAbility启动PageAbility和ServiceExtensionAbility启动UIAbility的方式完全相同。
```ts
import Extension from '@ohos.app.ability.ServiceExtensionAbility'
export default class ServiceExtension extends Extension {
onCreate(want) {
console.info("ServiceExtension onCreate")
}
onDestroy() {
console.info("ServiceExtension onDestroy")
}
onRequest(want, startId) {
console.info("ServiceExtension onRequest")
let wantFA = {
bundleName: "com.ohos.fa",
abilityName: "MainAbility",
};
this.context.startAbility(wantFA).then(() => {
console.info('Start Ability successfully.');
}).catch((error) => {
console.error("Ability failed: " + JSON.stringify(error));
});
}
}
```
# 启动远程PageAbility(仅对系统应用开放)
启动远程PageAbility同样通过featureAbility中的startAbility接口实现。
除引入'\@ohos.ability.featureAbility'外,还需引入'\@ohos.distributedHardware.deviceManager',通过DeviceManager(该组件在OpenHarmony上提供账号无关的分布式设备的认证组网能力)的getTrustedDeviceListSync接口(获取信任设备列表)获取远端的deviceId,写入want中,用于启动远程PageAbility。
由于当前DeviceManager的getTrustedDeviceListSync接口仅对系统应用开放,故现阶段非系统应用无法获取其他设备信息,无远程启动设备选择入口,远程启动Ability开发。
**表1** featureAbility接口说明
| 接口名 | 接口描述 |
| -------- | -------- |
| startAbility(parameter:&nbsp;StartAbilityParameter) | 启动Ability。 |
| startAbilityForResult(parameter:&nbsp;StartAbilityParameter) | 启动Ability,并在该Ability被销毁时返回执行结果。 |
**表2** deviceManager接口说明
| 接口名 | 接口描述 |
| -------- | -------- |
| getTrustedDeviceListSync():&nbsp;Array&lt;DeviceInfo&gt; | 同步获取所有可信设备列表。 |
在跨设备场景下,启动远程PageAbility首先需要向用户申请数据同步的权限,相关接口说明如下:
**表3** AtManager接口说明
| 接口名 | 接口描述 |
| -------- | -------- |
| checkAccessToken(tokenID:&nbsp;number,&nbsp;permissionName:&nbsp;string)<br>:&nbsp;Promise&lt;GrantStatus&gt; | 校验应用是否授予权限。使用Promise异步回调。返回值GrantStatus。建议使用checkAccessToken代替verifyAccessToken(已废弃),verifyAccessToken从API&nbsp;version&nbsp;9开始不再维护。 |
**表4** context接口说明
| 接口名 | 接口描述 |
| -------- | -------- |
| requestPermissionsFromUser(permissions:&nbsp;Array&lt;string&gt;,&nbsp;<br>requestCode:&nbsp;number,&nbsp;resultCallback:&nbsp;AsyncCallback&lt;<br>PermissionRequestResult&gt;):&nbsp;void | 以callback形式从系统请求某些权限,详见对应[接口文档](../reference/apis/js-apis-Context.md#contextrequestpermissionsfromuser7-1)。 |
如下示例代码展示了向用户申请数据同步权限的方法:
```ts
import abilityAccessCtrl from "@ohos.abilityAccessCtrl";
import featureAbility from '@ohos.ability.featureAbility';
import bundle from '@ohos.bundle.bundleManager';
async function RequestPermission() {
console.info('RequestPermission begin');
let array: Array<string> = ["ohos.permission.DISTRIBUTED_DATASYNC"];
let bundleFlag = 0;
let tokenID = undefined;
let userID = 100;
let appInfo = await bundle.getApplicationInfo('ohos.samples.etsDemo', bundleFlag, userID);
tokenID = appInfo.accessTokenId;
let atManager = abilityAccessCtrl.createAtManager();
let requestPermissions: Array<string> = [];
for (let i = 0;i < array.length; i++) {
let result = await atManager.verifyAccessToken(tokenID, array[i]);
console.info("checkAccessToken result:" + JSON.stringify(result));
if (result != abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
requestPermissions.push(array[i]);
}
}
console.info("requestPermissions:" + JSON.stringify(requestPermissions));
if (requestPermissions.length == 0 || requestPermissions == []) {
return;
}
let context = featureAbility.getContext();
context.requestPermissionsFromUser(requestPermissions, 1, (error, data)=>{
console.info("data:" + JSON.stringify(data));
console.info("data requestCode:" + data.requestCode);
console.info("data permissions:" + data.permissions);
console.info("data authResults:" + data.authResults);
});
console.info('RequestPermission end');
}
```
在获取数据同步权限后,需要获取可信设备列表,进行设备选择。
如下示例展示了通过getTrustedDeviceListSync获取可信设备列表,选择设备的方法。
```ts
import deviceManager from '@ohos.distributedHardware.deviceManager';
let dmClass;
function getDeviceManager() {
deviceManager.createDeviceManager('ohos.example.distributedService', (error, dm) => {
if (error) {
console.info('create device manager failed with ' + error)
}
dmClass = dm;
})
}
function getRemoteDeviceId() {
if (typeof dmClass === 'object' && dmClass != null) {
let list = dmClass.getTrustedDeviceListSync();
if (typeof (list) == 'undefined' || typeof (list.length) == 'undefined') {
console.info("MainAbility onButtonClick getRemoteDeviceId err: list is null");
return;
}
console.info("MainAbility onButtonClick getRemoteDeviceId success:" + list[0].deviceId);
return list[0].deviceId;
} else {
console.info("MainAbility onButtonClick getRemoteDeviceId err: dmClass is null");
}
}
```
设备选择完成后,通过调用startAbility接口,显式启动远程PageAbility。
如下示例展示了通过startAbility显式启动远程PageAbility的方法。
```ts
import featureAbility from '@ohos.ability.featureAbility';
function onStartRemoteAbility() {
console.info('onStartRemoteAbility begin');
let params;
let wantValue = {
bundleName: 'ohos.samples.etsDemo',
abilityName: 'ohos.samples.etsDemo.RemoteAbility',
deviceId: getRemoteDeviceId(), // getRemoteDeviceId的定义在前面的示例代码中
parameters: params
};
console.info('onStartRemoteAbility want=' + JSON.stringify(wantValue));
featureAbility.startAbility({
want: wantValue
}).then((data) => {
console.info('onStartRemoteAbility finished, ' + JSON.stringify(data));
});
console.info('onStartRemoteAbility end');
}
```
# 启动ServiceAbility
ServiceAbility的启动与其他Ability并无区别,应用开发者可以在PageAbility中通过featureAbility的startAbility接口拉起ServiceAbility,在ServiceAbility中通过particleAbility的startAbility接口拉起ServiceAbility。ServiceAbility的启动规则详见[组件启动规则](component-startup-rules.md)章节。
如下示例展示了在PageAbility中通过startAbility启动bundleName为"com.example.myapplication",abilityName为"ServiceAbility"的ServiceAbility的方法。启动FA模型的ServiceAbility时,需要在abilityName前拼接bundleName字符串。
```ts
import featureAbility from '@ohos.ability.featureAbility'
async function startServiceAbility() {
try {
console.info('Begin to start ability')
let param = {
want: {
bundleName: "com.example.myapplication",
abilityName: "com.example.myapplication.ServiceAbility"
}
}
await featureAbility.startAbility(param)
console.info(`Start ability succeed`)
} catch (error) {
console.error('Start ability failed with ' + error)
}
}
```
执行上述代码后,Ability将通过startAbility() 方法来启动ServiceAbility。
- 如果ServiceAbility尚未运行,则系统会先调用onStart()来初始化ServiceAbility,再回调Service的onCommand()方法来启动ServiceAbility。
- 如果ServiceAbility正在运行,则系统会直接回调ServiceAbility的onCommand()方法来启动ServiceAbility。
# FA模型启动Stage模型UIAbility
本文介绍FA模型的三种应用组件如何启动Stage模型的UIAbility组件。
## PageAbility启动UIAbility
在PageAbility中启动UIAbility和在PageAbility中启动PageAbility的方式完全相同。
```ts
import featureAbility from '@ohos.ability.featureAbility';
let parameter = {
"want": {
bundleName: "com.ohos.stage",
abilityName: "com.ohos.stage.MainAbility"
}
};
featureAbility.startAbility(parameter).then((code) => {
console.info('Ability verify code: ' + JSON.stringify(code));
}).catch((error) => {
console.error("Ability failed: " + JSON.stringify(error));
});
```
## PageAbility访问UIAbility(startAbilityForResult)
startAbilityForResult和startAbility的区别是当UIAbility销毁的时候会返回执行结果。
在PageAbility中通过startAbilityForResult启动UIAbility和在PageAbility中通过startAbilityForResult启动PageAbility的方式完全相同。
```ts
import featureAbility from '@ohos.ability.featureAbility';
let parameter = {
"want": {
bundleName: "com.ohos.stage",
abilityName: "com.ohos.stage.MainAbility"
}
};
featureAbility.startAbilityForResult(parameter).then((result) => {
console.info('Ability verify result: ' + JSON.stringify(result));
}).catch((error) => {
console.error("Ability failed: " + JSON.stringify(error));
});
```
## ServiceAbility/DataAbility启动UIAbility
在ServiceAbility/DataAbility中启动UIAbility和在ServiceAbility/DataAbility中启动PageAbility的方式完全相同。
```ts
import particleAbility from '@ohos.ability.particleAbility';
let parameter = {
"want": {
bundleName: "com.ohos.stage",
abilityName: "com.ohos.stage.MainAbility"
}
};
particleAbility.startAbility(parameter).then(() => {
console.info('Start Ability successfully.');
}).catch((error) => {
console.error("Ability failed: " + JSON.stringify(error));
});
```
# 停止PageAbility
停止PageAbility通过featureAbility中的terminateSelf接口实现。
**表1** featureAbility接口说明
| 接口名 | 接口描述 |
| -------- | -------- |
| terminateSelf() | 停止Ability。 |
| terminateSelfWithResult(parameter:&nbsp;AbilityResult) | 设置该PageAbility停止时返回给调用者的结果及数据并停止Ability。 |
如下示例展示了停止Ability的方法。
```ts
import featureAbility from '@ohos.ability.featureAbility'
(async () => {
try {
console.info('Begin to terminateSelf')
await featureAbility.terminateSelf()
console.info('terminateSelf succeed')
}
catch (error) {
console.error('terminateSelf failed with ' + error)
}
})()
```
# Storage接口切换
| FA模型接口 | Stage模型接口对应d.ts文件 | Stage模型对应接口 |
| -------- | -------- | -------- |
| GetStorageOptions | Stage模型无对应接口 | Storage接口功能使用Prefereces接口来代替,接口入参已经重新设计 |
| SetStorageOptions | Stage模型无对应接口 | Storage接口功能使用Prefereces接口来代替,接口入参已经重新设计 |
| ClearStorageOptions | Stage模型无对应接口 | Storage接口功能使用Prefereces接口来代替,接口入参已经重新设计 |
| DeleteStorageOptions | Stage模型无对应接口 | Storage接口功能使用Prefereces接口来代替,接口入参已经重新设计 |
| [static&nbsp;get(options:&nbsp;GetStorageOptions):&nbsp;void;](../reference/apis/js-apis-system-storage.md#storageget) | \@ohos.data.preferences.d.ts | [get(key:&nbsp;string,&nbsp;defValue:&nbsp;ValueType,&nbsp;callback:&nbsp;AsyncCallback&lt;ValueType&gt;):&nbsp;void;](../reference/apis/js-apis-data-preferences.md#get)<br/>[get(key:&nbsp;string,&nbsp;defValue:&nbsp;ValueType):&nbsp;Promise&lt;ValueType&gt;;](../reference/apis/js-apis-data-preferences.md#get-1) |
| [static&nbsp;set(options:&nbsp;SetStorageOptions):&nbsp;void;](../reference/apis/js-apis-system-storage.md#storageset) | \@ohos.data.preferences.d.ts | [put(key:&nbsp;string,&nbsp;value:&nbsp;ValueType,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-data-preferences.md#put)<br/>[put(key:&nbsp;string,&nbsp;value:&nbsp;ValueType):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-data-preferences.md#put-1) |
| [static&nbsp;clear(options?:&nbsp;ClearStorageOptions):&nbsp;void;](../reference/apis/js-apis-system-storage.md#storageclear) | \@ohos.data.preferences.d.ts | [clear(callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-data-preferences.md#clear)<br/>[clear():&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-data-preferences.md#clear-1) |
| [static&nbsp;delete(options:&nbsp;DeleteStorageOptions):&nbsp;void;](../reference/apis/js-apis-system-storage.md#storagedelete) | \@ohos.data.preferences.d.ts | [delete(key:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-data-preferences.md#delete)<br/>[delete(key:&nbsp;string):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-data-preferences.md#delete-1) |
# 线程模型
FA模型下的线程主要有如下三类:
- 主线程
负责管理其他线程
- Ability线程
- 每个Ability一个线程
- 输入事件分发
- UI绘制
- 应用代码回调(事件处理,生命周期)
- 接收Worker发送的消息
- Worker线程
执行耗时操作
基于OpenHarmony的线程模型,不同的业务功能运行在不同的线程上,业务功能的交互就需要线程间通信。线程间通信目前主要有Emitter和Worker两种方式,其中Emitter主要适用于线程间的事件同步, Worker主要用于新开一个线程执行耗时任务。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> FA模型每个ability都有一个独立的线程,Emiter可用于Ability线程内、Ability线程间、Ability线程与Worker线程的事件同步。
# 线程模型
OpenHarmony应用中每个进程都会有一个主线程,主线程有如下职责:
1. 负责管理其他线程
2. 同应用多个UIAbility组件共用一个主线程
3. 输入事件分发
4. UI绘制
5. 应用代码回调(事件处理,生命周期)
6. 接收Worker发送的消息
除主线程外,还有一类与主线程并行的独立线程Worker,主要用于执行耗时操作,但不可以直接操作UI。Worker线程在主线程中创建,与主线程相互独立。最多可以创建7个Worker:
![thread-model-stage](figures/thread-model-stage.png)
基于OpenHarmony的线程模型,不同的业务功能运行在不同的线程上,业务功能的交互就需要线程间通信。线程间通信目前主要有Emitter和Worker两种方式,其中Emitter主要适用于线程间的事件同步, Worker主要用于新开一个线程执行耗时任务。
**说明:**
* Stage模型只提供了主线程和Worker线程,Emitter主要用于主线程内或者主线程和Worker线程的事件同步。
\ No newline at end of file
# UIAbility组件与UI的数据同步
基于OpenHarmony的应用模型,可以通过以下两种方式来实现UIAbility组件与UI之间的数据同步。
1. EventHub:基于发布订阅模式来实现,事件需要先订阅后发布,订阅者收到消息后进行处理。
2. globalThis:ArkTS引擎实例内部的一个全局对象,在ArkTS引擎实例内部都能访问。
## 使用EventHub进行数据通信
EventHub提供了UIAbility组件/ExtensionAbility组件级别的事件机制,以UIAbility组件/ExtensionAbility组件为中心提供了订阅、取消订阅和触发事件的数据通信能力。接口说明请参见[EventHub](../reference/apis/js-apis-eventhub.md)
在使用EventHub之前,首先需要获取EventHub对象。[基类Context](application-context-stage.md)提供了EventHub对象,本章节以使用EventHub实现UIAbility与UI之间的数据通信为例进行说明。
1. 在UIAbility中调用eventHub.on()方法注册一个自定义事件“event1”,eventHub.on()有如下两种调用方式,使用其中一种即可。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
const TAG: string = '[Example].[Entry].[EntryAbility]';
export default class EntryAbility extends UIAbility {
func1(...data) {
// 触发事件,完成相应的业务操作
console.info(TAG, '1. ' + JSON.stringify(data));
}
onCreate(want, launch) {
// 获取eventHub
let eventhub = this.context.eventHub;
// 执行订阅操作
eventhub.on('event1', this.func1);
eventhub.on('event1', (...data) => {
// 触发事件,完成相应的业务操作
console.info(TAG, '2. ' + JSON.stringify(data));
});
}
}
```
2. 在UI界面中通过eventHub.emit()方法触发该事件,在触发事件的同时,根据需要传入参数信息。
```ts
import common from '@ohos.app.ability.common';
@Entry
@Component
struct Index {
private context = getContext(this) as common.UIAbilityContext;
eventHubFunc() {
// 不带参数触发自定义“event1”事件
this.context.eventHub.emit('event1');
// 带1个参数触发自定义“event1”事件
this.context.eventHub.emit('event1', 1);
// 带2个参数触发自定义“event1”事件
this.context.eventHub.emit('event1', 2, 'test');
// 开发者可以根据实际的业务场景设计事件传递的参数
}
// 页面展示
build() {
// ...
}
}
```
3. 在UIAbility的注册事件回调中可以得到对应的触发事件结果,运行日志结果如下所示。
```ts
[]
[1]
[2,'test']
```
4. 在自定义事件“event1”使用完成后,可以根据需要调用eventHub.off()方法取消该事件的订阅。
```ts
// context为UIAbility实例的AbilityContext
this.context.eventHub.off('event1');
```
## 使用globalThis进行数据同步
globalThis是ArkTS引擎实例内部的一个全局对象,引擎内部的UIAbility/ExtensionAbility/Page都可以使用,因此可以使用globalThis全局对象进行数据同步。
**图1** 使用globalThis进行数据同步
<img src="figures/globalThis1.png" alt="globalThis1" style="zoom:67%;" />
如上图所示,下面从如下三个场景和一个注意点来介绍globalThis的使用:
- [UIAbility和Page之间使用globalThis](#uiability和page之间使用globalthis)
- [UIAbility和UIAbility之间使用globalThis](#uiability和uiability之间使用globalthis)
- [UIAbility和ExtensionAbility之间使用globalThis](#uiability和extensionability之间使用globalthis)
- [globalThis使用的注意事项](#globalthis使用的注意事项)
### UIAbility和Page之间使用globalThis
globalThis为[ArkTS引擎实例](thread-model-stage.md)下的全局对象,可以通过globalThis绑定属性/方法来进行UIAbility组件与UI的数据同步。例如在UIAbility组件中绑定want参数,即可在UIAbility对应的UI界面上使用want参数信息。
1. 调用startAbility()方法启动一个UIAbility实例时,被启动的UIAbility创建完成后会进入onCreate()生命周期回调,且在onCreate()生命周期回调中能够接受到传递过来的want参数,可以将want参数绑定到globalThis上。
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
export default class EntryAbility extends UIAbility {
onCreate(want, launch) {
globalThis.entryAbilityWant = want;
// ...
}
// ...
}
```
2. 在UI界面中即可通过globalThis获取到want参数信息。
```ts
let entryAbilityWant;
@Entry
@Component
struct Index {
aboutToAppear() {
entryAbilityWant = globalThis.entryAbilityWant;
}
// 页面展示
build() {
// ...
}
}
```
### UIAbility和UIAbility之间使用globalThis
同一个应用中UIAbility和UIAbility之间的数据传递,可以通过将数据绑定到全局变量globalThis上进行同步,如在AbilityA中将数据保存在globalThis,然后跳转到AbilityB中取得该数据:
1. AbilityA中保存数据一个字符串数据并挂载到globalThis上。
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
export default class AbilityA extends UIAbility {
onCreate(want, launch) {
globalThis.entryAbilityStr = 'AbilityA'; // AbilityA存放字符串“AbilityA”到globalThis
// ...
}
}
```
2. AbilityB中获取对应的数据。
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
export default class AbilityB extends UIAbility {
onCreate(want, launch) {
// AbilityB从globalThis读取name并输出
console.info('name from entryAbilityStr: ' + globalThis.entryAbilityStr);
// ...
}
}
```
### UIAbility和ExtensionAbility之间使用globalThis
同一个应用中UIAbility和ExtensionAbility之间的数据传递,也可以通过将数据绑定到全局变量globalThis上进行同步,如在AbilityA中保存数据,在ServiceExtensionAbility中获取数据。
1. AbilityA中保存数据一个字符串数据并挂载到globalThis上。
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
export default class AbilityA extends UIAbility {
onCreate(want, launch) {
// AbilityA存放字符串“AbilityA”到globalThis
globalThis.entryAbilityStr = 'AbilityA';
// ...
}
}
```
2. ExtensionAbility中获取数据。
```ts
import Extension from '@ohos.app.ability.ServiceExtensionAbility'
export default class ServiceExtAbility extends Extension {
onCreate(want) {
// ServiceExtAbility从globalThis读取name并输出
console.info('name from entryAbilityStr: ' + globalThis.entryAbilityStr);
// ...
}
}
```
### globalThis使用的注意事项
**图2** globalThis注意事项
![globalThis2](figures/globalThis2.png)
- Stage模型下进程内的UIAbility组件共享ArkTS引擎实例,使用globalThis时需要避免存放相同名称的对象。例如AbilityA和AbilityB可以使用globalThis共享数据,在存放相同名称的对象时,先存放的对象会被后存放的对象覆盖。
- FA模型因为每个UIAbility组件之间引擎隔离,不会存在该问题。
- 对于绑定在globalThis上的对象,其生命周期与ArkTS虚拟机实例相同,建议在使用完成之后将其赋值为null,以减少对应用内存的占用。
Stage模型上同名对象覆盖导致问题的场景举例说明。
1. 在AbilityA文件中使用globalThis中存放了[UIAbilityContext](../reference/apis/js-apis-ability-context.md)
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
export default class AbilityA extends UIAbility {
onCreate(want, launch) {
globalThis.context = this.context; // AbilityA存放context到globalThis
// ...
}
}
```
2. 在AbilityA的页面中获取该[UIAbilityContext](../reference/apis/js-apis-ability-context.md)并进行使用。使用完成后将AbilityA实例切换至后台。
```ts
@Entry
@Component
struct Index {
onPageShow() {
let ctx = globalThis.context; // 页面中从globalThis中取出context并使用
let permissions = ['com.example.permission']
ctx.requestPermissionsFromUser(permissions,(result) => {
// ...
});
}
// 页面展示
build() {
// ...
}
}
```
3. 在AbilityB文件中使用globalThis中存放了[UIAbilityContext](../reference/apis/js-apis-ability-context.md),并且命名为相同的名称。
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
export default class AbilityB extends UIAbility {
onCreate(want, launch) {
// AbilityB覆盖了AbilityA在globalThis中存放的context
globalThis.context = this.context;
// ...
}
}
```
4. 在AbilityB的页面中获取该[UIAbilityContext](../reference/apis/js-apis-ability-context.md)并进行使用。此时获取到的globalThis.context已经表示为AbilityB中赋值的[UIAbilityContext](../reference/apis/js-apis-ability-context.md)内容。
```ts
@Entry
@Component
struct Index {
onPageShow() {
let ctx = globalThis.context; // Page中从globalThis中取出context并使用
let permissions = ['com.example.permission']
ctx.requestPermissionsFromUser(permissions,(result) => {
console.info('requestPermissionsFromUser result:' + JSON.stringify(result));
});
}
// 页面展示
build() {
// ...
}
}
```
5. 在AbilityB实例切换至后台,将AbilityA实例从后台切换回到前台。此时AbilityA的onCreate生命周期不会再次进入。
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
export default class AbilityA extends UIAbility {
onCreate(want, launch) { // AbilityA从后台进入前台,不会再走这个生命周期
globalThis.context = this.context;
// ...
}
}
```
6. 在AbilityA的页面再次回到前台时,其获取到的globalThis.context表示的为AbilityB的[UIAbilityContext](../reference/apis/js-apis-ability-context.md),而不是AbilityA的[UIAbilityContext](../reference/apis/js-apis-ability-context.md),在AbilityA的页面中使用则会出错。
```ts
@Entry
@Component
struct Index {
onPageShow() {
let ctx = globalThis.context; // 这时候globalThis中的context是AbilityB的context
let permissions=['com.example.permission'];
ctx.requestPermissionsFromUser(permissions,(result) => { // 使用这个对象就会导致进程崩溃
console.info('requestPermissionsFromUser result:' + JSON.stringify(result));
});
}
// 页面展示
build() {
// ...
}
}
```
# UIAbility组件间交互(设备内)
UIAbility是系统调度的最小单元。在设备内的功能模块之间跳转时,会涉及到启动特定的UIAbility,该UIAbility可以是应用内的其他UIAbility,也可以是其他应用的UIAbility(例如启动三方支付UIAbility)。
本章节将从如下场景分别介绍设备内UIAbility间的交互方式。对于跨设备的应用组件交互,请参见[应用组件跨设备交互(流转)](inter-device-interaction-hop-overview.md)
- [启动应用内的UIAbility](#启动应用内的uiability)
- [启动应用内的UIAbility并获取返回结果](#启动应用内的uiability并获取返回结果)
- [启动其他应用的UIAbility](#启动其他应用的uiability)
- [启动其他应用的UIAbility并获取返回结果](#启动其他应用的uiability并获取返回结果)
- [启动UIAbility的指定页面](#启动uiability的指定页面)
- [通过Call调用实现UIAbility交互(仅对系统应用开放)](#通过call调用实现uiability交互仅对系统应用开放)
## 启动应用内的UIAbility
当一个应用内包含多个UIAbility时,存在应用内启动UIAbility的场景。例如在支付应用中从入口UIAbility启动收付款UIAbility。
假设应用中有两个UIAbility:EntryAbility和FuncAbility(可以在应用的一个Module中,也可以在的不同Module中),需要从EntryAbility的页面中启动FuncAbility。
1. 在EntryAbility中,通过调用startAbility()方法启动UIAbility,[want](../reference/apis/js-apis-application-Want.md)为UIAbility实例启动的入口参数,其中bundleName为待启动应用的Bundle名称,abilityName为待启动的UIAbility名称,moduleName在待启动的UIAbility属于不同的Module时添加,parameters为自定义信息参数。示例中的context的获取方式参见[获取UIAbility的Context属性](uiability-usage.md#获取uiability的上下文信息)
```ts
let wantInfo = {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'module1', // moduleName非必选
parameters: { // 自定义信息
info: '来自EntryAbility Index页面',
},
}
// context为调用方UIAbility的AbilityContext
this.context.startAbility(wantInfo).then(() => {
// ...
}).catch((err) => {
// ...
})
```
2. 在FuncAbility的生命周期回调文件中接收EntryAbility传递过来的参数。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
import Window from '@ohos.window';
export default class FuncAbility extends UIAbility {
onCreate(want, launchParam) {
// 接收调用方UIAbility传过来的参数
let funcAbilityWant = want;
let info = funcAbilityWant?.parameters?.info;
// ...
}
}
```
3. 在FuncAbility业务完成之后,如需要停止当前UIAbility实例,在FuncAbility中通过调用terminateSelf()方法实现。
```ts
// context为需要停止的UIAbility实例的AbilityContext
this.context.terminateSelf((err) => {
// ...
});
```
## 启动应用内的UIAbility并获取返回结果
在一个EntryAbility启动另外一个FuncAbility时,希望在被启动的FuncAbility完成相关业务后,能将结果返回给调用方。例如在应用中将入口功能和帐号登录功能分别设计为两个独立的UIAbility,在帐号登录UIAbility中完成登录操作后,需要将登录的结果返回给入口UIAbility。
1. 在EntryAbility中,调用startAbilityForResult()接口启动FuncAbility,异步回调中的data用于接收FuncAbility停止自身后返回给EntryAbility的信息。示例中的context的获取方式参见[获取UIAbility的Context属性](uiability-usage.md#获取uiability的上下文信息)
```ts
let wantInfo = {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'module1', // moduleName非必选
parameters: { // 自定义信息
info: '来自EntryAbility Index页面',
},
}
// context为调用方UIAbility的AbilityContext
this.context.startAbilityForResult(wantInfo).then((data) => {
// ...
}).catch((err) => {
// ...
})
```
2. 在FuncAbility停止自身时,需要调用terminateSelfWithResult()方法,入参abilityResult为FuncAbility需要返回给EntryAbility的信息。
```ts
const RESULT_CODE: number = 1001;
let abilityResult = {
resultCode: RESULT_CODE,
want: {
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'module1',
parameters: {
info: '来自FuncAbility Index页面',
},
},
}
// context为被调用方UIAbility的AbilityContext
this.context.terminateSelfWithResult(abilityResult, (err) => {
// ...
});
```
3. FuncAbility停止自身后,EntryAbility通过startAbilityForResult()方法回调接收被FuncAbility返回的信息,RESULT_CODE需要与前面的数值保持一致。
```ts
const RESULT_CODE: number = 1001;
// ...
// context为调用方UIAbility的AbilityContext
this.context.startAbilityForResult(want).then((data) => {
if (data?.resultCode === RESULT_CODE) {
// 解析被调用方UIAbility返回的信息
let info = data.want?.parameters?.info;
// ...
}
}).catch((err) => {
// ...
})
```
## 启动其他应用的UIAbility
启动其他应用的UIAbility,通常用户只需要完成一个通用的操作(例如需要选择一个文档应用来查看某个文档的内容信息),推荐使用[隐式Want启动](want-overview.md#want的类型)。系统会根据调用方的want参数来识别和启动匹配到的应用UIAbility。
启动UIAbility有[显式Want启动和隐式Want启动](want-overview.md)两种方式。
- 显式Want启动:启动一个确定应用的UIAbility,在want参数中需要设置该应用bundleName和abilityName,当需要拉起某个明确的UIAbility时,通常使用显式Want启动方式。
- 隐式Want启动:根据匹配条件由用户选择启动哪一个UIAbility,即不明确指出要启动哪一个UIAbility(abilityName参数未设置),在调用startAbility()方法时,其入参want中指定了一系列的[entities](../reference/apis/js-apis-ability-wantConstant.md#wantconstantentity)字段(表示目标UIAbility额外的类别信息,如浏览器、视频播放器)和[actions](../reference/apis/js-apis-ability-wantConstant.md#wantconstantaction)字段(表示要执行的通用操作,如查看、分享、应用详情等)等参数信息,然后由系统去分析want,并帮助找到合适的UIAbility来启动。当需要拉起其他应用的UIAbility时,开发者通常不知道用户设备中应用的安装情况,也无法确定目标应用的bundleName和abilityName,通常使用隐式Want启动方式。
本章节主要讲解如何通过隐式Want启动其他应用的UIAbility。
1. 将多个待匹配的文档应用安装到设备,在其对应UIAbility的module.json5配置文件中,配置skills的[entities](../reference/apis/js-apis-ability-wantConstant.md#wantconstantentity)字段和[actions](../reference/apis/js-apis-ability-wantConstant.md#wantconstantaction)字段。
```json
{
"module": {
"abilities": [
{
// ...
"skills": [
{
"entities": [
// ...
"entity.system.default"
],
"actions": [
// ...
"ohos.want.action.viewData"
]
}
]
}
]
}
}
```
2. 在调用方want参数中的entities和action需要被包含在待匹配UIAbility的skills配置的entities和actions中。系统匹配到符合entities和actions参数条件的UIAbility后,会弹出选择框展示匹配到的UIAbility实例列表供用户选择使用。示例中的context的获取方式参见[获取UIAbility的Context属性](uiability-usage.md#获取uiability的上下文信息)
```ts
let wantInfo = {
deviceId: '', // deviceId为空表示本设备
// uncomment line below if wish to implicitly query only in the specific bundle.
// bundleName: 'com.example.myapplication',
action: 'ohos.want.action.viewData',
// entities can be omitted.
entities: ['entity.system.default'],
}
// context为调用方UIAbility的AbilityContext
this.context.startAbility(wantInfo).then(() => {
// ...
}).catch((err) => {
// ...
})
```
效果示意如下图所示,点击“打开PDF文档”时,会弹出选择框供用户选择。
<img src="figures/uiability-intra-device-interaction.png" alt="uiability-intra-device-interaction" style="zoom:50%;" />
3. 在文档应用使用完成之后,如需要停止当前UIAbility实例,通过调用terminateSelf()方法实现。
```ts
// context为需要停止的UIAbility实例的AbilityContext
this.context.terminateSelf((err) => {
// ...
});
```
## 启动其他应用的UIAbility并获取返回结果
当使用隐式Want启动其他应用的UIAbility并希望获取返回结果时,调用方需要使用startAbilityForResult()方法启动目标UIAbility。例如主应用中需要启动三方支付并获取支付结果。
1. 在支付应用对应UIAbility的module.json5配置文件中,配置skills的[entities](../reference/apis/js-apis-ability-wantConstant.md#wantconstantentity)字段和[actions](../reference/apis/js-apis-ability-wantConstant.md#wantconstantaction)字段。
```json
{
"module": {
"abilities": [
{
// ...
"skills": [
{
"entities": [
// ...
"entity.system.default"
],
"actions": [
// ...
"ohos.want.action.editData"
]
}
]
}
]
}
}
```
2. 调用方使用startAbilityForResult()方法启动支付应用的UIAbility,在调用方want参数中的entities和action需要被包含在待匹配UIAbility的skills配置的entities和actions中。异步回调中的data用于后续接收支付UIAbility停止自身后返回给调用方的信息。系统匹配到符合entities和actions参数条件的UIAbility后,会弹出选择框展示匹配到的UIAbility实例列表供用户选择使用。
```ts
let wantInfo = {
deviceId: '', // deviceId为空表示本设备
// uncomment line below if wish to implicitly query only in the specific bundle.
// bundleName: 'com.example.myapplication',
action: 'ohos.want.action.editData',
// entities can be omitted.
entities: ['entity.system.default'],
}
// context为调用方UIAbility的AbilityContext
this.context.startAbilityForResult(wantInfo).then((data) => {
// ...
}).catch((err) => {
// ...
})
```
3. 在支付UIAbility完成支付之后,需要调用terminateSelfWithResult()方法实现停止自身,并将abilityResult参数信息返回给调用方。
```ts
const RESULT_CODE: number = 1001;
let abilityResult = {
resultCode: RESULT_CODE,
want: {
bundleName: 'com.example.myapplication',
abilityName: 'EntryAbility',
moduleName: 'entry',
parameters: {
payResult: 'OKay',
},
},
}
// context为被调用方UIAbility的AbilityContext
this.context.terminateSelfWithResult(abilityResult, (err) => {
// ...
});
```
4. 在调用方startAbilityForResult()方法回调中接收支付应用返回的信息,RESULT_CODE需要与前面terminateSelfWithResult()返回的数值保持一致。
```ts
const RESULT_CODE: number = 1001;
let want = {
// Want参数信息
};
// context为调用方UIAbility的AbilityContext
this.context.startAbilityForResult(want).then((data) => {
if (data?.resultCode === RESULT_CODE) {
// 解析被调用方UIAbility返回的信息
let payResult = data.want?.parameters?.payResult;
// ...
}
}).catch((err) => {
// ...
})
```
## 启动UIAbility的指定页面
一个UIAbility可以对应多个页面,在不同的场景下启动该UIAbility时需要展示不同的页面,例如从一个UIAbility的页面中跳转到另外一个UIAbility时,希望启动目标UIAbility的指定页面。本文主要讲解目标UIAbility首次启动和目标UIAbility非首次启动两种启动指定页面的场景,以及在讲解启动指定页面之前会讲解到在调用方如何指定启动页面。
### 调用方UIAbility指定启动页面
调用方UIAbility启动另外一个UIAbility时,通常需要跳转到指定的页面。例如FuncAbility包含两个页面(Index对应首页,Second对应功能A页面),此时需要在传入的want参数中配置指定的页面路径信息,可以通过want中的parameters参数增加一个自定义参数传递页面跳转信息。示例中的context的获取方式参见[获取UIAbility的Context属性](uiability-usage.md#获取uiability的上下文信息)
```ts
let wantInfo = {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'module1', // moduleName非必选
parameters: { // 自定义参数传递页面信息
router: 'funcA',
},
}
// context为调用方UIAbility的AbilityContext
this.context.startAbility(wantInfo).then(() => {
// ...
}).catch((err) => {
// ...
})
```
### 目标UIAbility首次启动
目标UIAbility首次启动时,在目标UIAbility的onWindowStageCreate()生命周期回调中,解析EntryAbility传递过来的want参数,获取到需要加载的页面信息url,传入windowStage.loadContent()方法。
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
import Window from '@ohos.window'
export default class FuncAbility extends UIAbility {
funcAbilityWant;
onCreate(want, launchParam) {
// 接收调用方UIAbility传过来的参数
this.funcAbilityWant = want;
}
onWindowStageCreate(windowStage: Window.WindowStage) {
// Main window is created, set main page for this ability
let url = 'pages/Index';
if (this.funcAbilityWant?.parameters?.router) {
if (this.funcAbilityWant.parameters.router === 'funA') {
url = 'pages/Second';
}
}
windowStage.loadContent(url, (err, data) => {
// ...
});
}
}
```
### 目标UIAbility非首次启动
经常还会遇到一类场景,当应用A已经启动且处于主页面时,回到桌面,打开应用B,并从应用B再次启动应用A,且需要跳转到应用A的指定页面。例如联系人应用和短信应用配合使用的场景。打开短信应用主页,回到桌面,此时短信应用处于已打开状态且当前处于短信应用的主页。再打开联系人应用主页,进入联系人用户A查看详情,点击短信图标,准备给用户A发送短信,此时会再次拉起短信应用且当前处于短信应用的发送页面。
![uiability_not_first_started](figures/uiability_not_first_started.png)
针对以上场景,即当应用A的UIAbility实例已创建,并且处于该UIAbility实例对应的主页面中,此时,从应用B中需要再次启动应用A的该UIAbility,并且需要跳转到不同的页面,这种情况下要如何实现呢?
1. 在目标UIAbility中,默认加载的是Index页面。由于当前UIAbility实例之前已经创建完成,此时会进入UIAbility的onNewWant()回调中且不会进入onCreate()和onWindowStageCreate()生命周期回调,在onNewWant()回调中解析调用方传递过来的want参数,并挂在到全局变量globalThis中,以便于后续在页面中获取。
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
export default class FuncAbility extends UIAbility {
onNewWant(want, launchParam) {
// 接收调用方UIAbility传过来的参数
globalThis.funcAbilityWant = want;
// ...
}
}
```
2. 在FuncAbility中,此时需要在Index页面中通过页面路由Router模块实现指定页面的跳转,由于此时FuncAbility对应的Index页面是处于激活状态,不会重新变量声明以及进入aboutToAppear()生命周期回调中。因此可以在Index页面的onPageShow()生命周期回调中实现页面路由跳转的功能。
```ts
import router from '@ohos.router';
@Entry
@Component
struct Index {
onPageShow() {
let funcAbilityWant = globalThis.funcAbilityWant;
let url2 = funcAbilityWant?.parameters?.router;
if (url2 && url2 === 'funcA') {
router.replaceUrl({
url: 'pages/Second',
})
}
}
// 页面展示
build() {
// ...
}
}
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 当被调用方[Ability的启动模式](uiability-launch-type.md)设置为standard启动模式时,每次启动都会创建一个新的实例,那么[onNewWant()](../reference/apis/js-apis-application-ability.md#abilityonnewwant)回调就不会被用到。
## 通过Call调用实现UIAbility交互(仅对系统应用开放)
Call调用是UIAbility能力的扩展,它为UIAbility提供一种能够被外部调用并与外部进行通信的能力。Call调用支持前台与后台两种启动方式,使UIAbility既能被拉起到前台展示UI,也可以在后台被创建并运行。Call调用在调用方与被调用方间建立了IPC通信,因此应用开发者可通过Call调用实现不同Ability之间的数据共享。
Call调用的核心接口是startAbilityByCall方法,与startAbility接口的不同之处在于:
- startAbilityByCall支持前台与后台两种启动方式,而startAbility仅支持前台启动。
- 调用方可使用startAbilityByCall所返回的Caller对象与被调用方进行通信,而startAbilty不具备通信能力。
Call调用的使用场景主要包括:
- 需要与被启动的UIAbility进行通信。
- 希望被启动的UIAbility在后台运行。
**表1** Call调用相关名词解释
| 名词 | 描述 |
| -------- | -------- |
| CallerAbility | 进行Call调用的UIAbility(调用方)。 |
| CalleeAbility | 被Call调用的UIAbility(被调用方)。 |
| Caller | 实际对象,由startAbilityByCall接口返回,CallerAbility可使用Caller与CalleeAbility进行通信。 |
| Callee | 实际对象,被CalleeAbility持有,可与Caller进行通信。 |
Call调用示意图如下所示。
**图1** Call调用示意图
<img src="figures/call.png" alt="call" style="zoom:67%;" />
- CallerAbility调用startAbilityByCall接口获取Caller,并使用Caller对象的call方法向CalleeAbility发送数据。
- CalleeAbility持有一个Callee对象,通过Callee的on方法注册回调函数,当接收到Caller发送的数据时将会调用对应的回调函数。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 1. 当前仅支持系统应用使用Call调用。
>
> 2. CalleeAbility的启动模式需要为单实例。
>
> 3. Call调用既支持本地(设备内)Call调用,也支持跨设备Call调用,下面介绍设备内Call调用方法。跨设备Call调用方法请参见[跨设备Call调用](hop-multi-device-collaboration.md#通过跨设备call调用实现多端协同)。
### 接口说明
Call功能主要接口如下表所示。具体的API详见[接口文档](../reference/apis/js-apis-application-ability.md#caller)
**表2** Call功能主要接口
| 接口名 | 描述 |
| -------- | -------- |
| startAbilityByCall(want:&nbsp;Want):&nbsp;Promise&lt;Caller&gt; | 启动指定UIAbility并获取其Caller通信接口,默认为后台启动,通过配置want可实现前台启动,详见[接口文档](../reference/apis/js-apis-ability-context.md#abilitycontextstartabilitybycall)。AbilityContext与ServiceExtensionContext均支持该接口。 |
| on(method:&nbsp;string,&nbsp;callback:&nbsp;CalleeCallBack):&nbsp;void | 通用组件Callee注册method对应的callback方法。 |
| off(method:&nbsp;string):&nbsp;void | 通用组件Callee解注册method的callback方法。 |
| call(method:&nbsp;string,&nbsp;data:&nbsp;rpc.Sequenceable):&nbsp;Promise&lt;void&gt; | 向通用组件Callee发送约定序列化数据。 |
| callWithResult(method:&nbsp;string,&nbsp;data:&nbsp;rpc.Sequenceable):&nbsp;Promise&lt;rpc.MessageParcel&gt; | 向通用组件Callee发送约定序列化数据,&nbsp;并将Callee返回的约定序列化数据带回。 |
| release():&nbsp;void | 释放通用组件的Caller通信接口。 |
| on(type:&nbsp;"release",&nbsp;callback:&nbsp;OnReleaseCallback):&nbsp;void | 注册通用组件通信断开监听通知。 |
设备内通过Call调用实现UIAbility交互,涉及如下两部分开发:
- [创建Callee被调用端](#开发步骤创建callee被调用端)
- [访问Callee被调用端](#开发步骤访问callee被调用端)
### 开发步骤(创建Callee被调用端)
在Callee被调用端,需要实现指定方法的数据接收回调函数、数据的序列化及反序列化方法。在需要接收数据期间,通过on接口注册监听,无需接收数据时通过off接口解除监听。
1. 配置Ability的启动模式。
配置module.json5,将CalleeAbility配置为单实例"singleton"。
| Json字段 | 字段说明 |
| -------- | -------- |
| "launchType" | Ability的启动模式,设置为"singleton"类型。 |
Ability配置标签示例如下:
```json
"abilities":[{
"name": ".CalleeAbility",
"srcEntrance": "./ets/CalleeAbility/CalleeAbility.ts",
"launchType": "singleton",
"description": "$string:CalleeAbility_desc",
"icon": "$media:icon",
"label": "$string:CalleeAbility_label",
"visible": true
}]
```
2. 导入UIAbility模块。
```ts
import Ability from '@ohos.app.ability.UIAbility';
```
3. 定义约定的序列化数据。
调用端及被调用端发送接收的数据格式需协商一致,如下示例约定数据由number和string组成。
```ts
export default class MySequenceable {
num: number = 0
str: string = ""
constructor(num, string) {
this.num = num
this.str = string
}
marshalling(messageParcel) {
messageParcel.writeInt(this.num)
messageParcel.writeString(this.str)
return true
}
unmarshalling(messageParcel) {
this.num = messageParcel.readInt()
this.str = messageParcel.readString()
return true
}
}
```
4. 实现Callee.on监听及Callee.off解除监听。
被调用端Callee的监听函数注册时机,取决于应用开发者。注册监听之前的数据不会被处理,取消监听之后的数据不会被处理。如下示例在Ability的onCreate注册'MSG_SEND_METHOD'监听,在onDestroy取消监听,收到序列化数据后作相应处理并返回,应用开发者根据实际需要做相应处理。具体示例代码如下:
```ts
const TAG: string = '[CalleeAbility]';
const MSG_SEND_METHOD: string = 'CallSendMsg';
function sendMsgCallback(data) {
console.info('CalleeSortFunc called');
// 获取Caller发送的序列化数据
let receivedData = new MySequenceable(0, '');
data.readSequenceable(receivedData);
console.info(`receiveData[${receivedData.num}, ${receivedData.str}]`);
// 作相应处理
// 返回序列化数据result给Caller
return new MySequenceable(receivedData.num + 1, `send ${receivedData.str} succeed`);
}
export default class CalleeAbility extends Ability {
onCreate(want, launchParam) {
try {
this.callee.on(MSG_SEND_METHOD, sendMsgCallback);
} catch (error) {
console.info(`${MSG_SEND_METHOD} register failed with error ${JSON.stringify(error)}`);
}
}
onDestroy() {
try {
this.callee.off(MSG_SEND_METHOD);
} catch (error) {
console.error(TAG, `${MSG_SEND_METHOD} unregister failed with error ${JSON.stringify(error)}`);
}
}
}
```
### 开发步骤(访问Callee被调用端)
1. 导入UIAbility模块。
```ts
import Ability from '@ohos.app.ability.UIAbility';
```
2. 获取Caller通信接口。
Ability的context属性实现了startAbilityByCall方法,用于获取指定通用组件的Caller通信接口。如下示例通过this.context获取Ability实例的context属性,使用startAbilityByCall拉起Callee被调用端并获取Caller通信接口,注册Caller的onRelease监听。应用开发者根据实际需要做相应处理。
```ts
// 注册caller的release监听
private regOnRelease(caller) {
try {
caller.on("release", (msg) => {
console.info(`caller onRelease is called ${msg}`);
})
console.info('caller register OnRelease succeed');
} catch (error) {
console.info(`caller register OnRelease failed with ${error}`);
}
}
async onButtonGetCaller() {
try {
this.caller = await context.startAbilityByCall({
bundleName: 'com.samples.CallApplication',
abilityName: 'CalleeAbility'
})
if (this.caller === undefined) {
console.info('get caller failed')
return
}
console.info('get caller success')
this.regOnRelease(this.caller)
} catch (error) {
console.info(`get caller failed with ${error}`)
}
}
```
# UIAbility组件启动模式
UIAbility的启动模式是指UIAbility实例在启动时的不同呈现状态。针对不同的业务场景,系统提供了三种启动模式:
- [singleton(单实例模式)](#singleton启动模式)
- [standard(标准实例模式)](#standard启动模式)
- [specified(指定实例模式)](#specified启动模式)
## singleton启动模式
singleton启动模式为单实例模式,也是默认情况下的启动模式。
每次调用startAbility()方法时,如果应用进程中该类型的UIAbility实例已经存在,则复用系统中的UIAbility实例。系统中只存在唯一一个该UIAbility实例,即在最近任务列表中只存在一个该类型的UIAbility实例。
**图1** 单实例模式演示效果
<img src="figures/uiability-launch-type1.png" alt="uiability-launch-type1" style="zoom:50%;" />
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 应用的UIAbility实例已创建,该UIAbility配置为单实例模式,再次调用startAbility()方法启动该UIAbility实例,此时只会进入该UIAbility的[onNewWant()](../reference/apis/js-apis-application-ability.md#abilityonnewwant)回调,不会进入其onCreate()和onWindowStageCreate()生命周期回调。
如果需要使用singleton启动模式,在[module.json5配置文件](../quick-start/module-configuration-file.md)中的"launchType"字段配置为"singleton"即可。
```json
{
"module": {
// ...
"abilities": [
{
"launchType": "singleton",
// ...
}
]
}
}
```
## standard启动模式
standard启动模式为标准实例模式,每次调用startAbility()方法时,都会在应用进程中创建一个新的该类型UIAbility实例。即在最近任务列表中可以看到有多个该类型的UIAbility实例。这种情况下可以将UIAbility配置为standard(标准实例模式)。
**图2** 标准实例模式演示效果
<img src="figures/standard-mode.png" alt="standard-mode" style="zoom:50%;" />
standard启动模式的开发使用,在[module.json5配置文件](../quick-start/module-configuration-file.md)中的"launchType"字段配置为"standard"即可。
```json
{
"module": {
// ...
"abilities": [
{
"launchType": "standard",
// ...
}
]
}
}
```
## specified启动模式
specified启动模式为指定实例模式,针对一些特殊场景使用(例如文档应用中每次新建文档希望都能新建一个文档实例,重复打开一个已保存的文档希望打开的都是同一个文档实例)。
在UIAbility实例创建之前,允许开发者为该实例创建一个唯一的字符串Key,创建的UIAbility实例绑定Key之后,后续每次调用startAbility()方法时,都会询问应用使用哪个Key对应的UIAbility实例来响应startAbility()请求。运行时由UIAbility内部业务决定是否创建多实例,如果匹配有该UIAbility实例的Key,则直接拉起与之绑定的UIAbility实例,否则创建一个新的UIAbility实例。
**图3** 指定实例模式演示效果
<img src="figures/uiability-launch-type2.png" alt="uiability-launch-type2" style="zoom:50%;" />
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 应用的UIAbility实例已创建,该UIAbility配置为指定实例模式,再次调用startAbility()方法启动该UIAbility实例,且[AbilityStage](abilitystage.md)的[onAcceptWant()](../reference/apis/js-apis-application-abilitystage.md#abilitystageonacceptwant)回调匹配到一个已创建的UIAbility实例。此时,再次启动该UIAbility时,只会进入该UIAbility的[onNewWant()](../reference/apis/js-apis-application-ability.md#abilityonnewwant)回调,不会进入其onCreate()和onWindowStageCreate()生命周期回调。
例如有两个UIAbility:EntryAbility和FuncAbility,FuncAbility配置为specified启动模式,需要从EntryAbility的页面中启动FuncAbility。
1. 在FuncAbility中,将[module.json5配置文件](../quick-start/module-configuration-file.md)的"launchType"字段配置为"specified"。
```json
{
"module": {
// ...
"abilities": [
{
"launchType": "specified",
// ...
}
]
}
}
```
2. 在EntryAbility中,调用startAbility()方法时,在want参数中,增加一个自定义参数来区别UIAbility实例,例如增加一个"instanceKey"自定义参数。
```ts
// 在启动指定实例模式的UIAbility时,给每一个UIAbility实例配置一个独立的Key标识
// 例如在文档使用场景中,可以用文档路径作为Key标识
function getInstance() {
// ...
}
let want = {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'module1', // moduleName非必选
parameters: { // 自定义信息
instanceKey: getInstance(),
},
}
// context为调用方UIAbility的AbilityContext
this.context.startAbility(want).then(() => {
// ...
}).catch((err) => {
// ...
})
```
3. 由于FuncAbility的启动模式配置为了指定实例启动模式,在FuncAbility启动之前,会先进入其对应的AbilityStage的[onAcceptWant()](../reference/apis/js-apis-application-abilitystage.md#abilitystageonacceptwant)生命周期回调中,解析传入的want参数,获取"instanceKey"自定义参数。根据业务需要通过AbilityStage的[onAcceptWant()](../reference/apis/js-apis-application-abilitystage.md#abilitystageonacceptwant)生命周期回调返回一个字符串Key标识。[如果返回的Key对应一个已启动的UIAbility](mission-management-launch-type.md#fig14520125175314),则会将之前的UIAbility拉回前台并获焦,而不创建新的实例,否则创建新的实例并启动。
```ts
import AbilityStage from '@ohos.app.ability.AbilityStage';
export default class MyAbilityStage extends AbilityStage {
onAcceptWant(want): string {
// 在被调用方的AbilityStage中,针对启动模式为specified的UIAbility返回一个UIAbility实例对应的一个Key值
// 当前示例指的是module1 Module的FuncAbility
if (want.abilityName === 'FuncAbility') {
// 返回的字符串Key标识为自定义拼接的字符串内容
return `ControlModule_EntryAbilityInstance_${want.parameters.instanceKey}`;
}
return '';
}
}
```
例如在文档应用中,可以对不同的文档实例内容绑定不同的Key值。当每次新建文档的时候,可以传入不同的新Key值(如可以将文件的路径作为一个Key标识),此时AbilityStage中启动UIAbility时都会创建一个新的UIAbility实例;当新建的文档保存之后,回到桌面,或者新打开一个已保存的文档,回到桌面,此时再次打开该已保存的文档,此时AbilityStage中再次启动该UIAbility时,打开的仍然是之前原来已保存的文档界面。
以如下步骤所示进行举例说明。
1. 打开文件A,对应启动一个新的UIAbility实例,例如启动“UIAbility实例1”。
2. 在最近任务列表中关闭文件A的进程,此时UIAbility实例1被销毁,回到桌面,再次打开文件A,此时对应启动一个新的UIAbility实例,例如启动“UIAbility实例2”。
3. 回到桌面,打开文件B,此时对应启动一个新的UIAbility实例,例如启动“UIAbility实例3”。
4. 回到桌面,再次打开文件A,此时对应启动的还是之前的“UIAbility实例2”。
# UIAbility组件生命周期
## 概述
当用户打开、切换和返回到对应应用时,应用中的UIAbility实例会在其生命周期的不同状态之间转换。UIAbility类提供了一系列回调,通过这些回调可以知道当前UIAbility实例的某个状态发生改变,会经过UIAbility实例的创建和销毁,或者UIAbility实例发生了前后台的状态切换。
UIAbility的生命周期包括Create、Foreground、Background、Destroy四个状态,如下图所示。
**图1** UIAbility生命周期状态
<img src="figures/Ability-Life-Cycle.png" alt="Ability-Life-Cycle" style="zoom:50%;" />
## 生命周期状态说明
### Create状态
Create状态为在应用加载过程中,UIAbility实例创建完成时触发,系统会调用onCreate()回调。可以在该回调中进行应用初始化操作,例如变量定义资源加载等,用于后续的UI界面展示。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
import Window from '@ohos.window';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
// 应用初始化
}
// ...
}
```
### WindowStageCreate和WindowStageDestory状态
UIAbility实例创建完成之后,在进入Foreground之前,系统会创建一个WindowStage。WindowStage创建完成后会进入onWindowStageCreate()回调,可以在该回调中设置UI界面加载、设置WindowStage的事件订阅。
**图2** WindowStageCreate和WindowStageDestory状态
<img src="figures/Ability-Life-Cycle-WindowStage.png" alt="Ability-Life-Cycle-WindowStage" style="zoom:50%;" />
在onWindowStageCreate()回调中通过loadContent()方法设置应用要加载的页面并根据需要订阅WindowStage的[事件](../reference/apis/js-apis-window.md#windowstageeventtype9)(获焦/失焦、可见/不可见)。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
import Window from '@ohos.window';
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: Window.WindowStage) {
// 设置WindowStage的事件订阅(获焦/失焦、可见/不可见)
// 设置UI界面加载
windowStage.loadContent('pages/Index', (err, data) => {
// ...
});
}
}
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> WindowStage的相关使用请参见[窗口开发指导](../windowmanager/application-window-stage.md)。
对应于onWindowStageCreate()回调。在UIAbility实例销毁之前,则会先进入onWindowStageDestroy()回调,可以在该回调中释放UI界面资源。例如在onWindowStageDestroy()中注销获焦/失焦等WindowStage事件。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
import Window from '@ohos.window';
export default class EntryAbility extends UIAbility {
// ...
onWindowStageDestroy() {
// 释放UI界面资源
}
}
```
### Foreground和Background状态
Foreground和Background状态分别在UIAbility实例切换至前台和切换至后台时触发,对应于onForeground()回调和onBackground()回调。
onForeground()回调,在UIAbility的UI界面可见之前,如UIAbility切换至前台时触发。可以在onForeground()回调中申请系统需要的资源,或者重新申请在onBackground()中释放的资源。
onBackground()回调,在UIAbility的UI界面完全不可见之后,如UIAbility切换至后台时候触发。可以在onBackground()回调中释放UI界面不可见时无用的资源,或者在此回调中执行较为耗时的操作,例如状态保存等。
例如应用在使用过程中需要使用用户定位时,假设应用已获得用户的定位权限授权。在UI界面显示之前,可以在onForeground()回调中开启定位功能,从而获取到当前的位置信息。
当应用切换到后台状态,可以在onBackground()回调中停止定位功能,以节省系统的资源消耗。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onForeground() {
// 申请系统需要的资源,或者重新申请在onBackground中释放的资源
}
onBackground() {
// 释放UI界面不可见时无用的资源,或者在此回调中执行较为耗时的操作
// 例如状态保存等
}
}
```
### Destroy状态
Destroy状态在UIAbility实例销毁时触发。可以在onDestroy()回调中进行系统资源的释放、数据的保存等操作。
例如调用terminateSelf()方法停止当前UIAbility实例,从而完成UIAbility实例的销毁;或者用户使用最近任务列表关闭该UIAbility实例,完成UIAbility的销毁。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
import Window from '@ohos.window';
export default class EntryAbility extends UIAbility {
onDestroy() {
// 系统资源的释放、数据的保存等
}
}
```
# UIAbility组件概述
## 概述
UIAbility组件是一种包含UI界面的应用组件,主要用于和用户交互。
UIAbility组件是系统调度的基本单元,为应用提供绘制界面的窗口;一个UIAbility组件中可以通过多个页面来实现一个功能模块。每一个UIAbility组件实例,都对应于一个最近任务列表中的任务。
## 声明配置
为使应用能够正常使用UIAbility,需要在[module.json5配置文件](../quick-start/module-configuration-file.md)[abilities标签](../quick-start/module-configuration-file.md#abilities标签)中声明UIAbility的名称、入口、标签等相关信息。
```json
{
"module": {
// ...
"abilities": [
{
"name": "EntryAbility", // UIAbility组件的名称
"srcEntrance": "./ets/entryability/EntryAbility.ts", // UIAbility组件的代码路径
"description": "$string:EntryAbility_desc", // UIAbility组件的描述信息
"icon": "$media:icon", // UIAbility组件的图标
"label": "$string:EntryAbility_label", // UIAbility组件的标签
"startWindowIcon": "$media:icon", // UIAbility组件启动页面图标资源文件的索引
"startWindowBackground": "$color:start_window_background", // UIAbility组件启动页面背景颜色资源文件的索引
// ...
}
]
}
}
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> Ability的组成请参见在[模块中添加Ability](https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/ohos-adding-ability-0000001218280664-V3)。
# UIAbility组件基本用法
UIAbility组件的基本用法包括:指定UIAbility的启动页面以及获取UIAbility的上下文[UIAbilityContext](../reference/apis/js-apis-ability-context.md)
## 指定UIAbility的启动页面
应用中的UIAbility在启动过程中,需要指定启动页面,否则应用启动后会因为没有默认加载页面而导致白屏。可以在UIAbility的onWindowStageCreate()生命周期回调中,通过[WindowStage](../reference/apis/js-apis-window.md#windowstage9)对象的loadContent()方法设置启动页面。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
import Window from '@ohos.window';
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: Window.WindowStage) {
// Main window is created, set main page for this ability
windowStage.loadContent('pages/Index', (err, data) => {
// ...
});
}
// ...
}
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 在DevEco Studio中创建的UIAbility中,该UIAbility实例默认会加载Index页面,根据需要将Index页面路径替换为需要的页面路径即可。
## 获取UIAbility的上下文信息
UIAbility类拥有自身的上下文信息,该信息为[UIAbilityContext](../reference/apis/js-apis-ability-context.md)类的实例,[UIAbilityContext](../reference/apis/js-apis-ability-context.md)类拥有abilityInfo、currentHapModuleInfo等属性。通过UIAbilityContext可以获取UIAbility的相关配置信息,如包代码路径、Bundle名称、Ability名称和应用程序需要的环境状态等属性信息,以及可以获取操作UIAbility实例的方法(如startAbility()、connectServiceExtensionAbility()、terminateSelf()等)。
- 在UIAbility中可以通过this.context获取UIAbility实例的上下文信息。
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
// 获取UIAbility实例的上下文
let context = this.context;
// ...
}
}
```
- 在页面中获取UIAbility实例的上下文信息,包括导入依赖资源context模块和在组件中定义一个context变量两个部分。
```ts
import common from '@ohos.app.ability.common';
@Entry
@Component
struct Index {
private context = getContext(this) as common.UIAbilityContext;
startAbilityTest() {
let want = {
// Want参数信息
};
this.context.startAbility(want);
}
// 页面展示
build() {
// ...
}
}
```
也可以在导入依赖资源context模块后,在具体使用[UIAbilityContext](../reference/apis/js-apis-ability-context.md)前进行变量定义。
```ts
import common from '@ohos.app.ability.common';
@Entry
@Component
struct Index {
startAbilityTest() {
let context = getContext(this) as common.UIAbilityContext;
let want = {
// Want参数信息
};
context.startAbility(want);
}
// 页面展示
build() {
// ...
}
}
```
# 信息传递载体Want
请参见Stage模型的"[信息传递载体Want](want-overview.md)"。
# Want概述
## Want的定义与用途
[Want](../reference/apis/js-apis-application-Want.md)是对象间信息传递的载体,可以用于应用组件间的信息传递。其使用场景之一是作为startAbility()的参数,包含了指定的启动目标以及启动时需携带的相关数据,如bundleName和abilityName字段分别指明目标Ability所在应用的包名以及对应包内的Ability名称。当UIAbilityA启动UIAbilityB并需要传入一些数据给UIAbilityB时,Want可以作为一个载体将数据传给UIAbilityB。
**图1** Want用法示意
<img src="figures/usage-of-want.png" alt="usage-of-want" style="zoom:80%;" />
## Want的类型
- **显式Want**:在启动Ability时指定了abilityName和bundleName的Want称为显式Want。
当有明确处理请求的对象时,通过提供目标Ability所在应用的包名信息(bundleName),并在Want内指定abilityName便可启动目标Ability。显式Want通常用于在当前应用开发中启动某个已知的Ability。参数说明参见[Want参数说明](#Want参数说明)
```ts
let wantInfo = {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
}
```
- **隐式Want**:在启动UIAbility时未指定abilityName的Want称为隐式Want。
当请求处理的对象不明确时,希望在当前应用中使用其他应用提供的某个能力(通过[skills标签](../quick-start/module-configuration-file.md#skills标签)定义),而不关心提供该能力的具体应用,可以使用隐式Want。例如使用隐式Want描述需要打开一个链接的请求,而不关心通过具体哪个应用打开,系统将匹配声明支持该请求的所有应用。
```ts
let wantInfo = {
// uncomment line below if wish to implicitly query only in the specific bundle.
// bundleName: 'com.example.myapplication',
action: 'ohos.want.action.search',
// entities can be omitted
entities: [ 'entity.system.browsable' ],
uri: 'https://www.test.com:8080/query/student',
type: 'text/plain',
};
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> - 根据系统中待匹配Ability的匹配情况不同,使用隐式Want启动Ability时会出现以下三种情况。
> - 未匹配到满足条件的Ability:启动失败。
> - 匹配到一个满足条件的Ability:直接启动该Ability。
> - 匹配到多个满足条件的Ability(UIAbility):弹出选择框让用户选择。
>
> - 调用方传入的want参数中不带有abilityName和bundleName,则不允许通过隐式Want启动所有应用的ServiceExtensionAbility。
>
> - 调用方传入的want参数中带有bundleName,则允许使用startServiceExtensionAbility()方法隐式Want启动ServiceExtensionAbility,默认返回优先级最高的ServiceExtensionAbility,如果优先级相同,返回第一个。
## Want参数说明
| 名称 | 读写属性 | 类型 | 必填 | 描述 |
| -------- | -------- | -------- | -------- | -------- |
| deviceId | 只读 | string | 否 | 表示目标Ability所在设备ID。如果未设置该字段,则表明本设备。 |
| bundleName | 只读 | string | 否 | 表示目标Ability所在应用名称。 |
| moduleName | 只读 | string | 否 | 表示目标Ability所属的模块名称。 |
| abilityName | 只读 | string | 否 | 表示目标Ability名称。如果未设置该字段,则该Want为隐式。如果在Want中同时指定了bundleName,moduleName和abilityName,则Want可以直接匹配到指定的Ability。 |
| uri | 只读 | string | 否 | 表示携带的数据,一般配合type使用,指明待处理的数据类型。如果在Want中指定了uri,则Want将匹配指定的Uri信息,包括scheme,&nbsp;schemeSpecificPart,&nbsp;authority和path信息。 |
| type | 只读 | string | 否 | 表示携带数据类型,使用[MIME类型](https://www.iana.org/assignments/media-types/media-types.xhtml?utm_source=ld246.com%E3%80%82)规范。例如:"text/plain"、"image/\*"等。 |
| [action](../reference/apis/js-apis-ability-wantConstant.md) | 只读 | string | 否 | 表示要执行的通用操作(如:查看、分享、应用详情)。在隐式Want中,您可定义该字段,配合uri或parameters来表示对数据要执行的操作。如打开,查看该uri数据。例如,当uri为一段网址,action为ohos.want.action.viewData则表示匹配可查看该网址的Ability。 |
| [entities](../reference/apis/js-apis-ability-wantConstant.md) | 只读 | Array&lt;string&gt; | 否 | 表示目标Ability额外的类别信息(如:浏览器,视频播放器),在隐式Want中是对action的补充。在隐式Want中,您可定义该字段,来过滤匹配UIAbility类别,如必须是浏览器。例如,在action字段的举例中,可存在多个应用声明了支持查看网址的操作,其中有应用为普通社交应用,有的为浏览器应用,您可通过entity.system.browsable过滤掉非浏览器的其他应用。 |
| [flags](../reference/apis/js-apis-ability-wantConstant.md#wantconstantflags) | 只读 | number | 否 | 表示处理Want的方式。例如通过wantConstant.Flags.FLAG_ABILITY_CONTINUATION表示是否以设备间迁移方式启动Ability。 |
| parameters | 只读 | {[key:&nbsp;string]:&nbsp;any} | 否 | 此参数用于传递自定义数据,通过用户自定义的键值对进行数据填充,具体支持的数据类型如[Want&nbsp;API](../reference/apis/js-apis-application-Want.md)所示。 |
# 服务卡片开发指导
## 卡片概述
服务卡片(以下简称“卡片”)是一种界面展示形式,可以将应用的重要信息或操作前置到卡片,以达到服务直达、减少体验层级的目的。
卡片常用于嵌入到其他应用(当前只支持系统应用)中作为其界面的一部分显示,并支持拉起页面、发送消息等基础的交互功能。
卡片的基本概念:
- 卡片使用方:显示卡片内容的宿主应用,控制卡片在宿主中展示的位置。
- 卡片管理服务:用于管理系统中所添加卡片的常驻代理服务,包括卡片对象的管理与使用,以及卡片周期性刷新等。
- 卡片提供方:提供卡片显示内容原子化服务,控制卡片的显示内容、控件布局以及控件点击事件。
## 运作机制
卡片框架的运作机制如图1所示。
**图1** 卡片框架运作机制(FA模型)
![form-extension](figures/form-extension.png)
卡片使用方包含以下模块:
- 卡片使用:包含卡片的创建、删除、请求更新等操作。
- 通信适配层:由OpenHarmony SDK提供,负责与卡片管理服务通信,用于将卡片的相关操作到卡片管理服务。
卡片管理服务包含以下模块:
- 周期性刷新:在卡片添加后,根据卡片的刷新策略启动定时任务周期性触发卡片的刷新。
- 卡片缓存管理:在卡片添加到卡片管理服务后,对卡片的视图信息进行缓存,以便下次获取卡片时可以直接返回缓存数据,降低时延。
- 卡片生命周期管理:对于卡片切换到后台或者被遮挡时,暂停卡片的刷新;以及卡片的升级/卸载场景下对卡片数据的更新和清理。
- 卡片使用方对象管理:对卡片使用方的RPC对象进行管理,用于使用方请求进行校验以及对卡片更新后的回调处理。
- 通信适配层:负责与卡片使用方和提供方进行RPC通信。
卡片提供方包含以下模块:
- 卡片服务:由卡片提供方开发者实现,开发者实现生命周期处理创建卡片、更新卡片以及删除卡片等请求,提供相应的卡片服务。
- 卡片提供方实例管理模块:由卡片提供方开发者实现,负责对卡片管理服务分配的卡片实例进行持久化管理。
- 通信适配层:由OpenHarmony SDK提供,负责与卡片管理服务通信,用于将卡片的更新数据主动推送到卡片管理服务。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 实际开发时只需要作为卡片提供方进行卡片内容的开发,卡片使用方和卡片管理服务由系统自动处理。
## 接口说明
FormAbility生命周期接口如下:
| 接口名 | 描述 |
| -------- | -------- |
| onCreate(want:&nbsp;Want):&nbsp;formBindingData.FormBindingData | 卡片提供方接收创建卡片的通知接口。 |
| onCastToNormal(formId:&nbsp;string):&nbsp;void | 卡片提供方接收临时卡片转常态卡片的通知接口 |
| onUpdate(formId:&nbsp;string):&nbsp;void | 卡片提供方接收更新卡片的通知接口。 |
| onVisibilityChange(newStatus:&nbsp;{&nbsp;[key:&nbsp;string]:&nbsp;number&nbsp;}):&nbsp;void | 卡片提供方接收修改可见性的通知接口。 |
| onEvent(formId:&nbsp;string,&nbsp;message:&nbsp;string):&nbsp;void | 卡片提供方接收处理卡片事件的通知接口。 |
| onDestroy(formId:&nbsp;string):&nbsp;void | 卡片提供方接收销毁卡片的通知接口。 |
| onAcquireFormState?(want:&nbsp;Want):&nbsp;formInfo.FormState | 卡片提供方接收查询卡片状态的通知接口。 |
| onShare?(formId:&nbsp;string):&nbsp;{[key:&nbsp;string]:&nbsp;any} | 卡片提供方接收卡片分享的通知接口。 |
FormProvider类有如下API接口,具体的API介绍详见[接口文档](../reference/apis/js-apis-app-form-formprovider.md)
| 接口名 | 描述 |
| -------- | -------- |
| setFormNextRefreshTime(formId:&nbsp;string,&nbsp;minute:&nbsp;number,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void; | 设置指定卡片的下一次更新时间。 |
| setFormNextRefreshTime(formId:&nbsp;string,&nbsp;minute:&nbsp;number):&nbsp;Promise&lt;void&gt;; | 设置指定卡片的下一次更新时间,以promise方式返回。 |
| updateForm(formId:&nbsp;string,&nbsp;formBindingData:&nbsp;FormBindingData,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void; | 更新指定的卡片。 |
| updateForm(formId:&nbsp;string,&nbsp;formBindingData:&nbsp;FormBindingData):&nbsp;Promise&lt;void&gt;; | 更新指定的卡片,以promise方式返回。 |
formBindingData类有如下API接口,具体的API介绍详见[接口文档](../reference/apis/js-apis-app-form-formbindingdata.md)
| 接口名 | 描述 |
| -------- | -------- |
| createFormBindingData(obj?:&nbsp;Object&nbsp;\|&nbsp;string):&nbsp;FormBindingData | 创建一个FormBindingData对象。 |
## 开发步骤
FA卡片开发,即基于[FA模型](../ability/fa-brief.md)的卡片提供方开发,主要涉及如下关键步骤:
- [实现卡片生命周期接口](#实现卡片生命周期接口):开发FormAbility生命周期回调函数。
- [配置卡片配置文件](#配置卡片配置文件):配置应用配置文件config.json。
- [卡片信息的持久化](#卡片信息的持久化):对卡片信息进行持久化管理。
- [卡片数据交互](#卡片数据交互):通过updateForm()更新卡片显示的信息。
- [开发卡片页面](#开发卡片页面):使用HML+CSS+JSON开发JS卡片页面。
- [开发卡片事件](#开发卡片事件):为卡片添加router事件和message事件。
### 实现卡片生命周期接口
创建FA模型的卡片,需实现卡片的生命周期接口。先参考[IDE开发服务卡片指南](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-development-service-widget-0000001263280425)生成服务卡片模板。
1. 在form.ts中,导入相关模块
```ts
import formBindingData from '@ohos.app.form.formBindingData';
import formInfo from '@ohos.app.form.formInfo';
import formProvider from '@ohos.app.form.formProvider';
import dataStorage from '@ohos.data.storage';
```
2. 在form.ts中,实现卡片生命周期接口
```ts
export default {
onCreate(want) {
console.info('FormAbility onCreate');
// 使用方创建卡片时触发,提供方需要返回卡片数据绑定类
let obj = {
"title": "titleOnCreate",
"detail": "detailOnCreate"
};
let formData = formBindingData.createFormBindingData(obj);
return formData;
},
onCastToNormal(formId) {
// 使用方将临时卡片转换为常态卡片触发,提供方需要做相应的处理
console.info('FormAbility onCastToNormal');
},
onUpdate(formId) {
// 若卡片支持定时更新/定点更新/卡片使用方主动请求更新功能,则提供方需要重写该方法以支持数据更新
console.info('FormAbility onUpdate');
let obj = {
"title": "titleOnUpdate",
"detail": "detailOnUpdate"
};
let formData = formBindingData.createFormBindingData(obj);
formProvider.updateForm(formId, formData).catch((error) => {
console.info('FormAbility updateForm, error:' + JSON.stringify(error));
});
},
onVisibilityChange(newStatus) {
// 使用方发起可见或者不可见通知触发,提供方需要做相应的处理,仅系统应用生效
console.info('FormAbility onVisibilityChange');
},
onEvent(formId, message) {
// 若卡片支持触发事件,则需要重写该方法并实现对事件的触发
console.info('FormAbility onEvent');
},
onDestroy(formId) {
// 删除卡片实例数据
console.info('FormAbility onDestroy');
},
onAcquireFormState(want) {
console.info('FormAbility onAcquireFormState');
return formInfo.FormState.READY;
},
}
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> FormAbility不能常驻后台,即在卡片生命周期回调函数中无法处理长时间的任务。
### 配置卡片配置文件
卡片需要在应用配置文件config.json中进行配置。
- js模块,用于对应卡片的js相关资源,内部字段结构说明:
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 表示JS&nbsp;Component的名字。该标签不可缺省,默认值为default。 | 字符串 | 否 |
| pages | 表示JS&nbsp;Component的页面用于列举JS&nbsp;Component中每个页面的路由信息[页面路径+页面名称]。该标签不可缺省,取值为数组,数组第一个元素代表JS&nbsp;FA首页。 | 数组 | 否 |
| window | 用于定义与显示窗口相关的配置。 | 对象 | 可缺省 |
| type | 表示JS应用的类型。取值范围如下:<br/>normal:标识该JS&nbsp;Component为应用实例。<br/>form:标识该JS&nbsp;Component为卡片实例。 | 字符串 | 可缺省,缺省值为“normal” |
| mode | 定义JS组件的开发模式。 | 对象 | 可缺省,缺省值为空 |
配置示例如下:
```json
"js": [{
"name": "widget",
"pages": ["pages/index/index"],
"window": {
"designWidth": 720,
"autoDesignWidth": true
},
"type": "form"
}]
```
- abilities模块,用于对应卡片的FormAbility,内部字段结构说明:
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 表示卡片的类名。字符串最大长度为127字节。 | 字符串 | 否 |
| description | 表示卡片的描述。取值可以是描述性内容,也可以是对描述性内容的资源索引,以支持多语言。字符串最大长度为255字节。 | 字符串 | 可缺省,缺省为空。 |
| isDefault | 表示该卡片是否为默认卡片,每个Ability有且只有一个默认卡片。<br/>true:默认卡片。<br/>false:非默认卡片。 | 布尔值 | 否 |
| type | 表示卡片的类型。取值范围如下:<br/>JS:JS卡片。 | 字符串 | 否 |
| colorMode | 表示卡片的主题样式,取值范围如下:<br/>auto:自适应。<br/>dark:深色主题。<br/>light:浅色主题。 | 字符串 | 可缺省,缺省值为“auto”。 |
| supportDimensions | 表示卡片支持的外观规格,取值范围:<br/>1&nbsp;\*&nbsp;2:表示1行2列的二宫格。<br/>2&nbsp;\*&nbsp;2:表示2行2列的四宫格。<br/>2&nbsp;\*&nbsp;4:表示2行4列的八宫格。<br/>4&nbsp;\*&nbsp;4:表示4行4列的十六宫格。 | 字符串数组 | 否 |
| defaultDimension | 表示卡片的默认外观规格,取值必须在该卡片supportDimensions配置的列表中。 | 字符串 | 否 |
| updateEnabled | 表示卡片是否支持周期性刷新,取值范围:<br/>true:表示支持周期性刷新,可以在定时刷新(updateDuration)和定点刷新(scheduledUpdateTime)两种方式任选其一,优先选择定时刷新。<br/>false:表示不支持周期性刷新。 | 布尔类型 | 否 |
| scheduledUpdateTime | 表示卡片的定点刷新的时刻,采用24小时制,精确到分钟。<br/>updateDuration参数优先级高于scheduledUpdateTime,两者同时配置时,以updateDuration配置的刷新时间为准。 | 字符串 | 可缺省,缺省值为“0:0”。 |
| updateDuration | 表示卡片定时刷新的更新周期,单位为30分钟,取值为自然数。<br/>当取值为0时,表示该参数不生效。<br/>当取值为正整数N时,表示刷新周期为30\*N分钟。<br/>updateDuration参数优先级高于scheduledUpdateTime,两者同时配置时,以updateDuration配置的刷新时间为准。 | 数值 | 可缺省,缺省值为“0”。 |
| formConfigAbility | 表示卡片的配置跳转链接,采用URI格式。 | 字符串 | 可缺省,缺省值为空。 |
| formVisibleNotify | 标识是否允许卡片使用卡片可见性通知。 | 字符串 | 可缺省,缺省值为空。 |
| jsComponentName | 表示JS卡片的Component名称。字符串最大长度为127字节。 | 字符串 | 否 |
| metaData | 表示卡片的自定义信息,包含customizeData数组标签。 | 对象 | 可缺省,缺省值为空。 |
| customizeData | 表示自定义的卡片信息。 | 对象数组 | 可缺省,缺省值为空。 |
配置示例如下:
```json
"abilities": [{
"name": "FormAbility",
"description": "This is a FormAbility",
"formsEnabled": true,
"icon": "$media:icon",
"label": "$string:form_FormAbility_label",
"srcPath": "FormAbility",
"type": "service",
"srcLanguage": "ets",
"formsEnabled": true,
"formConfigAbility": "ability://com.example.entry.MainAbility",
"forms": [{
"colorMode": "auto",
"defaultDimension": "2*2",
"description": "This is a service widget.",
"formVisibleNotify": true,
"isDefault": true,
"jsComponentName": "widget",
"name": "widget",
"scheduledUpdateTime": "10:30",
"supportDimensions": ["2*2"],
"type": "JS",
"updateEnabled": true
}]
}]
```
### 卡片信息的持久化
因大部分卡片提供方都不是常驻服务,只有在需要使用时才会被拉起获取卡片信息,且卡片管理服务支持对卡片进行多实例管理,卡片ID对应实例ID,因此若卡片提供方支持对卡片数据进行配置,则需要对卡片的业务数据按照卡片ID进行持久化管理,以便在后续获取、更新以及拉起时能获取到正确的卡片业务数据。
```ts
const DATA_STORAGE_PATH = "/data/storage/el2/base/haps/form_store";
async function storeFormInfo(formId: string, formName: string, tempFlag: boolean) {
// 此处仅对卡片ID:formId,卡片名:formName和是否为临时卡片:tempFlag进行了持久化
let formInfo = {
"formName": formName,
"tempFlag": tempFlag,
"updateCount": 0
};
try {
const storage = await dataStorage.getStorage(DATA_STORAGE_PATH);
// put form info
await storage.put(formId, JSON.stringify(formInfo));
console.info(`storeFormInfo, put form info successfully, formId: ${formId}`);
await storage.flush();
} catch (err) {
console.error(`failed to storeFormInfo, err: ${JSON.stringify(err)}`);
}
}
// ...
onCreate(want) {
console.info('FormAbility onCreate');
let formId = want.parameters["ohos.extra.param.key.form_identity"];
let formName = want.parameters["ohos.extra.param.key.form_name"];
let tempFlag = want.parameters["ohos.extra.param.key.form_temporary"];
// 将创建的卡片信息持久化,以便在下次获取/更新该卡片实例时进行使用
// 此接口请根据实际情况实现,具体请参考:FormExtAbility Stage模型卡片实例
storeFormInfo(formId, formName, tempFlag);
let obj = {
"title": "titleOnCreate",
"detail": "detailOnCreate"
};
let formData = formBindingData.createFormBindingData(obj);
return formData;
}
// ...
```
且需要适配onDestroy卡片删除通知接口,在其中实现卡片实例数据的删除。
```ts
const DATA_STORAGE_PATH = "/data/storage/el2/base/haps/form_store";
async function deleteFormInfo(formId: string) {
try {
const storage = await dataStorage.getStorage(DATA_STORAGE_PATH);
// del form info
await storage.delete(formId);
console.info(`deleteFormInfo, del form info successfully, formId: ${formId}`);
await storage.flush();
} catch (err) {
console.error(`failed to deleteFormInfo, err: ${JSON.stringify(err)}`);
}
}
// ...
onDestroy(formId) {
console.info('FormAbility onDestroy');
// 删除之前持久化的卡片实例数据
// 此接口请根据实际情况实现,具体请参考:FormExtAbility Stage模型卡片实例
deleteFormInfo(formId);
}
// ...
```
具体的持久化方法可以参考[轻量级数据存储开发指导](../database/database-preference-guidelines.md)
需要注意的是,卡片使用方在请求卡片时传递给提供方应用的Want数据中存在临时标记字段,表示此次请求的卡片是否为临时卡片:
- 常态卡片:卡片使用方会持久化的卡片;
- 临时卡片:卡片使用方不会持久化的卡片;
由于临时卡片的数据具有非持久化的特殊性,某些场景例如卡片服务框架死亡重启,此时临时卡片数据在卡片管理服务中已经删除,且对应的卡片ID不会通知到提供方,所以卡片提供方需要自己负责清理长时间未删除的临时卡片数据。同时对应的卡片使用方可能会将之前请求的临时卡片转换为常态卡片。如果转换成功,卡片提供方也需要对对应的临时卡片ID进行处理,把卡片提供方记录的临时卡片数据转换为常态卡片数据,防止提供方在清理长时间未删除的临时卡片时,把已经转换为常态卡片的临时卡片信息删除,导致卡片信息丢失。
### 卡片数据交互
当卡片应用需要更新数据时(如触发了定时更新或定点更新),卡片应用获取最新数据,并调用updateForm()接口更新主动触发卡片的更新。
```ts
onUpdate(formId) {
// 若卡片支持定时更新/定点更新/卡片使用方主动请求更新功能,则提供方需要重写该方法以支持数据更新
console.info('FormAbility onUpdate');
let obj = {
"title": "titleOnUpdate",
"detail": "detailOnUpdate"
};
let formData = formBindingData.createFormBindingData(obj);
// 调用updateForm接口去更新对应的卡片,仅更新入参中携带的数据信息,其他信息保持不变
formProvider.updateForm(formId, formData).catch((error) => {
console.info('FormAbility updateForm, error:' + JSON.stringify(error));
});
}
```
### 开发卡片页面
开发者可以使用类Web范式(HML+CSS+JSON)开发JS卡片页面。生成如下卡片页面,可以这样配置卡片页面文件:
![widget-development-fa](figures/widget-development-fa.png)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 当前仅支持JS扩展的类Web开发范式来实现卡片的UI界面。
- HML:使用类Web范式的组件描述卡片的页面信息。
```html
<div class="container">
<stack>
<div class="container-img">
<image src="/common/widget.png" class="bg-img"></image>
</div>
<div class="container-inner">
<text class="title">{{title}}</text>
<text class="detail_text" onclick="routerEvent">{{detail}}</text>
</div>
</stack>
</div>
```
- CSS:HML中类Web范式组件的样式信息。
```css
.container {
flex-direction: column;
justify-content: center;
align-items: center;
}
.bg-img {
flex-shrink: 0;
height: 100%;
}
.container-inner {
flex-direction: column;
justify-content: flex-end;
align-items: flex-start;
height: 100%;
width: 100%;
padding: 12px;
}
.title {
font-size: 19px;
font-weight: bold;
color: white;
text-overflow: ellipsis;
max-lines: 1;
}
.detail_text {
font-size: 16px;
color: white;
opacity: 0.66;
text-overflow: ellipsis;
max-lines: 1;
margin-top: 6px;
}
```
- JSON:卡片页面中的数据和事件交互。
```json
{
"data": {
"title": "TitleDefault",
"detail": "TextDefault"
},
"actions": {
"routerEvent": {
"action": "router",
"abilityName": "com.example.entry.MainAbility",
"params": {
"message": "add detail"
}
}
}
}
```
### 开发卡片事件
卡片支持为组件设置交互事件(action),包括router事件和message事件,其中router事件用于Ability跳转,message事件用于卡片开发人员自定义点击事件。关键步骤说明如下:
1. 在hml中为组件设置onclick属性,其值对应到json文件的actions字段中。
2. 如何设置router事件:
- action属性值为"router";
- abilityName为跳转目标的Ability名(支持跳转FA模型的PageAbility组件和Stage模型的UIAbility组件),如目前DevEco创建的FA模型的MainAbility默认名为com.example.entry.MainAbility;
- params为传递给跳转目标Ability的自定义参数,可以按需填写。其值可以在目标Ability启动时的want中的parameters里获取。如FA模型MainAbility的onCreate生命周期里可以通过featureAbility.getWant()获取到want,然后在其parameters字段下获取到配置的参数;
3. 如何设置message事件:
- action属性值为"message";
- params为message事件的用户自定义参数,可以按需填写。其值可以在卡片生命周期函数onEvent中的message里获取;
示例如下:
- hml文件
```html
<div class="container">
<stack>
<div class="container-img">
<image src="/common/widget.png" class="bg-img"></image>
</div>
<div class="container-inner">
<text class="title" onclick="routerEvent">{{title}}</text>
<text class="detail_text" onclick="messageEvent">{{detail}}</text>
</div>
</stack>
</div>
```
- css文件
```css
.container {
flex-direction: column;
justify-content: center;
align-items: center;
}
.bg-img {
flex-shrink: 0;
height: 100%;
}
.container-inner {
flex-direction: column;
justify-content: flex-end;
align-items: flex-start;
height: 100%;
width: 100%;
padding: 12px;
}
.title {
font-size: 19px;
font-weight: bold;
color: white;
text-overflow: ellipsis;
max-lines: 1;
}
.detail_text {
font-size: 16px;
color: white;
opacity: 0.66;
text-overflow: ellipsis;
max-lines: 1;
margin-top: 6px;
}
```
- json文件
```json
{
"data": {
"title": "TitleDefault",
"detail": "TextDefault"
},
"actions": {
"routerEvent": {
"action": "router",
"abilityName": "com.example.entry.MainAbility",
"params": {
"message": "add detail"
}
},
"messageEvent": {
"action": "message",
"params": {
"message": "add detail"
}
}
}
}
```
## 相关实例
针对FA模型卡片提供方的开发,有以下相关实例可供参考:
- [FormAbility:FA模型卡片(ArkTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ability/FormAbility)
- [FormLauncher:卡片使用方(ArkTS)(API8)(Full SDK)](https://gitee.com/openharmony/applications_app_samples/tree/master/ability/FormLauncher)
# FormExtensionAbility(服务卡片)
## 卡片概述
FormExtensionAbility就是服务卡片扩展组件(以下简称“卡片”),是一种界面展示形式,可以将应用的重要信息或操作前置到卡片,以达到服务直达,减少体验层级的目的。
卡片常用于嵌入到其他应用(当前只支持系统应用)中作为其界面的一部分显示,并支持拉起页面、发送消息等基础的交互功能。
卡片的基本概念:
- 卡片使用方:显示卡片内容的宿主应用,控制卡片在宿主中展示的位置。
- 卡片管理服务:用于管理系统中所添加卡片的常驻代理服务,包括卡片对象的管理与使用,以及卡片周期性刷新等。
- 卡片提供方:提供卡片显示内容原子化服务,控制卡片的显示内容、控件布局以及控件点击事件。
## 运作机制
卡片框架的运作机制如图1所示。
**图1** 卡片框架运作机制(Stage模型)  
![form-extension](figures/form-extension.png)
卡片使用方包含以下模块:
- 卡片使用:包含卡片的创建、删除、请求更新等操作。
- 通信适配层:由OpenHarmony SDK提供,负责与卡片管理服务通信,用于将卡片的相关操作到卡片管理服务。
卡片管理服务包含以下模块:
- 周期性刷新:在卡片添加后,根据卡片的刷新策略启动定时任务周期性触发卡片的刷新。
- 卡片缓存管理:在卡片添加到卡片管理服务后,对卡片的视图信息进行缓存,以便下次获取卡片时可以直接返回缓存数据,降低时延。
- 卡片生命周期管理:对于卡片切换到后台或者被遮挡时,暂停卡片的刷新;以及卡片的升级/卸载场景下对卡片数据的更新和清理。
- 卡片使用方对象管理:对卡片使用方的RPC对象进行管理,用于使用方请求进行校验以及对卡片更新后的回调处理。
- 通信适配层:负责与卡片使用方和提供方进行RPC通信。
卡片提供方包含以下模块:
- 卡片服务:由卡片提供方开发者实现,开发者实现生命周期处理创建卡片、更新卡片以及删除卡片等请求,提供相应的卡片服务。
- 卡片提供方实例管理模块:由卡片提供方开发者实现,负责对卡片管理服务分配的卡片实例进行持久化管理。
- 通信适配层:由OpenHarmony SDK提供,负责与卡片管理服务通信,用于将卡片的更新数据主动推送到卡片管理服务。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 实际开发时只需要作为卡片提供方进行卡片内容的开发,卡片使用方和卡片管理服务由系统自动处理。
## 接口说明
FormExtensionAbility类拥有如下API接口,具体的API介绍详见[接口文档](../reference/apis/js-apis-app-form-formextensionability.md)
| 接口名 | 描述 |
| -------- | -------- |
| onAddForm(want:&nbsp;Want):&nbsp;formBindingData.FormBindingData | 卡片提供方接收创建卡片的通知接口。 |
| onCastToNormalForm(formId:&nbsp;string):&nbsp;void | 卡片提供方接收临时卡片转常态卡片的通知接口。 |
| onUpdateForm(formId:&nbsp;string):&nbsp;void | 卡片提供方接收更新卡片的通知接口。 |
| onChangeFormVisibility(newStatus:&nbsp;{&nbsp;[key:&nbsp;string]:&nbsp;number&nbsp;}):&nbsp;void | 卡片提供方接收修改可见性的通知接口。 |
| onFormEvent(formId:&nbsp;string,&nbsp;message:&nbsp;string):&nbsp;void | 卡片提供方接收处理卡片事件的通知接口。 |
| onRemoveForm(formId:&nbsp;string):&nbsp;void | 卡片提供方接收销毁卡片的通知接口。 |
| onConfigurationUpdate(config:&nbsp;Configuration):&nbsp;void | 当系统配置更新时调用。 |
| onShareForm?(formId:&nbsp;string):&nbsp;{&nbsp;[key:&nbsp;string]:&nbsp;any&nbsp;} | 卡片提供方接收卡片分享的通知接口。 |
FormExtensionAbility类还拥有成员context,为FormExtensionContext类,具体的API介绍详见[接口文档](../reference/apis/js-apis-formextensioncontext.md)
| 接口名 | 描述 |
| -------- | -------- |
| startAbility(want:&nbsp;Want,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void | 回调形式拉起一个卡片所属应用的UIAbility(系统接口,三方应用不支持调用,需申请后台拉起权限)。 |
| startAbility(want:&nbsp;Want):&nbsp;Promise&lt;void&gt; | Promise形式拉起一个卡片所属应用的UIAbility(系统接口,三方应用不支持调用,需申请后台拉起权限)。 |
formProvider类有如下API接口,具体的API介绍详见[接口文档](../reference/apis/js-apis-app-form-formprovider.md)
| 接口名 | 描述 |
| -------- | -------- |
| setFormNextRefreshTime(formId:&nbsp;string,&nbsp;minute:&nbsp;number,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void; | 设置指定卡片的下一次更新时间。 |
| setFormNextRefreshTime(formId:&nbsp;string,&nbsp;minute:&nbsp;number):&nbsp;Promise&lt;void&gt;; | 设置指定卡片的下一次更新时间,以promise方式返回。 |
| updateForm(formId:&nbsp;string,&nbsp;formBindingData:&nbsp;FormBindingData,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void; | 更新指定的卡片。 |
| updateForm(formId:&nbsp;string,&nbsp;formBindingData:&nbsp;FormBindingData):&nbsp;Promise&lt;void&gt;; | 更新指定的卡片,以promise方式返回。 |
formBindingData类有如下API接口,具体的API介绍详见[接口文档](../reference/apis/js-apis-app-form-formbindingdata.md)
| 接口名 | 描述 |
| -------- | -------- |
| createFormBindingData(obj?:&nbsp;Object&nbsp;\|&nbsp;string):&nbsp;FormBindingData | 创建一个FormBindingData对象。 |
## 开发步骤
Stage卡片开发,即基于[Stage模型](stage-model-development-overview.md)的卡片提供方开发,主要涉及如下关键步骤:
- [创建卡片FormExtensionAbility](#创建卡片formextensionability):卡片生命周期回调函数FormExtensionAbility开发。
- [配置卡片配置文件](#配置卡片配置文件):配置应用配置文件module.json5和profile配置文件。
- [卡片数据交互](#卡片数据交互):对卡片信息进行持久化管理。
- [卡片数据交互](#卡片数据交互):通过updateForm更新卡片显示的信息。
- [开发卡片页面](#开发卡片页面):使用HML+CSS+JSON开发JS卡片页面。
- [开发卡片事件](#开发卡片事件):为卡片添加router事件和message事件。
### 创建卡片FormExtensionAbility
创建Stage模型的卡片,需实现FormExtensionAbility生命周期接口。先参考[DevEco Studio服务卡片开发指南](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-development-service-widget-0000001263280425)生成服务卡片模板。
1. 在EntryFormAbility.ts中,导入相关模块。
```ts
import FormExtension from '@ohos.app.form.FormExtensionAbility';
import formBindingData from '@ohos.app.form.formBindingData';
import formInfo from '@ohos.app.form.formInfo';
import formProvider from '@ohos.app.form.formProvider';
import dataStorage from '@ohos.data.storage';
```
2. 在EntryFormAbility.ts中,实现FormExtension生命周期接口。
```ts
export default class EntryFormAbility extends FormExtension {
onAddForm(want) {
console.info('[EntryFormAbility] onAddForm');
// 使用方创建卡片时触发,提供方需要返回卡片数据绑定类
let obj = {
"title": "titleOnCreate",
"detail": "detailOnCreate"
};
let formData = formBindingData.createFormBindingData(obj);
return formData;
}
onCastToNormalForm(formId) {
// 使用方将临时卡片转换为常态卡片触发,提供方需要做相应的处理
console.info('[EntryFormAbility] onCastToNormalForm');
}
onUpdateForm(formId) {
// 若卡片支持定时更新/定点更新/卡片使用方主动请求更新功能,则提供方需要重写该方法以支持数据更新
console.info('[EntryFormAbility] onUpdateForm');
let obj = {
"title": "titleOnUpdate",
"detail": "detailOnUpdate"
};
let formData = formBindingData.createFormBindingData(obj);
formProvider.updateForm(formId, formData).catch((error) => {
console.info('[EntryFormAbility] updateForm, error:' + JSON.stringify(error));
});
}
onChangeFormVisibility(newStatus) {
// 使用方发起可见或者不可见通知触发,提供方需要做相应的处理,仅系统应用生效
console.info('[EntryFormAbility] onChangeFormVisibility');
}
onFormEvent(formId, message) {
// 若卡片支持触发事件,则需要重写该方法并实现对事件的触发
console.info('[EntryFormAbility] onFormEvent');
}
onRemoveForm(formId) {
// 删除卡片实例数据
console.info('[EntryFormAbility] onRemoveForm');
}
onConfigurationUpdate(config) {
console.info('[EntryFormAbility] nConfigurationUpdate, config:' + JSON.stringify(config));
}
onAcquireFormState(want) {
return formInfo.FormState.READY;
}
}
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> FormExtensionAbility不能常驻后台,即在卡片生命周期回调函数中无法处理长时间的任务。
### 配置卡片配置文件
1. 卡片需要在[module.json5配置文件](../quick-start/module-configuration-file.md)中的extensionAbilities标签下,配置ExtensionAbility相关信息。FormExtensionAbility需要填写metadata元信息标签,其中键名称为固定字符串"ohos.extension.form",资源为卡片的具体配置信息的索引。
配置示例如下:
```json
{
"module": {
// ...
"extensionAbilities": [
{
"name": "EntryFormAbility",
"srcEntrance": "./ets/entryformability/EntryFormAbility.ts",
"label": "$string:EntryFormAbility_label",
"description": "$string:EntryFormAbility_desc",
"type": "form",
"metadata": [
{
"name": "ohos.extension.form",
"resource": "$profile:form_config"
}
]
}
]
}
}
```
2. 卡片的具体配置信息。在上述FormExtensionAbility的元信息("metadata"配置项)中,可以指定卡片具体配置信息的资源索引。例如当resource指定为$profile:form_config时,会使用开发视图的resources/base/profile/目录下的form_config.json作为卡片profile配置文件。内部字段结构说明如下表所示。
**表1** 卡片profile配置文件
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 表示卡片的类名,字符串最大长度为127字节。 | 字符串 | 否 |
| description | 表示卡片的描述。取值可以是描述性内容,也可以是对描述性内容的资源索引,以支持多语言。字符串最大长度为255字节。 | 字符串 | 可缺省,缺省为空。 |
| src | 表示卡片对应的UI代码的完整路径。 | 字符串 | 否 |
| window | 用于定义与显示窗口相关的配置。 | 对象 | 可缺省 |
| isDefault | 表示该卡片是否为默认卡片,每个Ability有且只有一个默认卡片。<br/>true:默认卡片。<br/>false:非默认卡片。 | 布尔值 | 否 |
| colorMode | 表示卡片的主题样式,取值范围如下:<br/>auto:自适应。<br/>dark:深色主题。<br/>light:浅色主题。 | 字符串 | 可缺省,缺省值为“auto”。 |
| supportDimensions | 表示卡片支持的外观规格,取值范围:<br/>1&nbsp;\*&nbsp;2:表示1行2列的二宫格。<br/>2&nbsp;\*&nbsp;2:表示2行2列的四宫格。<br/>2&nbsp;\*&nbsp;4:表示2行4列的八宫格。<br/>4&nbsp;\*&nbsp;4:表示4行4列的十六宫格。 | 字符串数组 | 否 |
| defaultDimension | 表示卡片的默认外观规格,取值必须在该卡片supportDimensions配置的列表中。 | 字符串 | 否 |
| updateEnabled | 表示卡片是否支持周期性刷新,取值范围:<br/>true:表示支持周期性刷新,可以在定时刷新(updateDuration)和定点刷新(scheduledUpdateTime)两种方式任选其一,优先选择定时刷新。<br/>false:表示不支持周期性刷新。 | 布尔类型 | 否 |
| scheduledUpdateTime | 表示卡片的定点刷新的时刻,采用24小时制,精确到分钟。<br/>updateDuration参数优先级高于scheduledUpdateTime,两者同时配置时,以updateDuration配置的刷新时间为准。 | 字符串 | 可缺省,缺省值为“0:0”。 |
| updateDuration | 表示卡片定时刷新的更新周期,单位为30分钟,取值为自然数。<br/>当取值为0时,表示该参数不生效。<br/>当取值为正整数N时,表示刷新周期为30\*N分钟。<br/>updateDuration参数优先级高于scheduledUpdateTime,两者同时配置时,以updateDuration配置的刷新时间为准。 | 数值 | 可缺省,缺省值为“0”。 |
| formConfigAbility | 表示卡片的配置跳转链接,采用URI格式。 | 字符串 | 可缺省,缺省值为空。 |
| formVisibleNotify | 标识是否允许卡片使用卡片可见性通知。 | 字符串 | 可缺省,缺省值为空。 |
| metaData | 表示卡片的自定义信息,包含customizeData数组标签。 | 对象 | 可缺省,缺省值为空。 |
配置示例如下:
```json
{
"forms": [
{
"name": "widget",
"description": "This is a service widget.",
"src": "./js/widget/pages/index/index",
"window": {
"designWidth": 720,
"autoDesignWidth": true
},
"colorMode": "auto",
"isDefault": true,
"updateEnabled": true,
"scheduledUpdateTime": "10:30",
"updateDuration": 1,
"defaultDimension": "2*2",
"supportDimensions": [
"2*2"
]
}
]
}
```
### 卡片信息的持久化
因大部分卡片提供方都不是常驻服务,只有在需要使用时才会被拉起获取卡片信息,且卡片管理服务支持对卡片进行多实例管理,卡片ID对应实例ID,因此若卡片提供方支持对卡片数据进行配置,则需要对卡片的业务数据按照卡片ID进行持久化管理,以便在后续获取、更新以及拉起时能获取到正确的卡片业务数据。
```ts
const DATA_STORAGE_PATH = "/data/storage/el2/base/haps/form_store";
async function storeFormInfo(formId: string, formName: string, tempFlag: boolean) {
// 此处仅对卡片ID:formId,卡片名:formName和是否为临时卡片:tempFlag进行了持久化
let formInfo = {
"formName": formName,
"tempFlag": tempFlag,
"updateCount": 0
};
try {
const storage = await dataStorage.getStorage(DATA_STORAGE_PATH);
// put form info
await storage.put(formId, JSON.stringify(formInfo));
console.info(`[EntryFormAbility] storeFormInfo, put form info successfully, formId: ${formId}`);
await storage.flush();
} catch (err) {
console.error(`[EntryFormAbility] failed to storeFormInfo, err: ${JSON.stringify(err)}`);
}
}
export default class EntryFormAbility extends FormExtension {
// ...
onAddForm(want) {
console.info('[EntryFormAbility] onAddForm');
let formId = want.parameters["ohos.extra.param.key.form_identity"];
let formName = want.parameters["ohos.extra.param.key.form_name"];
let tempFlag = want.parameters["ohos.extra.param.key.form_temporary"];
// 将创建的卡片信息持久化,以便在下次获取/更新该卡片实例时进行使用
// 此接口请根据实际情况实现,具体请参考:FormExtAbility Stage模型卡片实例
storeFormInfo(formId, formName, tempFlag);
let obj = {
"title": "titleOnCreate",
"detail": "detailOnCreate"
};
let formData = formBindingData.createFormBindingData(obj);
return formData;
}
}
```
且需要适配onRemoveForm卡片删除通知接口,在其中实现卡片实例数据的删除。
```ts
const DATA_STORAGE_PATH = "/data/storage/el2/base/haps/form_store";
async function deleteFormInfo(formId: string) {
try {
const storage = await dataStorage.getStorage(DATA_STORAGE_PATH);
// del form info
await storage.delete(formId);
console.info(`[EntryFormAbility] deleteFormInfo, del form info successfully, formId: ${formId}`);
await storage.flush();
} catch (err) {
console.error(`[EntryFormAbility] failed to deleteFormInfo, err: ${JSON.stringify(err)}`);
}
}
// ...
export default class EntryFormAbility extends FormExtension {
// ...
onRemoveForm(formId) {
console.info('[EntryFormAbility] onRemoveForm');
// 删除之前持久化的卡片实例数据
// 此接口请根据实际情况实现,具体请参考:FormExtAbility Stage模型卡片实例
deleteFormInfo(formId);
}
}
```
具体的持久化方法可以参考[轻量级数据存储开发指导](../database/database-preference-guidelines.md)
需要注意的是,卡片使用方在请求卡片时传递给提供方应用的Want数据中存在临时标记字段,表示此次请求的卡片是否为临时卡片:
- 常态卡片:卡片使用方会持久化的卡片;
- 临时卡片:卡片使用方不会持久化的卡片;
由于临时卡片的数据具有非持久化的特殊性,某些场景例如卡片服务框架死亡重启,此时临时卡片数据在卡片管理服务中已经删除,且对应的卡片ID不会通知到提供方,所以卡片提供方需要自己负责清理长时间未删除的临时卡片数据。同时对应的卡片使用方可能会将之前请求的临时卡片转换为常态卡片。如果转换成功,卡片提供方也需要对对应的临时卡片ID进行处理,把卡片提供方记录的临时卡片数据转换为常态卡片数据,防止提供方在清理长时间未删除的临时卡片时,把已经转换为常态卡片的临时卡片信息删除,导致卡片信息丢失。
### 卡片数据交互
当卡片应用需要更新数据时(如触发了定时更新或定点更新),卡片应用获取最新数据,并调用updateForm()接口主动触发卡片的更新。
```ts
onUpdateForm(formId) {
// 若卡片支持定时更新/定点更新/卡片使用方主动请求更新功能,则提供方需要重写该方法以支持数据更新
console.info('[EntryFormAbility] onUpdateForm');
let obj = {
"title": "titleOnUpdate",
"detail": "detailOnUpdate"
};
let formData = formBindingData.createFormBindingData(obj);
// 调用updateForm接口去更新对应的卡片,仅更新入参中携带的数据信息,其他信息保持不变
formProvider.updateForm(formId, formData).catch((error) => {
console.info('[EntryFormAbility] updateForm, error:' + JSON.stringify(error));
});
}
```
### 开发卡片页面
开发者可以使用类Web范式(HML+CSS+JSON)开发JS卡片页面。生成如下卡片页面,可以这样配置卡片页面文件:
![widget-development-stage](figures/widget-development-stage.png)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 当前仅支持JS扩展的类Web开发范式来实现卡片的UI界面。
- HML:使用类Web范式的组件描述卡片的页面信息。
```html
<div class="container">
<stack>
<div class="container-img">
<image src="/common/widget.png" class="bg-img"></image>
</div>
<div class="container-inner">
<text class="title">{{title}}</text>
<text class="detail_text" onclick="routerEvent">{{detail}}</text>
</div>
</stack>
</div>
```
- CSS:HML中类Web范式组件的样式信息。
```css
.container {
flex-direction: column;
justify-content: center;
align-items: center;
}
.bg-img {
flex-shrink: 0;
height: 100%;
}
.container-inner {
flex-direction: column;
justify-content: flex-end;
align-items: flex-start;
height: 100%;
width: 100%;
padding: 12px;
}
.title {
font-size: 19px;
font-weight: bold;
color: white;
text-overflow: ellipsis;
max-lines: 1;
}
.detail_text {
font-size: 16px;
color: white;
opacity: 0.66;
text-overflow: ellipsis;
max-lines: 1;
margin-top: 6px;
}
```
- JSON:卡片页面中的数据和事件交互。
```json
{
"data": {
"title": "TitleDefault",
"detail": "TextDefault"
},
"actions": {
"routerEvent": {
"action": "router",
"abilityName": "EntryAbility",
"params": {
"message": "add detail"
}
}
}
}
```
### 开发卡片事件
卡片支持为组件设置交互事件(action),包括router事件和message事件,其中router事件用于Ability跳转,message事件用于卡片开发人员自定义点击事件。
关键步骤说明如下:
1. 在HML中为组件设置onclick属性,其值对应到JSON文件的actions字段中。
2. 设置router事件:
- action属性值为"router"。
- abilityName为跳转目标的Ability名(支持跳转FA模型的PageAbility组件和Stage模型的UIAbility组件),如目前DevEco Studio创建的Stage模型的UIAbility默认名为EntryAbility。
- params为传递给跳转目标Ability的自定义参数,可以按需填写。其值可以在目标Ability启动时的want中的parameters里获取。如Stage模型MainAbility的onCreate生命周期里的入参want的parameters字段下获取到配置的参数。
3. 设置message事件:
- action属性值为"message"。
- params为message事件的用户自定义参数,可以按需填写。其值可以在卡片生命周期函数onFormEvent()中的message里获取。
示例如下。
- HML文件
```html
<div class="container">
<stack>
<div class="container-img">
<image src="/common/widget.png" class="bg-img"></image>
</div>
<div class="container-inner">
<text class="title" onclick="routerEvent">{{title}}</text>
<text class="detail_text" onclick="messageEvent">{{detail}}</text>
</div>
</stack>
</div>
```
- CSS文件
```css
.container {
flex-direction: column;
justify-content: center;
align-items: center;
}
.bg-img {
flex-shrink: 0;
height: 100%;
}
.container-inner {
flex-direction: column;
justify-content: flex-end;
align-items: flex-start;
height: 100%;
width: 100%;
padding: 12px;
}
.title {
font-size: 19px;
font-weight: bold;
color: white;
text-overflow: ellipsis;
max-lines: 1;
}
.detail_text {
font-size: 16px;
color: white;
opacity: 0.66;
text-overflow: ellipsis;
max-lines: 1;
margin-top: 6px;
}
```
- JSON文件
```json
{
"data": {
"title": "TitleDefault",
"detail": "TextDefault"
},
"actions": {
"routerEvent": {
"action": "router",
"abilityName": "EntryAbility",
"params": {
"message": "add detail"
}
},
"messageEvent": {
"action": "message",
"params": {
"message": "add detail"
}
}
}
}
```
## 相关实例
针对Stage模型卡片提供方的开发,有以下相关实例可供参考:
- [FormExtAbility:Stage模型卡片(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/ability/FormExtAbility)
- [GalleryForm:图库卡片(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/ability/GalleryForm)
# 卡片切换
**卡片切换**主要包含如下三部分:
- 卡片页面布局:FA模型卡片和Stage模型卡片的布局都采用类web范式开发可以直接复用。
- 卡片配置文件:FA模型的卡片配置在config.json中,Stage卡片配置在module.json5和form_config.json中(如下图1和图2)。
- 卡片业务逻辑:FA模型和Stage模型在卡片入口文件以及生命周期存在细微的差异(如下图3和图4)。
| 配置项 | FA模型 | Stage模型 |
| ---------------- | ------------------------------------------- | ------------------------------------------------------------ |
| 配置项位置 | formAbility和forms配置都在config.json文件里 | 一级目录module.json5配置文件中配置extensionAbilities(针对formExtensionAbility的配置),二级目录form_config.json文件中配置forms(针对formExtensionAbility里包含的forms的详细配置) |
| 卡片代码路径 | srcPath,不带文件名 | srcEntrance,带文件名 |
| 语言 | srcLanguage支持配置为js或ets | 无此配置项,只支持ets |
| 是否使能卡片 | formsEnabled | 无,type配置项配置为form即使能 |
| ability类型 | type:service | type:form |
| 二级目录配置标签 | 无 | metadata:包含name、value、resource。其中resource用于指向卡片二级目录form_config.json文件的位置 |
入口配置差异示意图1:
![widget-switch1](figures/widget-switch1.png)
卡片信息配置差异示意图2:
![widget-switch2](figures/widget-switch2.png)
| 入口及生命周期 | FA模型 | Stage模型 |
| -------- | -------- | -------- |
| 入口文件 | srcPath指向的目录下的form.ts | srcEntrance指向的文件 |
| 生命周期 | export&nbsp;default | import&nbsp;FormExtension&nbsp;from&nbsp;'\@ohos.app.form.FormExtensionAbility';<br/>export&nbsp;default&nbsp;class&nbsp;FormAbility&nbsp;extends&nbsp;FormExtension |
入口文件差异示意图3:
![widget-switch3](figures/widget-switch3.png)
生命周期差异示意图4( 生命周期回调均一致,不需要调整):
![widget-switch4](figures/widget-switch4.png)
# 窗口属性
具体获取窗口实例、设置窗口属性的接口描述及示例见[接口文档](../windowmanager/application-window-fa.md)
# window接口切换
| FA模型接口 | Stage模型接口对应d.ts文件 | Stage模型对应接口 |
| -------- | -------- | -------- |
| [enum&nbsp;WindowType&nbsp;{<br/>TYPE_APP<br/>}](../reference/apis/js-apis-window.md#windowtype7) | \@ohos.window.d.ts | [createSubWindow(name:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;Window&gt;):&nbsp;void;](../reference/apis/js-apis-window.md#createsubwindow9)<br/>[createSubWindow(name:&nbsp;string):&nbsp;Promise;](../reference/apis/js-apis-window.md#createsubwindow9-1)<br/>FA模型应用通过window.create(id,&nbsp;WindowType.TYPE_APP)接口创建应用子窗口,Stage模型应用可使用WindowStage.CreateSubWindow()接口代替 |
| [create(id:&nbsp;string,&nbsp;type:&nbsp;WindowType,&nbsp;callback:&nbsp;AsyncCallback&lt;Window&gt;):&nbsp;void;](../reference/apis/js-apis-window.md#windowcreatedeprecated)<br/>[create(id:&nbsp;string,&nbsp;type:&nbsp;WindowType):&nbsp;Promise&lt;Window&gt;;](../reference/apis/js-apis-window.md#windowcreatedeprecated-1) | \@ohos.window.d.ts | [createWindow(config:&nbsp;Configuration,&nbsp;callback:&nbsp;AsyncCallback&lt;Window&gt;):&nbsp;void;](../reference/apis/js-apis-window.md#windowcreatewindow9)<br/>[createWindow(config:&nbsp;Configuration):&nbsp;Promise&lt;Window&gt;;](../reference/apis/js-apis-window.md#windowcreatewindow9-1) |
| [getTopWindow(callback:&nbsp;AsyncCallback&lt;Window&gt;):&nbsp;void;](../reference/apis/js-apis-window.md#windowgettopwindowdeprecated)<br/>[getTopWindow():&nbsp;Promise&lt;Window&gt;;](../reference/apis/js-apis-window.md#windowgettopwindowdeprecated-1) | \@ohos.window.d.ts | [getLastWindow(ctx:&nbsp;BaseContext,&nbsp;callback:&nbsp;AsyncCallback&lt;Window&gt;):&nbsp;void;](../reference/apis/js-apis-window.md#windowgetlastwindow9)<br/>[getLastWindow(ctx:&nbsp;BaseContext):&nbsp;Promise&lt;Window&gt;;](../reference/apis/js-apis-window.md#windowgetlastwindow9-1) |
# 公共事件与通知 # 通知
- [公共事件与通知概述](notification-brief.md) - [通知概述](notification-overview.md)
- [公共事件开发指导](common-event.md) - [订阅通知(仅对系统应用开放)](notification-subscription.md)
- [通知开发指导](notification-guidelines.md) - [使能通知开关](notification-enable.md)
- [调试助手使用指导](assistant-guidelines.md) - 发布通知
\ No newline at end of file - [发布基础类型通知](text-notification.md)
- [发布进度条类型通知](progress-bar-notification.md)
- [为通知添加行为意图](notification-with-wantagent.md)
\ No newline at end of file
# 公共事件开发指导
## 简介
OpenHarmony通过CES(Common Event Service,公共事件服务)为应用程序提供订阅、发布、退订公共事件的能力。
公共事件可分为系统公共事件和自定义公共事件。
+ 系统公共事件:系统将收集到的事件信息,根据系统策略发送给订阅该事件的用户程序。 例如:系统关键服务发布的系统事件(例如:hap安装,更新,卸载等)。
+ 自定义公共事件:应用自定义一些公共事件用来实现跨应用的事件通信能力。
每个应用都可以按需订阅公共事件,订阅成功且公共事件发布,系统会把其发送给应用。这些公共事件可能来自系统、其他应用和应用自身。
## 公共事件订阅开发指导
### 场景介绍
当需要订阅某个公共事件,获取某个公共事件传递的参数时,可以创建一个订阅者对象,用于作为订阅公共事件的载体,订阅公共事件并获取公共事件传递而来的参数。订阅部分系统公共事件需要先申请权限,订阅这些事件所需要的权限请见[公共事件权限列表](../reference/apis/js-apis-commonEvent.md#权限列表)
### 接口说明
| 接口名 | 接口描述 |
| ---------------------------------------------------------------------------------------------- | ----------- |
| createSubscriber(subscribeInfo: CommonEventSubscribeInfo, callback: AsyncCallback) | 创建订阅者对象(callback) |
| createSubscriber(subscribeInfo: CommonEventSubscribeInfo) | 创建订阅者对象(promise) |
| subscribe(subscriber: CommonEventSubscriber, callback: AsyncCallback) | 订阅公共事件 |
### 开发步骤
1. 导入CommonEvent模块。
```js
import commonEvent from '@ohos.commonEvent';
```
2. 创建订阅者信息,详细的订阅者信息数据类型及包含的参数请见[CommonEventSubscribeInfo文档](../reference/apis/js-apis-commonEvent.md#commoneventsubscribeinfo)介绍。
```js
//用于保存创建成功的订阅者对象,后续使用其完成订阅及退订的动作
private subscriber = null
//订阅者信息
var subscribeInfo = {
events: ["event"],
}
```
3. 创建订阅者,保存返回的订阅者对象subscriber,用于执行后续的订阅、退订等操作。
```js
//创建订阅者回调
commonEvent.createSubscriber(subscribeInfo, (err, subscriber) => {
if (err.code) {
console.error("[CommonEvent]CreateSubscriberCallBack err=" + JSON.stringify(err))
} else {
console.log("[CommonEvent]CreateSubscriber")
this.subscriber = subscriber
this.result = "Create subscriber succeed"
}
})
```
4. 创建订阅回调函数,订阅回调函数会在接收到事件时触发。订阅回调函数返回的data内包含了公共事件的名称、发布者携带的数据等信息,公共事件数据的详细参数和数据类型请见[CommonEventData文档](../reference/apis/js-apis-commonEvent.md#commoneventdata)介绍。
```js
//订阅公共事件回调
if (this.subscriber != null) {
commonEvent.subscribe(this.subscriber, (err, data) => {
if (err.code) {
console.error("[CommonEvent]SubscribeCallBack err=" + JSON.stringify(err))
} else {
console.log("[CommonEvent]SubscribeCallBack data=" + JSON.stringify(data))
this.result = "receive, event = " + data.event + ", data = " + data.data + ", code = " + data.code
}
})
this.result = "Subscribe succeed"
} else {
prompt.showToast({ message: "Need create subscriber" })
}
```
## 公共事件发布开发指导
### 场景介绍
当需要发布某个自定义公共事件时,可以通过此方法发布事件。发布的公共事件可以携带数据,供订阅者解析并进行下一步处理。
### 接口说明
| 接口名 | 接口描述 |
| ---------------------------------- | ------ |
| publish(event: string, callback: AsyncCallback) | 发布公共事件 |
| publish(event: string, options: CommonEventPublishData, callback: AsyncCallback) | 指定发布信息并发布公共事件 |
### 开发步骤
#### 发布公共事件开发步骤
1. 导入CommonEvent模块。
```js
import commonEvent from '@ohos.commonEvent';
```
2. 传入需要发布的事件名称和回调函数,发布事件。
```js
//发布公共事件
commonEvent.publish("event", (err) => {
if (err.code) {
console.error("[CommonEvent]PublishCallBack err=" + JSON.stringify(err))
} else {
console.info("[CommonEvent]Publish1")
}
})
```
#### 指定发布信息发布公共事件的开发步骤
1. 导入CommonEvent模块。
```js
import commonEvent from '@ohos.commonEvent'
```
2. 定义发布事件时需要指定的发布信息,发布信息所包含的详细参数及其参数类型请见[CommonEventPublishData文档](../reference/apis/js-apis-commonEvent.md#commoneventpublishdata)介绍。
```js
//公共事件相关信息
var options = {
code: 1, //公共事件的初始代码
data: "initial data",//公共事件的初始数据
}
```
3. 传入需要发布的事件名称、需要发布的指定信息和回调函数,发布事件。
```js
//发布公共事件
commonEvent.publish("event", options, (err) => {
if (err.code) {
console.error("[CommonEvent]PublishCallBack err=" + JSON.stringify(err))
} else {
console.info("[CommonEvent]Publish2")
}
})
```
## 公共事件取消订阅开发指导
### 场景介绍
订阅者需要取消已订阅的某个公共事件时,可以通过此方法取消订阅事件。
### 接口说明
| 接口名 | 接口描述 |
| ---------------------------------- | ------ |
| unsubscribe(subscriber: CommonEventSubscriber, callback?: AsyncCallback) | 取消订阅公共事件 |
### 开发步骤
1. 导入CommonEvent模块。
```js
import commonEvent from '@ohos.commonEvent';
```
2. 根据[公共事件订阅指导](#公共事件订阅开发指导)的步骤来订阅某个事件。
3. 调用CommonEvent中的unsubscribe方法取消订阅某事件。
```js
if (this.subscriber != null) {
commonEvent.unsubscribe(this.subscriber, (err) => {
if (err.code) {
console.error("[CommonEvent]UnsubscribeCallBack err=" + JSON.stringify(err))
} else {
console.log("[CommonEvent]Unsubscribe")
this.subscriber = null
this.result = "Unsubscribe succeed"
}
})
}
```
## 相关实例
针对公共事件开发,有以下相关实例可供参考:
- [`CommonEvent`:订阅公共事件(ArkTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/Notification/CommonEvent)
# 公共事件与通知开发概述
公共事件与通知提供了应用程序向系统其他应用程序发布消息、接收来自系统或其他应用特定消息的能力,这些消息可以是新闻推送、广告通知或者预警信息等。
CES(Common Event Service, 即公共事件服务)为应用程序提供发布、订阅及退订公共事件的能力。公共事件根据事件发送方不同可分为系统公共事件和自定义公共事件。
![ces](figures/ces.png)
- 系统公共事件:系统将收集到的事件信息,根据系统策略发送给订阅该事件的用户程序。 公共事件包括:终端设备用户可感知的亮灭屏事件,以及系统关键服务发布的系统事件(例如:USB插拔,网络连接,系统升级)等。
- 自定义公共事件:由应用自身定义的期望特定订阅者可以接收到的公共事件,这些公共事件往往与应用自身的业务逻辑相关。
ANS(Advanced Notification Service,即通知系统服务)为应用程序提供发布通知的能力。这些通知常见的使用场景如下:
- 显示接收到的短消息、即时通讯消息等;
- 显示应用的推送消息,如广告、版本更新、新闻通知等;
- 显示当前正在进行的事件,如播放音乐、导航信息、下载进度等。
通知消息将显示在系统下拉菜单栏,用户可对通知消息进行删除操作,或点击通知触发进一步的操作。
![ans](figures/ans.png)
# 使能通知开关
应用需要开启通知开关才能发送通知。开发者可以在通知发布前调用[requestEnableNotification()](../reference/apis/js-apis-notification.md#notificationrequestenablenotification8)方法,弹窗让用户选择是否开启使能开关,仅弹窗一次,后续调用该接口不再弹窗。
**图1** 使能通知开关示意图
![zh-cn_image_0000001416585590](figures/zh-cn_image_0000001416585590.png)
- 点击“允许”后,则表示允许应用发送通知。
- 点击“取消”后,再次调用[requestEnableNotification()](../reference/apis/js-apis-notification.md#notificationrequestenablenotification8)方法,则不再弹窗。此时如需要手动使能通知开关,操作步骤如下所示。
| ①从设备左上方下拉,进入通知界面 | ②点击右上角“设置”图标,进入通知界面,找到需要打开通知开关的应用 | ③打开“允许通知”开关 |
| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| ![zh-cn_image_0000001417062434](figures/zh-cn_image_0000001417062434.png) | ![zh-cn_image_0000001466462297](figures/zh-cn_image_0000001466462297.png) | ![zh-cn_image_0000001466782025](figures/zh-cn_image_0000001466782025.png) |
## 接口说明
详细接口见[接口文档](../reference/apis/js-apis-notification.md#notificationrequestenablenotification8)
**表1** 通知开关接口功能介绍
| **接口名** | **描述** |
| -------- | -------- |
| isNotificationEnabled(bundle:&nbsp;BundleOption,&nbsp;callback:&nbsp;AsyncCallback&lt;boolean&gt;):&nbsp;void | 查询通知开关。<br/>**说明:**<br/>仅支持系统应用调用。 |
| enableNotification(bundle:&nbsp;BundleOption,&nbsp;enable:&nbsp;boolean,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void | 设置通知开关。例如在“设置&nbsp;&gt;&nbsp;应用和服务&nbsp;&gt;&nbsp;应用管理”,进入对应应用信息的“通知管理”中设置通知开关状态。<br/>**说明:**<br/>仅支持系统应用调用。 |
| requestEnableNotification(callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void | 请求发送通知的许可,第一次调用弹窗供用户选择允许或禁止。 |
## 开发步骤
1. 导入NotificationManager模块。
```ts
import NotificationManager from '@ohos.notificationManager';
```
2. 请求发送通知的许可。
```ts
NotificationManager.requestEnableNotification().then(() => {
console.info(`[ANS] requestEnableNotification success`);
}).catch((err) => {
console.error(`[ANS] requestEnableNotification failed, errCode[${err}]`);
});
```
# 通知开发指导
## 场景简介
OpenHarmony通过ANS(Advanced Notification Service,通知系统服务)对通知类型的消息进行管理,支持多种通知类型,包括文本,长文本,多文本,图片,社交,媒体等。所有系统服务以及应用都可以通过通知接口发送通知消息,用户可以通过SystemUI查看所有通知消息。
通知常见的使用场景:
- 显示接收到短消息、即时消息等。
- 显示应用的推送消息,如广告、版本更新等。
- 显示当前正在进行的事件,如导航、下载等。
## 通知流程
通知业务流程由ANS通知子系统、通知发送端、通知订阅端组成。
一条通知从通知发送端产生,通过IPC通信发送到ANS,ANS再分发给通知订阅端。
系统应用还支持通知相关配置,如使能开关、配置参数由系统配置发起请求,发送到ANS存储到内存和数据库。
![1648113187545](figures/notification.png)
## 接口说明
部分接口仅系统应用才可以调用,且需要具备权限:SystemCapability.Notification.Notification ,接口返回值有两种返回形式:callback和promise,下表中为callback形式接口,promise和callback只是返回值方式不一样,功能相同,具体API说明详见[接口文档](../reference/apis/js-apis-notification.md)
**表1** 通知使能开关接口功能介绍
| 接口名 | 描述 |
| ------------------------------------------------------------ | ---------------- |
| isNotificationEnabled(bundle: BundleOption, callback: AsyncCallback\<boolean>): void | 查询通知使能开关 |
| enableNotification(bundle: BundleOption, enable: boolean, callback: AsyncCallback\<void>): void | 设置使能开关 |
用于查询和设置通知使能开关,若某个应用的通知使能关闭状态,则无法发送通知。
**表2** 通知订阅接口功能介绍
| 接口名 | 描述 |
| ------------------------------------------------------------ | ---------------- |
| subscribe(subscriber: NotificationSubscriber, info: NotificationSubscribeInfo, callback: AsyncCallback\<void>): void | 订阅指定应用通知 |
| subscribe(subscriber: NotificationSubscriber, callback: AsyncCallback\<void>): void | 订阅所有通知 |
| unsubscribe(subscriber: NotificationSubscriber, callback: AsyncCallback\<void>): void | 取消订阅通知 |
订阅接口有支持订阅所有通知、或订阅某些应用的通知。
**表3** 通知订阅回调接口功能介绍
| 接口名 | 描述 |
| ------------------------------------------------ | ---------------- |
| onConsume?:(data: SubscribeCallbackData) => void | 通知回调 |
| onCancel?:(data: SubscribeCallbackData) => void | 通知取消回调 |
| onUpdate?:(data: NotificationSortingMap) => void | 通知排序更新回调 |
| onConnect?:() => void; | 订阅成功回调 |
| onDisconnect?:() => void; | 取消订阅回调 |
**表4** 发送通知接口功能介绍
| 接口名 | 描述 |
| ------------------------------------------------------------ | ------------------------ |
| publish(request: NotificationRequest, callback: AsyncCallback\<void>): void | 发布通知 |
| publish(request: NotificationRequest, userId: number, callback: AsyncCallback\<void>): void | 指定用户发布通知 |
| cancel(id: number, label: string, callback: AsyncCallback\<void>): void | 取消指定的通知 |
| cancelAll(callback: AsyncCallback\<void>): void; | 取消所有该应用发布的通知 |
携带userId的publish接口,可以指定向该用户下订阅者发布通知。
## 开发指导
通知的开发步骤一般是订阅通知、开启通知使能、发布通知。
### 导入模块
```js
import Notification from '@ohos.notification';
```
### 通知订阅
通知接受端首选需要向通知子系统发起通知订阅。
```js
var subscriber = {
onConsume: function (data) {
let req = data.request;
console.info('===>onConsume callback req.id: ' + req.id);
},
onCancel: function (data) {
let req = data.request;
console.info('===>onCancel callback req.id: : ' + req.id);
},
onUpdate: function (data) {
console.info('===>onUpdate in test===>');
},
onConnect: function () {
console.info('===>onConnect in test===>');
},
onDisconnect: function () {
console.info('===>onDisConnect in test===>');
},
onDestroy: function () {
console.info('===>onDestroy in test===>');
},
};
Notification.subscribe(subscriber, (err, data) => { // callback形式调用异步接口
if (err.code) {
console.error('===>failed to subscribe because ' + JSON.stringify(err));
return;
}
console.info('===>subscribeTest success : ' + JSON.stringify(data));
});
```
### 通知发送
##### 开启通知使能
应用发布通知的使能开关默认是关闭的,需要通过下拉通知栏,在通知设置里打开通知开关。应用也可以通过调用Notification.requestEnableNotification接口,弹窗提示用户是否允许发送通知。
```js
Notification.requestEnableNotification().then((data) => {
console.info('===>requestEnableNotification success');
}).catch((err) => {
console.error('===>requestEnableNotification failed because ' + JSON.stringify(err));
});
```
##### 通知发布
发布通知,先要构造NotificationRequest对象,设置通知类型、标题、内容等一系列属性。下面以发布普通文本和携带wantAgent通知为例。
普通文本通知实例
```js
//构造NotificationRequest对象
var notificationRequest = {
id: 1,
content: {
contentType: Notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: "test_title",
text: "test_text",
additionalText: "test_additionalText"
}
}
}
//通知发送
Notification.publish(notificationRequest).then((data) => {
console.info('===>publish promise success req.id : ' + notificationRequest.id);
}).catch((err) => {
console.error('===>publish promise failed because ' + JSON.stringify(err));
});
```
携带wantAgent通知实例
wantAgent使用详见[wantAgent开发文档](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/ability/wantagent.md)
- 创建wantAgent对象
```js
import wantAgent from '@ohos.wantAgent';
//WantAgentInfo对象
var wantAgentInfo = {
wants: [
{
bundleName: 'ohos.samples.eTSNotification',
abilityName: 'ohos.samples.eTSNotification.MainAbility',
}
],
operationType: wantAgent.OperationType.START_ABILITY,
requestCode: 0,
wantAgentFlags:[wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
}
//wantAgent对象
var WantAgent;
//getWantAgent回调
function getWantAgentCallback(err, data) {
console.info("===>getWantAgentCallback===>");
if (err.code == 0) {
WantAgent = data;
} else {
console.info('----getWantAgent failed!----');
}
}
// 获取wantAgent对象
wantAgent.getWantAgent(wantAgentInfo, getWantAgentCallback)
```
- 发布通知
```js
//构造NotificationRequest对象
var notificationRequest = {
content: {
contentType: Notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: "AceApplication_Title",
text: "AceApplication_Text",
additionalText: "AceApplication_AdditionalText"
},
},
id: 1,
label: 'TEST',
wantAgent: WantAgent,
slotType: Notification.SlotType.OTHER_TYPES,
deliveryTime: new Date().getTime()
}
//通知发送
Notification.publish(notificationRequest).then((data) => {
console.info('===>publish promise success req.id : ' + notificationRequest.id);
}).catch((err) => {
console.error('===>publish promise failed because ' + JSON.stringify(err));
});
```
- 取消通知
取消通知可以分成取消指定的单条通知和取消所有通知,应用只能取消自己发布的通知。
```js
//cancel回调
function cancelCallback(err) {
console.info("===>cancelCallback===>");
}
Notification.cancel(1, "label", cancelCallback)
```
## 相关实例
针对通知开发,有以下相关可供参考:
- [`Notification:`订阅、发送通知(ArkTS)(API9)(Full SDK)](https://gitee.com/openharmony/applications_app_samples/tree/master/Notification/Notification)
# 通知概述
## 通知简介
所有系统服务以及应用都可以通过通知接口发送通知消息,用户可以通过通知栏查看通知内容,也可以点击通知来打开应用。
通知常见的使用场景:
- 显示接收到的短消息、即时消息等。
- 显示应用的推送消息,如广告、版本更新等。
- 显示当前正在进行的事件,如下载等。
OpenHarmony通过ANS(Advanced Notification Service,通知系统服务)对通知类型的消息进行管理,支持多种通知类型,如基础类型通知、进度条类型通知、后台代理提醒。
## 通知业务流程
通知业务流程由通知子系统、通知发送端、通知订阅端组成。
一条通知从通知发送端产生,通过[IPC通信](../connectivity/ipc-rpc-overview.md)发送到通知子系统,再由通知子系统分发给通知订阅端。
系统应用还支持通知相关配置,如使能开关、配置参数由系统配置发起请求,发送到通知子系统存储到内存和数据库。
![zh-cn_image_0000001466582017](figures/zh-cn_image_0000001466582017.png)
# 订阅通知(仅对系统应用开放)
应用需要接收通知,必须先发起订阅,通知子系统提供两种接口:订阅所有应用发布的通知和订阅某些应用发布的通知。
系统提供NotificationSubscriber对象,用于提供订阅成功、通知接收、通知取消、订阅取消等回调接口,将变化信息回调给订阅者。
## 接口说明
通知订阅主要接口如下。详细接口介绍请参见[API参考](../reference/apis/js-apis-notification.md#notification%E6%A8%A1%E5%9D%97)
**表1** 通知订阅接口介绍
| **接口名** | **描述** |
| -------- | -------- |
| subscribe(subscriber:&nbsp;NotificationSubscriber,&nbsp;info:&nbsp;NotificationSubscribeInfo,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void | 订阅指定应用通知。 |
| subscribe(subscriber:&nbsp;NotificationSubscriber,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void | 订阅所有通知。 |
**表2** 通知订阅回调接口介绍
| | |
| -------- | -------- |
| **接口名** | **描述** |
| onConsume?:(data:&nbsp;SubscribeCallbackData)&nbsp;=&gt;&nbsp;void | 通知回调。 |
| onCancel?:(data:&nbsp;SubscribeCallbackData)&nbsp;=&gt;&nbsp;void | 通知取消回调。 |
| onUpdate?:(data:&nbsp;NotificationSortingMap)&nbsp;=&gt;&nbsp;void | 通知排序更新回调。 |
| onConnect?:()&nbsp;=&gt;&nbsp;void; | 订阅成功回调。 |
| onDisconnect?:()&nbsp;=&gt;&nbsp;void; | 取消订阅回调。 |
| onDestroy?:()&nbsp;=&gt;&nbsp;void | 与通知子系统断开回调。 |
| onDoNotDisturbDateChange?:(mode:&nbsp;notification.DoNotDisturbDate)&nbsp;=&gt;&nbsp;void | 免打扰时间选项变更回调。 |
| onEnabledNotificationChanged?:(callbackData:&nbsp;EnabledNotificationCallbackData)&nbsp;=&gt;&nbsp;void | 通知开关变更回调。 |
## 开发步骤
1. 申请`ohos.permission.NOTIFICATION_CONTROLLER`权限,配置方式请参阅[访问控制授权申请指导](../security/accesstoken-guidelines.md#stage%E6%A8%A1%E5%9E%8B)
2. 导入通知订阅模块。
```ts
import NotificationSubscribe from '@ohos.notificationSubscribe';
```
3. 创建订阅者对象。
```ts
let subscriber = {
onConsume: function (data) {
let req = data.request;
console.info('[ANS] onConsume callback req.id: ' + req.id);
},
onCancel: function (data) {
let req = data.request;
console.info('[ANS] onCancel callback req.id: : ' + req.id);
},
onUpdate: function (data) {
console.info('[ANS] onUpdate in test');
},
onConnect: function () {
console.info('[ANS] onConnect in test');
},
onDisconnect: function () {
console.info('[ANS] onDisConnect in test');
},
onDestroy: function () {
console.info('[ANS] onDestroy in test');
},
};
```
4. 发起通知订阅。
```ts
NotificationSubscribe.subscribe(subscriber, (err, data) => { // callback形式调用异步接口
if (err) {
console.error(`[ANS] failed to subscribe, error[${err}]`);
return;
}
console.info(`[ANS] subscribeTest success : + ${data}`);
});
```
# 为通知添加行为意图
WantAgent提供了封装行为意图的能力,这里所说的行为意图主要是指拉起指定的应用组件及发布公共事件等能力。OpenHarmony支持以通知的形式,将WantAgent从发布方传递至接收方,从而在接收方触发WantAgent中指定的意图。例如,在通知消息的发布者发布通知时,通常期望用户可以通过通知栏点击拉起目标应用组件。为了达成这一目标,开发者可以将WantAgent封装至通知消息中,当系统接收到WantAgent后,在用户点击通知栏时触发WantAgent的意图,从而拉起目标应用组件。
为通知添加行为意图的实现方式如下图所示:发布通知的应用向应用组件管理服务AMS(Ability Manager Service)申请WantAgent,然后随其他通知信息一起发送给桌面,当用户在桌面通知栏上点击通知时,触发WantAgent动作。
**图1** 携带行为意图的通知运行机制
![notification-with-wantagent](figures/notification-with-wantagent.png)
## 接口说明
具体接口描述,详见[WantAgent接口文档](../reference/apis/js-apis-wantAgent.md#wantagent%E6%A8%A1%E5%9D%97)
| | |
| -------- | -------- |
| **接口名** | **描述** |
| getWantAgent(info:&nbsp;WantAgentInfo,&nbsp;callback:&nbsp;AsyncCallback&lt;WantAgent&gt;):&nbsp;void | 创建WantAgent。 |
| trigger(agent:&nbsp;WantAgent,&nbsp;triggerInfo:&nbsp;TriggerInfo,&nbsp;callback?:&nbsp;Callback&lt;CompleteData&gt;):&nbsp;void | 触发WantAgent意图。 |
| cancel(agent:&nbsp;WantAgent,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void | 取消WantAgent。 |
| getWant(agent:&nbsp;WantAgent,&nbsp;callback:&nbsp;AsyncCallback&lt;Want&gt;):&nbsp;void | 获取WantAgent的want。 |
| equal(agent:&nbsp;WantAgent,&nbsp;otherAgent:&nbsp;WantAgent,&nbsp;callback:&nbsp;AsyncCallback&lt;boolean&gt;):&nbsp;void | 判断两个WantAgent实例是否相等。 |
## 开发步骤
1. 导入模块。
```ts
import NotificationManager from '@ohos.notificationManager';
import wantAgent from '@ohos.app.ability.wantAgent';
```
2. 创建WantAgentInfo信息。
场景一:创建拉起Ability的WantAgent的WantAgentInfo信息。
```ts
let wantAgentObj = null; // 用于保存创建成功的wantAgent对象,后续使用其完成触发的动作。
// 通过WantAgentInfo的operationType设置动作类型。
let wantAgentInfo = {
wants: [
{
deviceId: '',
bundleName: 'com.example.test',
abilityName: 'com.example.test.MainAbility',
action: '',
entities: [],
uri: '',
parameters: {}
}
],
operationType: wantAgent.OperationType.START_ABILITY,
requestCode: 0,
wantAgentFlags:[wantAgent.WantAgentFlags.CONSTANT_FLAG]
}
```
场景二:创建发布公共事件的WantAgent的WantAgentInfo信息。
```ts
let wantAgentObj = null; // 用于保存创建成功的WantAgent对象,后续使用其完成触发的动作。
// wantAgentInfo
let wantAgentInfo = {
wants: [
{
action: 'event_name', // 设置事件名。
parameters: {},
}
],
operationType: wantAgent.OperationType.SEND_COMMON_EVENT,
requestCode: 0,
wantAgentFlags: [wantAgent.WantAgentFlags.CONSTANT_FLAG],
}
```
3. 创建WantAgent。
```ts
// 创建WantAgent
wantAgent.getWantAgent(wantAgentInfo, (err, data) => {
if (err) {
console.error('[WantAgent]getWantAgent err=' + JSON.stringify(err));
} else {
console.info('[WantAgent]getWantAgent success');
wantAgentObj = data;
}
});
```
4. 构造NotificationRequest对象。
```ts
// 构造NotificationRequest对象
let notificationRequest = {
content: {
contentType: NotificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: 'Test_Title',
text: 'Test_Text',
additionalText: 'Test_AdditionalText',
},
},
id: 1,
label: 'TEST',
wantAgent: wantAgentObj,
}
```
5. 发布WantAgent通知。
```ts
// 通知发送
NotificationManager.publish(notificationRequest, (err) => {
if (err) {
console.error(`[ANS] failed to publish, error[${err}]`);
return;
}
console.info(`[ANS] publish success `);
});
```
6. 用户通过点击通知栏上的通知,触发WantAgent的动作。
```ts
// 触发WantAgent
let triggerInfo = {
code: 0
}
wantAgent.trigger(wantAgentObj, triggerInfo, (completeData) => {
console.info('[WantAgent]getWantAgent success, completeData: ', + JSON.stringify(completeData));
});
```
# 发布进度条类型通知
进度条通知也是常见的通知类型,主要应用于文件下载、事务处理进度显示。OpenHarmony提供了进度条模板,发布通知应用设置好进度条模板的属性值,如模板名、模板数据,通过通知子系统发送到通知栏显示。
目前系统模板仅支持进度条模板,通知模板[NotificationTemplate](../reference/apis/js-apis-notification.md#notificationtemplate8)中的data参数为用户自定义数据,用于显示与模块相关的数据,效果示意如下图所示。
![zh-cn_image_0000001416903138](figures/zh-cn_image_0000001416903138.png)
## 接口说明
[isSupportTemplate()](../reference/apis/js-apis-notification.md#notificationissupporttemplate8)是查询模板是否支持接口,目前仅支持进度条模板。
| | |
| -------- | -------- |
| **接口名** | **描述** |
| isSupportTemplate(templateName:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;boolean&gt;):&nbsp;void | 查询模板是否存在。 |
## 开发步骤
1. [使能通知开关](notification-enable.md),获得用户授权后,才能使用通知功能。
2. 导入模块。
```ts
import NotificationManager from '@ohos.notificationManager';
```
3. 查询系统是否支持进度条模板,查询结果为支持downloadTemplate模板类通知。
```ts
NotificationManager.isSupportTemplate('downloadTemplate').then((data) => {
console.info(`[ANS] isSupportTemplate success`);
let isSupportTpl: boolean = data; // isSupportTpl的值为true表示支持支持downloadTemplate模板类通知,false表示不支持
// ...
}).catch((err) => {
console.error(`[ANS] isSupportTemplate failed, error[${err}]`);
});
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 查询系统支持进度条模板后,再进行后续的步骤操作。
4. 构造进度条模板对象,并发布通知。
```ts
let notificationRequest = {
id: 1,
content: {
contentType: NotificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: 'test_title',
text: 'test_text',
additionalText: 'test_additionalText'
}
},
// 构造进度条模板,name字段当前需要固定配置为downloadTemplate
template: {
name: 'downloadTemplate',
data: { title: 'File Title', fileName: 'music.mp4', progressValue: 45 }
}
}
// 发布通知
NotificationManager.publish(notificationRequest, (err) => {
if (err) {
console.error(`[ANS] failed to publish, error[${err}]`);
return;
}
console.info(`[ANS] publish success `);
});
```
# 发布基础类型通知
基础类型通知主要应用于发送短信息、提示信息、广告推送等,支持普通文本类型、长文本类型、多行文本类型和图片类型。
**表1** 基础类型通知中的内容分类
| 类型 | 描述 |
| -------- | -------- |
| NOTIFICATION_CONTENT_BASIC_TEXT | 普通文本类型。 |
| NOTIFICATION_CONTENT_LONG_TEXT | 长文本类型。 |
| NOTIFICATION_CONTENT_MULTILINE | 多行文本类型。 |
| NOTIFICATION_CONTENT_PICTURE | 图片类型。 |
目前系统仅通知栏订阅了通知,将通知显示在通知栏里。基础类型通知呈现效果示意图如下所示。
**图1** 基础类型通知呈现效果示意图  ![zh-cn_image_0000001466462305](figures/zh-cn_image_0000001466462305.png)
## 接口说明
通知发布接口如下表所示,不同发布类型通知由[NotificationRequest](../reference/apis/js-apis-notification.md#notificationrequest)的字段携带不同的信息。
| **接口名** | **描述** |
| -------- | -------- |
| publish(request:&nbsp;NotificationRequest,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void | 发布通知。 |
| cancel(id:&nbsp;number,&nbsp;label:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void | 取消指定的通知。 |
| cancelAll(callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void; | 取消所有该应用发布的通知。 |
## 开发步骤
1. [使能通知开关](notification-enable.md),获得用户授权后,才能使用通知功能。
2. 导入模块。
```ts
import NotificationManager from '@ohos.notificationManager';
```
3. 构造NotificationRequest对象,并发布通知。
- 普通文本类型通知由标题、文本内容和附加信息三个字段组成,其中标题和文本内容是必填字段,大小均需要小于200字节。
```ts
let notificationRequest = {
id: 1,
content: {
contentType: NotificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT, // 普通文本类型通知
normal: {
title: 'test_title',
text: 'test_text',
additionalText: 'test_additionalText',
}
}
}
NotificationManager.publish(notificationRequest, (err) => {
if (err) {
console.error(`[ANS] failed to publish, error[${err}]`);
return;
}
console.info(`[ANS] publish success`);
});
```
运行效果如下图所示。
![zh-cn_image_0000001466782033](figures/zh-cn_image_0000001466782033.png)
- 长文本类型通知继承了普通文本类型的字段,同时新增了长文本内容、内容概要和通知展开时的标题,其中长文本内容不超过1024字节,其他字段小于200字节。通知默认显示与普通文本相同,展开后,标题显示为展开后标题内容,内容为长文本内容。
```ts
let notificationRequest = {
id: 1,
content: {
contentType: NotificationManager.ContentType.NOTIFICATION_CONTENT_LONG_TEXT, // 长文本类型通知
longText: {
title: 'test_title',
text: 'test_text',
additionalText: 'test_additionalText',
longText: 'test_longText',
briefText: 'test_briefText',
expandedTitle: 'test_expandedTitle',
}
}
}
// 发布通知
NotificationManager.publish(notificationRequest, (err) => {
if (err) {
console.error(`[ANS] failed to publish, error[${err}]`);
return;
}
console.info(`[ANS] publish success`);
});
```
运行效果如下图所示。
![zh-cn_image_0000001416745530](figures/zh-cn_image_0000001416745530.png)
- 多行文本类型通知继承了普通文本类型的字段,同时新增了多行文本内容、内容概要和通知展开时的标题,其字段均小于200字节。通知默认显示与普通文本相同,展开后,标题显示为展开后标题内容,多行文本内容多行显示。
```ts
let notificationRequest = {
id: 1,
content: {
contentType: NotificationManager.ContentType.NOTIFICATION_CONTENT_MULTILINE, // 多行文本类型通知
multiLine: {
title: 'test_title',
text: 'test_text',
briefText: 'test_briefText',
longTitle: 'test_longTitle',
lines: ['line_01', 'line_02', 'line_03', 'line_04'],
}
}
}
// 发布通知
NotificationManager.publish(notificationRequest, (err) => {
if (err) {
console.error(`[ANS] failed to publish, error[${err}]`);
return;
}
console.info(`[ANS] publish success`);
});
```
运行效果如下图所示。
![zh-cn_image_0000001417062446](figures/zh-cn_image_0000001417062446.png)
- 图片类型通知继承了普通文本类型的字段,同时新增了图片内容、内容概要和通知展开时的标题,图片内容为PixelMap型对象,其大小不能超过2M。
```ts
let notificationPicture: PixelMap = undefined; // 需要获取图片PixelMap信息
let notificationRequest = {
id: 1,
content: {
contentType: NotificationManager.ContentType.NOTIFICATION_CONTENT_PICTURE,
picture: {
title: 'test_title',
text: 'test_text',
additionalText: 'test_additionalText',
briefText: 'test_briefText',
expandedTitle: 'test_expandedTitle',
picture: notificationPicture
}
}
}
// 发布通知
NotificationManager.publish(notificationRequest, (err) => {
if (err) {
console.error(`[ANS] failed to publish, error[${err}]`);
return;
}
console.info(`[ANS] publish success `);
});
```
运行效果如下图所示。
![zh-cn_image_0000001466582045](figures/zh-cn_image_0000001466582045.png)
# 入门 # 入门
- 快速入门 - 快速入门
- [开发准备](start-overview.md) - [开发准备](start-overview.md)
- [使用ArkTS语言开发(Stage模型)](start-with-ets-stage.md) - [使用ArkTS语言开发(Stage模型)](start-with-ets-stage.md)
- [使用ArkTS语言开发(FA模型)](start-with-ets-fa.md) - [使用ArkTS语言开发(FA模型)](start-with-ets-fa.md)
- [使用JS语言开发(FA模型)](start-with-js-fa.md) - [使用JS语言开发(FA模型)](start-with-js-fa.md)
- 开发基础知识 - 开发基础知识
- [应用包结构配置文件的说明(FA模型)](package-structure.md) - 应用程序包基础知识
- [应用包结构配置文件的说明(Stage模型)](stage-structure.md) - [应用程序包概述](application-package-overview.md)
- [SysCap说明](syscap.md) - 应用程序包结构
- [Stage模型应用程序包结构](application-package-structure-stage.md)
- [FA模型应用程序包结构](application-package-structure-fa.md)
- [HAR包结构](har-structure.md)
- 应用程序包多HAP机制
- [多HAP机制设计目标](multi-hap-objective.md)
- [多HAP构建视图](multi-hap-build-view.md)
- [多HAP发布部署流程](multi-hap-release-deployment.md)
- [多HAP使用规则](multi-hap-rules.md)
- [多HAP运行机制及数据通信方式](multi-hap-principles.md)
- [应用程序包安装和卸载流程](application-package-install-uninstall.md)
- 应用配置文件(Stage模型)
- [应用配置文件概述(Stage模型)](application-configuration-file-overview-stage.md)
- [app.json5配置文件](app-configuration-file.md)
- [module.json5配置文件](module-configuration-file.md)
- 应用配置文件(FA模型)
- [应用配置文件概述(FA模型)](application-configuration-file-overview-fa.md)
- [app对象内部结构](app-structure.md)
- [deviceConfig内部结构](deviceconfig-structure.md)
- [module对象内部结构](module-structure.md)
- [资源分类与访问](resource-categories-and-access.md) - [资源分类与访问](resource-categories-and-access.md)
- 学习ArkTS语言 - 学习ArkTS语言
- [初识ArkTS语言](arkts-get-started.md) - [初识ArkTS语言](arkts-get-started.md)
- ArkTS语法(声明式UI) - ArkTS语法(声明式UI)
- [基本UI描述](arkts-basic-ui-description.md) - [基本UI描述](arkts-basic-ui-description.md)
......
# app.json5配置文件
先通过一个示例,整体认识一下app.json5配置文件。
```json
{
"app": {
"bundleName": "com.application.myapplication",
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:app_icon",
"label": "$string:app_name",
"description": "$string:description_application",
"distributedNotificationEnabled": true,
"minAPIVersion": 9,
"targetAPIVersion": 9,
"apiReleaseType": "Release",
"debug": false,
"entityType": "media",
"car": {
"minAPIVersion": 8,
}
},
}
```
app.json5配置文件包含以下标签。
**表1** **app.json5文件配置标签说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| bundleName | 标识应用的包名,用于标识应用的唯一性。该标签不可缺省。标签的值命名规则&nbsp;<br/>-&nbsp;字符串以字母、数字、下划线和符号“.”组成。<br/>-&nbsp;以字母开头。<br/>-&nbsp;最小长度7个字节,最大长度127个字节。<br/>推荐采用反域名形式命名(如com.example.demo,建议第一级为域名后缀com,第二级为厂商/个人名,第三级为应用名,也可以多级)。<br/>其中,随系统源码编译的应用建议命名为“com.ohos.demo”形式,&nbsp;ohos标识OpenHarmony系统应用。 | 字符串 | 该标签不可缺省。 |
| debug | 标识应用是否可调试,该标签由IDE编译构建时生成。<br/>-&nbsp;true:可调试。<br/>-&nbsp;false:不可调式。 | 布尔值 | 该标签可以缺省,缺省为false。 |
| icon | 标识[应用的图标](../application-models/application-component-configuration-stage.md),标签值为图标资源文件的索引。 | 字符串 | 该标签不可缺省。 |
| label | 标识[应用的名称](../application-models/application-component-configuration-stage.md),标签值为字符串资源的索引。 | 字符串 | 该标签不可缺省。 |
| description | 标识应用的描述信息,标签值是字符串类型(最大255个字节)或对描述内容的字符串资源索引。 | 字符串 | 该标签可缺省,缺省值为空。 |
| vendor | 标识对应用开发厂商的描述。该标签的值是字符串类型(最大255个字节)。 | 字符串 | 该标签可以缺省,缺省为空。 |
| versionCode | 标识应用的版本号,该标签值为32位非负整数。此数字仅用于确定某个版本是否比另一个版本更新,数值越大表示版本越高。开发者可以将该值设置为任何正整数,但是必须确保应用的新版本都使用比旧版本更大的值。该标签不可缺省,versionCode值应小于2^31次方。 | 数值 | 该标签不可缺省。 |
| versionName | 标识应用版本号的文字描述,用于向用户展示。<br/>该标签仅由数字和点构成,推荐采用“A.B.C.D”四段式的形式。四段式推荐的含义如下所示。<br/>第一段:主版本号/Major,范围0-99,重大修改的版本,如实现新的大功能或重大变化。<br/>第二段:次版本号/Minor,范围0-99,表示实现较突出的特点,如新功能添加或大问题修复。<br/>第三段:特性版本号/Feature,范围0-99,标识规划的新版本特性。<br/>第四段:修订版本号/Patch,范围0-999,表示维护版本,修复bug。<br/>标签最大字节长度为127。 | 字符串 | 该标签不可缺省。 |
| minCompatibleVersionCode | 标识应用能够兼容的最低历史版本号,用于跨设备兼容性判断。 | 数值 | 该标签可缺省,缺省值等于versionCode标签值。 |
| minAPIVersion | 标识应用运行需要的SDK的API最小版本。 | 数值 | 由bundle-profile.json5中的compatibleSdkVersion生成。 |
| targetAPIVersion | 标识应用运行需要的API目标版本。 | 数值 | 由bundle-profile.json5中的compileSdkVersion生成。 |
| apiReleaseType | 标识应用运行需要的API目标版本的类型,采用字符串类型表示。取值为“CanaryN”、“BetaN”或者“Release”,其中,N代表大于零的整数。<br/>-&nbsp;Canary:受限发布的版本。<br/>-&nbsp;Beta:公开发布的Beta版本。<br/>-&nbsp;Release:公开发布的正式版本。<br/>该字段由DevEco&nbsp;Studio读取当前使用的SDK的Stage来生成。 | 字符串 | 该标签可缺省,由IDE生成并覆盖。 |
| distributedNotificationEnabled | 标识应用是否开启分布式通知,当开启分布式通知时,同一分布式组网下的两个设备(A和B),当设备A收到一条消息时,设备B会收到一天分布式消息用于设备B的使用者去查看设备A的消息。<br/>-&nbsp;true:开启。<br/>-&nbsp;false:不开启。 | 布尔值 | 该标签可缺省,缺省值为false。 |
| entityType | 标识应用的类别,分别有:<br/>-&nbsp;game:游戏类。<br/>-&nbsp;media:影音类。<br/>-&nbsp;communication:社交通信类。<br/>-&nbsp;news:新闻类。<br/>-&nbsp;travel:出行类。<br/>-&nbsp;utility:工具类。<br/>-&nbsp;shopping:购物类。<br/>-&nbsp;education:教育类。<br/>-&nbsp;kids:少儿类。<br/>-&nbsp;business:商务类。<br/>-&nbsp;photography:拍摄类。<br/>-&nbsp;unspecified:不属于上述的任何一类。 | 字符串 | 该标签可以缺省,缺省为unspecified。 |
| multiProjects | 标识当前工程是否支持多个工程的联合开发。<br/>-&nbsp;true:当前工程支持多个工程的联合开发。<br/>-&nbsp;false:当前工程不支持多个工程的联合开发。 | 布尔值 | 可缺省,缺省值为false。 |
| tablet | 标识对tablet设备做的特殊配置,可以配置的属性字段有上文提到的:minAPIVersion、distributedNotificationEnabled。<br/>如果使用该属性对tablet设备做了特殊配置,则应用在tablet设备中会采用此处配置的属性值,并忽略在app.json5公共区域配置的属性值。 | 对象 | 该标签可缺省,缺省时tablet设备使用app.json5公共区域配置的属性值。 |
| tv | 标识对tv设备做的特殊配置,可以配置的属性字段有上文提到的:minAPIVersion、distributedNotificationEnabled。<br/>如果使用该属性对tv设备做了特殊配置,则应用在tv设备中会采用此处配置的属性值,并忽略在app.json5公共区域配置的属性值。 | 对象 | 该标签可缺省,缺省时tv设备使用app.json5公共区域配置的属性值。 |
| wearable | 标识对wearable设备做的特殊配置,可以配置的属性字段有上文提到的:minAPIVersion、distributedNotificationEnabled。<br/>如果使用该属性对wearable设备做了特殊配置,则应用在wearable设备中会采用此处配置的属性值,并忽略在app.json5公共区域配置的属性值。 | 对象 | 该标签可缺省,缺省时wearable设备使用app.json5公共区域配置的属性值。 |
| car | 标识对car设备做的特殊配置,可以配置的属性字段有上文提到的:minAPIVersion、distributedNotificationEnabled。<br/>如果使用该属性对car设备做了特殊配置,则应用在car设备中会采用此处配置的属性值,并忽略在app.json5公共区域配置的属性值。 | 对象 | 该标签可缺省,缺省时car设备使用app.json5公共区域配置的属性值。 |
| default | 标识对default设备做的特殊配置,可以配置的属性字段有上文提到的:minAPIVersion、distributedNotificationEnabled。<br/>如果使用该属性对default设备做了特殊配置,则应用在default设备中会采用此处配置的属性值,并忽略在app.json5公共区域配置的属性值。 | 对象 | 该标签可缺省,缺省时default设备使用app.json5公共区域配置的属性值。 |
# app对象内部结构
app对象包含应用全局配置信息,内部结构如下:
### **表1** **app对象内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| bundleName | 标识应用的包名,用于标识应用的唯一性。包名是由字母、数字、下划线(_)和点号(.)组成的字符串,必须以字母开头。支持的字符串长度为7~127字节。包名通常采用反向域名形式表示(例如,"com.example.myapplication")。建议第一级为域名后缀"com",第二级为厂商/个人名,也可以采用多级。 | 字符串 | 不可缺省。 |
| vendor | 标识对应用开发厂商的描述。字符串长度不超过255字节。 | 字符串 | 可缺省,缺省值为空。 |
|version | 标识应用的版本信息。 | 对象 | 不可缺省。 |
| apiVersion | 标识应用程序所依赖的OpenHarmony&nbsp;API版本。 | 对象 | 可缺省,缺省值为空。 |
| smartWindowSize | 标识应用在模拟器中运行时使用的屏幕尺寸。 | 字符串 | 可缺省,缺省值为空。 |
| smartWindowDeviceType | 标识应用在模拟器中运行时可以模拟的设备。 | 字符串数组 | 可缺省,缺省值为空。 |
#### **表2** **version对象内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 标识应用的版本号,用于向应用的终端用户呈现。取值可以自定义,长度不超过127字节。自定义规则如下:API5及更早的版本:推荐使用三段数字版本号(也兼容两段式版本号),如A.B.C(也兼容A.B),其中A、B、C取值为0-999范围内的整数。除此之外不支持其他格式。<br/>A段,一般表示主版本号(Major)。<br/>B段,一般表示次版本号(Minor)。<br/>C段,一般表示修订版本号(Patch)。API6版本起:推荐采用四段式数字版本号,如A.B.C.D,其中A、B、C取值为0-99范围内的整数,D的取值为0-999范围内的整数。<br/>A段,一般表示主版本号(Major)。<br/>B段,一般表示次版本号(Minor)。<br/>C段,一般表示特性版本号(Feature)。<br/>D段,一般表示修订版本号(Patch)。 | 数值 | 不可缺省。 |
| code | 标识应用的版本号,仅用于OpenHarmony管理该应用,不对应用的终端用户呈现。取值规则如下:API5及更早版本:二进制32位以内的非负整数,需要从version.name的值转换得到。转换规则为:code值=A&nbsp;\*&nbsp;1,000,000&nbsp;+&nbsp;B&nbsp;\*&nbsp;1,000&nbsp;+&nbsp;C例如,version.name字段取值为2.2.1,则code值为2002001。API6版本起:code的取值不与version.name字段的取值关联,开发者可自定义code取值,取值范围为2^31以内的非负整数,但是每次应用版本的更新,均需要更新code字段的值,新版本code取值必须大于旧版本code的值。 | 数值 | 不可缺省。 |
| minCompatibleVersionCode | 标识应用可兼容的最低版本号,用于跨设备场景下,判断其他设备上该应用的版本是否兼容。格式与version.code字段的格式要求相同。 | 数值 | 可缺省,缺省值为code标签值。 |
#### **表3** **apiVersion内部结构**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| compatible | 运行应用所需要的最低API版本,取值范围为0~2147483647。 | 数值 | 配置在build.profile中,打包时由IDE填充到config.json中。 |
| target | 用于标识应用运行时使用的API版本,取值范围为0~2147483647。 | 数值 | 配置在build.profile中,打包时由IDE填充到config.json中。 |
| releaseType | 用于标识应用运行时SDK的状态。<br/>canary:面向特定开发者早期预览版本,不承诺质量,不承诺API稳定。<br/>beta:公开发布的Beta版本,早期Beta版本不承诺API稳定,经历若干次发布后,通过Release&nbsp;Notes对开发者声明该Beta版本为API稳定里程碑,后续版本的API冻结。<br/>release:正式发布版本,承诺质量,API不可变更。当版本处于此状态时版本号中不呈现Stage字段。 | 字符串 | 配置在build.profile中,打包时由IDE填充到config.json中。 |
### app对象示例
```json
"app": {
"bundleName": "com.example.myapplication",
"vendor": "example",
"version": {
"code": 8,
"name": "8.0.1"
},
"apiVersion": {
"compatible": 8,
"target": 9,
"releaseType": "Beta1"
}
}
```
# 应用配置文件概述(FA模型)
每个应用项目必须在项目的代码目录下加入配置文件,这些配置文件会向OpenHarmony的编译工具、OpenHarmony操作系统和应用市场提供描述应用的基本信息。
应用配置文件需申明以下内容:
- 应用的软件包名称,应用的开发厂商,版本号等应用的基本配置信息,这些信息被要求设置在app这个字段下。
- 应用的组件的基本信息,包括所有的Ability,设备类型,组件的类型以及当前组件所使用的语法类型。
- 应用在具体设备上的配置信息,这些信息会影响应用在设备上的具体功能。
在FA模型的应用开发过程中,需要在config.json配置文件中对应用的包结构进行声明。
## 配置文件的内部结构
config.json由app、deviceConfig和module三个部分组成,缺一不可。
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| [app](app-structure.md) | 标识应用的全局配置信息。同一个应用的不同HAP的app配置必须保持一致。 | 对象 | 不可缺省。 |
| [deviceConfig](deviceconfig-structure.md) | 标识应用在具体设备上的配置信息。 | 对象 | 不可缺省。 |
| [module](module-structure.md) | 标识HAP的配置信息。该标签下的配置只对当前HAP生效。 | 对象 | 不可缺省。 |
config.json示例:
```json
{
"app": {
"vendor": "example",
"bundleName": "com.example.demo",
"version": {
"code": 1000000,
"name": "1.0.0"
}
},
"deviceConfig": {
},
"module": {
"mainAbility": ".MainAbility_entry",
"deviceType": [
"tablet"
],
"commonEvents": [
{
"name": ".MainAbility",
"permission": "ohos.permission.GET_BUNDLE_INFO",
"data": [
"com.example.demo",
"100"
],
"events": [
"install",
"update"
]
}
],
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"orientation": "unspecified",
"visible": true,
"srcPath": "MainAbility_entry",
"name": ".MainAbility_entry",
"srcLanguage": "ets",
"icon": "$media:icon",
// $string:MainAbility_entry_desc为资源索引
"description": "$string:MainAbility_entry_desc",
"formsEnabled": false,
// $string:MainAbility_entry_label为资源索引
"label": "$string:MainAbility_entry_label",
"type": "page",
"launchType": "standard"
}
],
"distro": {
"moduleType": "entry",
"installationFree": false,
"deliveryWithInstall": true,
"moduleName": "myapplication"
},
"package": "com.example.myapplication",
"srcPath": "",
"name": ".myapplication",
"js": [
{
"mode": {
"syntax": "ets",
"type": "pageAbility"
},
"pages": [
"pages/index"
],
"name": ".MainAbility_entry",
"window": {
"designWidth": 720,
"autoDesignWidth": false
}
}
]
}
}
```
# 应用配置文件概述(Stage模型)
每个应用项目必须在项目的代码目录下加入配置文件,这些配置文件会向编译工具、操作系统和应用市场提供应用的基本信息。
在基于Stage模型开发的应用项目代码下,都存在一个app.json5及一个或多个module.json5这两种配置文件。
[app.json5](app-configuration-file.md)主要包含以下内容:
- 应用的全局配置信息,包含应用的包名、开发厂商、版本号等基本信息。
- 特定设备类型的配置信息。
[module.json5](module-configuration-file.md)主要包含以下内容:
- Module的基本配置信息,例如Module名称、类型、描述、支持的设备类型等基本信息。
- [应用组件](../application-models/stage-model-development-overview.md)信息,包含UIAbility组件和ExtensionAbility组件的描述信息。
- 应用运行过程中所需的权限信息。
# 应用程序包安装和卸载流程
OpenHarmony包管理服务模块对外提供安装、更新和卸载应用的功能,开发者可以调用包管理服务的安装和卸载接口来实现应用的安装、更新和卸载。开发者将应用上架应用市场后,用户可以在端侧设备上进行应用的安装和卸载。
**图1** 应用程序包安装和卸载流程  
![hap-intall-uninstall](figures/hap-intall-uninstall.png)
# 应用程序包概述
用户应用程序泛指运行在设备的操作系统之上,为用户提供特定服务的程序,简称“应用”。一个应用所对应的软件包文件,称为“应用程序包”。
OpenHarmony提供了应用程序包开发、安装、查询、更新、卸载的管理机制,方便开发者开发和管理OpenHarmony应用,具体如下:
- 应用软件所涉及的文件多种多样,开发者可通过OpenHarmony提供的集成开发工具将其开发的可执行代码、资源、三方库等文件整合到一起制作成OpenHarmony应用程序包,便于开发者对应用程序的部署。
- 应用软件所涉及的设备类型多种多样,开发者可通过OpenHarmony提供的应用程序包配置文件指定其应用程序包的分发设备类型,便于应用市场对应用程序包的分发管理。
- 应用软件所包含的功能多种多样,将不同的功能特性按模块来划分和管理是一种良好的设计方式。OpenHarmony提供了同一应用程序的多包管理的机制,开发者可以将不同的功能特性聚合到不同的包中,方便后续的维护与扩展。
- 应用软件涉及的芯片平台多种多样,有x86、ARM等,还有32位、64位之分,OpenHarmony为应用程序包屏蔽了芯片平台的差异,使应用程序包在不同的芯片平台都能够安装运行。
- 应用软件涉及的软件信息多种多样,有应用版本、应用名称、组件、申请权限等的信息,OpenHarmony包管理为开发者提供了这些信息的查询接口,方便开发者在程序中查询所需要的包信息。
- 应用软件涉及的资源多种多样,有媒体资源、原生资源、字符资源以及国际化的资源等,OpenHarmony包管理将不同的资源归档到不同的目录中,并集成资源索引文件,方便应用对资源的查找和使用。
# FA模型应用程序包结构
基于[FA模型](application-configuration-file-overview-fa.md)开发的应用,其应用程序包结构如图[应用程序包结构(FA模型)](figures/FA_3.png)所示。开发者需要熟悉应用程序包结构相关的基本概念。
FA模型与Stage模型不同之处在于HAP内部文件存放位置不同,FA模型将所有的资源文件、库文件和代码文件都放在assets文件夹中,在文件夹内部进一步区分。
- config.json是应用配置文件,IDE会自动生成一部分模块代码,开发者按需修改其中的配置。详细字段请参见[应用配置文件](app-structure.md)
- assets是HAP所有的资源文件、库文件和代码文件的集合,内部可以分为entry和js文件夹。entry文件夹中存放的是resources目录和resources.index文件。
- resources目录用于存放应用的资源文件(字符串、图片等),便于开发者使用和维护,详见[资源文件的使用](../key-features/multi-device-app-dev/resource-usage.md/)
- resources.index是资源索引表,由IDE调用SDK工具生成。
- js文件夹中存放的是编译后的代码文件。
- pack.info是Bundle中用于描述每个HAP属性的文件,例如app中的bundleName和versionCode信息、module中的name、type和abilities等信息,由IDE工具生成Bundle包时自动生成。
**图1** 应用程序包结构(FA模型)  
![FA_3](figures/FA_3.png)
# Stage模型应用程序包结构
基于[Stage模型](application-configuration-file-overview-stage.md)开发的应用,经编译打包后,其应用程序包结构如图[应用程序包结构(Stage模型)](figures/Stage-.png)所示。开发者需要熟悉应用程序包结构相关的基本概念。
- 在开发态,一个应用包含一个或者多个Module,可以在[DevEco Studio](https://developer.harmonyos.com/cn/develop/deveco-studio/)工程中[创建一个或者多个Module](https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/ohos-adding-deleting-module-0000001218760594-V3)。Module是OpenHarmony应用/服务的基本功能单元,包含了源代码、资源文件、第三方库及应用/服务配置文件,每一个Module都可以独立进行编译和运行。Module分为“Ability”和“Library”两种类型,“Ability”类型的Module对应于编译后的HAP(Harmony Ability Package);“Library”类型的Module对应于[HAR](har-structure.md)(Harmony Ability Resources)包,即编译后的.tgz文件。
一个Module可以包含一个或多个[UIAbility](../application-models/uiability-overview.md)组件,如[Module与UIAbility组件关系示意图](figures/ability-and-module.png)所示。
**图1** Module与UIAbility组件关系示意图  
![ability-and-module](figures/ability-and-module.png)
全文中介绍到的Module默认指的是“Ability”类型的Module。
- 开发者通过DevEco Studio把应用程序编译为一个或者多个.hap后缀的文件,即HAP。HAP是OpenHarmony应用安装的基本单位,包含了编译后的代码、资源、三方库及配置文件。HAP可分为Entry和Feature两种类型。
- Entry类型的HAP:是应用的主模块,在[module.json5配置文件](module-configuration-file.md)中的type标签配置为“entry”类型。在同一个应用中,同一设备类型只支持一个Entry类型的HAP,通常用于实现应用的入口界面、入口图标、主特性功能等。
- Feature类型的HAP:是应用的动态特性模块,在[module.json5配置文件](module-configuration-file.md)中的type标签配置为“feature”类型。一个应用程序包可以包含一个或多个Feature类型的HAP,也可以不包含;Feature类型的HAP通常用于实现应用的特性功能,可以配置成按需下载安装,也可以配置成随Entry类型的HAP一起下载安装(请参见[module对象内部结构](module-configuration-file.md)中的“deliveryWithInstall”)。
- 每个OpenHarmony应用可以包含多个.hap文件,一个应用中的.hap文件合在一起称为一个Bundle,而bundleName就是应用的唯一标识(请参见[app.json5配置文件](app-configuration-file.md)中的bundleName标签)。需要特别说明的是:在应用上架到应用市场时,需要把应用包含的所有.hap文件(即Bundle)打包为一个.app后缀的文件用于上架,这个.app文件称为App Pack(Application Package),其中同时包含了描述App Pack属性的pack.info文件;在云端分发和端侧安装时,都是以HAP为单位进行分发和安装的。
- 打包后的HAP包结构包括ets、libs、resources等文件夹和resources.index、module.json、pack.info等文件。
- ets目录用于存放应用代码编译后的字节码文件。
- libs目录用于存放库文件。库文件是OpenHarmony应用依赖的第三方代码(例如.so、.jar、.bin、.har等二进制文件)。
- resources目录用于存放应用的资源文件(字符串、图片等),便于开发者使用和维护,详见[资源文件的使用](../key-features/multi-device-app-dev/resource-usage.md/)
- resources.index是资源索引表,由IDE编译工程时生成。
- module.json是HAP的配置文件,内容由工程配置中的module.json5和app.json5组成,该文件是HAP中必不可少的文件。IDE会自动生成一部分默认配置,开发者按需修改其中的配置。详细字段请参见[应用配置文件](application-configuration-file-overview-stage.md)
- pack.info是Bundle中用于描述每个HAP属性的文件,例如app中的bundleName和versionCode信息、module中的name、type和abilities等信息,由IDE工具生成Bundle包时自动生成。
**图2** 应用程序包结构(Stage模型)  
![Stage-](figures/Stage-.png)
# deviceConfig内部结构
deviceConfig包含设备上的应用配置信息,可以包含default,tv,car,wearable等属性。default标签内的配置适用于所有通用设备,其他设备类型如果有特殊的需求,则需要在该设备类型的标签下进行配置。
### **表1** **deviceConfig对象内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| default | 能够使用全部系统能力的OpenHarmony设备。 | 对象 | 可缺省,缺省值为空。 |
| tablet | 标识平板的应用配置信息。 | 对象 | 可缺省,缺省值为空。 |
| tv | 标识智慧屏特有的应用配置信息。 | 对象 | 可缺省,缺省值为空。 |
| car | 标识车机特有的应用配置信息。 | 对象 | 可缺省,缺省值为空。 |
| wearable | 标识智能穿戴特有的应用配置信息。 | 对象 | 可缺省,缺省值为空。 |
上表中各类设备对象的内部结构说明请见表2。
#### **表2** **deviceConfig设备对象内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| process | 标识应用或者Ability的进程名。如果在deviceConfig标签下配置了process标签,则该应用的所有Ability都运行在这个进程中。如果在abilities标签下也为某个Ability配置了process标签,则该Ability就运行在这个进程中。该标签最大长度为31。 | 字符串 | 可缺省,缺省值为空。 |
| keepAlive | 标识应用是否始终保持运行状态,仅支持系统应用配置,三方应用配置不生效。该标签为布尔类型,可缺省,缺省值为false,如果配置为true,应用将始终保持为运行状态,并在系统启动的时候被系统驱动起来,应用进程退出后,系统也会重新启动应用进程。 | 布尔值 | 可缺省,缺省值为false。 |
| supportBackup | 标识应用是否支持备份和恢复。如果配置为"false",则不支持为该应用执行备份或恢复操作。 | 布尔值 | 可缺省,缺省值为false。 |
| compressNativeLibs | 标识libs库是否以压缩存储的方式打包到HAP。如果配置为"false",则libs库以不压缩的方式存储,HAP在安装时无需解压libs,运行时会直接从HAP内加载libs库。 | 布尔值 | 可缺省,缺省值为false。 |
| network | 标识网络安全性配置。该标签允许应用通过配置文件的安全声明来自定义其网络安全,无需修改应用代码。 | 对象 | 可缺省,缺省值为空。 |
#### **表3** **network对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| cleartextTraffic | 标识是否允许应用使用明文网络流量(例如,明文HTTP)。<br/>true:允许应用使用明文流量的请求。false:拒绝应用使用明文流量的请求。 | 布尔值 | 可缺省,缺省值为false。 |
| securityConfig | 标识应用的网络安全配置信息。 | 对象 | 可缺省,缺省为空。 |
#### **表4** **securityConfig对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| domainSettings | 标识自定义的网域范围的安全配置,支持多层嵌套,即一个domainSettings对象中允许嵌套更小网域范围的domainSettings对象。 | 对象类型 | 可缺省,缺省为空。 |
#### **表5** **domainSettings对象内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| cleartextPermitted | 标识自定义的网域范围内是否允许明文流量传输。当cleartextTraffic和security同时存在时,自定义网域是否允许明文流量传输以cleartextPermitted的取值为准。true:允许明文流量传输。false:拒绝明文流量传输。 | 布尔类型 | 可缺省,缺省值为空。 |
| domains | 标识域名配置信息,包含两个参数:subdomains和name。subdomains(布尔类型):表示是否包含子域名。如果为"true",此网域规则将与相应网域及所有子网域(包括子网域的子网域)匹配。否则,该规则仅适用于精确匹配项。name(字符串):表示域名名称。 | 对象数组 | 可缺省,缺省值为空。 |
### deviceConfig示例
```json
"deviceConfig": {
"default": {
"process": "com.example.test.example",
"supportBackup": false,
"network": {
"cleartextTraffic": true,
"securityConfig": {
"domainSettings": {
"cleartextPermitted": true,
"domains": [
{
"subdomains": true,
"name": "example.ohos.com"
}
]
}
}
}
}
}
```
...@@ -60,7 +60,7 @@ full-SDK需要手动下载。请参考[版本说明书](../../release-notes/Open ...@@ -60,7 +60,7 @@ full-SDK需要手动下载。请参考[版本说明书](../../release-notes/Open
`oh-uni-package.json`文件配置信息如下,其中,`apiVersion`的值以SDK对应的API version为准,`version`的值以SDK文件的版本号为准: `oh-uni-package.json`文件配置信息如下,其中,`apiVersion`的值以SDK对应的API version为准,`version`的值以SDK文件的版本号为准:
``` ```json
{ {
"apiVersion": "X", "apiVersion": "X",
"displayName": "Ets", "displayName": "Ets",
......
# HAR包结构
HAR(Harmony Ability Resources)包用于实现多个模块或多个工程间的代码共享。HAR包不同于HAP,不能独立安装运行在设备上,只能作为应用模块的依赖项被引用。
HAR包对应DevEco Studio工程中的“Library”类型的[Module](https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/ohos-adding-deleting-module-0000001218760594-V3)
OpenHarmony的HAR包复用标准的[npm包](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-development-npm-package-0000001222578434)发布方式,会打包成tar包(后缀为.tgz)。打包后的HAR包中包含源代码、资源文件、module.json文件(Stage模型)或config.json文件(FA模型)等。
# module.json5配置文件
先通过一个示例,整体认识一下module.json5配置文件。
```json
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"default",
"tablet"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"virtualMachine": "ark",
"metadata": [
{
"name": "string",
"value": "string",
"resource": "$profile:distrofilter_config"
}
],
"abilities": [
{
"name": "EntryAbility",
"srcEntrance": "./ets/entryability/EntryAbility.ts",
"description": "$string:EntryAbility_desc",
"icon": "$media:icon",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:start_window_background",
"visible": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
]
}
],
"requestPermissions": [
{
"name": "ohos.abilitydemo.permission.PROVIDER",
"reason": "$string:reason",
"usedScene": {
"abilities": [
"FormAbility"
],
"when": "inuse"
}
}
]
}
}
```
module.json5配置文件包含以下标签。
**表1** **module.json5配置文件配置标签说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 标识当前Module的名称,标签值采用字符串表示(最大长度31个字节),该名称在整个应用要唯一。 | 字符串 | 该标签不可缺省。 |
| type | 标识当前Module的类型。类型有两种,分别:<br/>-&nbsp;entry:应用的主模块。<br/>-&nbsp;feature:应用的动态特性模块。 | 字符串 | 该标签不可缺省。 |
| srcEntrance | 标识当前Module所对应的代码路径,标签值为字符串(最长为127字节)。 | 字符串 | 该标签可缺省,缺省值为空。 |
| description | 标识当前Module的描述信息,标签值是字符串类型(最长255字节)或对描述内容的字符串资源索引。 | 字符串 | 该标签可缺省,缺省值为空。 |
| process | 标识当前Module的进程名,标签值为字符串类型(最长为31个字节)。如果在HAP标签下配置了process,该应用的所有UIAbility、DataShareExtensionAbility、ServiceExtensionAbility都运行在该进程中。<br/>**说明:**<br/>- 仅支持系统应用配置,三方应用配置不生效。 | 字符串 | 可缺省,缺省为app.json5文件下app标签下的bundleName。 |
| mainElement | 标识当前Module的入口UIAbility名称或者ExtensionAbility名称。标签最大字节长度为255。 | 字符串 | 该标签可缺省,缺省值为空。 |
| [deviceTypes](#devicetypes标签) | 标识当前Module可以运行在哪类设备上,标签值采用字符串数组的表示。 | 字符串数组 | 该标签不可缺省,可以为空值。 |
| deliveryWithInstall | 标识当前Module是否在用户主动安装的时候安装,表示该Module对应的HAP是否跟随应用一起安装。<br/>-&nbsp;true:主动安装时安装。<br/>-&nbsp;false:主动安装时不安装。 | 布尔值 | 该标签不可缺省。 |
| installationFree | 标识当前Module是否支持免安装特性。<br/>-&nbsp;true:表示支持免安装特性,且符合免安装约束。<br/>-&nbsp;false:表示不支持免安装特性。<br/>**说明:**<br/>- 当应用的entry类型Module的该字段配置为true时,该应用的feature类型的该字段也需要配置为true。<br/>- 当应用的entry类型Module的该字段配置为false时,该应用的feature类型的该字段根据业务需求配置true或false。 | 布尔值 | 该标签不可缺省。 |
| virtualMachine | 标识当前Module运行的目标虚拟机类型,供云端分发使用,如应用市场和分发中心。<br/>该标签值为字符串。如果目标虚拟机类型为ArkTS引擎,则其值为“ark+版本号”。 | 字符串 | 该标签由IDE构建HAP的时候自动插入。 |
| uiSyntax(deprecated) | 标识当前Module&nbsp;syntax定义该JS&nbsp;Component的语法类型。<br/>-&nbsp;hml:标识该JS&nbsp;Component使用hml/css/js进行开发。<br/>-&nbsp;ets:标识该JS&nbsp;Component使用ArkTS声明式语法进行开发。 | 字符串 | 该标签可缺省,默认值为hml,该标签从API9开始废弃。 |
| [pages](#pages标签) | 标识当前Module的profile资源,用于列举JS&nbsp;Component中每个页面信息。该标签最大长度为255个字节。 | 字符串 | 在有UIAbility的场景下,该标签不可缺省。 |
| [metadata](#metadata标签) | 标识当前Module的自定义元信息,标签值为数组类型,只对当前Module、UIAbility、ExtensionAbility生效。 | 对象数组 | 该标签可缺省,缺省值为空。 |
| [abilities](#abilities标签) | 标识当前Module中UIAbility的配置信息,标签值为数组类型,只对当前UIAbility生效。 | 对象 | 该标签可缺省,缺省值为空。 |
| [extensionAbilities](#extensionabilities标签) | 标识当前Module中ExtensionAbility的配置信息,标签值为数组类型,只对当前ExtensionAbility生效。 | 对象 | 该标签可缺省,缺省值为空。 |
| [requestPermissions](#requestpermissions标签) | 标识当前应用运行时需向系统申请的权限集合。 | 对象 | 该标签可缺省,缺省值为空。 |
| [testRunner](#testrunner标签) | 标识当前Module用于支持对测试框架的配置。 | 对象 | 该标签可缺省,缺省值为空。 |
## deviceTypes标签
**表2** deviceType标签配置说明
| 设备类型 | 枚举值 | 说明 |
| -------- | -------- | -------- |
| 平板 | tablet | - |
| 智慧屏 | tv | - |
| 智能手表 | wearable | 系统能力较丰富的手表,具备电话功能。 |
| 车机 | car | - |
| 默认设备 | default | 能够使用全部系统能力的OpenHarmony设备。 |
deviceTypes示例:
```json
{
"module": {
"name": "myHapName",
"type": "feature",
"deviceTypes" : [
"tablet"
]
}
}
```
## pages标签
该标签是一个profile文件资源,用于指定描述页面信息的配置文件。
```json
{
"module": {
// ...
"pages": "$profile:main_pages", // 通过profile下的资源文件配置
}
}
```
在开发视图的resources/base/profile下面定义配置文件**main_pages**.json,其中文件名(**main_pages**)可自定义,需要和前文中pages标签指定的信息对应,配置文件中列举了当前应用组件中的页面信息。
```json
{
"src": [
"pages/index/mainPage",
"pages/second/payment",
"pages/third/shopping_cart",
"pages/four/owner"
]
}
```
## metadata标签
该标签标识HAP的自定义元信息,标签值为数组类型,包含name,value,resource三个子标签。
**表3** **metadata标签说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 该标签标识数据项的键名称,字符串类型(最大长度255字节)。 | 字符串 | 该标签可缺省,缺省值为空。 |
| value | 该标签标识数据项的值,标签值为字符串(最大长度255字节)。 | 字符串 | 该标签可缺省,缺省值为空。 |
| resource | 该标签标识定义用户自定义数据格式,标签值为标识该数据的资源的索引值。该标签最大字节长度为255字节。 | 字符串 | 该标签可缺省,缺省值为空。 |
```json
{
"module": {
"metadata": [{
"name": "module_metadata",
"value": "a test demo for module metadata",
"resource": "$profile:shortcuts_config",
}],
"abilities": [{
"metadata": [{
"name": "ability_metadata",
"value": "a test demo for ability",
"resource": "$profile:config_file"
},
{
"name": "ability_metadata_2",
"value": "a string test",
"resource": "$profile:config_file"
}],
}],
"extensionAbilities": [{
"metadata": [{
"name": "extensionAbility_metadata",
"value": "a test for extensionAbility",
"resource": "$profile:config_file"
},
{
"name": "extensionAbility_metadata_2",
"value": "a string test",
"resource": "$profile:config_file"
}],
}]
}
}
```
## abilities标签
ablities标签描述UIAbility组件的配置信息,标签值为数组类型,该标签下的配置只对当前UIAbility生效。
**表4** **abilities标签说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 标识当前UIAbility组件的名称,该名称在整个应用要唯一,标签值采用字符串表示(最大长度127个字节)。 | 字符串 | 该标签不可缺省。 |
| srcEntrance | 该标签标识入口UIAbility的代码路径,标签值为字符串(最长为127字节)。 | 字符串 | 该标签不可缺省。 |
| [launchType](../application-models/uiability-launch-type.md) | 标识当前UIAbility组件的启动模式,可选标签值:<br/>-&nbsp;standard:标准实例模式,每次启动创建一个新的实例。<br/>-&nbsp;singleton:单实例模式,仅第一次启动创建新实例。<br/>-&nbsp;specified:指定实例模式,运行时由开发者决定是否创建新实例。 | 字符串 | 可缺省,该标签缺省为“singleton”。 |
| description | 标识当前UIAbility组件的描述信息,标签值是字符串类型(最长255字节)或对描述内容的资源索引,要求采用资源索引方式,以支持多语言。 | 字符串 | 该标签可缺省,缺省值为空。 |
| icon | 标识当前UIAbility组件的图标,标签值为图标资源文件的索引。 | 字符串 | 该标签可缺省,缺省值为空。<br/>如果UIAbility被配置为MainElement,该标签必须配置。 |
| label | 标识当前UIAbility组件对用户显示的名称,标签值配置为该名称的资源索引以支持多语言。<br/>如果UIAbility被配置当前Module的mainElement时,该标签必须配置,且应用内唯一。 | 字符串 | 该标签不可缺省。 |
| permissions | 标识当前UIAbility组件自定义的权限信息。当其他应用访问该UIAbility时,需要申请相应的权限信息。<br/>一个数组元素为一个权限名称。通常采用反向域名格式(最大255字节),取值为系统预定义的权限。 | 字符串数组 | 该标签可缺省,缺省值为空。 |
| [metadata](#metadata标签) | 标识当前UIAbility组件的元信息。 | 对象数组 | 该标签可缺省,缺省值为空。 |
| visible | 标识当前UIAbility组件是否可以被其他应用调用。<br/>-&nbsp;true:表示可以被其他应用调用。<br/>-&nbsp;false:表示不可以被其他应用调用。 | 布尔值 | 该标签可缺省,缺省值为false。 |
| continuable | 标识当前UIAbility组件是否可以[迁移](../application-models/hop-cross-device-migration.md)<br/>-&nbsp;true:表示可以被迁移。<br/>-&nbsp;false:表示不可以被迁移。 | 布尔值 | 该标签可缺省,缺省值为false。 |
| [skills](#skills标签) | 标识当前UIAbility组件或ExtensionAbility组件能够接收的[Want](../application-models/want-overview.md)的特征集,为数组格式。<br/>配置规则:<br/>-&nbsp;对于Entry类型的HAP,OpenHarmony应用可以配置多个具有入口能力的skills标签(即配置了action.system.home和entity.system.home)。<br/>-&nbsp;对于Feature类型的HAP,只有OpenHarmony应用可以配置具有入口能力的skills标签,OpenHarmony服务不允许配置。 | 对象数组 | 该标签可缺省,缺省值为空。 |
| backgroundModes | 标识当前UIAbility组件的长时任务集合。指定用于满足特定类型的长时任务。<br/>长时任务类型有如下:<br/>-&nbsp;dataTransfer:通过网络/对端设备进行数据下载、备份、分享、传输等业务。<br/>-&nbsp;audioPlayback:音频输出业务。<br/>-&nbsp;audioRecording:音频输入业务。<br/>-&nbsp;location:定位、导航业务。<br/>-&nbsp;bluetoothInteraction:蓝牙扫描、连接、传输业务(穿戴)。<br/>-&nbsp;multiDeviceConnection:多设备互联业务。<br/>-&nbsp;wifiInteraction:Wi-Fi扫描、连接、传输业务(克隆多屏)。<br/>-&nbsp;voip:音视频电话,VoIP业务。<br/>-&nbsp;taskKeeping:计算业务。 | 字符串数组 | 该标签可缺省,缺省值为空。 |
| startWindowIcon | 标识当前UIAbility组件启动页面图标资源文件的索引。取值示例:$media:icon。<br/>该标签最大字节长度为255。 | 字符串 | 不可缺省。 |
| startWindowBackground | 标识当前UIAbility组件启动页面背景颜色资源文件的索引。取值示例:$color:red。<br/>改标签最大字节长度为255。 | 字符串 | 不可缺省。 |
| removeMissionAfterTerminate | 标识当前UIAbility组件销毁后是否从任务列表中移除任务,为布尔类型:<br/>-&nbsp;true表示销毁后移除任务。<br/>-&nbsp;false表示销毁后不移除任务。 | 布尔值 | 该标签可缺省,缺省值为false。 |
| orientation | 标识当前UIAbility组件启动时的方向。该方向的取值范围包括:<br/>-&nbsp;unspecified:未指定方向,由系统自动判断显示方向。<br/>-&nbsp;landscape:横屏。<br/>-&nbsp;portrait:竖屏。<br/>-&nbsp;landscape_inverted:反向横屏。<br/>-&nbsp;portrait_inverted:反向竖屏。<br/>-&nbsp;auto_rotation:随传感器旋转。<br/>-&nbsp;auto_rotation_landscape:传感器横屏旋转,包括了横屏和反向横屏。<br/>-&nbsp;auto_rotation_portrait:传感器竖屏旋转,包括了竖屏和反向竖屏。<br/>-&nbsp;auto_rotation_restricted:传感器开关打开,方向可随传感器旋转。<br/>-&nbsp;auto_rotation_landscape_restricted:传感器开关打开,方向可随传感器旋转为横屏,&nbsp;包括了横屏和反向横屏。<br/>-&nbsp;auto_rotation_portrait_restricted:传感器开关打开,方向随可传感器旋转为竖屏,&nbsp;包括了横屏和反向横屏。<br/>-&nbsp;locked:传感器开关关闭,方向锁定。 | 字符串 | 该标签可缺省,缺省值为unspecified。 |
| supportWindowMode | 标识当前UIAbility组件所支持的窗口模式,包含:<br/>-&nbsp;fullscreen:全屏模式。<br/>-&nbsp;split:分屏模式。<br/>-&nbsp;floating:悬浮窗模式。 | 字符串数组 | 该标签可缺省,缺省值为<br/>["fullscreen",&nbsp;"split",&nbsp;"floating"]。 |
| priority | 标识当前UIAbility组件的优先级,仅支持系统应用配置,三方应用配置不生效。[隐式查询](../application-models/explicit-implicit-want-mappings.md)时,优先级越高,UIAbility在返回列表越靠前。该标签取值为integer类型,取值范围0-10。数值越大,优先级越高。 | 数值 | 该标签可缺省,缺省值为0。 |
| maxWindowRatio | 标识当前UIAbility组件支持的最大的宽高比。该标签最小取值为0。 | 数值 | 该标签可缺省,缺省值为平台支持的最大的宽高比。 |
| minWindowRatio | 标识当前UIAbility组件支持的最小的宽高比。该标签最小取值为0。 | 数值 | 该标签可缺省,缺省值为平台支持的最小的宽高比。 |
| maxWindowWidth | 标识当前UIAbility组件支持的最大的窗口宽度,宽度单位为vp。该标签最小取值为0。 | 数值 | 该标签可缺省,缺省值为平台支持的最大的窗口宽度。 |
| minWindowWidth | 标识当前UIAbility组件支持的最小的窗口宽度,&nbsp;宽度单位为vp。该标签最小取值为0。 | 数值 | 该标签可缺省,缺省值为平台支持的最小的窗口宽度。 |
| maxWindowHeight | 标识当前UIAbility组件支持的最大的窗口高度,&nbsp;高度单位为vp。该标签最小取值为0。 | 数值 | 该标签可缺省,缺省值为平台支持的最大的窗口高度。 |
| minWindowHeight | 标识当前UIAbility组件支持的最小的窗口高度,&nbsp;高度单位为vp。该标签最小取值为0。 | 数值 | 该标签可缺省,缺省值为平台支持的最小的窗口高度。 |
| excludeFromMissions | 标识当前UIAbility组件是否在最近任务列表中显示。<br/>-&nbsp;true:表示不在任务列表中显示。<br/>-&nbsp;false:表示在任务列表中显示。<br/>**说明:**<br/>- 仅支持系统应用配置,三方应用配置不生效。 | 布尔值 | 该标签可缺省,缺省值为false。 |
abilities示例:
```json
{
"abilities": [{
"name": "EntryAbility",
"srcEntrance": "./ets/entryability/EntryAbility.ts",
"launchType":"standard",
"description": "$string:description_main_ability",
"icon": "$media:icon",
"label": "Login",
"permissions": [],
"metadata": [],
"visible": true,
"continuable": true,
"skills": [{
"actions": ["action.system.home"],
"entities": ["entity.system.home"],
"uris": []
}],
"backgroundModes": [
"dataTransfer",
"audioPlayback",
"audioRecording",
"location",
"bluetoothInteraction",
"multiDeviceConnection",
"wifiInteraction",
"voip",
"taskKeeping"
],
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:red",
"removeMissionAfterTerminate": true,
"orientation": " ",
"supportWindowMode": ["fullscreen", "split", "floating"],
"maxWindowRatio": 3.5,
"minWindowRatio": 0.5,
"maxWindowWidth": 2560,
"minWindowWidth": 1400,
"maxWindowHeight": 300,
"minWindowHeight": 200,
"excludeFromMissions": false
}]
}
```
## skills标签
该标签标识UIAbility组件或者ExtensionAbility组件能够接收的[Want](../application-models/want-overview.md)的特征。
**表5** **skills标签说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| actions | 标识能够接收的Want的[Action值的集合](../application-models/actions-entities.md),取值通常为系统预定义的action值,也允许自定义。 | 字符串数组 | 可缺省,缺省值为空。 |
| entities | 标识能够接收Want的[Entity值的集合](../application-models/actions-entities.md)。 | 字符串数组 | 可缺省,缺省值为空。 |
|uris | 标识与Want中URI(Uniform&nbsp;Resource&nbsp;Identifier)相匹配的集合。 | 对象数组 | 可缺省,缺省值为空。 |
**表6** **uris对象内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| scheme | 标识URI的协议名部分,常见的有http、https、file、ftp等。 | 字符串 | uris中仅配置type时可以缺省,缺省值为空,否则不可缺省。 |
| host | 标识URI的主机地址部分,该字段要在schema存在时才有意义。常见的方式:<br/>-&nbsp;域名方式,如example.com。<br/>-&nbsp;IP地址方式,如10.10.10.1。 | 字符串 | 可缺省,缺省值为空。 |
| port | 标识URI的端口部分。如http默认端口为80,https默认端口是443,ftp默认端口是21。该字段要在schema和host都存在时才有意义。 | 字符串 | 可缺省,缺省值为空。 |
| path&nbsp;\|&nbsp;pathStartWith&nbsp;\|&nbsp;pathRegex | 标识URI的路径部分,path、pathStartWith和pathRegex配置时三选一。path标识URI与want中的路径部分全匹配,pathStartWith标识URI与want中的路径部分允许前缀匹配,pathRegex标识URI与want中的路径部分允许正则匹配。该字段要在schema和host都存在时才有意义。 | 字符串 | 可缺省,缺省值为空。 |
| type | 标识与Want相匹配的数据类型,使用[MIME](https://www.iana.org/assignments/media-types/media-types.xhtml?utm_source=ld246.com%E3%80%82)(Multipurpose&nbsp;Internet&nbsp;Mail&nbsp;Extensions)类型规范。可与schema同时配置,也可以单独配置。 | 字符串 | 可缺省,缺省值为空。 |
skills示例:
```json
{
"abilities": [
{
"skills": [
{
"actions": [
"action.system.home"
],
"entities": [
"entity.system.home"
],
"uris": [
{
"scheme":"http",
"host":"example.com",
"port":"80",
"path":"path",
"type": "text/*"
}
]
}
]
}
]
}
```
## extensionAbilities标签
描述extensionAbilities的配置信息,标签值为数组类型,该标签下的配置只对当前extensionAbilities生效。
**表7** **extensionAbilities标签说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 标识当前ExtensionAbility组件的名称,标签值最大长度为127个字节,该名称在整个应用要唯一。 | 字符串 | 该标签不可缺省。 |
| srcEntrance | 标识当前ExtensionAbility组件所对应的代码路径,标签值最大长度为127字节。 | 字符串 | 该标签不可缺省。 |
| description | 标识当前ExtensionAbility组件的描述,标签值最大长度为255字节,标签也可以是描述内容的资源索引,用于支持多语言。 | 字符串 | 该标签可缺省,缺省值为空。 |
| icon | 标识当前ExtensionAbility组件的图标,标签值为资源文件的索引。如果ExtensionAbility组件被配置为MainElement,该标签必须配置。 | 字符串 | 该标签可缺省,缺省值为空。 |
| label | 标识当前ExtensionAbility组件对用户显示的名称,标签值配置为该名称的资源索引以支持多语言。<br/>**说明:**<br/>- 如果ExtensionAbility被配置当前Module的mainElement时,该标签必须配置,且应用内唯一。 | 字符串 | 该标签不可缺省。 |
| type | 标识当前ExtensionAbility组件的类型,取值为:<br/>-&nbsp;form:卡片的ExtensionAbility。<br/>-&nbsp;workScheduler:延时任务的ExtensionAbility。<br/>-&nbsp;inputMethod:输入法的ExtensionAbility。<br/>-&nbsp;service:后台运行的service组件。<br/>-&nbsp;accessibility:辅助能力的ExtensionAbility。<br/>-&nbsp;dataShare:数据共享的ExtensionAbility。<br/>-&nbsp;fileShare:文件共享的ExtensionAbility。<br/>-&nbsp;staticSubscriber:静态广播的ExtensionAbility。<br/>-&nbsp;wallpaper:壁纸的ExtensionAbility。<br/>-&nbsp;backup:数据备份的ExtensionAbility。<br/>-&nbsp;window:该ExtensionAbility会在启动过程中创建一个window,为开发者提供界面开发。开发者开发出来的界面将通过abilityComponent控件组合到其他应用的窗口中。<br/>-&nbsp;thumbnail:获取文件缩略图的ExtensionAbility,开发者可以对自定义文件类型的文件提供缩略。<br/>-&nbsp;preview:该ExtensionAbility会将文件解析后在一个窗口中显示,开发者可以通过将此窗口组合到其他应用窗口中。<br/>**说明:**<br/>- 其中service和dataShare类型,仅支持系统应用配置,三方应用配置不生效。 | 字符串 | 该标签不可缺省。 |
| permissions | 标识当前ExtensionAbility组件自定义的权限信息。当其他应用访问该ExtensionAbility时,需要申请相应的权限信息。<br/>一个数组元素为一个权限名称。通常采用反向域名格式(最大255字节),可以是系统预定义的权限,也可以是该应用自定义的权限。如果是后者,需与defPermissions标签中定义的某个权限的name标签值一致。 | 字符串数组 | 该标签可缺省,缺省值为空。 |
| uri | 标识当前ExtensionAbility组件提供的数据URI,为字符数组类型(最大长度255),用反向域名的格式表示。<br/>**说明:**<br/>- 该标签在type为dataShare类型的ExtensionAbility时,不可缺省。 | 字符串 | 该标签可缺省,缺省值为空。 |
|skills | 标识当前ExtensionAbility组件能够接收的[Want](../application-models/want-overview.md)的特征集,为数组格式。<br/>配置规则:entry包可以配置多个具有入口能力的skills标签(配置了action.system.home和entity.system.home)的ExtensionAbility,其中第一个配置了skills标签的ExtensionAbility中的label和icon作为OpenHarmony服务或应用的label和icon。<br/>**说明:**<br/>- OpenHarmony服务的Feature包不能配置具有入口能力的skills标签。<br/>- OpenHarmony应用的Feature包可以配置具有入口能力的skills标签。 | 数组 | 该标签可缺省,缺省值为空。 |
| [metadata](#metadata标签) | 标识当前ExtensionAbility组件的元信息。 | 对象 | 该标签可缺省,缺省值为空。 |
| visible | 标识当前ExtensionAbility组件是否可以被其他应用调用,为布尔类型。<br/>-&nbsp;true:表示可以被其他应用调用。<br/>-&nbsp;false:表示不可以被其他应用调用。 | 布尔值 | 该标签可缺省,缺省值为false。 |
extensionAbilities示例:
```json
{
"extensionAbilities": [
{
"name": "FormName",
"srcEntrance": "./form/MyForm.ts",
"icon": "$media:icon",
"label" : "$string:extension_name",
"description": "$string:form_description",
"type": "form",
"permissions": ["ohos.abilitydemo.permission.PROVIDER"],
"readPermission": "",
"writePermission": "",
"visible": true,
"uri":"scheme://authority/path/query",
"skills": [{
"actions": [],
"entities": [],
"uris": []
}],
"metadata": [
{
"name": "ohos.extension.form",
"resource": "$profile:form_config",
}
]
}
]
}
```
## requestPermissions标签
该标签标识应用运行时需向系统申请的权限集合。
**表8** **requestPermissions标签说明**
| 属性 | 含义 | 类型 | 取值范围 | 默认值 |
| -------- | -------- | -------- | -------- | -------- |
| name | 必须,填写需要使用的权限名称。 | 字符串 | 自定义。 | 无。 |
| reason | 可选,当申请的权限为user_grant权限时此字段必填,用于描述申请权限的原因。<br/>**说明:**<br/>- 当申请的权限为user_grant权限时,如果未填写该字段则不允许在应用市场上架,并且需要进行多语种适配。 | 字符串 | 使用string类资源引用。格式为$string:&nbsp;\*\*\*。 | 空。 |
| usedScene | 可选,当申请的权限为user_grant权限时此字段必填。描述权限使用的场景由abilities和when组成。其中abilities可以配置为多个UIAbility组件,when表示调用时机。<br/>**说明:**<br/>- 默认为可选,当申请的权限为user_grant权限时,abilities标签必填,when标签可选。 | abilities:UIAbility或者ExtensionAbility名称的字符串数组<br/>when:字符串 | abilities:UIAbility或者ExtensionAbility组件的名称。<br/>when:inuse(使用时)、always(始终)。 | abilities:空。<br/>when:空。 |
requestPermissions示例:
```json
{
"module" : {
"requestPermissions": [
{
"name": "ohos.abilitydemo.permission.PROVIDER",
"reason": "$string:reason",
"usedScene": {
"abilities": [
"EntryFormAbility"
],
"when": "inuse"
}
}
]
}
}
```
## shortcuts标签
shortcuts标识应用的快捷方式信息。标签值为数组,最多可以配置四个快捷方式。其包含四个子标签shortcutId、label、icon、wants。
metadata中指定shortcut信息,其中:
- name:指定shortcuts的名称。使用ohos.ability.shortcuts作为shortcuts信息的标识。
- resource:指定shortcuts信息的资源位置。
| 属性 | 含义 | 类型 | 默认值 |
| -------- | -------- | -------- | -------- |
| shortcutId | 标识快捷方式的ID。字符串的最大长度为63字节。 | 字符串 | 该标签不可缺省。 |
| label | 标识快捷方式的标签信息,即快捷方式对外显示的文字描述信息。取值可以是描述性内容,也可以是标识label的资源索引。字符串最大长度为255字节。 | 字符串 | 该标签可缺省,缺省值为空。 |
| icon | 标识快捷方式的图标,标签值为资源文件的索引。 | 字符串 | 该标签可缺省,缺省值为空。 |
| [wants](../application-models/want-overview.md) | 标识快捷方式内定义的目标wants信息集合,每个wants可配置bundleName和abilityName两个子标签。<br/>bundleName:表示快捷方式的目标包名,字符串类型。<br/>abilityName:表示快捷方式的目标组件名,字符串类型。 | 对象 | 该标签可缺省,缺省为空。 |
1. 在/resource/base/profile/目录下配置shortcuts_config.json配置文件。
```json
{
"shortcuts": [
{
"shortcutId": "id_test1",
"label": "$string:shortcut",
"icon": "$media:aa_icon",
"wants": [
{
"bundleName": "com.ohos.hello",
"abilityName": "EntryAbility"
}
]
}
]
}
```
2. 在module.json5配置文件的abilities标签中,针对需要添加快捷方式的UIAbility进行配置metadata标签,使shortcut配置文件对该UIAbility生效。
```json
{
"module": {
// ...
"abilities": [
{
"name": "EntryAbility",
"srcEntrance": "./ets/entryability/EntryAbility.ts",
// ...
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"metadata": [
{
"name": "ohos.ability.shortcuts",
"resource": "$profile:shortcuts_config"
}
]
}
]
}
}
```
## distroFilter标签
该标签下的子标签均为可选字段,在应用市场云端分发时做精准匹配使用,distroFilter用于定义HAP对应的细分设备规格的分发策略,以便在应用市场进行云端分发应用包时做精准匹配。该标签可配置的分发策略维度包括API Version、屏幕形状、屏幕尺寸、屏幕分辨率,设备的国家与地区码。在进行分发时,通过deviceType与这五个属性的匹配关系,唯一确定一个用于分发到设备的HAP。该标签需要配置在/resource/profile资源目录下。
**表9** **distroFilter标签配置说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| apiVersion | 标识支持的apiVersion范围。 | 对象数组 | 该标签可缺省,缺省值为空。 |
| screenShape | 标识屏幕形状的支持策略。 | 对象数组 | 该标签可缺省,缺省值为空。 |
| screenWindow | 标识应用运行时窗口的分辨率支持策略。该字段仅支持对轻量级智能穿戴设备进行配置。 | 对象数组 | 该标签可缺省,缺省值为空。 |
| screenDensity | 标识屏幕的像素密度(dpi:Dot&nbsp;Per&nbsp;Inch)。该字段可选,如果配置了该字段,取值必须合法。该标签为字符串数组,字符串范围如下。<br/>-&nbsp;sdpi:表示小规模的屏幕密度(Small-scale&nbsp;Dots&nbsp;per&nbsp;Inch),适用于dpi取值为(0,120]的设备。<br/>-&nbsp;mdpi:表示中规模的屏幕密度(Medium-scale&nbsp;Dots&nbsp;Per&nbsp;Inch),适用于dpi取值为(120,160]的设备。<br/>-&nbsp;ldpi:表示大规模的屏幕密度(Large-scale&nbsp;Dots&nbsp;Per&nbsp;Inch),适用于dpi取值为(160,240]的设备。<br/>-&nbsp;xldpi:表示大规模的屏幕密度(Extra&nbsp;Large-scale&nbsp;Dots&nbsp;Per&nbsp;Inch),适用于dpi取值为(240,320]的设备。<br/>-&nbsp;xxldpi:表示大规模的屏幕密度(Extra&nbsp;Extra&nbsp;Large-scale&nbsp;Dots&nbsp;Per&nbsp;Inch),适用于dpi取值为(320,480]的设备。<br/>-&nbsp;xxxldpi:表示大规模的屏幕密度(Extra&nbsp;Extra&nbsp;Extra&nbsp;Large-scale&nbsp;Dots&nbsp;Per&nbsp;Inch),适用于dpi取值为(480,&nbsp;640]的设备。 | 对象数组 | 该标签可缺省,缺省值为空。 |
| countryCode | 表示应用需要分发的国家地区码,具体值以[ISO-3166-1](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/basic-resource-file-categories-0000001052066099)标准为准。支持多个国家和地区枚举定义。 | 对象数组 | 该标签可缺省,缺省值为空。 |
**表10** **apiVersion标签说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| policy | 标识该子属性取值规则。配置为“exclude”或“include”。<br/>-&nbsp;exclude:表示需要排除的value属性。<br/>-&nbsp;include:表示需要包含的value属性。 | 字符串 | 该标签不可缺省。 |
| value | 支持的取值为API&nbsp;Version存在的整数值,例如4、5、6。场景示例:某应用,针对相同设备型号,同时在网的为使用API&nbsp;5和API&nbsp;6开发的两个软件版本,则允许上架2个entry类型的安装包,分别支持到对应设备侧软件版本的分发。 | 数组 | 该标签不可缺省。 |
**表11** **screenShape对象的内部结构**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| policy | 标识该子属性取值规则。配置为“exclude”或“include”。<br/>-&nbsp;exclude:表示需要排除的value属性。<br/>-&nbsp;include:表示需要包含的value属性。 | 字符串 | 该标签不可缺省。 |
| value | 支持的取值为circle(圆形)、rect(矩形)。场景示例:针对智能穿戴设备,可为圆形表盘和矩形表盘分别提供不同的HAP。 | 字符串数组 | 该标签不可缺省。 |
**表12** **screenWindow对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| policy | 标识该子属性取值规则。配置为“exclude”或“include”。<br/>-&nbsp;exclude:表示该字段取值不包含value枚举值匹配规则的匹配该属性。<br/>-&nbsp;include:表示该字段取值满足value枚举值匹配规则的匹配该属性。 | 字符串 | 该标签不可缺省。 |
| value | 单个字符串的取值格式为“宽&nbsp;\*&nbsp;高”,取值为整数像素值,例如“454&nbsp;\*&nbsp;454”。 | 字符串数组 | 该标签不可缺省。 |
**表13** **screenDensity对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| policy | 标识该子属性取值规则。配置为“exclude”或“include”。<br/>-&nbsp;exclude:表示需要排除的value属性。<br/>-&nbsp;include:表示需要包含的value属性。 | 字符串 | 该标签不可缺省。 |
| value | 该标签标识屏幕的像素密度(dpi&nbsp;:Dot&nbsp;Per&nbsp;Inch)。 | 字符串数组 | 该标签不可缺省。 |
**表14** **countryCode对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| policy | 标识该子属性取值规则。配置为“exclude”或“include”。<br/>-&nbsp;exclude:表示需要排除的value属性。<br/>-&nbsp;include:表示需要包含的value属性。 | 字符串 | 该标签不可缺省。 |
| value | 标识应用需要分发的国家地区码。 | 字符串数组 | 该标签不可缺省。 |
在开发视图的resources/base/profile下面定义配置文件distro_filter_config.json,文件名可以自定义。
```json
{
"distroFilter": {
"apiVersion": {
"policy": "include",
"value": [
3,
4
]
},
"screenShape": {
"policy": "include",
"value": [
"circle",
"rect"
]
},
"screenWindow": {
"policy": "include",
"value": [
"454*454",
"466*466"
]
},
"screenDensity": {
"policy": "exclude",
"value": [
"ldpi",
"xldpi"
]
},
"countryCode": { // 支持中国和香港地区分发
"policy": "include",
"value": [
"CN",
"HK"
]
}
}
}
```
在module.json5配置文件的module标签中定义metadata信息。
```json
{
"module": {
// ...
"metadata": [
{
"name": "ohos.module.distro",
"resource": "$profile:distro_filter_config",
}
]
}
}
```
## testRunner标签
此标签用于支持对测试框架的配置。
**表15** **testRunner标签说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 标识测试框架对象名称。该标签最大字节长度为255个字节。 | 字符串 | 不可缺省。 |
| srcPath | 标识测试框架代码路径。该标签最大字节长度为255个字节。 | 字符串 | 不可缺省。 |
testRunner标签示例:
```json
{
"module": {
// ...
"testRunner": {
"name": "myTestRunnerName",
"srcPath": "etc/test/TestRunner.ts"
}
}
}
```
# module对象内部结构
module对象包含HAP的配置信息。
### **表1** **module对象内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| mainAbility | 服务中心图标露出的Ability,常驻进程拉起时会启动mainAbility。 | 字符串 | 可缺省,缺省值为空。 |
| package | 标识HAP的包结构名称,在应用内保证唯一性。采用反向域名格式(建议与HAP的工程目录保持一致)。字符串长度为1-127个字节。 | 字符串 | 不可缺省。 |
| name | 标识HAP的类名。采用反向域名方式标识,前缀要与同级的package标签指定的包名一致,也可采用"."开头的命名方式。字符串长度不超过255字节。 | 字符串 | 可缺省,缺省值为空。 |
| description | 标识HAP的描述信息。字符串长度不超过255字节。如果字符串超出长度或者需要支持多语言,可以采用资源索引的方式添加描述内容。 | 字符串 | 可缺省,缺省值为空。 |
| supportedModes | 标识应用支持的运行模式,当前只定义了驾驶模式(drive)。该标签只适用于车机。 | 字符串数组 | 可缺省,缺省值为空。 |
|deviceType | 标识允许Ability运行的设备类型。系统预定义的设备类型包括:tablet(平板)、tv(智慧屏)、car(车机)、wearable(智能穿戴)等。 | 字符串数组 | 不可缺省。 |
|distro | 标识HAP发布的具体描述。 | 对象 | 不可缺省。 |
|metaData | 标识HAP的元信息。 | 对象 | 可缺省,缺省值为空。 |
| abilities | 标识当前模块内的所有Ability。采用对象数据格式。 | 对象数组 | 可缺省,缺省值为空。 |
| js | 标识基于ArkUI框架开发的JS模块集合,其中的每个元素代表一个JS模块的信息。 | 对象数组 | 可缺省,缺省值为空。 |
| shortcuts | 标识应用的快捷方式信息。采用对象数组格式,其中的每个元素表示一个快捷方式对象。 | 对象数组 | 可缺省,缺省值为空。 |
| reqPermissions | 标识应用运行时向系统申请的权限。 | 对象数组 | 可缺省,缺省值为空。 |
| colorMode | 标识应用自身的颜色模式,目前支持如下三种模式:<br/>-&nbsp;dark:表示按照深色模式选取资源。<br/>-&nbsp;light:表示按照浅色模式选取资源。<br/>-&nbsp;auto:表示跟随系统的颜色模式值选取资源。 | 字符串 | 可缺省,缺省值为"auto"。 |
| distroFilter | 标识应用的分发规则。该标签用于定义HAP对应的细分设备规格的分发策略,以便在应用市场进行云端分发应用包时做精准匹配。该标签可配置的分发策略维度包括API&nbsp;Version、屏幕形状、屏幕分辨率。在进行分发时,通过deviceType与这三个属性的匹配关系,唯一确定一个用于分发到设备的HAP。 | 对象 | 可缺省,缺省值为空。但当应用中包含多个entry模块时,必须配置该标签。 |
|commonEvents | 定义了公共事件静态订阅者的信息,该字段中需要声明静态订阅者的名称、权限要求及订阅事件列表信息,当订阅的公共事件发送时,该公共事件静态订阅者将被拉起。这里的静态订阅者区分于常用的动态订阅者,前者无需在业务代码中主动调用订阅事件的接口,在公共事件发布时可能未被拉起,而动态订阅者则在业务代码中主动调用公共事件订阅的相关API,因此需要应用处于活动状态。 | 对象数组 | 可缺省,缺省为空。 |
| entryTheme | 此标签标识OpenHarmony内部主题的关键字。将标记值设置为名称的资源索引。 | 字符串 | 可缺省,缺省值为空。 |
|testRunner | 此标签用于支持对测试框架的配置。 | 对象 | 可缺省,缺省值为空。 |
module示例:
```json
{
"module": {
"mainAbility": ".MainAbility",
"deviceType": [
"default",
"tablet"
],
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"orientation": "unspecified",
"visible": true,
"srcPath": "MainAbility",
"name": ".MainAbility",
"srcLanguage": "ets",
"icon": "$media:icon",
"description": "$string:MainAbility_desc",
"formsEnabled": false,
"label": "$string:MainAbility_label",
"type": "page",
"launchType": "standard"
}
],
"distro": {
"moduleType": "entry",
"installationFree": false,
"deliveryWithInstall": true,
"moduleName": "entry"
},
"package": "com.example.entry",
"srcPath": "",
"name": ".entry",
"js": [
{
"mode": {
"syntax": "ets",
"type": "pageAbility"
},
"pages": [
"pages/Index"
],
"name": ".MainAbility",
"window": {
"designWidth": 720,
"autoDesignWidth": false
}
}
]
}
}
```
#### **表2** **distro对象内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| moduleName | 标识当前HAP的名称,最大长度为31个字节。 | 字符串 | 不可缺省。 |
| moduleType | 标识当前HAP的类型,包括三种类型:entry、feature和har。 | 字符串 | 不可缺省。 |
| installationFree | 标识当前HAP是否支持免安装特性。true:表示支持免安装特性,且符合免安装约束。false:表示不支持免安装特性。另外还需注意:当entry.hap该字段配置为true时,与该entry.hap相关的所有feature.hap该字段也需要配置为true。当entry.hap该字段配置为false时,与该entry.hap相关的各feature.hap该字段可按业务需求配置true或false。 | 布尔值 | 不可缺省。 |
| deliveryWithInstall | 标识当前HAP是否在用户主动安装HAP所在应用的时候一起安装。true:&nbsp;安装应用时当前HAP随应用一起下载安装。false:安装应用时当前HAP并不下载安装,后续使用是按需下载。 | 布尔值 | 不可缺省。 |
distro示例:
```json
"distro": {
"moduleName": "ohos_entry",
"moduleType": "entry",
"installationFree": true,
"deliveryWithInstall": true
}
```
#### **表3** **metadata对象内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| parameters | 标识调用Ability时所有调用参数的元信息。每个调用参数的元信息由以下三个标签组成:description、name、type。 | 对象数组 | 可缺省,缺省值为空 |
| results | 标识Ability返回值的元信息。每个返回值的元信息由以下三个标签组成:description、name、type。 | 对象数组 | 可缺省,缺省值为空。 |
| customizeData | 该标签标识父级组件的自定义元信息,Parameters和results在application不可配。 | 对象数组 | 可缺省,缺省值为空。 |
#### **表4** **parameters对象内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| description | 标识对调用参数的描述,可以是表示描述内容的字符串,也可以是对描述内容的资源索引以支持多语言。该标签最大长度为255个字节。 | 字符串 | 可缺省,缺省值为空。 |
| name | 标识调用参数的名称。该标签最大长度为255个字节。 | 字符串 | 不可缺省。 |
| type | 标识调用参数的类型,如Integer。 | 字符串 | 不可缺省。 |
#### **表5** **results对象内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| description | 标识对返回值的描述,可以是表示描述内容的字符串,也可以是对描述内容的资源索引以支持多语言。该标签最大长度为255个字节。 | 字符串 | 可缺省,缺省值为空。 |
| name | 标识返回值的名字。该标签最大长度为255个字节。 | 字符串 | 可缺省,缺省值为空。 |
| type | 标识返回值的类型,如Integer。 | 字符串 | 不可缺省 |
#### **表6** **customizeData对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 标识数据项的键名称,字符串类型(最大长度255字节)。 | 字符串 | 可缺省,缺省值为空。 |
| value | 标识数据项的值名称,字符串类型(最大长度255字节)。 | 字符串 | 可缺省,缺省值为空。 |
| extra | 标识用户自定义数据格式,标签值为标识该数据的资源的索引值。 | 字符串 | 可缺省,缺省值为空。 |
metadata对象示例:
```json
"metaData": {
"parameters" : [{
"name" : "a test for metadata parameter",
"type" : "Float",
// "$string:parameters_description"为文件资源索引值
"description" : "$string:parameters_description"
}],
"results" : [{
"name" : "a test for metadata result",
"type" : "Float",
"description" : "$string:results_description"
}],
"customizeData" : [{
"name" : "a customizeData",
"value" : "string",
"extra" : "$string:customizeData_description"
}]
}
```
#### **表7** **deviceType标签配置说明**
| 设备类型 | 枚举值 | 说明 |
| -------- | -------- | -------- |
| 平板 | tablet | - |
| 智慧屏 | tv | - |
| 智能手表 | wearable | 系统能力较丰富的手表,具备电话功能。 |
| 车机 | car | - |
| 默认设备 | default | 能够使用全部系统能力的OpenHarmony设备。 |
#### **表8** **abilities对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| process | 运行应用程序或Ability的进程名称。如果在deviceConfig标记中配置了进程,则应用程序的所有能力都在此进程中运行。您还可以为特定能力设置流程属性,以便该能力可以在此流程中运行。如果此属性设置为与其他应用程序相同的进程名称,则所有这些应用程序可以在同一进程中运行,前提是他们具有相同的联合用户ID和相同的签名。该标签最大字节数为31个字节。 | 字符串 | 可缺省,缺省值为空。 |
| name | 标识Ability名称。取值可采用反向域名方式表示,由包名和类名组成,如"com.example.myapplication.MainAbility";也可采用"."开头的类名方式表示,如".MainAbility"。<br/>Ability的名称,需在一个应用的范围内保证唯一。说明:在使用DevEco&nbsp;Studio新建项目时,默认生成首个Ability的配置,即"config.json"中"MainAbility"的配置。如使用其他IDE工具,可自定义名称。该标签最大长度为127个字节。 | 字符串 | 不可缺省 |
| description | 标识对Ability的描述。取值可以是描述性内容,也可以是对描述性内容的资源索引,以支持多语言。该标签最大长度为255个字节。 | 字符串 | 可缺省,缺省值为空。 |
| icon | 标识Ability图标资源文件的索引。取值示例:$media:ability_icon。如果在该Ability的skills属性中,actions的取值包含&nbsp;"action.system.home",entities取值中包含"entity.system.home",则该Ability的icon将同时作为应用的icon。如果存在多个符合条件的Ability,则取位置靠前的Ability的icon作为应用的icon。<br/>说明:应用的"icon"和"label"是用户可感知配置项,需要区别于当前所有已有的应用"icon"或"label"(至少有一个不同)。 | 字符串 | 可缺省,缺省值为空。 |
| label | 标识Ability对用户显示的名称。取值可以是Ability名称,也可以是对该名称的资源索引,以支持多语言。如果在该Ability的skills属性中,actions的取值包含&nbsp;"action.system.home",entities取值中包含"entity.system.home",则该Ability的label将同时作为应用的label。如果存在多个符合条件的Ability,则取位置靠前的Ability的label作为应用的label。<br/>说明:&nbsp;应用的"icon"和"label"是用户可感知配置项,需要区别于当前所有已有的应用"icon"或"label"(至少有一个不同)。该标签为资源文件中定义的字符串的引用,或以"{}"包括的字符串。该标签最大长度为255个字节。 | 字符串 | 可缺省,缺省值为空。 |
| uri | 标识Ability的统一资源标识符。该标签最大长度为255个字节。 | 字符串 | 可缺省,对于data类型的Ability不可缺省。 |
| launchType | 标识Ability的启动模式,支持"standard"和"singleton"两种模式:<br/>standard:表示该Ability可以有多实例。该模式适用于大多数应用场景。<br/>singleton:表示该Ability在所有任务栈中仅可以有一个实例。例如,具有全局唯一性的呼叫来电界面即采用"singleton"模式。该标签仅适用于默认设备、平板、智慧屏、车机、智能穿戴。 | 字符串 | 可缺省,缺省值为"singleton"。 |
| visible | 标识Ability是否可以被其他应用调用。<br/>true:可以被其他应用调用。<br/>false:不能被其他应用调用。 | 布尔类型 | 可缺省,缺省值为"false"。 |
| permissions | 标识其他应用的Ability调用此Ability时需要申请的权限集合,一个数组元素为一个权限名称。通常采用反向域名格式(最大255字节),取值为系统预定义的权限。 | 字符串数组 | 可缺省,缺省值为空。 |
|skills | 标识Ability能够接收的want的特征。 | 对象数组 | 可缺省,缺省值为空。 |
| deviceCapability | 标识Ability运行时要求设备具有的能力,采用字符串数组的格式表示。该标签为数组,支持最多配置512个元素,单个元素最大字节长度为64。 | 字符串数组 | 可缺省,缺省值为空。 |
| metaData | 元数据。 | 对象 | 可缺省,缺省值为空。 |
| type | 标识Ability的类型。取值范围如下:<br/>page:表示基于Page模板开发的FA,用于提供与用户交互的能力。<br/>service:表示基于Service模板开发的PA,用于提供后台运行任务的能力。<br/>data:表示基于Data模板开发的PA,用于对外部提供统一的数据访问对象。<br/>CA:表示支持其他应用以窗口方式调起该Ability。 | 字符串 | 不可缺省。 |
| orientation | 标识该Ability的显示模式。该标签仅适用于page类型的Ability。取值范围如下:<br/>unspecified:由系统自动判断显示方向。<br/>landscape:横屏模式。<br/>portrait:竖屏模式。<br/>followRecent:跟随栈中最近的应用。 | 字符串 | 可缺省,缺省值为"unspecified"。 |
| backgroundModes | 标识后台服务的类型,可以为一个服务配置多个后台服务类型。该标签仅适用于service类型的Ability。取值范围如下:<br/>dataTransfer:通过网络/对端设备进行数据下载、备份、分享、传输等业务。<br/>audioPlayback:音频输出业务。<br/>audioRecording:音频输入业务。<br/>pictureInPicture:画中画、小窗口播放视频业务。<br/>voip:音视频电话、VOIP业务。<br/>location:定位、导航业务。<br/>bluetoothInteraction:蓝牙扫描、连接、传输业务。<br/>wifiInteraction:WLAN扫描、连接、传输业务。<br/>screenFetch:录屏、截屏业务。<br/>multiDeviceConnection:多设备互联业务 | 字符串数组 | 可缺省,缺省值为空。 |
| grantPermission | 指定是否可以向Ability内任何数据授予权限。 | 布尔值 | 可缺省,缺省值为空。 |
| readPermission | 标识读取Ability的数据所需的权限。该标签仅适用于data类型的Ability。取值为长度不超过255字节的字符串。该标签仅适用于默认设备、平板、智慧屏、车机、智能穿戴。 | 字符串 | 可缺省,缺省为空。 |
| writePermission | 标识向Ability写数据所需的权限。该标签仅适用于data类型的Ability。取值为长度不超过255字节的字符串。 | 字符串 | 可缺省,缺省为空。 |
| configChanges | 标识Ability关注的系统配置集合。当已关注的配置发生变更后,Ability会收到onConfigurationUpdated回调。取值范围:<br/>mcc:表示IMSI移动设备国家/地区代码(MCC)发生变更。典型场景:检测到SIM并更新MCC。<br/>mnc:IMSI移动设备网络代码(MNC)发生变更。典型场景:检测到SIM并更新MNC。<br/>locale:表示语言区域发生变更。典型场景:用户已为设备文本的文本显示选择新的语言类型。<br/>layout:表示屏幕布局发生变更。典型场景:当前有不同的显示形态都处于活跃状态。<br/>fontSize:表示字号发生变更。典型场景:用户已设置新的全局字号。<br/>orientation:表示屏幕方向发生变更。典型场景:用户旋转设备。<br/>density:表示显示密度发生变更。典型场景:用户可能指定不同的显示比例,或当前有不同的显示形态同时处于活跃状态。<br/>size:显示窗口大小发生变更。<br/>smallestSize:显示窗口较短边的边长发生变更。<br/>colorMode:颜色模式发生变更。 | 字符串数组 | 可缺省,缺省为空。 |
| mission | 标识Ability指定的任务栈。该标签仅适用于page类型的Ability。默认情况下应用中所有Ability同属一个任务栈。 | 字符串 | 可缺省,缺省为应用的包名。 |
| targetAbility | 标识当前Ability重用的目标Ability。该标签仅适用于page类型的Ability。如果配置了targetAbility属性,则当前Ability(即别名Ability)的属性中仅name、icon、label、visible、permissions、skills生效,其他属性均沿用targetAbility中的属性值。目标Ability必须与别名Ability在同一应用中,且在配置文件中目标Ability必须在别名之前进行声明。 | 字符串 | 可缺省,缺省值为空。表示当前Ability不是一个别名Ability。 |
| formsEnabled | 标识Ability是否支持卡片(forms)功能。该标签仅适用于page类型的Ability。<br/>true:支持卡片能力。<br/>false:不支持卡片能力。 | 布尔值 | 可缺省,缺省值为false。 |
| forms | 标识服务卡片的属性。该标签仅当formsEnabled为"true"时,才能生效。 | 对象数组 | 可缺省,缺省值为空。 |
| srcLanguage | Ability开发语言的类型,开发者创建工程时由开发者手动选择开发语言。 | 字符串 | 可缺省,缺省值为“js”。 |
| srcPath | 该标签标识Ability对应的JS组件代码路径,该标签最大长度为127字节。 | 字符串 | 不可缺省。 |
| uriPermission | 标识该Ability有权访问的应用程序数据。此属性由模式和路径子属性组成。此属性仅对类型提供者的能力有效。 | 对象 | 可缺省,缺省值为空。 |
| startWindowIcon | 标识该Ability启动页面图标资源文件的索引。该标签仅适用于page类型的Ability。取值示例:$media:icon。 | 字符串 | 可缺省,缺省值为空。 |
| startWindowBackground | 标识该Ability启动页面背景颜色资源文件的索引。该标签仅适用于page类型的Ability。取值示例:$color:red。 | 字符串 | 可缺省,缺省值为空。 |
| removeMissionAfterTerminate | 该标签标识Ability销毁后是否从任务列表中移除任务。该标签仅适用于page类型的Ability。true表示销毁后移除任务,&nbsp;false表示销毁后不移除任务。 | 布尔值 | 可缺省,缺省值为false。 |
#### **表9** **uriPermission对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| path | uriPermission标识的路径,该标签最大字节长度为255个字节。 | 字符串 | 不可缺省。 |
| mode | uriPermission的匹配模式。 | 字符串 | 可缺省,缺省值为default。 |
abilities示例:
```json
"abilities": [
{
"name": ".MainAbility",
"description": "test main ability",
// $media:ic_launcher 为媒体类资源
"icon": "$media:ic_launcher",
// $string:example 为字符串类资源
"label": "$string:example",
"launchType": "standard",
"orientation": "unspecified",
"permissions": [],
"visible": true,
"skills": [
{
"actions": [
"action.system.home"
],
"entities": [
"entity.system.home"
]
}
],
"configChanges": [
"locale",
"layout",
"fontSize",
"orientation"
],
"type": "page",
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:red",
"removeMissionAfterTerminate": true
},
{
"name": ".PlayService",
"description": "example play ability",
"icon": "$media:ic_launcher",
"label": "$string:example",
"launchType": "standard",
"orientation": "unspecified",
"visible": false,
"skills": [
{
"actions": [
"action.play.music",
"action.stop.music"
],
"entities": [
"entity.audio"
]
}
],
"type": "service",
"backgroundModes": [
"audioPlayback"
]
},
{
"name": ".UserADataAbility",
"type": "data",
"uri": "dataability://com.example.world.test.UserADataAbility",
"visible": true
}
]
```
#### **表10** **skills对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| actions | 标识能够接收的want的action值,可以包含一个或多个action。取值通常为系统预定义的action值。 | 字符串数组 | 可缺省,缺省值为空。 |
| entities | 标识能够接收的want的Ability的类别(如视频、桌面应用等),可以包含一个或多个entity。 | 字符串数组 | 可缺省,缺省值为空。 |
| uris | 该标签标识向want过滤器添加数据规范集合。该规范可以是只有数据类型(mimeType属性),可以是只有URI,也可以是既有数据类型又有URI。<br/>URI由其各个部分的单独属性指定:&lt;scheme&gt;://&lt;host&gt;:&lt;port&gt;[&lt;path&gt;\|&lt;pathStartWith&gt;\|&lt;pathRegex&gt;]。该标签可缺省,缺省值为空。<br/>其中,scheme字段配置为uri时必配;当只设置数据类型(mimeType)时,则scheme字段为非必配项。 | 对象数组 | 可缺省,缺省值为空。 |
#### **表11** **uris对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| scheme | 标识uri的scheme值。 | 字符串 | 不可缺省。 |
| host | 标识uri的host值。 | 字符串 | 可缺省,缺省值为空。 |
| port | 标识uri的port值。 | 字符串 | 可缺省,缺省值为空。 |
| pathStartWith | 标识uri的pathStartWith值。 | 字符串 | 可缺省,缺省值为空。 |
| path | 标识uri的path值。 | 字符串 | 可缺省,缺省值为空。 |
| pathRegx | 标识uri的pathRegx值。 | 字符串 | 可缺省,缺省值为空。 |
| type | 标识uri的type值。type为MIME-TYPE属性,为资源的媒体类型,常见的类型有"audio/aac","text/css"等。 | 字符串 | 可缺省,缺省值为空。 |
skills示例:
```json
"skills": [
{
"actions": [
"action.system.home"
],
"entities": [
"entity.system.home"
],
"uris": [
{
"scheme": "http",
"host": "www.example.com",
"port": "8080",
"path": "query/student/name",
"type": "text/*"
}
]
}
]
```
#### **表12** **reqPermissions权限申请字段说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 需要使用的权限名称。 | 字符串 | 否 |
| reason | 描述申请权限的原因。需要做多语种适配。 | 字符串 | 分情况:当申请的权限为user_grant时,必须填写此字段,否则不允许在应用市场上架;其他权限可缺省,缺省为空 |
| usedScene | 描述权限使用的场景和时机。场景类型如下两种:<br/>-&nbsp;ability:ability的名称,可配置多个。<br/>-&nbsp;when:调用时机,可填的值有inuse(使用时)、always(始终)。 | 对象 | 可缺省,缺省值为空。<br/>when可缺省,缺省值为"inuse" |
#### **表13** **usedScene对象内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| ability | 标识哪些Ability需要此权限,里面配置Ability的名称。 | 字符串数组 | 可以缺省,缺省表示所有Ability都需要此权限。 |
| when | 标识此权限的使用时间:<br/>inuse:&nbsp;使用时需要此权限。<br/>always:&nbsp;所有时间都需要此权限。 | 枚举值 | 可缺省,缺省值为空。 |
#### **表14** **js对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 标识JS&nbsp;Component的名字。该标签不可缺省,默认值为default。 | 字符串 | 不可缺省。 |
| pages | 标识JS&nbsp;Component的页面用于列举JS&nbsp;Component中每个页面的路由信息[页面路径+页面名称]。该标签不可缺省,取值为数组,数组第一个元素代表JS&nbsp;FA首页。 | 字符串数组 | 不可缺省。 |
| window | 用于定义与显示窗口相关的配置。 | 对象 | 可缺省,缺省值见表15。 |
| type | 标识JS应用的类型。取值范围如下:<br/>normal:标识该JS&nbsp;Component为应用实例。<br/>form:标识该JS&nbsp;Component为卡片实例。 | 字符串 | 可缺省,缺省值为"normal"。 |
|mode | 定义JS组件的开发模式。 | 对象 | 可缺省,缺省值为空。 |
#### **表15** **window对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| designWidth | 标识页面设计基准宽度。以此为基准,根据实际设备宽度来缩放元素大小。 | 数值 | 可缺省,缺省值为720px。 |
| autoDesignWidth | 标识页面设计基准宽度是否自动计算。当配置为true时,designWidth将会被忽略,设计基准宽度由设备宽度与屏幕密度计算得出。 | 布尔值 | 可缺省,缺省值为false。 |
#### **表16** **mode对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| type | 定义JS组件的功能类型。 | 字符串,取值为"pageAbility"、"form" | 可缺省,缺省值为pageAbility。 |
| syntax | 定义JS组件的语法类型。 | 字符串,取值为"hml","ets" | 可缺省,默认值为"hml"。 |
js示例:
```json
"js": [
{
"name": "default",
"pages": [
"pages/index/index",
"pages/detail/detail"
],
"window": {
"designWidth": 720,
"autoDesignWidth": false
},
"type": "form"
}
]
```
#### **表17** **shortcuts对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| shortcutId | 标识快捷方式的ID。字符串的最大长度为63字节。 | 字符串 | 不可缺省。 |
| label | 标识快捷方式的标签信息,即快捷方式对外显示的文字描述信息。取值可以是描述性内容,也可以是标识label的资源索引。字符串最大长度为63字节。 | 字符串 | 可缺省,缺省为空。 |
| icon | 标识快捷方式的图标信息。取值为表示icon的资源索引。 | 字符串 | 可缺省,缺省为空。 |
| intents | 标识快捷方式内定义的目标intent信息集合,每个intent可配置两个子标签,targetClass,&nbsp;targetBundle。 | 对象数组 | 可缺省,缺省为空。 |
#### **表18** **intents对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| targetClass | 标识快捷方式目标类名。 | 字符串 | 可缺省,缺省值为空。 |
| targetBundle | 标识快捷方式目标Ability所在应用的包名。 | 字符串 | 可缺省,缺省值为空。 |
shortcuts示例:
```json
"shortcuts": [
{
"shortcutId": "id",
// $string:shortcut 为配置的字符串资源值
"label": "$string:shortcut",
"intents": [
{
"targetBundle": "com.example.world.test",
"targetClass": "com.example.world.test.entry.MainAbility"
}
]
}
]
```
#### **表19** **forms对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 标识卡片的类名。字符串最大长度为127字节。 | 字符串 | 不可缺省。 |
| description | 标识卡片的描述。取值可以是描述性内容,也可以是对描述性内容的资源索引,以支持多语言。字符串最大长度为255字节。 | 字符串 | 可缺省,缺省为空。 |
| isDefault | 标识该卡片是否为默认卡片,每个Ability有且只有一个默认卡片。<br/>true:默认卡片。<br/>false:非默认卡片。 | 布尔值 | 不可缺省。 |
| type | 标识卡片的类型。取值范围如下:<br/>JS:JS卡片。 | 字符串 | 不可缺省。 |
| colorMode | 标识卡片的主题样式,取值范围如下:<br/>auto:自适应。<br/>dark:深色主题。<br/>light:浅色主题。 | 字符串 | 可缺省,缺省值为"auto"。 |
| supportDimensions | 标识卡片支持的外观规格,取值范围:<br/>1&nbsp;\*&nbsp;2:表示1行2列的二宫格。<br/>2&nbsp;\*&nbsp;1:表示2行1列的二宫格。<br/>2&nbsp;\*&nbsp;2:表示2行2列的四宫格。<br/>2&nbsp;\*&nbsp;4:表示2行4列的八宫格。<br/>4&nbsp;\*&nbsp;4:表示4行4列的十六宫格。 | 字符串数组 | 不可缺省。 |
| defaultDimension | 标识卡片的默认外观规格,取值必须在该卡片supportDimensions配置的列表中。 | 字符串 | 不可缺省。 |
| updateEnabled | 标识卡片是否支持周期性刷新,取值范围:<br/>true:表示支持周期性刷新,可以在定时刷新(updateDuration)和定点刷新(scheduledUpdateTime)两种方式任选其一,优先选择定时刷新。<br/>false:表示不支持周期性刷新。 | 布尔类型 | 不可缺省。 |
| scheduledUpdateTime | 标识卡片的定点刷新的时刻,采用24小时制,精确到分钟。 | 字符串 | 可缺省,缺省值为"0:0"。 |
| updateDuration | 标识卡片定时刷新的更新周期,单位为30分钟,取值为自然数。<br/>当取值为0时,表示该参数不生效。<br/>当取值为正整数N时,表示刷新周期为30\*N分钟。 | 数值 | 可缺省,缺省值为"0"。 |
| formConfigAbility | 标识用于调整卡片的设施或活动的名称。 | 字符串 | 可缺省,缺省值为空。 |
| jsComponentName | 标识JS卡片的Component名称。字符串最大长度为127字节。仅当卡片类型为JS卡片时,需要配置该标签。 | 字符串 | 不可缺省。 |
| metaData | 标识卡片的自定义信息,包含customizeData数组标签。 | 对象 | 可缺省,缺省值为空。 |
| customizeData | 标识自定义的卡片信息。 | 对象数组 | 可缺省,缺省值为空。 |
#### **表20** **customizeData对象内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 标识数据项的键名称。字符串最大长度为255字节。 | 字符串 | 可缺省,缺省值为空。 |
| value | 标识数据项的值。字符串最大长度为255字节。 | 字符串 | 可缺省,缺省值为空。 |
| extra | 标识当前custom数据的格式,取值为表示extra的资源值。 | 字符串 | 可缺省,缺省值为空。 |
forms示例:
```json
"forms": [
{
"name": "Form_Js",
"description": "It's Js Form",
"type": "JS",
"jsComponentName": "card",
"colorMode": "auto",
"isDefault": true,
"updateEnabled": true,
"scheduledUpdateTime": "11:00",
"updateDuration": 1,
"defaultDimension": "2*2",
"supportDimensions": [
"2*2",
"2*4",
"4*4"
]
},
{
"name": "Form_Js",
"description": "It's JS Form",
"type": "Js",
"colorMode": "auto",
"isDefault": false,
"updateEnabled": true,
"scheduledUpdateTime": "21:05",
"updateDuration": 1,
"defaultDimension": "1*2",
"supportDimensions": [
"1*2"
],
"landscapeLayouts": [
"$layout:ability_form"
],
"portraitLayouts": [
"$layout:ability_form"
],
"formConfigAbility": "ability://com.example.myapplication.fa/.MainAbility",
"metaData": {
"customizeData": [
{
"name": "originWidgetName",
"value": "com.example.weather.testWidget"
}
]
}
}
]
```
#### **表21** **distroFilter对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| apiVersion | 标识支持的apiVersion范围。 | 对象数组 | 可缺省,缺省值为空。 |
|screenShape | 标识屏幕形状的支持策略。 | 对象数组 | 可缺省,缺省值为空。 |
| screenWindow | 标识应用运行时窗口的分辨率支持策略。该字段仅支持对轻量级智能穿戴设备进行配置。 | 对象数组 | 可缺省,缺省值为空。 |
|screenDensity | 标识屏幕的像素密度(dpi:Dots&nbsp;Per&nbsp;Inch)。 | 对象数组 | 可缺省,缺省值为空。 |
| countryCode | 标识分发应用时的国家码。具体值参考ISO-3166-1的标准,支持多个国家和地区的枚举定义。 | 对象数组 | 可缺省,缺省值为空。 |
#### **表22** **apiVersion对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| policy | 标识该子属性取值规则。配置为“exclude”或“include”。<br/>-&nbsp;exclude:表示需要排除的value属性。<br/>-&nbsp;include:表示需要包含的value属性。 | 字符串 | 不可缺省。 |
| value | 支持的取值为API&nbsp;Version存在的整数值,例如4、5、6。场景示例:某应用,针对相同设备型号,同时在网的为使用API&nbsp;5和API&nbsp;6开发的两个软件版本,则允许上架2个entry类型的安装包,分别支持到对应设备侧软件版本的分发。 | 数组 | 不可缺省。 |
#### **表23** **screenShape对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| policy | 标识该子属性取值规则。配置为“exclude”或“include”。<br/>-&nbsp;exclude:表示需要排除的value属性。<br/>-&nbsp;include:表示需要包含的value属性。 | 字符串 | 不可缺省。 |
| value | 支持的取值为API&nbsp;Version存在的整数值,例如4、5、6。场景示例:某应用,针对相同设备型号,同时在网的为使用API&nbsp;5和API&nbsp;6开发的两个软件版本,则允许上架2个entry类型的安装包,分别支持到对应设备侧软件版本的分发。 | 数组 | 不可缺省。 |
#### **表24** **screenWindow对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| policy | 标识该子属性取值规则。配置为“exclude”或“include”。<br/>-&nbsp;exclude:表示需要排除的value属性。<br/>-&nbsp;include:表示需要包含的value属性。 | 字符串 | 不可缺省。 |
| value | 支持的取值为API&nbsp;Version存在的整数值,例如4、5、6。场景示例:某应用,针对相同设备型号,同时在网的为使用API&nbsp;5和API&nbsp;6开发的两个软件版本,则允许上架2个entry类型的安装包,分别支持到对应设备侧软件版本的分发。 | 数组 | 不可缺省。 |
#### **表25** **screenDensity对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| policy | 标识该子属性取值规则。配置为“exclude”或“include”。<br/>-&nbsp;exclude:表示需要排除的value属性。<br/>-&nbsp;include:表示需要包含的value属性。 | 字符串 | 不可缺省。 |
| value | 取值范围如下:<br/>sdpi:表示小规模的屏幕密度(Small-scale&nbsp;Dots&nbsp;Per&nbsp;Inch),适用于dpi取值为(0,120]的设备。<br/>mdpi:表示中规模的屏幕密度(Medium-scale&nbsp;Dots&nbsp;Per&nbsp;Inch),适用于dpi取值为(120,160]的设备。<br/>ldpi:表示大规模的屏幕密度(Large-scale&nbsp;Dots&nbsp;Per&nbsp;Inch),适用于dpi取值为(160,240]的设备。<br/>xldpi:表示特大规模的屏幕密度(Extra&nbsp;Large-scale&nbsp;Dots&nbsp;Per&nbsp;Inch),适用于dpi取值为(240,320]的设备。<br/>xxldpi:表示超大规模的屏幕密度(Extra&nbsp;Extra&nbsp;Large-scale&nbsp;Dots&nbsp;Per&nbsp;Inch),适用于dpi取值为(320,480]的设备。<br/>xxxldpi:表示超特大规模的屏幕密度(Extra&nbsp;Extra&nbsp;Extra&nbsp;Large-scale&nbsp;Dots&nbsp;Per&nbsp;Inch),适用于dpi取值为(480,640]的设备。 | 数组 | 不可缺省。 |
#### **表26** **countryCode对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| policy | 标识该子属性取值规则。配置为“exclude”或“include”。<br/>-&nbsp;exclude:表示需要排除的value属性。<br/>-&nbsp;include:表示需要包含的value属性。 | 字符串 | 不可缺省。 |
| value | 该标签标识应用需要分发的国家码,标签为字符串数组,子串表示支持的国家或地区,由两个大写字母表示。 | 字符串数组 | 不可缺省。 |
distroFilter示例:
```json
"distroFilter": {
"apiVersion": {
"policy": "include",
"value": [4,5]
},
"screenShape": {
"policy": "include",
"value": ["circle","rect"]
},
"screenWindow": {
"policy": "include",
"value": ["454*454","466*466"]
},
"screenDensity":{
"policy": "exclude",
"value": ["ldpi","xldpi"]
},
"countryCode": {
"policy":"include",
"value":["CN","HK"]
}
}
```
#### **表27** **commonEvents对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 标识静态公共事件名称,该标签最大长度为127字节。 | 字符串 | 不可缺省。 |
| permission | 此标签标识实现静态公共事件所需要申请的权限,该标签最大长度为255字节。 | 字符串 | 可缺省,缺省值为空。 |
| data | 标识配置当前静态公共事件要携带的附加数据数组。 | 字符串数组 | 可缺省,缺省值为空。 |
| type | 该标签用于配置当前静态公共事件的分类数组。 | 字符串数组 | 可缺省,缺省值为空。 |
| events | 此标签标识可接收的意图的一组事件值。一般由系统预定义,也可以自定义。 | 字符串数组 | 不可缺省。 |
commonEvents示例:
```json
"commonEvents": [
{
"name": ".MainAbility",
"permission": "ohos.permission.GET_BUNDLE_INFO",
"data": [
"com.example.demo",
"100"
],
"events": [
"install",
"update"
]
}
]
```
#### **表28** **testRunner对象的内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 标识测试框架对象名称,该标签最大长度为255字节。 | 字符串 | 不可缺省。 |
| srcPath | 标识测试框架代码路径,该标签最大长度为255字节。 | 字符串 | 不可缺省。 |
```json
"testRunner": {
"name": "myTestRunnerName",
"srcPath": "etc/test/TestRunner.ts"
}
```
definePermission仅支持系统应用配置,三方应用配置不生效。
#### **表29** **definePermissions对象内部结构说明**
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------- | -------- | -------- |
| name | 标识权限的名称,该标签最大长度为255字节。 | 字符串 | 不可缺省。 |
| grantMode | 标识权限的授予方式,支持如下两种授予模式如下:<br/>-&nbsp;system_grant:安装后系统自动授予该权限。<br/>-&nbsp;user_grant:使用时动态申请,用户授权后才可使用。 | 字符串 | 可缺省,缺省值为system_grant。 |
| availableLevel | 标识权限限制类别,可选值如下:<br/>-&nbsp;system_core:系统核心权限。<br/>-&nbsp;system_basic:系统基础权限。<br/>-&nbsp;normal:普通权限。所有应用允许申请的权限。 | 字符串 | 可缺省,缺省值为normal。 |
| provisionEnable | 标识权限是否支持证书方式申请权限,包括高级别的权限。配置为true标识开发者可以通过provision方式申请权限。 | 布尔值 | 可缺省,缺省值为true。 |
| distributedSceneEnabled | 标识权限是否支持分布式场景下使用该权限。 | 布尔值 | 可缺省,缺省值为false。 |
| label | 标识权限的简短描述,配置为对描述内容的资源索引。 | 字符串 | 可缺省,缺省值为空。 |
| description | 标识权限的详细描述,可以是字符串(最大长度为255字节),或者为对描述内容的资源索引。 | 字符串 | 可缺省,缺省值为空。 |
# 多HAP构建视图
IDE支持在一个应用工程中进行多个HAP的开发与构建,如[多HAP构建视图](figures/hap-multi-view.png)所示。
**图1** 多HAP构建视图  
![hap-multi-view](figures/hap-multi-view.png)
1. IDE开发态视图
- AppScope目录
- [app.json5](app-configuration-file.md):配置应用全局描述信息,例如应用包名、版本号、应用图标、应用名称和依赖的SDK版本号等。
- resources目录:放置应用的图标资源和应用名称字符串资源。
**说明:**
- 该目录由IDE自动生成,名称不可更改。
- AppScope目录下面的文件名与Entry、Feature模块下面的文件名不能重复,否则IDE会报错。
- entry或者featrue目录(名称可由开发者自定义)
- 由IDE引导开发者创建的Module,在该Module中实现应用的业务逻辑;可以创建多个Module,图中entry和featrue即是创建的两个Module。
- resources目录:放置该Module中所使用到的资源。
- ets目录:开发者的业务逻辑。
- [module.json5](module-configuration-file.md):配置该Module的描述信息,如:Module的名称、Module的入口代码路径、包含的组件信息等。
2. 编译打包后的视图
- 一个开发态的Module编译后生成一个部署态的HAP,Module和HAP一一对应。
- HAP中的module.json由开发视图中的app.json5和module.json5合成。
- 所有的HAP最终会编译到一个App Pack中(以.app为后缀的包文件),用于发布到应用市场。
# 多HAP机制设计目标
- 方便开发者模块化的管理应用,好的应用一般都是模块化管理,模块之间属于松耦合关系。多HAP方便了开发者将业务划分成多个模块,每个模块放到独立的HAP中。例如支付类应用,有统一的主界面,主界面管理“扫一扫”、“收付款”、“消息”、“理财”等各个模块。其中主界面管理其他模块的逻辑在Entry包中实现,而“扫一扫”、“收付款”、“消息”和“理财”等模块在不同的Feature包中实现。可以同时开发多个Feature包,能够实现Feature包单独的开发测试,最终由Entry包统一集成Feature包的特性。
- 方便开发者将多HAP合理地组合并部署到不同的设备上。例如应用程序包含一个Entry包和两个Featrue包(Feature1和Feature2)。其中Entry包可以部署到设备A和设备B,Feature1只能部署到设备A,Feature2包只部署到设备B上,那么开发者就可以方便的组合Entry和Feature1部署到设备A上,组合Entry和Feature2部署到设备B上。
- 方便开发者按需加载所需模块,减少包大小。开发者可以将一个应用的某些HAP配置成按需加载。应用在启动阶段初始用不到的特性,可以配置暂不加载,当用户用到这些特性的时候,可由应用自动下载这些特性HAP,一定程度上减少应用包的大小。
- 方便应用资源共享,减少程序包大小。多个HAP都需要用到的资源(包括公共资源文件、公共页面等)以及so(shared object)文件可以放到单独的HAP中,其他HAP可以到该HAP中访问资源和so文件,也一定程度上可以减少应用程序包大小。
# 多HAP运行机制及数据通信方式
多HAP机制主要是为方便开发者进行模块化管理。HAP和应用运行时的进程并不是一一对应的,具体运行机制如下:
- 默认情况下,应用中(同一包名)的所有UIAbility、ServiceExtensionAbility、DataShareExtensionAbility运行在同一个独立进程中,其他同类型ExtensionAbility分别运行在单独的进程。
- HAP支持在module.json5(Stage模型)或者config.json(FA模型)中通过process标签配置单独的进程(仅系统应用支持,三方应用不支持)。配置了process的HAP,其组件运行在单独的process进程中,多个HAP可以配置相同的process,则这些HAP运行在相同进程中,process配置的详细说明请参见[module.json5配置文件](module-configuration-file.md)
- 应用运行时,同一进程中的UIAbility组件被启动时,才加载对应HAP的资源和代码。
基于上述机制,多HAP数据通信方式如下:
- 同一进程内的数据通信,请参见[线程间通信](../application-models/thread-model-stage.md)
- 跨进程的数据通信,请参见[进程间通信](../application-models/process-model-stage.md)。。
- 多HAP如果运行在同一进程,则多HAP间组件的通信方式与同一HAP内组件的通信方式相同。
# 多HAP发布部署流程
多HAP发布部署流程如下:
1. 开发者通过IDE按照业务的需要创建多个Module,在相应的Module中完成自身业务的开发。
2. 通过IDE编译打包,生成App包。
3. 将该App包上架到应用市场云端,应用市场会对上架的App包校验签名,校验签名通过后会将App包中的HAP拆分出来,同时对拆分出的HAP重新添加签名,接着对HAP进行分发。
4. 用户在设备上的应用市场客户端能够看到各种各样的应用,这些应用均由云端分发而来,有些是多HAP应用,有些是单HAP应用。用户选择某个应用后,应用市场将下载应用包含的全部HAP。
5. 下载完成后,应用市场客户端再调用系统中包管理服务的安装接口安装下载的HAP,包管理服务以应用为单位将其中所有HAP部署到指定目录下,以完成应用的安装。
**图1** 多HAP发布部署流程  
![hap-release](figures/hap-release.png)
# 多HAP使用规则
- App Pack包不能直接安装到设备上,只是上架应用市场的单元。
- App Pack包中所有HAP的配置文件中的bundleName标签必须一致。
- App Pack包中所有HAP的配置文件中的versionCode标签必须一致。
- App Pack包中同一设备类型的所有HAP中必须有且只有一个entry类型的HAP,featrue类型的HAP可以有一个或者多个,也可以没有。
- App Pack包中的每个HAP必须配置moduleName标签,同一设备类型的所有HAP对应的moduleName标签必须唯一。
- 同一应用的所有HAP签名证书要保持一致。上架应用市场是以App Pack的形式上架,并对其进行了签名。应用市场分发时会将所有HAP从App Pack中拆分出来,同时对其中的所有HAP进行重签名,这样保证了所有HAP签名证书的一致性。在调试阶段,开发者通过命令行或IDE将HAP安装到设备上时要保证所有HAP签名证书一致,否则会出现安装失败的问题。
# 应用包结构配置文件的说明(FA模型)
在FA模型的应用开发的工程中,需要在config.json配置文件中对应用的包结构进行声明。
## 配置文件的内部结构
“config.json”由app,deviceConfig和module三个部分组成,缺一不可。配置文件的内部结构说明参见表1。
表1 配置文件的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ------------ | ------------------------------------------------------------ | -------- | ---------- |
| app | 标识应用的全局配置信息。同一个应用的不同HAP包的app配置必须保持一致。参考[app对象内部结构](#app对象内部结构)。 | 对象 | 不可缺省。 |
| deviceConfig | 标识应用在具体设备上的配置信息。参考[deviceConfig对象内部结构](#deviceconfig对象的内部结构)。 | 对象 | 不可缺省。 |
| module | 标识HAP包的配置信息。该标签下的配置只对当前HAP包生效。参考[module对象的内部结构](#module对象的内部结构)。 | 对象 | 不可缺省。 |
config.json示例:
```json
{
"app": {
"bundleName": "com.example.myapplication",
"vendor": "example",
"version": {
"code": 1000000,
"name": "1.0.0"
}
},
"deviceConfig": {},
"module": {
"package": "com.example.myapplication",
"name": ".entry",
"mainAbility": ".MainAbility",
"deviceType": [
"default",
"tablet"
],
"distro": {
"deliveryWithInstall": true,
"moduleName": "entry",
"moduleType": "entry",
"installationFree": false
},
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"orientation": "unspecified",
"formsEnabled": false,
"name": ".MainAbility",
"srcLanguage": "ets",
"srcPath": "MainAbility",
"icon": "$media:icon",
"description": "$string:ability_desc",
"label": "$string:ability_label",
"type": "page",
"visible": true,
"launchType": "standard"
}
],
"js": [
{
"mode": {
"syntax": "ets",
"type": "pageAbility"
},
"pages": [
"pages/LoginPage",
"pages/MinePage",
"pages/RegistrationSuccessPage",
"pages/PrivacyPage",
"pages/CustomerServicePage"
],
"name": ".MainAbility",
"window": {
"designWidth": 720,
"autoDesignWidth": false
}
}
]
}
}
```
### app对象内部结构
app对象包含应用全局配置信息,内部结构说明参见表2。
表2 app对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ----------------- | ------------------------------------------------------------ | -------- | --------------------------- |
| bundleName | 标识应用的包名,用于标识应用的唯一性。包名是由字母、数字、下划线(_)和点号(.)组成的字符串,必须以字母开头。支持的字符串长度为7~127字节。</br>包名通常采用反向域名形式表示(例如,"com.example.myapplication")。建议第一级为域名后缀"com",第二级为厂商/个人名,也可以采用多级。 | 字符串 | 不可缺省。 |
| vendor | 标识对应用开发厂商的描述。字符串长度不超过255字节。 | 字符串 | 可缺省,缺省值为空。 |
| version | 标识应用的版本信息。参考表3。 | 对象 | 不可缺省。 |
| apiVersion | 标识应用程序所依赖的OpenHarmony API版本。参考表4。 | 对象 | 可缺省,缺省值为空。 |
| smartWindowSize | 标识应用在模拟器中运行时使用的屏幕尺寸。 | 字符串 | 可缺省,缺省值为空。 |
| smartWindowDeviceType | 标识应用在模拟器中运行时可以模拟的设备。 | 字符串数组 | 可缺省,缺省值为空。 |
表3 version内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ------------------------ | ------------------------------------------------------------ | -------- | -------------------------- |
| name | 标识应用的版本号,用于向应用的终端用户呈现。取值可以自定义,长度不超过127字节。自定义规则如下:<br />API5及更早的版本:推荐使用三段数字版本号(也兼容两段式版本号),如A.B.C(也兼容A.B),其中A、B、C取值为0-999范围内的整数。除此之外不支持其他格式。<br /> A段,一般表示主版本号(Major)。<br /> B段,一般表示次版本号(Minor)。<br /> C段,一般表示修订版本号(Patch)。<br />API6版本起:推荐采用四段式数字版本号,如A.B.C.D,其中A、B、C取值为0-99范围内的整数,D的取值为0-999范围内的整数。<br /> A段,一般表示主版本号(Major)。<br /> B段,一般表示次版本号(Minor)。<br /> C段,一般表示特性版本号(Feature)。<br /> D段,一般表示修订版本号(Patch)。 | 数值 | 不可缺省。 |
| code | 标识应用的版本号,仅用于OpenHarmony管理该应用,不对应用的终端用户呈现。取值规则如下:<br />API5及更早版本:二进制32位以内的非负整数,需要从version.name的值转换得到。转换规则为:<br /> code值=A * 1,000,000 + B * 1,000 + C 例如,version.name字段取值为2.2.1,则code值为2002001。<br /> API6版本起:code的取值不与version.name字段的取值关联,开发者可自定义code取值,取值范围为2^31以内的非负整数,<br />但是每次应用版本的更新,均需要更新code字段的值,新版本code取值必须大于旧版本code的值。 | 数值 | 不可缺省。 |
| minCompatibleVersionCode | 标识应用可兼容的最低版本号,用于跨设备场景下,判断其他设备上该应用的版本是否兼容。<br /> 格式与version.code字段的格式要求相同。 | 数值 | 可缺省,缺省值为code标签值。 |
表4 apiVersion内部结构
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ----------- | ----------------------------------------------------------- | -------- | ---------- |
| compatible | 运行应用所需要的最低API版本,取值范围为0~2147483647。 | 数值 | 配置在build.profile中,打包时由IDE填充到config.json中。 |
| target | 用于标识应用运行所需的目标API版本,取值范围为0~2147483647。 | 数值 | 配置在build.profile中,打包时由IDE填充到config.json中。 |
| releaseType | 用于标识应用运行时SDK的状态。<br />canary:面向特定开发者早期预览版本,不承诺质量,不承诺API稳定。<br />beta:公开发布的Beta版本,早期Beta版本不承诺API稳定,经历若干次发布后,通过Release Notes对开发者声明该Beta版本为API稳定里程碑,后续版本的API冻结。<br />release:正式发布版本,承诺质量,API不可变更。当版本处于此状态时版本号中不呈现Stage字段。 | 字符串 | 配置在build.profile中,打包时由IDE填充到config.json中。 |
app实例:
```json
{
"app": {
"bundleName": "com.example.myapplication",
"vendor": "example",
"version": {
"code": 1000000,
"name": "1.0.0"
},
"apiVersion": {
"compatible": 9,
"target": 9,
"releaseType": "Beta1"
}
}
}
```
### deviceConfig对象的内部结构
deviceConfig包含设备上的应用配置信息,可以包含default,tv,car,wearable等属性。default标签内的配置适用于所有通用设备,其他设备类型如果有特殊的需求,则需要在该设备类型的标签下进行配置。内部结构说明参见表5。
表5 deviceConfig对象的内部结构说明
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | ----------------------------------------- | -------- | ------------------ |
| default | 能够使用全部系统能力的OpenHarmony设备。 | 对象 | 可缺省,缺省值为空。 |
| tablet | 标识平板的应用配置信息。 | 对象 | 可缺省,缺省值为空。 |
| tv | 标识智慧屏特有的应用配置信息。 | 对象 | 可缺省,缺省值为空。 |
| car | 标识车机特有的应用配置信息。 | 对象 | 可缺省,缺省值为空。 |
| wearable | 标识智能穿戴特有的应用配置信息。| 对象 | 可缺省,缺省值为空。 |
default、tablet、tv、car、wearable等对象的内部结构说明如下:
表6 deviceConfig设备对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ------------------ | ------------------------------------------------------------ | -------- | ----------------------- |
| process | 标识应用或者Ability的进程名。如果在deviceConfig标签下配置了process标签,则该应用的所有Ability都运行在这个进程中。如果在abilities标签下也为某个Ability配置了process标签,<br />则该Ability就运行在这个进程中。该标签最大长度为31。 | 字符串 | 可缺省,缺省值为空。 |
| keepAlive | 标识应用是否始终保持运行状态,仅支持系统应用配置,三方应用配置不生效。该标签为布尔类型,可缺省,缺省值为false,如果配置为true,应用将始终保持为运行状态,<br />并在系统启动的时候被系统驱动起来,应用进程退出后,系统也会重新启动应用进程。 | 布尔值 | 可缺省,缺省值为false。 |
| supportBackup | 标识应用是否支持备份和恢复。如果配置为false,则不支持为该应用执行备份或恢复操作。 | 布尔值 | 可缺省,缺省值为false。 |
| compressNativeLibs | 标识libs库是否以压缩存储的方式打包到HAP包。如果配置为false,则libs库以不压缩的方式存储,HAP包在安装时无需解压libs,运行时会直接从HAP内加载libs库。 | 布尔值 | 可缺省,缺省值为false。 |
| network | 标识网络安全性配置。该标签允许应用通过配置文件的安全声明来自定义其网络安全,无需修改应用代码。参考表7。 | 对象 | 可缺省,缺省值为空。 |
表7 network对象的内部结构说明
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| ---------------- | ------------------------------------------------------------ | -------- | ----------------------- |
| cleartextTraffic | 标识是否允许应用使用明文网络流量(例如,明文HTTP)。<br /> true:允许应用使用明文流量请求。<br /> false:拒绝应用使用明文流量的请求。 | 布尔值 | 可缺省,缺省值为false。 |
| securityConfig | 标识应用的网络安全配置信息。参考表8。 | 对象 | 可缺省,缺省值为空。 |
表8 securityConfig对象的内部结构说明
| 属性名称 | 子属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| -------------- | ------------------ | ------------------------------------------------------------ | -------- | ---------------- |
| domainSettings | - | 标识自定义的网域范围的安全配置,支持多层嵌套,即一个domainSettings对象中允许嵌套更小网域范围的domainSettings对象。 | 对象 | 可缺省,缺省值为空。 |
| | cleartextPermitted | 标识自定义的网域范围内是否允许明文流量传输。当cleartextTraffic和security同时存在时,自定义网域是否允许明文流量传输以cleartextPermitted的取值为准。<br />true:允许明文流量传输。<br />false:拒绝明文流量传输。 | 布尔值 | 可缺省,缺省值为空。 |
| | domains | 标识域名配置信息,包含两个参数:subdomains和name。<br /> subdomains(布尔类型):表示是否包含子域名。如果为true,此网域规则将与相应网域及所有子网域(包括子网域的子网域)匹配。<br />否则,该规则仅适用于精确匹配项。name(字符串):表示域名名称。 | 对象数组 | 可缺省,缺省值为空。 |
deviceConfig示例:
```json
{
"deviceConfig": {
"default": {
"process": "com.example.myapplication",
"supportBackup": false,
"network": {
"cleartextTraffic": true,
"securityConfig": {
"domainSettings": {
"cleartextPermitted": true,
"domains": [
{
"subdomains": true,
"name": "example.ohos.com"
}
]
}
}
}
}
}
}
```
### module对象的内部结构
module对象包含HAP包的配置信息,内部结构说明参见表9。
表9 module对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ----------------- | ------------------------------------------------------------ | ---------- | ------------------------------------------------------------ |
| mainAbility | 服务中心图标露出的ability,常驻进程拉起时会启动mainAbility。 | 字符串 | 可缺省,缺省值为空。 |
| package | 标识HAP的包结构名称,在应用内保证唯一性。采用反向域名格式(建议与HAP的工程目录保持一致)。字符串长度为1-127个字节。 | 字符串 | 不可缺省。 |
| name | 标识HAP的类名。采用反向域名方式标识,前缀要与同级的package标签指定的包名一致,也可采用"."开头的命名方式。字符串长度不超过255字节。 | 字符串 | 可缺省,缺省值为空。 |
| description | 标识HAP的描述信息。字符串长度不超过255字节。如果字符串超出长度或者需要支持多语言,可以采用资源索引的方式添加描述内容。 | 字符串 | 可缺省,缺省值为空。 |
| supportedModes | 标识应用支持的运行模式,当前只定义了驾驶模式(drive)。该标签只适用于车机。 | 字符串数组 | 可缺省,缺省值为空。 |
| deviceType | 标识允许Ability运行的设备类型。系统预定义的设备类型包括:tablet(平板)、tv(智慧屏)、car(车机)、wearable(智能穿戴)等。 | 字符串数组 | 不可缺省。 |
| distro | 标识HAP发布的具体描述。参考表10。 | 对象 | 不可缺省。 |
| metaData | 标识HAP的元信息。参考表11。 | 对象 | 可缺省,缺省值为空。 |
| abilities | 标识当前模块内的所有Ability。采用对象数据格式。参考表15。 | 对象数组 | 可缺省,缺省值为空。 |
| js | 标识基于ArkUI框架开发的JS模块集合,其中的每个元素代表一个JS模块的信息。参考表21。 | 对象数组 | 可缺省,缺省值为空。 |
| shortcuts | 标识应用的快捷方式信息。采用对象数组格式,其中的每个元素表示一个快捷方式对象。参考表24。 | 对象数组 | 可缺省,缺省值为空。 |
| reqPermissions | 标识应用运行时向系统申请的权限。参考表19。 | 对象数组 | 可缺省,缺省值为空。 |
| colorMode | 标识应用自身的颜色模式。<br /> dark:表示按照深色模式选取资源。<br /> light:表示按照浅色模式选取资源。<br /> auto:表示跟随系统的颜色模式值选取资源。 | 字符串 | 可缺省,缺省值为"auto"。 |
| distroFilter | 标识应用的分发规则。<br /> 该标签用于定义HAP包对应的细分设备规格的分发策略,以便在应用市场进行云端分发应用包时做精准匹配。该标签可配置的分发策略维度包括:<br />API Version、屏幕形状、屏幕尺寸、屏幕分辨率、国家和地区码。<br />在进行分发时,通过deviceType与这五个属性的匹配关系,唯一确定一个用于分发到设备的HAP。参考表27。 | 对象 | 可缺省,缺省值为空。但当应用中包含多个entry模块时,必须配置该标签。 |
| commonEvents | 定义了公共事件静态订阅者的信息,该字段中需要声明静态订阅者的名称、权限要求及订阅事件列表信息,当订阅的公共事件发送时,<br />该公共事件静态订阅者将被拉起。这里的静态订阅者区分于常用的动态订阅者,前者无需在业务代码中主动调用订阅事件的接口,<br />在公共事件发布时可能未被拉起,而动态订阅者则在业务代码中主动调用公共事件订阅的相关API,因此需要应用处于活动状态。参考表33。 | 对象数组 | 可缺省,缺省值为空。 |
| entryTheme | 此标签标识OpenHarmony内部主题的关键字。将标记值设置为名称的资源索引。 | 字符串 | 可缺省,缺省值为空。 |
| testRunner | 此标签用于支持对测试框架的配置,参考表34。 | 对象 | 可缺省,缺省值为空。 |
module示例:
```json
{
"module": {
"package": "com.example.myapplication",
"name": ".entry",
"mainAbility": ".MainAbility",
"deviceType": [
"default",
"tablet"
],
"distro": {
"deliveryWithInstall": true,
"moduleName": "entry",
"moduleType": "entry",
"installationFree": false
},
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"orientation": "unspecified",
"formsEnabled": false,
"name": ".MainAbility",
"srcLanguage": "ets",
"srcPath": "MainAbility",
"icon": "$media:icon",
"description": "$string:ability_desc",
"label": "$string:ability_label",
"type": "page",
"visible": true,
"launchType": "standard"
}
],
"js": [
{
"mode": {
"syntax": "ets",
"type": "pageAbility"
},
"pages": [
"pages/LoginPage",
"pages/MinePage",
"pages/RegistrationSuccessPage",
"pages/PrivacyPage",
"pages/CustomerServicePage"
],
"name": ".MainAbility",
"window": {
"designWidth": 720,
"autoDesignWidth": false
}
}
]
}
}
```
表10 distro对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ---------------- | ------------------------------------------------------------ | -------- | ---------- |
| moduleName | 标识当前HAP的名称,最大长度为31个字节。 | 字符串 | 不可缺省。 |
| moduleType | 标识当前HAP的类型,包括三种类型:entry、feature和har。 | 字符串 | 不可缺省。 |
| installationFree | 标识当前HAP是否支持免安装特性。<br /> true:表示支持免安装特性,且符合免安装约束。<br /> false:表示不支持免安装特性。<br /> 另外还需注意:<br /> 当entry.hap该字段配置为true时,与该entry.hap相关的所有feature.hap该字段也需要配置为true。<br /> 当entry.hap该字段配置为false时,与该entry.hap相关的各feature.hap该字段可按业务 需求配置true或false。 | 布尔值 | 不可缺省。 |
| deliveryWithInstall | 标识当前HAP是否在用户主动安装HAP所在应用的时候一起安装。<br /> true:安装应用时当前HAP随应用一起下载安装。<br /> false:安装应用时当前HAP并不下载安装,后续使用时按需下载。| 布尔值 | 不可缺省。 |
distro示例:
```json
{
"module": {
"distro": {
"deliveryWithInstall": true,
"moduleName": "entry",
"moduleType": "entry",
"installationFree": false
}
}
}
```
表11 metaData对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ------------- | ------------------------------------------------------------ | -------- | -------------------- |
| parameters | 标识调用Ability时所有调用参数的元信息。每个调用参数的元信息由以下三个标签组成:description、name、type。参考表12。 | 对象数组 | 可缺省,缺省值为空。 |
| results | 标识Ability返回值的元信息。每个返回值的元信息由以下三个标签组成:description、name、type。参考表13。 | 对象数组 | 可缺省,缺省值为空。 |
| customizeData | 该标签标识父级组件的自定义元信息,Parameters和results在application不可配。参考表14 | 对象数组 | 可缺省,缺省值为空。 |
表12 parameters对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ----------- | ------------------------------------------------------------ | -------- | ------------------ |
| description | 标识对调用参数的描述,可以是表示描述内容的字符串,也可以是对描述内容的资源索引以支持多语言。该标签最大长度为255个字节。 | 字符串 | 可缺省,缺省值为空。 |
| name | 标识调用参数的名称。该标签最大长度为255个字节。 | 字符串 | 可缺省,缺省值为空。 |
| type | 标识调用参数的类型,如Integer。 | 字符串 | 不可缺省。 |
表13 results对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ----------- | ------------------------------------------------------------ | -------- | -------------------- |
| description | 标识对返回值的描述,可以是表示描述内容的字符串,也可以是对描述内容的资源索引以支持多语言。该标签最大长度为255个字节。 | 字符串 | 可缺省,缺省值为空。 |
| name | 标识返回值的名字。该标签最大长度为255个字节。 | 字符串 | 可缺省,缺省值为空。 |
| type | 标识返回值的类型,如Integer。 | 字符串 | 不可缺省。 |
表14 customizeData对象的内部结构说明
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | ---------------------------------------------------------- | -------- | -------------------- |
| name | 标识数据项的键名称,字符串类型(最大长度255字节)。 | 字符串 | 可缺省,缺省值为空。 |
| value | 标识数据项的值名称,字符串类型(最大长度255字节)。 | 字符串 | 可缺省,缺省值为空。 |
| extra | 标识用户自定义数据格式,标签值为标识该数据的资源的索引值。 | 字符串 | 可缺省,缺省值为空。 |
metaData示例:
```json
{
"module": {
"metaData": {
"parameters": [
{
"name": "string",
"type": "Float",
"description": "$string:parameters_desc"
}
],
"results": [
{
"name": "string",
"type": "Float",
"description": "$string:results_desc"
}
],
"customizeData": [
{
"name": "string",
"value": "string",
"extra": "$string:customizeData_desc"
}
]
}
}
}
```
表15 abilities对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ---------------- | ------------------------------------------------------------ | ---------- | -------------------------------------------------------- |
| process | 运行应用程序或Ability的进程名称。如果在deviceConfig标记中配置了进程,则应用程序的所有能力都在此进程中运行。您还可以为特定能力设置流程属性,以便该能力可以在此流程中运行。如果此属性设置为与其他应用程序相同的进程名称,则所有这些应用程序可以在同一进程中运行,前提是他们具有相同的联合用户ID和相同的签名。运行OHOS的设备不支持此属性。该标签最大字节数为31个字节。 | 字符串 | 可缺省,缺省值为空。 |
| name | 标识Ability名称。取值可采用反向域名方式表示,由包名和类名组成,如“com.example.myapplication.MainAbility”;也可采用“.”开头的类名方式表示,如“.MainAbility”。<br /> Ability的名称,需在一个应用的范围内保证唯一。<br /> 说明:在使用DevEco Studio新建项目时,默认生成首个Ability的配置,即“config.json”中“MainAbility”的配置。如使用其他IDE工具,可自定义名称。该标签最大长度为127。 | 字符串 | 不可缺省。 |
| description | 标识对Ability的描述。取值可以是描述性内容,也可以是对描述性内容的资源索引,以支持多语言。该标签最大长度为255个字节。 | 字符串 | 可缺省,缺省值为空。 |
| icon | 标识Ability图标资源文件的索引。取值示例:$media:ability_icon。如果在该Ability的skills属性中,actions的取值包含 “action.system.home”,entities取值中包含“entity.system.home”,则该Ability的icon将同时作为应用的icon。如果存在多个符合条件的Ability,则取位置靠前的Ability的icon作为应用的icon。<br /> 说明:应用的“icon”和“label”是用户可感知配置项,需要区别于当前所有已有的应用“icon”或“label”(至少有一个不同)。 | 字符串 | 可缺省,缺省值为空。 |
| label | 标识Ability对用户显示的名称。取值可以是Ability名称,也可以是对该名称的资源索引,以支持多语言。如果在该Ability的skills属性中,actions的取值包含 “action.system.home”,entities取值中包含“entity.system.home”,则该Ability的label将同时作为应用的label。如果存在多个符合条件的Ability,则取位置靠前的Ability的label作为应用的label。<br /> 说明: 应用的“icon”和“label”是用户可感知配置项,需要区别于当前所有已有的应用“icon”或“label”(至少有一个不同)。该标签为资源文件中定义的字符串的引用,或以"{}"包括的字符串。该标签最大长度为255。 | 字符串 | 可缺省,缺省值为空。 |
| uri | 标识Ability的统一资源标识符。该标签最大长度为255。 | 字符串 | 可缺省,对于data类型的Ability不可缺省。 |
| launchType | 标识Ability的启动模式,支持“standard”和“singleton”两种模式:<br />standard:表示该Ability可以有多实例。该模式适用于大多数应用场景。<br />singleton:表示该Ability在所有任务栈中仅可以有一个实例。例如,具有全局唯一性的呼叫来电界面即采用“singleton”模式。 | 字符串 | 可缺省,缺省值为“singleton”。 |
| visible | 标识Ability是否可以被其他应用调用。<br />true:可以被其他应用调用。<br />false:不能被其他应用调用。 | 布尔值 | 可缺省,缺省值为false。 |
| permissions | 标识其他应用的Ability调用此Ability时需要申请的权限集合,一个数组元素为一个权限名称。通常采用反向域名格式(最大255字节),取值为系统预定义的权限。 | 字符串数组 | 可缺省,缺省值为空。 |
| skills | 标识Ability能够接收的want的特征。参考表17。 | 对象数组 | 可缺省,缺省值为空。 |
| deviceCapability | 标识Ability运行时要求设备具有的能力,采用字符串数组的格式表示。该标签为数组,支持最多配置512个元素,单个元素最大字节长度为64。 | 字符串数组 | 可缺省,缺省值为空。 |
| metaData | 元数据,参考表11。 | 对象 | 可缺省,缺省值为空。 |
| type | 标识Ability的类型。取值范围如下:<br />page:表示基于Page模板开发的FA,用于提供与用户交互的能力。<br />service:表示基于Service模板开发的PA,用于提供后台运行任务的能力。<br />data:表示基于Data模板开发的PA,用于对外部提供统一的数据访问抽象。<br />CA:表示支持其他应用以窗口方式调起该Ability。 | 字符串 | 不可缺省。 |
| orientation | 标识该Ability的显示模式。该标签仅适用于page类型的Ability。取值范围如下:<br />unspecified:由系统自动判断显示方向。<br />landscape:横屏模式。<br />portrait:竖屏模式。<br />followRecent:跟随栈中最近的应用。 | 字符串 | 可缺省,缺省值为“unspecified”。 |
| backgroundModes | 标识后台服务的类型,可以为一个服务配置多个后台服务类型。该标签仅适用于service类型的Ability。取值范围如下:<br />dataTransfer:通过网络/对端设备进行数据下载、备份、分享、传输等业务。<br />audioPlayback:音频输出业务。<br />audioRecording:音频输入业务。<br />pictureInPicture:画中画、小窗口播放视频业务。<br />voip:音视频电话、VOIP业务。<br />location:定位、导航业务。<br />bluetoothInteraction:蓝牙扫描、连接、传输业务。<br />wifiInteraction:WLAN扫描、连接、传输业务。<br />screenFetch:录屏、截屏业务。<br />multiDeviceConnection:多设备互联业务 | 字符串数组 | 可缺省,缺省值为空。 |
| grantPermission | 指定是否可以向Ability内任何数据授予权限。 | 布尔值 | 可缺省,缺省值为空。 |
| readPermission | 标识读取Ability的数据所需的权限。该标签仅适用于data类型的Ability。取值为长度不超过255字节的字符串。 | 字符串 | 可缺省,缺省值为空。 |
| writePermission | 标识向Ability写数据所需的权限。该标签仅适用于data类型的Ability。取值为长度不超过255字节的字符串。 | 字符串 | 可缺省,缺省值为空。 |
| configChanges | 标识Ability关注的系统配置集合。当已关注的配置发生变更后,Ability会收到onConfigurationUpdated回调。取值范围:<br />mcc:表示IMSI移动设备国家/地区代码(MCC)发生变更。典型场景:检测到SIM并更新MCC。<br />mnc:IMSI移动设备网络代码(MNC)发生变更。典型场景:检测到SIM并更新MNC。<br />locale:表示语言区域发生变更。典型场景:用户已为设备文本的文本显示选择新的语言类型。<br />layout:表示屏幕布局发生变更。典型场景:当前有不同的显示形态都处于活跃状态。<br />fontSize:表示字号发生变更。典型场景:用户已设置新的全局字号。<br />orientation:表示屏幕方向发生变更。典型场景:用户旋转设备。<br />density:表示显示密度发生变更。典型场景:用户可能指定不同的显示比例,或当前有不同的显示形态同时处于活跃状态。<br />size:显示窗口大小发生变更。<br />smallestSize:显示窗口较短边的边长发生变更。<br />colorMode:颜色模式发生变更。 | 字符串数组 | 可缺省,缺省值为空。 |
| mission | 标识Ability指定的任务栈。该标签仅适用于page类型的Ability。默认情况下应用中所有Ability同属一个任务栈。 | 字符串 | 可缺省,缺省为应用的包名。 |
| targetAbility | 标识当前Ability重用的目标Ability。该标签仅适用于page类型的Ability。如果配置了targetAbility属性,则当前Ability(即别名Ability)的属性中仅name、icon、label、visible、permissions、skills生效,其它属性均沿用targetAbility中的属性值。目标Ability必须与别名Ability在同一应用中,且在配置文件中目标Ability必须在别名之前进行声明。 | 字符串 | 可缺省,缺省值为空。表示当前Ability不是一个别名Ability。 |
| formsEnabled | 标识Ability是否支持卡片(forms)功能。该标签仅适用于page类型的Ability。<br />true表示支持卡片能力,false表示不支持卡片能力。 | 布尔值 | 可缺省,缺省值为false。 |
| forms | 标识服务卡片的属性。该标签仅当formsEnabled为true时,才能生效。参考表26。 | 对象数组 | 可缺省,缺省值为空。 |
| srcLanguage | Ability开发语言的类型,开发者创建工程时由开发者手动选择开发语言。 | 字符串 | 可缺省,取值为"js"或"ets" |
| srcPath | 该标签标识Ability对应的JS组件代码路径,该标签最大长度为127字节。 | 字符串 | 可缺省,缺省值为空。 |
| uriPermission | 标识该Ability有权访问的应用程序数据。此属性由模式和路径子属性组成。此属性仅对类型提供者的能力有效。运行OHOS的设备不支持此属性。参考表16。 | 对象 | 可缺省,缺省值为空。 |
| startWindowIcon | 标识该Ability启动页面图标资源文件的索引。该标签仅适用于page类型的ability。取值示例:$media:icon。 | 字符串 | 可缺省,缺省值为空。|
| startWindowBackground | 标识该Ability启动页面背景颜色资源文件的索引。该标签仅适用于page类型的ability。取值示例:$color:red。 | 字符串 | 可缺省,缺省值为空。|
| removeMissionAfterTerminate | 该标签标识ability销毁后是否从任务列表中移除任务。该标签仅适用于page类型的ability。true表示销毁后移除任务, false表示销毁后不移除任务。 | 布尔值 | 可缺省,缺省值为false。 |
表16 uriPermission对象的内部结构说明
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | ----------------------- | -------- | ------------------------- |
| path | uriPermission标识的路径,该标签最大字节长度为255个字节。 | 字符串 | 不可缺省。 |
| mode | uriPermission的匹配模式 | 字符串 | 可缺省,缺省值为"default"。 |
abilities示例:
```json
{
"module": {
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"orientation": "unspecified",
"formsEnabled": false,
"name": ".MainAbility",
"srcLanguage": "ets",
"srcPath": "MainAbility",
"icon": "$media:icon",
"description": "$string:ability_desc",
"label": "$string:ability_label",
"type": "page",
"visible": true,
"launchType": "standard"
}
]
}
}
```
表17 skills对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| -------- | ------------------------------------------------------------ | ---------- | -------------------- |
| actions | 标识能够接收的want的action值,可以包含一个或多个action。取值通常为系统预定义的action值。 | 字符串数组 | 可缺省,缺省值为空。 |
| entities | 标识能够接收的want的Ability的类别(如视频、桌面应用等),可以包含一个或多个entity。 | 字符串数组 | 可缺省,缺省值为空。 |
| uris | 该标签标识向want过滤器添加数据规范集合。该规范可以是只有数据类型(mimeType属性),可以是只有URI,也可以是既有数据类型又有URI。<br />URI由其各个部分的单独属性指定:\<scheme>://\<host>:\<port>/[\<path>\|\<pathStartWith>\|\<pathRegx>]。其中,scheme字段配置为uri时必配;当只设置数据类型(mimeType)时,则scheme字段为非必配项。参考表18。 | 对象数组 | 可缺省,缺省值为空。 |
表18 uris对象的内部结构说明
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| ------------- | -------------------------- | -------- | -------------------- |
| scheme | 标识uri的scheme值。 | 字符串 | 不可缺省。 |
| host | 标识uri的host值。 | 字符串 | 可缺省,缺省值为空。 |
| port | 标识uri的port值。 | 字符串 | 可缺省,缺省值为空。 |
| pathStartWith | 标识uri的pathStartWith值。 | 字符串 | 可缺省,缺省值为空。 |
| path | 标识uri的path值。 | 字符串 | 可缺省,缺省值为空。 |
| pathRegx | 标识uri的pathRegx值。 | 字符串 | 可缺省,缺省值为空。 |
| type | 标识uri的type值。 | 字符串 | 可缺省,缺省值为空。 |
skills示例:
```json
{
"module": {
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
],
"uris": [
{
"scheme": "http",
"host": "www.example.com",
"port": "8080",
"path": "query/student/name",
"type": "text/*"
}
]
}
]
}
]
}
}
```
表19 reqPermissions权限申请字段说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ---------- | ------------------------------------------------------------ | -------- | ------------------ |
| name | 需要使用的权限名称。 | 字符串 | 不可缺省。 |
| reason | 描述申请权限的原因。需要做多语种适配。 | 字符串 | 分情况:当申请的权限为user_grant时,必须填写此字段,否则不允许在应用市场上架;其它权限可缺省,缺省值为空。 |
| usedScene | 描述权限使用的场景和时机。场景类型如下两种:</br>ability:ability的名称,可配置多个。</br>when:调用时机,可填的值有inuse(使用时)、always(始终) | 对象 | 可缺省,缺省值为空。when可缺省,缺省值为“inuse”。 |
具体示例可参考[访问控制开发指导](../security/accesstoken-guidelines.md#fa模型)
表20 usedScene对象内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ------- | --------------------| -------- | ------ |
| ability | 标识哪些Ability需要此权限,里面配置Ability的名称。| 字符串数组 | 可缺省,缺省表示所有Ability都需要此权限。 |
| when | 标识使用此权限的使用时间:</br>inuse:使用时需要此权限。</br>always:所有时间都需要此权限。 | 枚举值 | 可缺省,缺省值为空。 |
表21 js对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| -------- | ------------------------------------------------------------ | -------- | ------------------------ |
| name | 标识JS Component的名字。该标签不可缺省,默认值为default。 | 字符串 | 不可缺省。 |
| pages | 标识JS Component的页面用于列举JS Component中每个页面的路由信息[页面路径+页面名称]。该标签不可缺省,取值为数组,数组第一个元素代表JS FA首页。 | 字符串数组 | 不可缺省。 |
| window | 用于定义与显示窗口相关的配置。参考表22。 | 对象 | 可缺省,缺省值参考表22。 |
| type | 标识JS应用的类型。取值范围如下:<br />normal:标识该JS Component为应用实例。<br />form:标识该JS Component为卡片实例。 | 字符串 | 可缺省,缺省值为“normal” |
| mode | 定义JS组件的开发模式。参考表23。 | 对象 | 可缺省,缺省值为空。 |
表22 window对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| --------------- | ------------------------------------------------------------ | -------- | ----------------------- |
| designWidth | 标识页面设计基准宽度。以此为基准,根据实际设备宽度来缩放元素大小。 | 数值 | 可缺省,缺省值为720px。 |
| autoDesignWidth | 标识页面设计基准宽度是否自动计算。当配置为true时,designWidth将会被忽略,设计基准宽度由设备宽度与屏幕密度计算得出。 | 布尔值 | 可缺省,缺省值为false。 |
表23 mode对象的内部结构说明
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------------------- | ----------------------------------- | --------------------------- |
| type | 定义JS组件的功能类型 | 字符串,取值为"pageAbility"、"form" | 可缺省,缺省值为"pageAbility"。 |
| syntax | 定义JS组件的语法类型 | 字符串,取值为"hml","ets" | 可缺省,缺省值为"hml"。 |
js示例:
```json
{
"module": {
"js": [
{
"mode": {
"syntax": "ets",
"type": "pageAbility"
},
"pages": [
"pages/LoginPage",
"pages/MinePage",
"pages/RegistrationSuccessPage",
"pages/PrivacyPage",
"pages/CustomerServicePage"
],
"name": ".MainAbility",
"window": {
"designWidth": 720,
"autoDesignWidth": false
}
}
]
}
}
```
表24 shortcuts对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ---------- | ------------------------------------------------------------ | -------- | ------------------ |
| shortcutId | 标识快捷方式的ID。字符串的最大长度为63字节。 | 字符串 | 不可缺省。 |
| label | 标识快捷方式的标签信息,即快捷方式对外显示的文字描述信息。取值可以是描述性内容,也可以是标识label的资源索引。字符串最大长度为63字节。 | 字符串 | 可缺省,缺省值为空。 |
| icon | 标识快捷方式的图标信息。取值为表示icon的资源索引。 | 字符串 | 可缺省,缺省值为空。 |
| intents | 标识快捷方式内定义的目标intent信息集合,每个intent可配置两个子标签,targetClass, targetBundle。参考表25。 | 对象数组 | 可缺省,缺省值为空。 |
表25 intents对象的内部结构说明
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| ------------ | --------------------------------------- | -------- | -------------------- |
| targetClass | 标识快捷方式目标类名。 | 字符串 | 可缺省,缺省值为空。 |
| targetBundle | 标识快捷方式目标Ability所在应用的包名。 | 字符串 | 可缺省,缺省值为空。 |
shortcuts示例:
```json
{
"module": {
"shortcuts": [
{
"shortcutId": "id",
"label": "$string:shortcut",
"intents": [
{
"targetBundle": "com.example.myapplication",
"targetClass": "com.example.myapplication.MainAbility"
}
]
}
]
}
}
```
表26 forms对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ------------------- | ------------------------------------------------------------ | ---------- | ------------------------ |
| name | 标识卡片的类名。字符串最大长度为127字节。 | 字符串 | 不可缺省。 |
| description | 标识卡片的描述。取值可以是描述性内容,也可以是对描述性内容的资源索引,以支持多语言。字符串最大长度为255字节。 | 字符串 | 可缺省,缺省值为空。 |
| isDefault | 标识该卡片是否为默认卡片,每个Ability有且只有一个默认卡片。<br />true:默认卡片。<br />false:非默认卡片。 | 布尔值 | 不可缺省。 |
| type | 标识卡片的类型。取值范围如下:<br />JS:JS卡片。 | 字符串 | 不可缺省。 |
| colorMode | 标识卡片的主题样式,取值范围如下:<br />auto:自适应。<br />dark:深色主题。<br />light:浅色主题。 | 字符串 | 可缺省,缺省值为“auto”。 |
| supportDimensions | 标识卡片支持的外观规格,取值范围:<br />1 * 2:表示1行2列的二宫格。<br />2 * 1:表示2行1列的二宫格。<br />2 * 2:表示2行2列的四宫格。<br />2 * 4:表示2行4列的八宫格。<br />4 * 4:表示4行4列的十六宫格。 | 字符串数组 | 不可缺省。 |
| defaultDimension | 标识卡片的默认外观规格,取值必须在该卡片supportDimensions配置的列表中。 | 字符串 | 不可缺省。 |
| updateEnabled | 标识卡片是否支持周期性刷新,取值范围:<br />true:表示支持周期性刷新,可以在定时刷新(updateDuration)和定点刷新(scheduledUpdateTime)两种方式任选其一,优先选择定时刷新。<br />false:表示不支持周期性刷新。 | 布尔值 | 不可缺省。 |
| scheduledUpdateTime | 标识卡片的定点刷新的时刻,采用24小时制,精确到分钟。 | 字符串 | 可缺省,缺省值为“0:0”。 |
| updateDuration | 标识卡片定时刷新的更新周期,单位为30分钟,取值为自然数。<br />当取值为0时,表示该参数不生效。<br />当取值为正整数N时,表示刷新周期为30*N分钟。 | 数值 | 可缺省,缺省值为0。 |
| formConfigAbility | 标识用于调整卡片的设施或活动的名称。 | 字符串 | 可缺省,缺省值为空。 |
| formVisibleNotify | 标识是否允许卡片使用卡片可见性通知 | 字符串 | 可缺省,缺省值为空。 |
| jsComponentName | 标识JS卡片的Component名称。字符串最大长度为127字节。仅当卡片类型为JS卡片时,需要配置该标签。 | 字符串 | 不可缺省。 |
| metaData | 标识卡片的自定义信息,包含customizeData数组标签。参考表11。 | 对象 | 可缺省,缺省值为空。 |
| customizeData | 标识自定义的卡片信息。参考表14。 | 对象数组 | 可缺省,缺省值为空。 |
forms示例:
```json
{
"module": {
"abilities": [
{
"forms": [
{
"name": "Form_Js",
"description": "It's Js Form",
"type": "JS",
"jsComponentName": "card",
"colorMode": "auto",
"isDefault": true,
"updateEnabled": true,
"scheduledUpdateTime": "11:00",
"updateDuration": 1,
"defaultDimension": "2*2",
"supportDimensions": [
"2*2",
"2*4",
"4*4"
]
},
{
"name": "Form_Js",
"description": "It's JS Form",
"type": "Js",
"colorMode": "auto",
"isDefault": false,
"updateEnabled": true,
"scheduledUpdateTime": "21:05",
"updateDuration": 1,
"defaultDimension": "1*2",
"supportDimensions": [
"1*2"
],
"landscapeLayouts": [
"$layout:ability_form"
],
"portraitLayouts": [
"$layout:ability_form"
],
"formConfigAbility": "ability://com.example.myapplication.fa/.MainAbility",
"metaData": {
"customizeData": [
{
"name": "originWidgetName",
"value": "com.example.myapplication.testWidget"
}
]
}
}
]
}
}
}
```
表27 distroFilter对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ------------- | ------------------------------------------------------------ | -------- | -------------------- |
| apiVersion | 标识支持的apiVersion范围。参考表28。 | 对象 | 可缺省,缺省值为空。 |
| screenShape | 标识屏幕形状的支持策略。参考表29。 | 对象数组 | 可缺省,缺省值为空。 |
| screenWindow | 标识应用运行时窗口的分辨率支持策略。该字段仅支持对轻量级智能穿戴设备进行配置。参考表30。 | 对象数组 | 可缺省,缺省值为空。 |
| screenDensity | 标识屏幕的像素密度(dpi:Dots Per Inch)。参考表31。 | 对象数组 | 可缺省,缺省值为空。 |
| countryCode | 标识分发应用时的国家码。具体值参考ISO-3166-1的标准,支持多个国家和地区的枚举定义。参考表32。 | 对象数组 | 可缺省,缺省值为空。 |
表28 apiVersion对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| -------- | ------------------------------------------------------------ | -------- | -------------------- |
| policy | 标识该子属性取值的黑白名单规则。配置为“exclude”或“include”。“include”表示该字段取值为白名单,满足value枚举值匹配规则的表示匹配该属性。 | 字符串 | 可缺省,缺省值为空。 |
| value | 支持的取值为API Version存在的整数值,例如4、5、6。场景示例:某应用,针对相同设备型号,<br />同时在网的为使用API 5和API 6开发的两个软件版本,则允许上架2个entry类型的安装包,分别支持到对应设备侧软件版本的分发。 | 数组 | 可缺省,缺省值为空。 |
表29 screenShape对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| -------- | ------------------------------------------------------------ | -------- | -------------------- |
| policy | 标识该子属性取值的黑白名单规则。配置为“exclude”或“include”。“include”表示该字段取值为白名单,满足value枚举值匹配规则的表示匹配该属性。 | 字符串 | 可缺省,缺省值为空。 |
| value | 支持的取值为circle(圆形)、rect(矩形)。场景示例:针对智能穿戴设备,可为圆形表盘和矩形表盘分别提供不同的HAP。 | 数组 | 可缺省,缺省值为空。 |
表30 screenWindow对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| -------- | ------------------------------------------------------------ | -------- | -------------------- |
| policy | 标识该子属性取值的黑白名单规则。配置为“exclude”或“include”。“include”表示该字段取值为白名单,满足value枚举值匹配规则的表示匹配该属性。 | 字符串 | 可缺省,缺省值为空。 |
| value | 单个字符串的取值格式为:“宽 * 高”,取值为整数像素值,例如“454 * 454”。 | 数组 | 可缺省,缺省值为空。 |
表31 screenDensity对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| -------- | ------------------------------------------------------------ | -------- | -------------------- |
| policy | 标识该子属性取值的黑白名单规则。配置为“exclude”或“include”。“include”表示该字段取值为白名单,满足value枚举值匹配规则的表示匹配该属性。 | 字符串 | 可缺省,缺省值为空。 |
| value | 取值范围如下:<br />sdpi:表示小规模的屏幕密度(Small-scale Dots Per Inch),适用于dpi取值为(0,120]的设备。<br />mdpi:表示中规模的屏幕密度(Medium-scale Dots Per Inch),适用于dpi取值为(120,160]的设备。<br />ldpi:表示大规模的屏幕密度(Large-scale Dots Per Inch),适用于dpi取值为(160,240]的设备。<br />xldpi:表示特大规模的屏幕密度(Extra Large-scale Dots Per Inch),适用于dpi取值为(240,320]的设备。<br />xxldpi:表示超大规模的屏幕密度(Extra Extra Large-scale Dots Per Inch),适用于dpi取值为(320,480]的设备。<br />xxxldpi:表示超特大规模的屏幕密度(Extra Extra Extra Large-scale Dots Per Inch),适用于dpi取值为(480,640]的设备。 | 数组 | 可缺省,缺省值为空。 |
表32 countryCode对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| -------- | ------------------------------------------------------------ | ---------- | -------------------- |
| policy | 标识该子属性取值的黑白名单规则。配置为“exclude”或“include”。“include”表示该字段取值为白名单,满足value枚举值匹配规则的表示匹配该属性。 | 字符串 | 可缺省,缺省值为空。 |
| value | 该标签标识应用需要分发的国家码,标签为字符串数组,子串表示支持的国家或地区,由两个大写字母表示。 | 字符串数组 | 可缺省,缺省值为空。 |
distroFilter示例:
```json
{
"module": {
"distroFilter": {
"apiVersion": {
"policy": "include",
"value": [
4,
5
]
},
"screenShape": {
"policy": "include",
"value": [
"circle",
"rect"
]
},
"screenWindow": {
"policy": "include",
"value": [
"454*454",
"466*466"
]
},
"screenDensity": {
"policy": "exclude",
"value": [
"ldpi",
"xldpi"
]
},
"countryCode": {
"policy": "include",
"value": [
"CN",
"HK"
]
}
}
}
}
```
表33 commonEvents对象的内部结构说明
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| ---------- | ------------------------------------------------------------ | ---------- | ------------------ |
| name | 标识静态公共事件名称,该标签最大长度为127字节。 | 字符串 | 不可缺省。 |
| permission | 此标签标识实现静态公共事件所需要申请的权限,该标签最大长度为127字节。 | 字符串 | 可缺省,缺省值为空。 |
| data | 标识配置当前静态公共事件要携带的附加数据数组。 | 字符串数组 | 可缺省,缺省值为空。 |
| type | 该标签用于配置当前静态公共事件的分类数组。 | 字符串数组 | 可缺省,缺省值为空。 |
| events | 此标签标识可接收的意图的一组事件值。一般由系统预定义,也可以自定义。 | 字符串数组 | 不可缺省。 |
commonEvents示例:
```json
{
"module": {
"commonEvents": [
{
"name": "MainAbility",
"permission": "string",
"data": [
"string",
"string"
],
"events": [
"string",
"string"
]
}
]
}
}
```
表34 testRunner对象的内部结构说明
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | -------------------- | -------- | ---------- |
| name | 标识测试框架对象名称,该标签最大长度为255字节。 | 字符串 | 不可缺省。 |
| srcPath | 标识测试框架代码路径,该标签最大长度为255字节。 | 字符串 | 不可缺省。 |
```json
{
"module": {
"testRunner": {
"name": "myTestRunnerName",
"srcPath": "etc/test/TestRunner.ts"
}
}
}
```
表35 definePermissions对象内部结构说明
definePermission仅支持系统应用配置,三方应用配置不生效。
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ----------------------- | ------------------------------------------------------------ | -------- | ---------- |
| name | 标识权限的名称,该标签最大长度为255字节。 | 字符串 | 不可缺省。 |
| grantMode | 标识权限的授予方式,支持如下两种授予模式:<br />system_grant:安装后系统自动授予该权限。<br />user_grant:使用时动态申请,用户授权后才可使用。 | 字符串 | 可缺省,缺省值为"system_grant"。 |
| availableLevel | 标识权限限制类别。可选值如下:<br />system_core:系统核心权限。<br />system_basic:系统基础权限。<br />normal:普通权限。所有应用允许申请的权限。 | 字符串 | 可缺省,缺省值为"normal"。 |
| provisionEnable | 标识权限是否支持证书方式申请权限,包括高级别的权限。配置为true标识需要开发者可以通过provision方式申请权限。 | 布尔值 | 可缺省,缺省值为true。 |
| distributedSceneEnabled | 标识权限是否支持分布式场景下使用该权限。 | 布尔值 | 可缺省,缺省值为false。 |
| label | 标识权限的简短描述,配置为对描述内容的资源索引。 | 字符串 | 可缺省,缺省值为空。 |
| description | 标识权限的详细描述,可以是字符串(最大长度255字节),或者为对描述内容的资源索引。 | 字符串 | 可缺省,缺省值为空。 |
# 应用包结构配置文件的说明(Stage模型)
在开发stage模型的应用程序时,需要在app.json5和module.json5配置文件中对应用的包结构进行声明。
## 配置文件内部结构
配置文件由app.json5和module.json5两部分组成。配置文件的内部结构参见表1。
表1 配置文件的内部结构说明
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | ------------------------------------------------------------ | -------- | ---------- |
| app | 标识应用的全局配置信息。参考[app对象内部结构](#app对象内部结构)。 | 对象 | 不可缺省。 |
| module | 标识HAP包的配置信息。该标签下的配置只对当前HAP包生效。参考[module对象内部结构](#module对象内部结构)。 | 对象 | 不可缺省。 |
### app对象内部结构
该标签为整个应用的属性,影响应用中所有HAP及组件。该标签的内部结构参见表2。
表2 app对象的内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ------------------------------ | ------------------------------------------------------------ | -------- | ------------------------------------------- |
| bundleName | 该标签标识应用的包名,用于标识应用的唯一性。标签的值命名规则 :<br /> 1)字符串以字母、数字、下划线和符号”.”组成;<br /> 2)以字母开头;<br /> 3)最小长度7字节,最大长度127个字节。<br /> 推荐采用反域名形式命名(如 :com.example.xxx,建议第一级为域名后缀com,第二级为厂商/个人名,第三级为应用名,也可以多级)。 | 字符串 | 不可缺省。 |
| debug | 该标签标识应用是否可调试。该标签由IDE编译构建时产生。 | 布尔值 | 可缺省,缺省值为false。 |
| icon | 该标签标识应用的图标,标签值为图标资源文件的索引。 | 字符串 | 不可缺省。 |
| label | 该标签标识应用的名称,标签值为字符串资源的索引。 | 字符串 | 不可缺省。 |
| description | 该标签标识App的描述信息,标签值是是字符串类型或对描述内容的字符串资源索引。 | 字符串 | 可缺省,缺省值为空。 |
| vendor | 该标签是对应用开发厂商的描述。最大长度255字节。 | 字符串 | 可缺省,缺省值为空。 |
| versionCode | 该标签标识应用的版本号,该标签值为32位非负整数。此数字仅用于确定某个版本是否比另一个版本更新,数值越大表示版本越高。<br />开发者可以将该值设置为任何正整数,但是必须确保应用的新版本都使用比旧版本更大的值。versionCode 值应小于2的31次方。 | 数值 | 不可缺省。 |
| versionName | 该标签标识版本号的文字描述,用于向用户展示。<br />该标签仅由数字和点构成,推荐采用“A.B.C.D”四段式的形式。四段式推荐的含义如下所示。<br/>第一段 :主版本号/Major,范围0-99,重大修改的版本,如实现新的大功能或重大变化。<br/>第二段 :次版本号/Minor,范围0-99,表示实现较突出的特点,如新功能添加和大问题修复。<br/>第三段 :特性版本号/Feature,范围0-99,标识规划的新版本特性。<br/>第四段 :修订版本号/Patch,范围0-999,表示维护版本,修复bug。 | 字符串 | 不可缺省。 |
| minCompatibleVersionCode | 该标签标识该app能够兼容的最低历史版本号,用于跨设备兼容性判断。 | 数值 | 可缺省。缺省值等于versionCode标签值。|
| minAPIVersion | 该标签标识应用运行需要的SDK的API最小版本。 | 数值 | 可缺省,缺省值为bundle-profile.json5中的compatibleSdkVersion。|
| targetAPIVersion | 该标签标识应用运行需要的API目标版本。 | 数值 | 可缺省,缺省值为bundle-profile.json5中的compileSdkVersion。|
| apiReleaseType | 该标签标识应用运行需要的API目标版本的类型,采用字符串类型表示。取值为“CanaryN”、“BetaN”或者“Release”,其中,N代表大于零的整数。<br />Canary :受限发布的版本。<br/>Beta :公开发布的Beta版本。<br/>Release :公开发布的正式版本。<br/>该字段由IDE读取当前使用的SDK的stage来生成。 | 字符串 | 可缺省,由IDE生成并覆盖。 |
| distributedNotificationEnabled | 该标签标记该应用是否开启分布式通知。 | 布尔值 | 可缺省,缺省值为true。 |
| entityType | 该标签标记该应用的类别,具体有 :游戏类(game),影音类(media)、社交通信类(communication)、新闻类(news)、<br />出行类(travel)、工具类(utility)、购物类(shopping)、教育类(education)、少儿类(kids)、商务类(business)、拍摄类(photography)、未指定(unspecified)。 | 字符串 | 可缺省,缺省值为"unspecified"。 |
| multiProjects | 标识当前工程是否支持多工程。 | 布尔值 | 可缺省,缺省值为false。 |
| 设备类型 | 该标签可以配置多个,表示具体设备上的特殊配置信息,具体的设备类型有:"tablet"、"tv"、"wearable"、"car"、"default",可包含的字段有:minAPIVersion、distributedNotificationEnabled。 | 对象 | 可缺省,缺省值使用app下面相关的字段。 |
app.json示例 :
```json
{
"app": {
"bundleName": "com.example.myapplication",
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:app_icon",
"label": "$string:app_name",
"distributedNotificationEnabled": true,
"minCompatibleVersionCode": 9,
"minAPIVersion": 9,
"targetAPIVersion": 9,
"apiReleaseType": "Canary1",
"debug": false,
"description": "$string:app_description",
"entityType": "game",
"car": {
"minAPIVersion": 9
}
}
}
```
### module对象内部结构
HAP包的配置信息,该标签下的配置只对当前HAP包生效。
表3 module对象内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| -------------------- | ------------------------------------------------------------ | ---------- | ------------------------------------------------------------ |
| name | 该标签标识当前module的名字。module打包成HAP后,表示HAP的名称,标签值采用字符串表示(最大长度31字节),该名称在整个应用要唯一。 | 字符串 | 不可缺省。 |
| type | 该标签标识当前module的类型。类型有两种,分别是entry、feature。 | 字符串 | 不可缺省。 |
| srcEntrance | 该标签标识HAP所对应的入口js代码路径,标签值为字符串(最大长度127字节)。 | 字符串 | 可缺省,缺省值为空。 |
| description | 该标签标识HAP包的描述信息,标签值是是字符串类型或对描述内容的字符串资源索引。 | 字符串 | 可缺省,缺省值为空。 |
| process | 该标签标识HAP的进程名,标签值为字符串类型(最大长度31字节)。如果在HAP标签下配置了process,该应用的所有ability都运行在该进程中。该标签只支持系统应用配置。 | 字符串 | 可缺省,缺省值为app标签下的bundleName。 |
| mainElement | 该标签标识HAP的入口Ability名称或者Extension名称。只有配置为mainElement的Ability或者Extension才允许在服务中心露出。 | 字符串 | 创建OpenHarmony原子化服务时,不可缺省。OpenHarmony应用下,可缺省,缺省值为空。 |
| deviceTypes | 该标签标识HAP可以运行在哪类设备上,标签值采用字符串数组的表示,系统预定义的设备类型见表4。 | 字符串数组 | 不可缺省。 |
| deliveryWithInstall | 该标签标识当前HAP是否在用户主动安装的时候安装,true表示主动安装时安装,false表示主动安装时不安装。 | 布尔值 | 不可缺省。 |
| installationFree | 标识当前HAP是否支持免安装特性。所有Hap包都需要配置不可缺省。<br/>true :表示支持免安装特性,且符合免安装约束。<br/>false :表示不支持免安装特性。<br/><br/>当entry.hap该字段配置为true时,与该entry.hap相关的所有feature.hap该字段也需要配置为true。<br/>当entry.hap该字段配置为false时,与该entry.hap相关的各feature.hap该字段可按业务需求配置true或false。 | 布尔值 | 不可缺省。 |
| virtualMachine | 该标签用于标识当前HAP运行的目标虚拟机类型,供云端分发使用,如应用市场和分发中心。<br/>该标签值为字符串。如果目标虚拟机类型为方舟虚拟机,则其值为"ark + 版本号"。 该标签由IDE构建HAP的时候自动插入。 | 字符串 | 该标签由IDE构建HAP的时候自动插入。 |
| uiSyntax(deprecated) | uiSyntax定义该JS Component的语法类型。<br />hml标识该JS Component使用hml/css/js进行开发;<br/>ets标识该JS Component使用ArkUI声明式语法进行开发。 | 字符串 | 可缺省,缺省值为"hml",该字段从API9开始废弃。 |
| pages | 标识当前Module的profile资源,用于列举JS Component中每个页面信息。该标签最大长度为255个字节。 | 字符串 | 在有ability的场景下,不可缺省。 |
| metadata | 该标签标识Hap的自定义元信息。参考[metadata对象内部结构](#metadata对象内部结构)。 | 对象数组 | 可缺省,缺省值为空。 |
| abilities | 描述元能力的配置信息,该标签下的配置只对当前ability生效。参考[abilities对象内部结构](#abilities对象内部结构)。 | 对象数组 | 可缺省,缺省值为空。 |
| extensionAbilities | 描述extensionAbilities的配置信息,该标签下的配置只对当前extensionAbility生效。参考[extensionAbilities对象内部结构](#extensionabilities对象内部结构)。 | 对象数组 | 可缺省,缺省值为空。 |
| definePermissions | 标识HAP定义的权限,仅支持系统应用配置,三方应用配置不生效。参考[definePermissions对象内部结构](#definepermissions对象内部结构)。 | 对象数组 | 可缺省,缺省值为空。 |
| requestPermissions | 该标签标识应用运行时需向系统申请的权限集合。参考[requestPermissions对象内部结构](#requestpermissions对象内部结构)。 | 对象数组 | 可缺省,缺省值为空。 |
| testRunner | 该标签用于支持对测试框架的配置,参考[testRunner对象内部结构说明](#testrunner对象内部结构)。 | 对象 | 可缺省,缺省值为空。 |
module.json5示例:
```json
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"default",
"tablet"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"metadata": [
{
"name": "name1",
"value": "value1",
"resource": "$profile:config_file1"
},
{
"name": "name2",
"value": "value2",
"resource": "$profile:config_file2"
}
],
"abilities": [
{
"name": "EntryAbility",
"srcEntrance": "./ets/entryability/EntryAbility.ts",
"description": "$string:ability_desc",
"icon": "$media:icon",
"label": "$string:ability_label",
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:start_window_background",
"visible": true,
"backgroundModes": [
"dataTransfer",
"audioPlayback",
"audioRecording",
"location",
"bluetoothInteraction",
"multiDeviceConnection",
"wifiInteraction",
"voip",
"taskKeeping"
],
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
]
}
],
"requestPermissions": [
{
"name": "permissionName",
"reason": "$string:reason",
"usedScene": {
"abilities": [
"EntryFormAbility"
],
"when": "inuse"
}
}
],
"extensionAbilities": [
{
"name": "EntryFormAbility",
"srcEntrance": "./ets/entryformability/EntryFormAbility.ts",
"label": "$string:EntryFormAbility_label",
"description": "$string:EntryFormAbility_desc",
"type": "form",
"metadata": [
{
"name": "ohos.extension.form",
"resource": "$profile:form_config"
}
]
}
]
}
}
```
pages示例 :
1.在开发视图的resources/base/profile下面定义配置文件main_pages.json(文件名称可由开发者定义):
```json
{
"src": [
"pages/LoginPage",
"pages/MinePage",
"pages/RegistrationSuccessPage",
"pages/PrivacyPage",
"pages/CustomerServicePage"
]
}
```
2.在module.json5的module标签下定义pages信息 :
```json
{
"module": {
"pages": "$profile:main_pages"
}
}
```
表4 deviceTypes对象的系统预定义设备
| 设备类型 | 枚举值 | 说明 |
| -------- | ----------- | -------- |
| 平板 | tablet | - |
| 智慧屏 | tv | - |
| 智能手表 | wearable | 系统能力较丰富的手表,具备电话功能。 |
| 车机 | car | - |
| 默认设备 | default | 能够使用全部系统能力的OpenHarmony设备。 |
deviceTypes示例 :
```json
{
"module": {
"deviceTypes": [
"default",
"tablet"
]
}
}
```
#### metadata对象内部结构
描述的module、ability、extensionAbility配置信息,标签值为数组类型,该标签下的配置只对当前module、或者ability、或者extensionAbility生效。
表5 metadata对象内部结构说明
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | ------------------------------------------------------------ | -------- | -------------------------- |
| name | 该标签标识数据项的键名称,最大长度255字节。 | 字符串 | 可缺省,缺省值为空。 |
| value | 该标签标识数据项的值,最大长度255字节。 | 字符串 | 可缺省,缺省值为空。 |
| resource | 该标签标识定义用户自定义数据格式,标签值为标识该数据的资源的索引值。 | 字符串 | 可缺省,缺省值为空。 |
metadata示例:
```json
{
"module": {
"metadata": [
{
"name": "name1",
"value": "value1",
"resource": "$profile:config_file1"
},
{
"name": "name2",
"value": "value2",
"resource": "$profile:config_file2"
}
]
}
}
```
#### distroFilter对象内部结构
标识应用的分发规则。
该标签用于定义HAP包对应的细分设备规格的分发策略,以便在应用市场进行云端分发应用包时做精准匹配。该标签可配置的分发策略维度包括API Version、屏幕形状、窗口分辨率、屏幕分辨率、国家码。在进行分发时,通过deviceType与这五个属性的匹配关系,唯一确定一个用于分发到设备的HAP。<br/>
配置方式如下:<br/>
module标签配置metadata信息。name :"ohos.module.distro"。resource :指定distroFilter信息的资源位置。
表6 distroFilter对象内部结构
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| ------------- | ------------------------------------------------------------ | -------- | -------------------------- |
| apiVersion | 标识支持的apiVersion。 | 对象 | 可缺省,缺省值为空。 |
| screenShape | 标识屏幕形状的支持策略。仅支持liteWearable设备配置。 | 对象 | 可缺省,缺省值为空。 |
| screenWindow | 标识应用运行时窗口的分辨率支持策略。仅支持liteWearable设备配置。 | 对象 | 可缺省,缺省值为空。 |
| screenDensity | 标识屏幕的像素密度(dpi : Dot Per Inch)。 | 对象 | 可缺省,缺省值为空。 |
| countryCode | 标识应用需要分发的国家地区码。具体值以ISO-3166-1标准为准。 | 对象 | 可缺省,缺省值为空。 |
表7 apiVersion对象内部结构
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| -------- | ------------------------------------------------------------ | -------- | -------------------- |
| policy | 标识该子属性取值的黑白名单规则。配置为"exclude"或"include"。"include"表示该字段取值为白名单,满足value枚举值匹配规则的表示匹配该属性。 | 字符串 | 可缺省,缺省值为空。 |
| value | 支持的取值为API Version存在的整数值,例如4、5、6,最小取值为3。场景示例 :某应用,针对相同设备型号,同时在网的为使用API 5和API 6开发的两个软件版本,<br />则允许上架2个entry类型的安装包,分别支持到对应设备侧软件版本的分发。 | 数值数组 | 可缺省,缺省值为空。 |
表8 screenShape对象内部结构
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| -------- | ------------------------------------------------------------ | -------- | -------------------- |
| policy | 标识该子属性取值的黑白名单规则。配置为"exclude"或"include"。"include"表示该字段取值为白名单,满足value枚举值匹配规则的表示匹配该属性。 | 字符串 | 可缺省,缺省值为空。 |
| value | 支持的取值为circle(圆形屏幕)、rect(矩形屏幕)。场景示例:针对智能穿戴设备,可为圆形表盘和矩形表盘分别提供不同的HAP。 | 字符串数组 | 可缺省,缺省值为空。 |
表9 screenWindow对象内部结构
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | ------------------------------------------------------------ | -------- | -------------------- |
| policy | 标识该子属性取值的黑白名单规则。配置为"include"。"include"表示该字段取值为白名单,满足value枚举值匹配规则的表示匹配该属性。 | 字符串 | 可缺省,缺省值为空。 |
| value | 单个字符串的取值格式为 :“宽 * 高”,取值为整数像素值,例如“454 * 454”。 | 字符串数组 | 可缺省,缺省值为空。 |
表10 screenDensity对象内部结构
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| -------- | ------------------------------------------------------------ | -------- | -------------------- |
| policy | 标识该子属性取值的黑白名单规则。配置为"exclude"或"include"。"include"表示该字段取值为白名单,满足value枚举值匹配规则的表示匹配该属性。 | 字符串 | 可缺省,缺省值为空。 |
| value | 字符串范围如下:<br />sdpi :表示小规模的屏幕密度(Small-scale Dots per Inch),适用于dpi取值为(0,120]的设备。<br />mdpi :表示中规模的屏幕密度(Medium-scale Dots Per Inch),适用于dpi取值为(120,160]的设备。<br />ldpi :表示大规模的屏幕密度(Large-scale Dots Per Inch),适用于dpi取值为(160,240]的设备。<br /> xldpi :表示大规模的屏幕密度(Extra Large-scale Dots Per Inch),适用于dpi取值为(240,320]的设备。<br />xxldpi :表示大规模的屏幕密度(Extra Extra Large-scale Dots Per Inch),适用于dpi取值为(320,480]的设备。<br />xxxldpi :表示大规模的屏幕密度(Extra Extra Extra Large-scale Dots Per Inch),适用于dpi取值为(480, 640]的设备。 | 字符串数组 | 可缺省,缺省值为空。 |
表11 countryCode对象内部结构
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| -------- | ------------------------------------------------------------ | -------- | -------------------- |
| policy | 标识该子属性取值的黑白名单规则。配置为"exclude"或"include"。"include"表示该字段取值为白名单,满足value枚举值匹配规则的表示匹配该属性。 | 字符串 | 可缺省,缺省值为空。 |
| value | 支持多个国家和地区枚举定义。字符串表示所支持的国家或地区,由两个大写字母组成。 | 字符串数组 | 可缺省,缺省值为空。 |
distroFilter示例 :
1.在开发视图的resources/base/profile下面定义配置文件distro_filter_config.json(文件名称可由开发者定义):
```json
{
"distroFilter": {
"apiVersion": {
"policy": "include",
"value": [
4,
5
]
},
"screenShape": {
"policy": "include",
"value": [
"circle",
"rect"
]
},
"screenWindow": {
"policy": "include",
"value": [
"454*454",
"466*466"
]
},
"screenDensity": {
"policy": "exclude",
"value": [
"ldpi",
"xldpi"
]
},
"countryCode": {
"policy": "include",
"value": [
"CN",
"HK"
]
}
}
}
```
2.在module.json5的module标签下配置metadata信息:
```json
{
"module": {
"metadata": [
{
"name": "ohos.module.distro",
"resource": "$profile:distro_filter_config"
}
]
}
}
```
#### skills对象内部结构
该标签标识ability或者extension能够接收的意图的特征。
表12 skill对象内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| -------- | ------------------------------------------------------------ | ---------- | -------------------- |
| actions | 该标签标识能够接收的意图的action值的集合,取值通常为系统预定义的action值,也允许自定义。 | 字符串数组 | 可缺省,缺省值为空。 |
| entities | 该标签标识能够接收Want的元能力的类别集合,取值通常为系统预定义的类别,也允许自定义。 | 字符串数组 | 可缺省,缺省值为空。 |
| uris | 该标签标识与意图中URI(Uniform Resource Identifier)相匹配的集合。uris内部结构参考表13。 | 对象数组 | 可缺省,缺省值为空。 |
表13 uris对象内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| -------- | ------------------- | -------- | -------------------- |
| scheme | 标识URI的协议名部分,常见的有http、https、file、ftp等。 | 字符串 | 当配置type时可缺省,缺省值为空。没有配置type时不可缺省。 |
| host | 标识URI的主机地址部分,常见的有域名的方式,如example.com,ip地址的方式,如192.0.0.1。该字段要在scheme存在时才有意义。 | 字符串 | 可缺省,缺省值为空。 |
| port | 标识URI的端口部分。如http默认端口为80,https默认端口是443,ftp默认端口是21。该字段要在scheme和host都存在时才有意义。| 字符串 | 可缺省,缺省值为空。 |
| path \| pathStartWith \| <br />pathRegex | 标识URI的路径部分,path、pathStartWith和pathRegex配置时三选一。path标识URI与want中的路径部分全匹配,<br />pathStartWith标识URI与want中的路径部分允许前缀匹配,pathRegex标识URI与want中的路径部分允许正则匹配。<br />该字段要在scheme和host都存在时才有意义。| 字符串 | 可缺省,缺省值为空。 |
| type | 标识数据类型,使用MIME(Multipurpose Internet Mail Extensions)类型规范。可与scheme同时配置,也可以单独配置。| 字符串 | 可缺省,缺省值为空。 |
skills示例 :
```json
{
"module": {
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
],
"uris": [
{
"scheme": "https",
"host": "www.example.com",
"port": "8080",
"path": "query/student/name",
"pathStartWith": "query/student",
"pathRegex": "query/.*/name",
"type": "text/*"
}
]
}
]
}
],
"extensionAbilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
],
"uris": [
{
"scheme": "https",
"host": "www.example.com",
"port": "8080",
"path": "query/student/name",
"pathStartWith": "query/student",
"pathRegex": "query/.*/name",
"type": "text/*"
}
]
}
]
}
]
}
}
```
#### abilities对象内部结构
abilities描述Ability组件的配置信息,标签值为数组类型。
表14 ability对象内部结构说明
| 属性 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| --------------- | ------------------------------------------------------------ | ---------- | ------------------------------------------------------------ |
| name | 该标签标识当前Ability组件的逻辑名,该名称在整个应用要唯一,标签值采用字符串表示(最大长度127字节)。 | 字符串 | 不可缺省。 |
| srcEntrance | 该标签标识Ability组件所对应的js代码路径,标签值为字符串(最大长度127字节)。 | 字符串 | 不可缺省。 |
| launchType | 该标签标识Ability组件的启动模式,可选标签值:<br/>"standard":多实例,每次启动创建一个新的实例。<br/>"singleton":单实例,仅第一次启动创建新实例。<br/>"specified":运行时由开发者决定是否创建新实例。 | 字符串 | 可缺省,缺省值为"singleton"。 |
| description | 该标签标识Ability组件的描述信息,标签值是是字符串类型或对描述内容的资源索引,要求采用资源索引方式,以支持多语言。 | 字符串 | 可缺省,缺省值为空。 |
| icon | 该标签标识Ability组件的图标,标签值为图标资源文件的索引。 | 字符串 | 可缺省,缺省值为空。<br/>如果Ability组件被配置为MainElement,该标签必须配置。 |
| permissions | 该标签标识被其它应用的Ability组件调用时需要申请的权限的集合,一个数组元素为一个权限名称。通常采用反向域名格式(最大长度255字节),<br />取值为系统预定义的权限。 | 字符串数组 | 可缺省,缺省值为空。 |
| metadata | 该标签标识Ability组件的元信息。参考[metadata对象内部结构](#metadata对象内部结构)。 | 对象数组 | 可缺省,缺省值为空。 |
| visible | 该标签标识Ability组件是否可以被其它应用调用,true表示可以被其它应用调用, false表示不可以被其它应用调用。 | 布尔值 | 可缺省,缺省值为false。 |
| continuable | 该标签标识Ability组件是否可以迁移,true表示可以被迁移, false表示不可以被迁移。 | 布尔值 | 可缺省,缺省值为false。 |
| skills | 该标签标识Ability组件能够接收的意图的特征集。<br />配置规则 : entry包可以配置多个具有入口能力的skills标签(配置了action.system.home和entity.system.home)的Ability组件,<br />其中第一个配置了skills标签的Ability组件中的label和icon作为OpenHarmony服务或应用的label和icon。<br/>OpenHarmony服务的Feature包不能配置具有入口能力的skills标签。<br/>OpenHarmony应用的Feature包可以配置具有入口能力的skills标签。 <br />参考[skills对象内部结构](#skills对象内部结构)。 | 对象数组 | 可缺省,缺省值为空。 |
| backgroundModes | 该标签标识Ability组件的长时任务集合。指定用于满足特定类型的长时任务。<br />长时任务类型有如下 :<br/>dataTransfer :通过网络/对端设备进行数据下载、备份、分享、传输等业务。<br/>audioPlayback :音频输出业务。<br/>audioRecording :音频输入业务。<br/>location :定位、导航业务。<br/>bluetoothInteraction :蓝牙扫描、连接、传输业务(穿戴)。<br/>multiDeviceConnection :多设备互联业务。<br/>wifiInteraction :Wifi扫描、连接、传输业务(克隆 多屏)。<br/>voip :音视频电话,VOIP业务。<br/>taskKeeping :计算业务。 <br/> | 字符串数组 | 可缺省,缺省值为空。 |
| startWindowIcon | 标识该Ability组件启动页面图标资源文件的索引。取值示例:$media:icon。 | 字符串 | 不可缺省。|
| startWindowBackground | 标识该Ability组件启动页面背景颜色资源文件的索引。取值示例:$color:red。 | 字符串 | 不可缺省。|
| removeMissionAfterTerminate | 该标签标识Ability组件销毁后是否从任务列表中移除任务。true表示销毁后移除任务, false表示销毁后不移除任务。 | 布尔值 | 可缺省,缺省值为false。|
| orientation | 标识该Ability组件启动时的方向。取值范围包括:<br/>unspecified: 未指定方向,由系统自动判断显示方向,<br/>landscape:横屏,<br/> portrait:竖屏,<br/>landscape_inverted: 反向横屏, <br/>portrait_inverted: 反向竖屏, <br/>auto_rotation: 随传感器旋转, <br/>auto_rotation_landscape: 传感器横屏旋转,包括了横屏和反向横屏,<br/>auto_rotation_portrait: 传感器竖屏旋转,包括了竖屏和反向竖屏,<br/>auto_rotation_restricted: 传感器开关打开,方向可随传感器旋转,<br/>auto_rotation_landscape_restricted: 传感器开关打开,方向可随传感器旋转为横屏, 包括了横屏和反向横屏, <br/>auto_rotation_portrait_restricted: 传感器开关打开,方向随可传感器旋转为竖屏, 包括了横屏和反向横屏, <br/>locked: 传感器开关关闭,方向锁定。 | 字符串 | 可缺省,缺省值为"unspecified"。|
|supportWindowMode|标识该Ability组件所支持的窗口模式,取值范围包括:<br/> fullscreen: 全屏模式, <br /> split: 分屏模式, <br />floating: 悬浮窗模式。 |字符串数组 | 可缺省,缺省值为<br/>["fullscreen", "split", "floating"]。|
|maxWindowRatio|标识该Ability组件支持的最大的宽高比。| 数值 |可缺省,缺省值为平台支持的最大的宽高比。|
|minWindowRatio|标识该Ability组件支持的最小的宽高比。| 数值 |可缺省,缺省值为平台支持的最小的宽高比。|
|maxWindowWidth|标识该Ability组件支持的最大的窗口宽度,宽度单位为vp。| 数值 |可缺省,缺省值为平台支持的最大的窗口宽度。|
|minWindowWidth|标识该Ability组件支持的最小的窗口宽度, 宽度单位为vp。| 数值 |可缺省,缺省值为平台支持的最小的窗口宽度。|
|maxWindowHeight|标识该Ability组件支持的最大的窗口高度, 高度单位为vp。| 数值 |可缺省,缺省值为平台支持的最大的窗口高度。|
|minWindowHeight|标识该Ability组件支持的最小的窗口高度, 高度单位为vp。| 数值 |可缺省,缺省值为平台支持的最小的窗口高度。|
abilities示例 :
```json
{
"module": {
"abilities": [
{
"name": "EntryAbility",
"srcEntrance": "./ets/entryability/EntryAbility.ts",
"description": "$string:ability_desc",
"icon": "$media:icon",
"label": "$string:ability_label",
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:start_window_background",
"visible": true,
"backgroundModes": [
"dataTransfer",
"audioPlayback",
"audioRecording",
"location",
"bluetoothInteraction",
"multiDeviceConnection",
"wifiInteraction",
"voip",
"taskKeeping"
],
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"orientation": "landscape",
"supportWindowMode": [
"fullscreen",
"split",
"floating"
],
"maxWindowRatio": 3.5,
"minWindowRatio": 0.5,
"maxWindowWidth": 2560,
"minWindowWidth": 1400,
"maxWindowHeight": 300,
"minWindowHeight": 200
}
]
}
}
```
#### shortcuts对象内部结构
标识应用的快捷方式信息。最多可以配置四个快捷方式。<br/>
配置方式如下:<br/>
ability标签配置metadata信息。name :"ohos.ability.shortcuts"。resource :指定shortcuts信息的资源位置。
表15 shortcut对象内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ---------- | ------------------------------------------------------------ | -------- | -------------------------- |
| shortcutId | 标识快捷方式的ID。最大长度为63字节。 | 字符串 | 不可缺省。 |
| label | 标识快捷方式的标签信息,即快捷方式对外显示的文字描述信息。取值可以是描述性内容,也可以是标识label的资源索引。字符串最大长度为63字节。 | 字符串 | 可缺省,缺省值为空。 |
| icon | 该标签标识shortcut的图标,标签值为资源文件的索引。 | 字符串 | 可缺省,缺省值为空。 |
| wants | 该标签标识快捷方式内定义的目标wants信息集合,每个want可配置两个子标签,bundleName,abilityName。<br />bundleName :快捷方式目标包名,字符串类型。<br />abilityName :快捷方式的目标组件名,字符串类型。 | 对象数组 | 可缺省,缺省值为空。 |
shortcuts示例 :
1.在开发视图的resources/base/profile下面定义配置文件shortcuts_config.json(文件名称可由开发者定义):
```json
{
"shortcuts": [
{
"shortcutId": "shortcut_id",
"label": "$string:label",
"icon": "$media:icon",
"wants": [
{
"bundleName": "com.example.myapplication",
"abilityName": "abilityName"
}
]
}
]
}
```
2.在module.json5的abilities标签下配置metadata信息:
```json
{
"module": {
"abilities": [
{
"name": "EntryAbility",
"srcEntrance": "./ets/entryability/EntryAbility.ts",
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"metadata": [
{
"name": "ohos.ability.shortcuts",
"resource": "$profile:shortcuts_config"
}
]
}
]
}
}
```
#### extensionAbilities对象内部结构
extensionAbilities描述extensionAbility的配置信息,标签值为数组类型。
表16 extensionAbility对象内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ----------- | ------------------------------------------------------------ | ---------- | ----------------------------- |
| name | 该标签标识当前ExtensionAbility组件的逻辑名,标签值采用字符串表示(最大长度127字节),该名称在整个应用要唯一。 | 字符串 | 不可缺省。 |
| srcEntrance | 该标签标识ExtensionAbility组件所对应的js代码路径,标签值为字符串(最大长度127字节)。 | 字符串 | 不可缺省。 |
| description | 该标签标识ExtensionAbility组件的描述,标签值是是字符串类型或对描述内容的资源索引,以支持多语言。 | 字符串 | 可缺省,缺省值为空。 |
| icon | 该标签标识ExtensionAbility组件图标,标签值为资源文件的索引。 | 字符串 | 可缺省,缺省值为空。如果ExtensionAbility组件被配置为MainElement,不可缺省。 |
| label | 该标签标识ExtensionAbility组件对用户显示的名称,标签值配置为该名称的资源索引以支持多语言。 | 字符串 | 可缺省,缺省值为空。如果ExtensionAbility组件被配置为MainElement,该标签必须配置,且应用内唯一。 |
| type | 该标签标识ExtensionAbility组件的类型,取值为form、workScheduler、inputMethod、service、accessibility、dataShare、fileShare、staticSubscriber、wallpaper、backup、window、enterpriseAdmin、thumbnail、preview其中之一。 | 字符串 | 不可缺省。 |
| permissions | 该标签标识被其它应用的ability调用时需要申请的权限的集合,字符串数组类型,每个数组元素为一个权限名称,通常采用反向域名方式表示(最大长度255字节),取值为系统预定义权限或者应用自定义权限,如果是后者,需与defPermissions标签中定义的某个权限的name标签值一致。 | 字符串数组 | 可缺省,缺省值为空。 |
| uri | 该标签标识ability提供的数据URI,为字符数组类型(最大长度255字节),用反向域名的格式表示。 | 字符串 | 可缺省,缺省值为空。该标签在type为dataShare类型的ExtensionAbility组件时,不可缺省。 |
| skills | 该标签标识ability能够接收的意图的特征集,为数组格式。<br />配置规则 : entry包可以配置多个具有入口能力的skills标签(配置了action.system.home和entity.system.home)的ability,其中第一个配置了skills标签的ability中的label和icon作为OpenHarmony服务或应用的label和icon。<br/>OpenHarmony服务的Feature包不能配置具有入口能力的skills标签。<br/>OpenHarmony应用的Feature包可以配置具有入口能力的skills标签。 <br />参考[skills对象内部结构](#skills对象内部结构)。 | 对象数组 | 可缺省,缺省值为空。 |
| metadata | 该标签标识ExtensionAbility组件的元信息。参考[metadata对象内部结构](#metadata对象内部结构)。 | 对象数组 | 可缺省,缺省值为空。 |
| visible | 该标签标识ExtensionAbility组件是否可以被其它应用调用。true表示可以被其它应用调用, false表示不可以被其它应用调用。 | 布尔值 | 可缺省,缺省值为false。 |
| readPermission | 该标签标识读取ExtensionAbility组件的数据所需的权限。最大长度255字节。type为dataShare类型的ExtensionAbility组件支持该配置。该标签只对系统应用生效。 | 字符串 | 可缺省,缺省值为空。 |
| writePermission | 该标签标识向ExtensionAbility组件写数据所需的权限。最大长度255字节。type为dataShare类型的ExtensionAbility组件支持该配置。该标签只对系统应用生效。 | 字符串 | 可缺省,缺省值为空。 |
extensionAbilities示例 :
```json
{
"module": {
"extensionAbilities": [
{
"name": "EntryFormAbility",
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"srcEntrance": "./ets/entryformability/EntryFormAbility.ts",
"label": "$string:EntryFormAbility_label",
"description": "$string:EntryFormAbility_desc",
"type": "form",
"metadata": [
{
"name": "ohos.extension.form",
"resource": "$profile:form_config"
}
]
}
]
}
}
```
#### forms对象内部结构
forms标签标识卡片的配置,form卡片是可以嵌入桌面上并接收定期更新的应用简要视图。<br/>
配置方式如下:<br/>
extensionAbility标签配置type为form,并配置metadata信息:name :"ohos.extension.form"。resource :指定form信息的资源位置。
表17 form对象内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ------------------- | ------------------------------------------------------------ | ---------- | ----------------------------- |
| name | 标识卡片的名称。最大长度为127字节。 | 字符串 | 不可缺省。 |
| description | 标识卡片的描述。取值可以是描述性内容,也可以是对描述性内容的资源索引,以支持多语言。最大长度为255字节。 | 字符串 | 可缺省,缺省值为空。 |
| src | 该标签标识JS卡片对应的UI代码。建议开发者通过自适应布局显示不同规格卡片,如果不同规格卡片布局相差较大,建议通过不同卡片来区分。 | 字符串 | 可缺省,缺省值为空。 |
| window | 该标签标识JS卡片的自适应能力。参考[window对象内部结构](#window对象内部结构)。 | 对象 | 可缺省,缺省值为空。 |
| isDefault | 标识该卡片是否为默认卡片,每个Ability有且只有一个默认卡片。 true :默认卡片。 false :非默认卡片。 | 布尔值 | 不可缺省。 |
| colorMode | 标识卡片的主题样式,取值范围如下 : <br/>auto :自适应。<br/> dark :深色主题。<br/> light :浅色主题。<br/>| 字符串 | 可缺省,缺省值为“auto”。 |
| supportDimensions | 标识卡片支持的外观规格,取值范围 :<br/>1 * 2 :表示1行2列的二宫格。<br/> 2 * 1 :表示2行1列的二宫格。<br/> 2 * 2 :表示2行2列的四宫格。<br/> 2 * 4 :表示2行4列的八宫格。<br/> 4 * 4 :表示4行4列的十六宫格。 | 字符串数组 | 不可缺省。 |
| defaultDimension | 标识卡片的默认外观规格,取值必须在该卡片supportDimensions配置的列表中。 | 字符串 | 不可缺省。 |
| updateEnabled | 该标签标识该卡片是否支持实时刷新,true标识卡片支持实时刷新,false表示不支持。 | 布尔值 | 不可缺省。 |
| scheduledUpdateTime | 该标签标识卡片定点刷新的时间,采用24小时计数,精确到分钟。 | 字符串 | 可缺省,缺省值为空。 |
| updateDuration | 该标签标识卡片定时刷新的更新频率,单位为30分钟,取值为30的倍数。卡片的最高频率为每30分钟刷新一次,和定点刷新二选一,二者都配置的情况下,定时优先。 | 数值 | 可缺省,缺省值为空。 |
| metadata | 该标签标识卡片的元信息。参考[metadata对象内部结构](#metadata对象内部结构)。 | 对象数组 | 可缺省,缺省值为空。 |
| formConfigAbility | 该标签标识卡片调整的Ability名称。最大长度127字节。该标签值必须满足下面的格式 :<br/>ability://单个ability名字。<br/>单个ability名字必须为本应用的ability。 | 字符串 | 可缺省,缺省值为空。 |
| formVisibleNotify | 该标签标识卡片是否被允许使用卡片可见性通知。 | 布尔值 | 可缺省,缺省值为false。 |
form示例 :
1.在开发视图的resources/base/profile下面定义配置文件form_config.json(文件名称可由开发者定义):
```json
{
"forms": [
{
"name": "widget",
"description": "This is a service widget.",
"src": "./js/widget/pages/index/index",
"window": {
"designWidth": 720,
"autoDesignWidth": true
},
"colorMode": "auto",
"isDefault": true,
"updateEnabled": true,
"scheduledUpdateTime": "10:30",
"updateDuration": 1,
"defaultDimension": "2*2",
"supportDimensions": [
"2*2"
]
}
]
}
```
2.在module.json5的extensionAbilities标签下配置metadata信息:
```json
{
"module": {
"extensionAbilities": [
{
"type": "form",
"metadata": [
{
"name": "ohos.extension.form",
"resource": "$profile:form_config"
}
]
}
]
}
}
```
#### window对象内部结构
定义与显示窗口相关的配置。
表18 window对象内部结构说明
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | ------------------------------------------------------------ | -------- | -------------------------- |
| designWidth | 定义页面设计基准宽度,根据实际设备宽度来缩放元素大小。 | 数值 | 可缺省,缺省值为750。 |
| autoDesignWidth | 定义页面设计基准宽度是否自动计算,当设置为true时,designWidth将被忽略,设计基准宽度由设备宽度与屏幕密度计算得出。 | 布尔值 | 可缺省,缺省值为false。 |
window示例 :
```json
{
"forms": [
{
"window": {
"designWidth": 720,
"autoDesignWidth": true
}
}
]
}
```
#### commonEvents对象内部结构
commonEvents标签标识注册静态公共事件信息。<br/>
配置方式如下:<br/>
extensionAbility标签配置type为staticSubscriber,并配置metadata信息:name :"ohos.extability.staticSubscriber"。resource :指定commonEvents信息的资源位置。
表19 commonEvent对象内部结构
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| ---------- | ------------------------------------------------------------ | ---------- | -------------------------- |
| name | 该标签指明当前静态公共事件对应的ability名,该类需要在ability中标明。 | 字符串 | 不可缺省。 |
| permission | 该标签标识实现该静态公共事件需要申请的权限,以字符串类型表示一个权限名称,通常采用反向域名方式表示(最大长度255字节)。 | 字符串 | 可缺省,缺省值为空。 |
| types | 该标签配置当前静态公共事件的类别数组,字符串数组类型,每个数组元素为一个类别名称。 | 字符串数组 | 可缺省,缺省值为空。 |
| events | 该标签标识能够接收的意图的event值的集合,取值通常为系统预定义的event值,也允许自定义。 | 字符串数组 | 不可缺省。 |
commonEvents示例 :
1.在开发视图的resources/base/profile下面定义配置文件common_event_config.json(文件名称可由开发者定义):
```json
{
"commonEvents": [
{
"name": "abilityName",
"permission": "permissionName",
"types": [
"type1",
"type2"
],
"events": [
"event1",
"event2"
]
}
]
}
```
2.在module.json5的extensionAbilities标签下配置metadata信息:
```json
{
"module": {
"extensionAbilities": [
{
"name": "subscriber",
"srcEntrance": "./ets/subscriber/Subscriber.ts",
"type": "staticSubscriber",
"metadata": [
{
"name": "ohos.extability.staticSubscriber",
"resource": "$profile:common_event_config"
}
]
}
]
}
}
```
#### definePermissions对象内部结构
该标签标识HAP定义的权限。该标签只支持系统应用配置。
表20 definePermission对象内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ---------------------- | ------------------------------------------------------------ | -------- | ------------------------------ |
| name | 标识权限的名称。 | 字符串 | 不可缺省。 |
| grantMode | 标识权限的授予方式,授予模式如下:<br />system_grant:安装后系统自动授予该权限。<br />user_grant:应用动态申请,用户授权后才可使用。 | 字符串 | 可缺省,缺省值为"system_grant"。 |
| availableLevel | 标识权限限制门限,可选值为system_core、system_basic、normal。<br />system_core:系统核心权限。<br />system_basic:系统基础权限。<br />normal:普通权限。所有应用允许申请的权限。 | 字符串 | 可缺省,缺省值为"normal"。 |
| provisionEnable | 标识权限是否支持证书方式申请权限,包括高级别的权限,true标识需要开发者可以通过provision证书acls方式申请权限。 | 布尔值 | 可缺省,缺省值为true。 |
| distributedSceneEnable | 标识权限是否支持分布式场景下使用该权限。 | 布尔值 | 可缺省,缺省值为false。 |
| label | 标识权限的简短描述,配置为对描述内容的资源索引。 | 字符串 | 可缺省,缺省值为空。 |
| description | 标识权限的详细描述,可以是表示描述内容的字符串,也可以是对描述内容的资源索引。 | 字符串 | 可缺省,缺省值为空。 |
definePermissions示例 :
```json
{
"module": {
"definePermissions": [
{
"name": "permissionName",
"grantMode": "user_grant",
"availableLevel": "system_basic",
"provisionEnable": false,
"distributedSceneEnable": true,
"label": "$string:label",
"description": "$string:description"
}
]
}
}
```
#### requestPermissions对象内部结构
该标签标识应用运行时需向系统申请的权限集合。
表21 requestPermission对象内部结构说明
| 属性名称 | 含义 | 数据类型<div style="width:20px"> | 是否可缺省 |
| ------| ------| -------- | ------------------------------ |
| name | 需要申请的权限名称。| 字符串 | 不可缺省。 |
| reason | 申请权限的原因。配置为描述内容的资源索引,以支持多语言。 | 字符串 | 可缺省,缺省值为空。当申请权限的grantMode为user_grant时不可缺省。 |
| usedScene | 权限使用的场景和时机。参考[usedScene对象内部结构](#usedscene对象内部结构)。| 对象 | 可缺省,缺省值为空。当申请权限的grantMode为user_grant时不可缺省。 |
requestPermissions示例 :
```json
{
"module": {
"requestPermissions": [
{
"name": "permissionName",
"reason": "$string:reason",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "inuse"
}
}
]
}
}
```
权限访问的更多说明,可参考[访问控制开发指导](../security/accesstoken-guidelines.md)
#### usedScene对象内部结构
该标签标识权限使用的场景和时机。
表22 usedScene对象内部结构说明
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| ------- | --------------------| -------- | ------ |
| abilities | 标识需要使用到该权限的ability。| 字符串数组 | 不可缺省。 |
| when | 标识使用该权限的时机,可选值为inuse和always。inuse表示仅前台使用,always表示前后台都可使用。 | 字符串 | 可缺省,缺省值为空。 |
usedScene示例 :
```json
{
"module": {
"requestPermissions": [
{
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "inuse"
}
}
]
}
}
```
#### testRunner对象内部结构
该标签用于支持对测试框架的配置
表23 testRunner对象内部结构
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
| -------- | ---------------------- | -------- | ---------- |
| name | 标识测试框架对象名称。 | 字符串 | 不可缺省。 |
| srcPath | 标识测试框架代码路径。 | 字符串 | 不可缺省。 |
testRunner示例 :
```json
{
"module": {
"testRunner": {
"name": "testRunnerName",
"srcPath": "ets/test/TestRunner.ts"
}
}
}
```
# 开发参考 # 开发参考
- [Syscap列表](syscap-list.md) - [系统能力SystemCapability使用指南](syscap.md)
- [系统能力SystemCapability列表](syscap-list.md)
- [组件参考(基于ArkTS的声明式开发范式)](arkui-ts/Readme-CN.md) - [组件参考(基于ArkTS的声明式开发范式)](arkui-ts/Readme-CN.md)
- [组件参考(兼容JS的类Web开发范式)](arkui-js/Readme-CN.md) - [组件参考(兼容JS的类Web开发范式)](arkui-js/Readme-CN.md)
- [JS服务卡片UI组件参考](js-service-widget-ui/Readme-CN.md) - [JS服务卡片UI组件参考](js-service-widget-ui/Readme-CN.md)
- [接口参考(JS及TS API)](apis/Readme-CN.md) - [接口参考(ArkTS及JS API)](apis/Readme-CN.md)
- [错误码参考](errorcodes/Readme-CN.md) - [错误码参考](errorcodes/Readme-CN.md)
- 接口参考(Native API) - 接口参考(Native API)
- [OpenHarmony Native API](native-apis/Readme-CN.md) - [OpenHarmony Native API](native-apis/Readme-CN.md)
......
...@@ -45,7 +45,7 @@ APL等级的详细说明及如何将应用的APL等级声明为normal以上, ...@@ -45,7 +45,7 @@ APL等级的详细说明及如何将应用的APL等级声明为normal以上,
## 系统能力说明 ## 系统能力说明
系统能力(SystemCapability,简称SysCap),指操作系统中每一个相对独立的特性。不同的设备对应不同的系统能力集,每个系统能力对应多个接口。开发者可根据系统能力来判断是否可以使用某接口。具体可参考[SysCap使用指南](../../quick-start/syscap.md) 系统能力(SystemCapability,简称SysCap),指操作系统中每一个相对独立的特性。不同的设备对应不同的系统能力集,每个系统能力对应多个接口。开发者可根据系统能力来判断是否可以使用某接口。具体可参考[系统能力SystemCapability使用指南](../syscap.md)
文档在每一个接口描述中说明了接口的系统能力,如:**系统能力**:SystemCapability.xxx.xxx 文档在每一个接口描述中说明了接口的系统能力,如:**系统能力**:SystemCapability.xxx.xxx
......
...@@ -772,7 +772,7 @@ async function createTonePlayerBefore(){ ...@@ -772,7 +772,7 @@ async function createTonePlayerBefore(){
音频采集器选项信息。 音频采集器选项信息。
**系统能力:** SystemCapability.Multimedia.Audio.Capturer **系统能力:** 以下各项对应的系统能力均为SystemCapability.Multimedia.Audio.Capturer
| 名称 | 类型 | 必填 | 说明 | | 名称 | 类型 | 必填 | 说明 |
| ------------ | --------------------------------------- | ---- | ---------------- | | ------------ | --------------------------------------- | ---- | ---------------- |
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
- [窗口错误码](errorcode-window.md) - [窗口错误码](errorcode-window.md)
- 媒体 - 媒体
- [Audio错误码](errorcode-audio.md) - [Audio错误码](errorcode-audio.md)
- [Media错误码](errorcode-media.md)
- [媒体会话管理错误码](errorcode-avsession.md) - [媒体会话管理错误码](errorcode-avsession.md)
- 资源管理 - 资源管理
- [I18n错误码](errorcode-i18n.md) - [I18n错误码](errorcode-i18n.md)
......
...@@ -8,5 +8,5 @@ ...@@ -8,5 +8,5 @@
- [申请能效资源开发指导](efficiency-resources-apply-dev-guide.md) - [申请能效资源开发指导](efficiency-resources-apply-dev-guide.md)
- 后台代理提醒 - 后台代理提醒
- [后台代理提醒开发概述](background-agent-scheduled-reminder-overview.md) - [后台代理提醒概述](reminder-agent-overview.md)
- [后台代理提醒开发指导](background-agent-scheduled-reminder-guide.md) - [后台代理提醒开发指导](reminder-agent-development.md)
# 后台代理提醒开发指导
## 场景介绍
后台代理提醒主要提供后台提醒发布接口,开发者在应用开发时,可以调用这些接口去创建定时提醒,包括倒计时、日历、闹钟三种提醒类型。使用后台代理提醒能力后,应用可以被冻结或退出,计时和弹出提醒的功能将被后台系统服务代理。
## 接口说明
reminderAgentManager:封装了发布、取消提醒类通知的方法。
具体后台提醒相关功能接口请见[后台代理提醒](../reference/apis/js-apis-reminderAgentManager.md)
**表1** reminderAgentManager主要接口
| 接口名 | 描述 |
| -------- | -------- |
| publishReminder(reminderReq:&nbsp;ReminderRequest,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void<br/>publishReminder(reminderReq:&nbsp;ReminderRequest):&nbsp;Promise&lt;number&gt; | 发布一个定时提醒类通知。<br/>单个应用有效的提醒个数最多支持30个(不包括已经超时,即后续不会再提醒的提醒实例)<br/>整个系统有效的提醒个数最多支持2000个(不包括已经超时,即后续不会再提醒的提醒实例) |
| cancelReminder(reminderId:&nbsp;number,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void<br/>cancelReminder(reminderId:&nbsp;number):&nbsp;Promise&lt;void&gt; | 取消一个指定的提醒类通知。(reminderId从publishReminder的返回值获取) |
| getValidReminders(callback:&nbsp;AsyncCallback&lt;Array&lt;ReminderRequest&gt;&gt;):&nbsp;void<br/>getValidReminders():&nbsp;Promise&lt;Array&lt;ReminderRequest&gt;&gt; | 获取当前应用设置的所有有效的提醒。 |
| cancelAllReminders(callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void<br/>cancelAllReminders():&nbsp;Promise&lt;void&gt; | 取消当前应用设置的所有提醒 |
| addNotificationSlot(slot:&nbsp;NotificationSlot,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void<br/>addNotificationSlot(slot:&nbsp;NotificationSlot):&nbsp;Promise&lt;void&gt; | 注册一个提醒类需要使用的NotificationSlot |
| removeNotificationSlot(slotType:&nbsp;notification.SlotType,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void<br/>removeNotificationSlot(slotType:&nbsp;notification.SlotType):&nbsp;Promise&lt;void&gt; | 删除指定类型的NotificationSlot |
## 开发步骤
> **说明:**
>
> 1. 应用需要配置权限:ohos.permission.PUBLISH_AGENT_REMINDER。
>
> 2. 应用需要申请通知弹窗:[Notification.requestEnableNotification](../reference/apis/js-apis-notification.md#notificationrequestenablenotification8)。
> 只有用户授权后,提醒代理的功能才能使用。
1、定义目标提醒代理。
2、发布相应的提醒代理。
```ts
import reminderAgentManager from '@ohos.reminderAgentManager';
import notification from '@ohos.notification';
// 倒计时实例定义:
let timer : reminderAgentManager.ReminderRequestTimer = {
reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_TIMER,
triggerTimeInSeconds: 10,
actionButton: [
{
title: "close",
type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE
}
],
wantAgent: {
pkgName: "com.example.device",
abilityName: "com.example.device.MainAbility"
},
maxScreenWantAgent: {
pkgName: "com.example.device",
abilityName: "com.example.device.MainAbility"
},
title: "this is title",
content: "this is content",
expiredContent: "this reminder has expired",
notificationId: 100,
slotType: notification.SlotType.SOCIAL_COMMUNICATION
}
// 日历实例定义:
let calendar : reminderAgentManager.ReminderRequestCalendar = {
reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_CALENDAR,
dateTime: {
year: 2050,
month: 7,
day: 30,
hour: 11,
minute: 14,
second: 30
},
repeatMonths: [1],
repeatDays: [1],
actionButton: [
{
title: "close",
type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE
},
{
title: "snooze",
type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_SNOOZE
},
],
wantAgent: {
pkgName: "com.example.device",
abilityName: "com.example.device.MainAbility"
},
maxScreenWantAgent: {
pkgName: "com.example.device",
abilityName: "com.example.device.MainAbility"
},
ringDuration: 5,
snoozeTimes: 2,
timeInterval: 5,
title: "this is title",
content: "this is content",
expiredContent: "this reminder has expired",
snoozeContent: "remind later",
notificationId: 100,
slotType: notification.SlotType.SOCIAL_COMMUNICATION
}
// 闹钟实例定义:
let alarm : reminderAgentManager.ReminderRequestAlarm = {
reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_ALARM,
hour: 11,
minute: 14,
daysOfWeek: [0],
actionButton: [
{
title: "close",
type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE
},
{
title: "snooze",
type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_SNOOZE
},
],
wantAgent: {
pkgName: "com.example.device",
abilityName: "com.example.device.MainAbility"
},
maxScreenWantAgent: {
pkgName: "com.example.device",
abilityName: "com.example.device.MainAbility"
},
ringDuration: 5,
snoozeTimes: 2,
timeInterval: 5,
title: "this is title",
content: "this is content",
expiredContent: "this reminder has expired",
snoozeContent: "remind later",
notificationId: 100,
slotType: notification.SlotType.SOCIAL_COMMUNICATION
}
@Entry
@Component
struct Index {
@State message: string = 'test'
publishReminder() {
try {
reminderAgentManager.publishReminder(timer).then(res => {
console.log("publishReminder promise reminderId:" + res);
}).catch(err => {
console.log("publishReminder err code:" + err.code + " message:" + err.message);
})
} catch (error) {
console.log("publishReminder code:" + error.code + " message:" + error.message);
};
}
build() {
Row() {
Column() {
Text("Index")
.fontSize(50)
.fontWeight(FontWeight.Bold)
Button() { Text('倒计时提醒代理').fontSize(25).fontWeight(FontWeight.Bold) }.type(ButtonType.Capsule)
.margin({ top: 10 }).backgroundColor('#0D9FFB').width(250).height(40)
.onClick(() => {
// 示例通过按钮控制提醒代理的发布
this.publishReminder();
})
}
.width('100%')
}
.height('100%')
}
}
```
## 相关实例
基于后台代理提醒开发,有以下相关实例可供参考:
- [`AlarmClock`:后台代理提醒(ArkTS)(API8)](https://gitee.com/openharmony/app_samples/tree/master/Notification/AlarmClock)
- [`FlipClock`:翻页时钟(ArkTS)(API8)(Full SDK)](https://gitee.com/openharmony/applications_app_samples/tree/master/CompleteApps/FlipClock)
- [闹钟应用(ArkTS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/CommonEventAndNotification/AlarmClock)
\ No newline at end of file
# 后台代理提醒概述
OpenHarmony设计了相关的后台活动规范。三方应用退后台后如果没有执行相关的后台任务,会被挂起。而对于某些应用,可能需要在某些指定的时刻,处理一些工作。如购物类应用,可能需要在某些时间点,提醒用户有抢购活动可以参加。此类功能通常的实现是应用使用定时器,在时间达到后,由系统拉起应用,执行相关的任务。但是给应用开放了定时器的功能,可能会造成这个机制被滥用,导致后台被挂起的应用频繁地用定时器唤醒。为了避免恶意的后台活动,同时满足应用的业务诉求,设计了后台代理提醒功能。
开发者在应用开发时,使用后台代理提醒能力后,应用可以被挂起或退出,计时和弹出提醒的功能将被后台系统服务代理。避免的应用被频繁唤醒的问题,有助于降低功耗。
## 提醒实例类型
- **倒计时类型**:基于倒计时的提醒功能,适用于短时的计时提醒业务。
- **日历类型**:基于日历的提醒功能,适用于较长时间的提醒业务。
- **闹钟类型**:基于时钟的提醒功能,应用可以使用此功能,实现闹钟相关的业务。
# 后台代理提醒开发指导
## 接口说明
后台代理提醒功能主要提供后台提醒通知发布接口,开发者可调用这些接口创建定时提醒,包括倒计时、日历、闹钟三种提醒类型。[reminderAgentManager](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-reminderAgentManager.md)封装了发布、取消提醒通知的方法。
**表1** reminderAgentManager主要接口
| 接口名 | 描述 |
| -------- | -------- |
| publishReminder(reminderReq:&nbsp;ReminderRequest,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):&nbsp;void<br/>publishReminder(reminderReq:&nbsp;ReminderRequest):&nbsp;Promise&lt;number&gt; | 发布一个定时提醒类通知。<br/>-&nbsp;单个应用有效的提醒个数最多支持30个(不包括已经超时,即后续不会再提醒的提醒实例)。<br/>-&nbsp;整个系统有效的提醒个数最多支持2000个(不包括已经超时,即后续不会再提醒的提醒实例)。 |
| cancelReminder(reminderId:&nbsp;number,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void<br/>cancelReminder(reminderId:&nbsp;number):&nbsp;Promise&lt;void&gt; | 取消一个指定的提醒类通知(reminderId从publishReminder的返回值获取)。 |
| getValidReminders(callback:&nbsp;AsyncCallback&lt;Array&lt;ReminderRequest&gt;&gt;):&nbsp;void<br/>getValidReminders():&nbsp;Promise&lt;Array&lt;ReminderRequest&gt;&gt; | 获取当前应用设置的所有有效的提醒。 |
| cancelAllReminders(callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void<br/>cancelAllReminders():&nbsp;Promise&lt;void&gt; | 取消当前应用设置的所有提醒。 |
| addNotificationSlot(slot:&nbsp;NotificationSlot,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void<br/>addNotificationSlot(slot:&nbsp;NotificationSlot):&nbsp;Promise&lt;void&gt; | 注册一个提醒类需要使用的NotificationSlot。 |
| removeNotificationSlot(slotType:&nbsp;notification.SlotType,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void<br/>removeNotificationSlot(slotType:&nbsp;notification.SlotType):&nbsp;Promise&lt;void&gt; | 删除指定类型的NotificationSlot。 |
## 开发步骤
1. 申请`ohos.permission.PUBLISH_AGENT_REMINDER`权限,配置方式请参阅[访问控制授权申请指导](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/accesstoken-guidelines.md#stage%E6%A8%A1%E5%9E%8B)
2. [使能通知开关](notification-enable.md),获得用户授权后,才能使用代理提醒功能。
3. 导入模块。
```
import reminderAgentManager from '@ohos.reminderAgentManager';
import NotificationManager from '@ohos.notificationManager';
```
4. 定义目标提醒代理。开发者根据实际需要,选择定义如下类型的提醒。
- 定义倒计时实例。
```
let targetReminderAgent: reminderAgentManager.ReminderRequestTimer = {
reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_TIMER, // 提醒类型为倒计时类型
triggerTimeInSeconds: 10,
actionButton: [ // 设置弹出的提醒通知信息上显示的按钮类型和标题,支持“关闭”和“延迟”两种类型,其中“延迟”按钮类型需要与snoozeTimes和timeInterval参数结合使用
{
title: 'close',
type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE
}
],
wantAgent: { // 点击提醒通知后跳转的目标UIAbility信息
pkgName: 'com.example.myapplication',
abilityName: 'EntryAbility'
},
maxScreenWantAgent: { // 全屏显示提醒到达时自动拉起的目标Ability信息
pkgName: 'com.example.myapplication',
abilityName: 'EntryAbility'
},
title: 'this is title', // 指明提醒标题
content: 'this is content', // 指明提醒内容
expiredContent: 'this reminder has expired', // 指明提醒过期后需要显示的内容
notificationId: 100, // 指明提醒使用的通知的ID号,相同ID号的提醒会覆盖
slotType: NotificationManager.SlotType.SOCIAL_COMMUNICATION // 指明提醒的Slot类型
}
```
- 定义日历实例。
```
let targetReminderAgent: reminderAgentManager.ReminderRequestCalendar = {
reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_CALENDAR, // 提醒类型为日历类型
dateTime: { // 指明提醒的目标时间
year: 2023,
month: 7,
day: 30,
hour: 11,
minute: 14,
second: 30
},
repeatMonths: [1], // 指明重复提醒的月份
repeatDays: [1], // 指明重复提醒的日期
actionButton: [ // 设置弹出的提醒通知信息上显示的按钮类型和标题,支持“关闭”和“延迟”两种类型,其中“延迟”按钮类型需要与snoozeTimes和timeInterval参数结合使用
{
title: 'close',
type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE
},
{
title: 'snooze',
type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_SNOOZE
},
],
wantAgent: { // 点击提醒通知后跳转的目标UIAbility信息
pkgName: 'com.example.myapplication',
abilityName: 'EntryAbility'
},
maxScreenWantAgent: { // 点击提醒通知后跳转的目标UIAbility信息
pkgName: 'com.example.myapplication',
abilityName: 'EntryAbility'
},
ringDuration: 5, // 指明响铃时长(单位:秒)
snoozeTimes: 2, // 指明延迟提醒次数
timeInterval: 5, // 执行延迟提醒间隔(单位:秒)
title: 'this is title', // 指明提醒标题
content: 'this is content', // 指明提醒内容
expiredContent: 'this reminder has expired', // 指明提醒过期后需要显示的内容
snoozeContent: 'remind later', // 指明延迟提醒时需要显示的内容
notificationId: 100, // 指明提醒使用的通知的ID号,相同ID号的提醒会覆盖
slotType: NotificationManager.SlotType.SOCIAL_COMMUNICATION // 指明提醒的Slot类型
}
```
- 定义闹钟实例。
```
let targetReminderAgent: reminderAgentManager.ReminderRequestAlarm = {
reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_ALARM, // 提醒类型为闹钟类型
hour: 23, // 指明提醒的目标时刻
minute: 9, // 指明提醒的目标分钟
daysOfWeek: [2], // 指明每周哪几天需要重复提醒
actionButton: [ // 设置弹出的提醒通知信息上显示的按钮类型和标题,支持“关闭”和“延迟”两种类型,其中“延迟”按钮类型需要与snoozeTimes和timeInterval参数结合使用
{
title: 'close',
type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE
},
{
title: 'snooze',
type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_SNOOZE
},
],
wantAgent: { // 点击提醒通知后跳转的目标UIAbility信息
pkgName: 'com.example.myapplication',
abilityName: 'EntryAbility'
},
maxScreenWantAgent: { // 点击提醒通知后跳转的目标UIAbility信息
pkgName: 'com.example.myapplication',
abilityName: 'EntryAbility'
},
ringDuration: 5, // 指明响铃时长(单位:秒)
snoozeTimes: 2, // 指明延迟提醒次数
timeInterval: 5, // 执行延迟提醒间隔(单位:秒)
title: 'this is title', // 指明提醒标题
content: 'this is content', // 指明提醒内容
expiredContent: 'this reminder has expired', // 指明提醒过期后需要显示的内容
snoozeContent: 'remind later', // 指明延迟提醒时需要显示的内容
notificationId: 99, // 指明提醒使用的通知的ID号,相同ID号的提醒会覆盖
slotType: NotificationManager.SlotType.SOCIAL_COMMUNICATION // 指明提醒的Slot类型
}
```
5. 发布相应的提醒代理。代理发布后,应用即可使用后台代理提醒功能。
```
try {
reminderAgentManager.publishReminder(targetReminderAgent).then(res => {
console.info('publishReminder promise reminderId: ' + res);
let reminderId: number = res;
// ...
}).catch(err => {
console.info('publishReminder err code: ' + err.code + ' message:' + err.message);
})
} catch (error) {
console.info('publishReminder code: ' + error.code + ' message:' + error.message);
}
```
以闹钟为例,运行效果如下图所示。
![zh-cn_image_0000001416585578](figures/zh-cn_image_0000001416585578.png)
6. 若需要删除提醒任务,可以通过调用[reminderAgentManager.cancelReminder()](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-reminderAgentManager.md#reminderagentmanagercancelreminder)方法来实现。
```
let reminderId = 0; // reminderId的值从发布提醒代理成功之后的回调中获得
try {
reminderAgentManager.cancelReminder(reminderId).then(() => {
console.log("cancelReminder promise");
}).catch(err => {
console.log("promise err code: " + err.code + ", message:" + err.message);
});
} catch (error) {
console.log("cancelReminder code: " + error.code + ", message: " + error.message);
};
```
# 后台代理提醒概述
为保障用户体验,OpenHarmony对后台应用进程进行了有序治理,应用程序不能随意驻留在后台,同时应用后台行为受到严格管理,防止恶意应用行为。但对于某些退居后台或已退出的应用,可能需要在指定的时刻,向用户发送一些业务提醒通知。例如购物类应用,希望在指定时间点提醒用户有优惠活动。为满足此类业务诉求,OpenHarmony提供后台代理提醒功能,在应用退居后台或退出后,计时和提醒通知功能被系统后台代理接管。
后台代理提醒业务类型:
- 倒计时类:基于倒计时的提醒功能,适用于短时的计时提醒业务。
- 日历类:基于日历的提醒功能,适用于较长时间的提醒业务。
- 闹钟类:基于时钟的提醒功能,适用于闹钟相关业务。
# 工具
- [aa工具](aa-tool.md)
- [bm工具](bm-tool.md)
- 打包拆包工具
- [打包工具](packing-tool.md)
- [拆包工具](unpacking-tool.md)
- [cem工具](cem-tool.md)
- [anm工具](anm-tool.md)
# aa工具
Ability assistant(Ability助手,简称为aa),是实现应用及测试用例启动功能的工具,为开发者提供基本的应用调试和测试的能力。通过该工具,开发者可以在hdc shell中,发送命令以执行各种系统操作,例如启动应用组件、强制停止进程、打印应用组件相关信息等。
- help
用于显示aa相关的帮助信息。
**返回值**
返回对应的帮助信息。
**使用方法**
```bash
aa help
```
- start
用于启动一个应用组件,目标组件可以是FA模型的PageAbility和ServiceAbility组件,也可以是Stage模型的UIAbility和ServiceExtensionAbility组件,且目标组件相应配置文件中的visible标签不能配置为false。
| 参数 | 参数说明 |
| -------- | -------- |
| -h/--help | 帮助信息。 |
| -d | 可选参数,deviceId。 |
| -a | 必选参数,abilityName。 |
| -b | 必选参数,bundleName。 |
| -D | 可选参数,调试模式。 |
**返回值**
当启动成功时,返回"start ability successfully.";当启动失败时,返回"error: failed to start ability.",同时会包含相应的失败信息。
**使用方法**
```bash
aa start [-d <deviceId>] -a <abilityName> -b <bundleName> [-D]
```
- stop-service
用于停止ServiceAbility。
| 参数 | 参数说明 |
| -------- | -------- |
| -h/--help | 帮助信息。 |
| -d | 可选参数,deviceId。 |
| -a | 必选参数,abilityName。 |
| -b | 必选参数,bundleName。 |
**返回值**
当成功停止ServiceAbility时,返回"stop service ability successfully.";当停止失败时,返回"error: failed to stop service ability."。
**使用方法**
```bash
aa stop-service [-d <deviceId>] -a <abilityName> -b <bundleName>
```
- dump
用于打印应用组件的相关信息。
| 参数 | 二级参数 | 参数说明 |
| -------- | -------- | -------- |
| -h/--help | - | 帮助信息。 |
| -a/--all | - | 打印所有mission内的应用组件信息。 |
| -l/--mission-list | type(缺省打印全部) | 打印任务栈信息。<br/>可取值:<br/>-&nbsp;NORMAL<br/>-&nbsp;DEFAULT_STANDARD<br/>-&nbsp;DEFAULT_SINGLE<br/>-&nbsp;LAUNCHER |
| -e/--extension | elementName | 打印扩展组件信息。 |
| -u/--userId | UserId | 打印指定UserId的栈信息,需要和其他参数组合使用,例如aa&nbsp;dump&nbsp;-a&nbsp;-u&nbsp;100、aa&nbsp;dump&nbsp;-d&nbsp;-u&nbsp;100。 |
| -d/--data | - | 打印DataAbility相关信息。 |
| -i/--ability | AbilityRecord&nbsp;ID | 打印指定应用组件详细信息。 |
| -c/--client | - | 打印应用组件详细信息,需要和其他参数组合使用,例如aa&nbsp;dump&nbsp;-a&nbsp;-c、aa&nbsp;dump&nbsp;-i&nbsp;21&nbsp;-c。 |
**使用方法**
```bash
aa dump -a
```
![aa-dump-a](figures/aa-dump-a.png)
```bash
aa dump -l
```
![aa-dump-l](figures/aa-dump-l.png)
```bash
aa dump -i 12
```
![aa-dump-i](figures/aa-dump-i.png)
- force-stop
通过bundleName强制停止一个进程。
**返回值**
当成功强制停止该进程时,返回"force stop process successfully.";当强制停止失败时,返回"error: failed to force stop process."。
**使用方法**
```bash
aa force-stop <bundleName>
```
# anm工具
Advanced Notification Manager(通知管理工具,简称anm)是实现通知打印、设置通知参数等功能的工具,为开发者提供基本的通知调试和测试能力。通过该工具,开发者可以在hdc shell中,发送命令以执行各种系统操作,例如打印已发布通知详细信息、设置通知缓存个数、使能通知等。
### help
* **介绍**
打印帮助信息。
* **用法**
```bash
anm help
```
### dump
* **介绍**
打印通知相关信息。
* **用法**
```bash
anm dump [<options>]
```
参数如下表所示
| 参数 | 参数说明 |
| ---------------- | -------------------------------- |
| -A/--active | 打印所有活跃的通知信息 |
| -R/--recent | 打印最近的通知信息 |
| -D/--distributed | 打印来自其他设备的分布式通知信息 |
| -b/--bundle | 可选参数,设置指定的包名打印 |
| -u/--user-id | 可选参数,设置指定的用户ID打印 |
| -h/--help | 帮助信息 |
* **示例**:打印活跃的通知信息
```bash
anm dump -A
```
![anm-dump-A](figures/anm-dump-A.png)
### Setting
* **介绍**
设置通知参数。
* **用法**
```bash
anm setting [<options>]
```
参数如下表所示
| 参数 | 参数说明 |
| ------------------------ | ------------------------------------ |
| -c/--recent-count | 设置保存在内存中的最近通知的最大个数 |
| -e/--enable-notification | 设置通知使能开关 |
| -h/--help | 帮助信息 |
* **示例**:设置保存在内存中的最近通知的最大数为100个
```bash
anm setting -c 100
```
# bm工具
Bundle Manager(包管理工具,简称bm)是实现应用安装、卸载、更新、查询等功能的工具,bm为开发者提供基本的应用安装包的调试能力,开发者可以在hdc shell中,执行bm命令以触发各种系统操作,例如:安装应用,卸载应用,查询安装包信息等。
**表1** bm工具命令列表
| 命令 | 描述 |
| -------- | -------- |
| help | 帮助命令,显示bm支持的命令信息 |
| install | 安装命令,用来安装应用 |
| uninstall | 卸载命令,用来卸载应用 |
| dump | 查询命令,用来查询应用的相关信息 |
| clean | 清理命令,用来清理应用的缓存和数据 |
| enable | 使能命令,用来使能应用,使能后应用可以继续使用 |
| disable | 禁用命令,用来禁用应用,禁用后应用无法使用 |
| get | 获取udid命令,用来获取设备的udid |
| quickfix | 快速修复相关命令,用来执行补丁相关操作,如补丁安装、补丁查询 |
## 帮助命令
**表2** help命令列表
| 命令 | 描述 |
| -------- | -------- |
| bm&nbsp;help | 显示bm工具的能够支持的命令信息 |
示例:
```bash
# 显示帮助信息
bm help
```
## 安装命令
```bash
bm install [-h] [-p path] [-u userId] [-r] [-w waitting-time]
```
**表3** 安装命令列表
| 命令 | 是否必选 | 描述 |
| -------- | -------- | -------- |
| -h | 否,默认输出帮助信息 | 显示install支持的命令信息 |
| -p | 是 | 安装HAP包路径,支持指定路径和多个HAP同时安装 |
| -u | 否,默认安装到当前所有用户上 | 给指定用户安装一个HAP包 |
| -r | 否,默认值为覆盖安装 | 覆盖安装一个HAP包 |
| -w | 否,默认等待5s | 安装HAP包时指定bm工具等待时间,最小的等待时长为5s,最大的等待时长为600s,&nbsp;默认缺省为5s |
示例:
```bash
bm install -p /data/app/ohosapp.hap -u 100 -w 5s -r
// 执行结果
install bundle successfully.
```
## 卸载命令
```bash
bm uninstall [-h help] [-n bundleName] [-m moduleName] [-u userId] [-k]
```
**表4** 卸载命令列表
| 命令 | 是否必选 | 描述 |
| -------- | -------- | -------- |
| -h | 否,默认输出帮助信息 | 显示uninstall支持的命令信息 |
| -n | 是 | 指定包名卸载应用 |
| -m | 否,默认卸载所有模块 | 指定卸载应用的一个模块 |
| -u | 否,默认卸载当前所有用户下该应用 | 指定用户卸载应用 |
| -k | 否,默认卸载应用时不保存应用数据 | 卸载应用时保存应用数据 |
示例:
```bash
bm uninstall -n com.ohos.app -m com.ohos.app.MainAbility -u 100 -k
// 执行结果
uninstall bundle successfully.
```
## 查询命令
```bash
bm dump [-h help] [-a] [-n bundleName] [-s shortcutInfo] [-u userId] [-d deviceId]
```
注:-u未指定情况下,默认为所有用户。
**表5** 查询命令列表
| 命令 | 是否必选 | 描述 |
| -------- | -------- | -------- |
| -h | 否,默认输出帮助信息 | 显示dump支持的命令信息 |
| -a | 是 | 查询系统已经安装的所有应用 |
| -n | 是 | 查询指定包名的详细信息 |
| -s | 是 | 查询指定包名下的快捷方式信息 |
| -d | 否,默认查询当前设备 | 查询指定设备中的包信息 |
| -u | 否,默认查询当前设备上的所有用户 | 查询指定用户下指定包名的详细信息 |
示例:
```bash
# 显示所有已安装的包名
bm dump -a
# 查询该应用的详细信息
bm dump -n com.ohos.app -u 100
# 查询该应用的快捷方式信息
bm dump -s com.ohos.app -u 100
# 查询跨设备应用信息
bm dump -n com.ohos.app -d xxxxx
```
## 清理命令
```bash
bm clean [-h] [-c] [-n bundleName] [-d] [-u userId]
```
注:-u未指定情况下,默认为当前活跃用户。
**表6** 清理命令列表
| 命令 | 描述 |
| -------- | -------- |
| -h | 显示clean支持的命令信息 |
| -c&nbsp;-n | 清除指定包名的缓存数据 |
| -d&nbsp;-n | 清除指定包名的数据目录 |
| -u | 清除指定用户下包名的缓存数据 |
示例:
```bash
# 清理该应用下的缓存数据
bm clean -c -n com.ohos.app -u 100
// 执行结果
clean bundle cache files successfully.
# 清理该应用下的用户数据
bm clean -d -n com.ohos.app -u 100
// 执行结果
clean bundle data files successfully.
```
## 使能命令
```bash
bm enable [-h] [-n bundleName] [-a abilityName] [-u userId]
```
注:-u未指定情况下,默认为当前活跃用户。
**表7** 使能命令列表
| 命令 | 描述 |
| -------- | -------- |
| -h | 显示enable支持的命令信息 |
| -n | 使能指定包名的应用 |
| -a | 使能指定包名下的元能力模块 |
| -u | 使能指定用户和包名的应用 |
示例:
```bash
# 使能该应用
bm enable -n com.ohos.app -a com.ohos.app.MainAbility -u 100
// 执行结果
enable bundle successfully.
```
## 禁用命令
```bash
bm disable [-h] [-n bundleName] [-a abilityName] [-u userId]
```
注:-u未指定情况下,默认为当前活跃用户。
**表8** 禁用命令列表
| 命令 | 描述 |
| -------- | -------- |
| -h | 显示disable支持的命令信息 |
| -n | 禁用指定包名的应用 |
| -a | 禁用指定包名下的元能力模块 |
| -u | 禁用指定用户和包名下的应用 |
示例:
```bash
# 禁用该应用
bm disable -n com.ohos.app -a com.ohos.app.MainAbility -u 100
// 执行结果
disable bundle successfully.
```
## 获取udid
```bash
bm get [-h] [-u]
```
**表9** 获取udid命令列表
| 命令 | 描述 |
| -------- | -------- |
| -h | 显示get支持的命令信息 |
| -u | 获取设备的udid |
示例:
```bash
# 获取设备的udid
bm get -u
// 执行结果
udid of current device is :
23CADE0C
```
## 快速修复
```bash
bm quickfix [-h] [-a -f filePath] [-q -b bundleName]
```
**表10** 快速修复命令列表
| 命令 | 描述 |
| -------- | -------- |
| -h | 显示quickfix支持的命令信息 |
| -a&nbsp;-f | 执行快速修复补丁安装命令,file-path对应hqf文件,支持传递1个或多个hqf文件,或传递hqf文件所在的目录。 |
| -q&nbsp;-b | 根据包名查询补丁信息,bundle-name对应包名。 |
示例:
```bash
# 根据包名查询补丁包信息
bm quickfix -q -b com.ohos.app
// 执行结果
// Information as follows:
// ApplicationQuickFixInfo:
// bundle name: com.ohos.app
// bundle version code: xxx
// bundle version name: xxx
// patch version code: x
// patch version name:
// cpu abi:
// native library path:
// type:
# 快速修复补丁安装
bm quickfix -a -f /data/app/
//执行结果
apply quickfix succeed.
```
# 调试助手使用指导 # cem工具
​ 公共事件与通知提供了供开发者查看公共事件信息及通知信息、发布公共事件等一些调试功能的工具。这些工具已经随系统集成,开发者进入shell环境,可以直接调用相关命令。 Common Event Manager(公共事件管理工具, 简称cem)是实现公共事件信息打印、发布公共事件等功能的工具,为开发者提供基本的公共事件调试和测试能力。通过该工具,开发者可以在hdc shell中,发送命令执行各种系统操作,例如打印所有公共事件订阅者、已发送公共事件和接受者、模拟发布公共事件等。
## cem调试助手 ## cem调试助手
### help
* 介绍
打印帮助信息。
* 用法
```
cem help
```
### publish ### publish
* 介绍 * 介绍
...@@ -12,7 +24,9 @@ ...@@ -12,7 +24,9 @@
* 用法 * 用法
`cem publish [<options>]` ```
cem publish [<options>]
```
参数如下表所示 参数如下表所示
...@@ -25,19 +39,19 @@ ...@@ -25,19 +39,19 @@
| -d/--data | 可选参数,公共事件携带数据 | | -d/--data | 可选参数,公共事件携带数据 |
| -h/--help | 帮助信息 | | -h/--help | 帮助信息 |
* 示例 * 示例:
`cem publish --event "testevent"`
发布名称为testevent的公共事件 ```bash
# 发布名称为testevent的公共事件
cem publish --event "testevent"
```
![cem-publish-event](figures/cem-publish-event.png) ![cem-publish-event](figures/cem-publish-event.png)
```bash
# 发布名称为testevent的粘性有序公共事件,该事件的结果码为100,携带数据内容为“this is data”
`cem publish -e "testevent" -s -o -c 100 -d "this is data" ` cem publish -e "testevent" -s -o -c 100 -d "this is data"
```
发布名称为testevent的粘性有序公共事件,该事件的结果码为100,携带数据内容为“this is data”
![cem-publish-all](figures/cem-publish-all.png) ![cem-publish-all](figures/cem-publish-all.png)
...@@ -49,7 +63,9 @@ ...@@ -49,7 +63,9 @@
* 用法 * 用法
`cem dump [<options>]` ```
cem dump [<options>]
```
参数如下表所示 参数如下表所示
...@@ -61,74 +77,9 @@ ...@@ -61,74 +77,9 @@
* 示例 * 示例
`cem dump -e "testevent"` ```bash
# 打印公共事件名称为testevent的具体信息
​ 打印公共事件名称为testevent的具体信息。 cem dump -e "testevent"
```
​ ![cem-dump-e](figures/cem-dump-e.png)
### help
* 介绍
打印帮助信息。
* 用法
`cem help`
* 示例
![cem-help](figures/cem-help.png)
## anm调试助手
### dump
* 介绍
打印通知相关信息。
* 用法
`anm dump [<options>]`
参数如下表所示
| 参数 | 参数说明 |
| ---------------- | ---------------------------------------- |
| -A/--active | 打印所有活跃的通知信息 |
| -R/--recent | 打印最近的通知信息 |
| -D/--distributed | 打印来自其他设备的分布式通知信息 |
| --setRecentCount | 可选参数,设置打印最近的通知消息缓存个数 |
| -h/--help | 帮助信息 |
* 示例
`anm dump -A`
打印活跃的通知信息
![anm-dump-A](figures/anm-dump-A.png)
`anm dump --setRecentCount 10`
设置打印最近通知消息缓存数量为10
### help
* 介绍
打印帮助信息。
* 用法
`anm help`
* 示例
![anm-help](figures/anm-help.png) ![cem-dump-e](figures/cem-dump-e.png)
\ No newline at end of file
# 打包工具
打包工具是OpenHarmony提供的一种调测工具,支持通过命令行的方式生成HAP、将多个HAP打包为App Pack(Application Package),或将多个HAP和App Pack打包为App Pack。App Pack为应用市场上架时所需的包格式。
打包所用的app_packing_tool.jar,可以在本地下载的OpenHarmony的SDK库中找到。
- 打包为HAP
Stage模型打包命令如下:
```bash
java -jar app_packing_tool.jar --mode <option> --json-path <option> --resources-path <option> --ets-path <option> --index-path <option> --pack-info-path <option> --out-path <option> --force <option>
```
FA模型打包命令如下:
```bash
java -jar app_packing_tool.jar --mode <option> --json-path <option> --maple-so-path <option> --profile-path <option> --maple-so-dir <option> --dex-path <option> --lib-path <option> --resources-path <option> --index-path <option> --out-path <option> --force <option>
```
命令参数含义及规范请见下表。
| 指令 | 是否必选项 | 描述 |
| -------- | -------- | -------- |
| --mode | 是 | 打包类型,此处为hap。 |
| --json-path | 是 | .json文件路径,FA模型文件名必须为config.json;stage模型文件名必须为module.json5。 |
| --profile-path | 否 | CAPABILITY.profile文件路径 |
| --maple-so-path | 否 | maple&nbsp;so文件输入路径,so文件路径,文件名必须以.so为后缀。如果是多个so需要用","分隔。 |
| --maple-so-dir | 否 | maple&nbsp;so目录输入路径。 |
| --dex-path | 否 | 1.dex文件路径,文件名必须以.dex为后缀。如果是多个dex需要用","分隔。<br/>2.dex文件路径也可以为目录。 |
| --lib-path | 否 | lib库文件路径。 |
| --resources-path | 否 | resources资源包路径。 |
| --index-path | 否 | .index文件路径,文件名必须为resources.index。 |
| --pack-info-path | 否 | pack.info文件路径,文件名必须为pack.info。 |
| --rpcid-path | 否 | rpcid.sc文件路径,文件名必须为rpcid.sc。 |
| --js-path | 否 | 存放js文件目录路径,仅stage模型生效。 |
| --ets-path | 否 | 存放ets文件的目录路径,仅stage模型生效。 |
| --out-path | 是 | 目标文件路径,文件名必须以.hap为后缀。 |
| --force | 否 | 默认值为false,如果为true,表示当目标文件存在时,强制删除。 |
- 将多个HAP打包为APP包
命令如下:
```bash
java -jar app_packing_tool.jar --mode <option> --hap-path <option> --out-path <option> --signature-path <option> --certificate-path <option> --pack-info-path <option> --force <option>
```
命令参数含义及规范请见下表。
| 指令 | 是否必选项 | 描述 |
| -------- | -------- | -------- |
| --mode | 是 | 打包类型,此处为app。在将多个HAP打入同一个app时,需保证每个HAP的versionCode、versionName字段相同。 |
| --hap-path | 是 | 1.HAP文件路径,文件名必须以.hap为后缀。如果是多个HAP需要用","分隔。<br/>2.HAP文件路径也可以是目录。 |
| --pack-info-path | 是 | 文件名必须为pack.info。 |
| --out-path | 是 | 目标文件路径,文件名必须以.app为后缀。 |
| --signature-path | 否 | 签名路径。 |
| --certificate-path | 否 | 证书路径,请参见[签名指导](../security/hapsigntool-guidelines.md)。 |
| --force | 否 | 默认值为false,如果为true,表示当目标文件存在时,强制删除。 |
- 多个HAP或者多个APP打包为APP包
命令如下:
```bash
java -jar app_packing_tool.jar --mode <option> --hap-list <option> --app-list <option> --out-path <option>
```
命令参数含义及规范请见下表。
| 指令 | 是否必选项 | 描述 |
| -------- | -------- | -------- |
| --mode | 是 | 打包类型,此处为multiApp。在将多个HAP打入同一个APP时,需保证每个HAP满足合法性校验规则。 |
| --hap-list | 否 | 1.HAP文件路径,文件名必须以.hap为后缀。如果是多个HAP需要用","分隔。<br/>2.HAP文件路径也可以是目录。 |
| --app-list | 否 | 1.APP文件路径,文件名必须以.app为后缀。如果是多个APP包需要用","分隔。<br/>2.APP文件路径也可以是目录。<br/>3.--hap-list命令与--app-list不可以都不传。 |
| --out-path | 是 | 目标文件路径,文件名必须以.app为后缀。 |
| --force | 否 | 默认值为false,如果为true,表示当目标文件存在时,强制删除。 |
多工程打包HAP合法性校验规则:
- 需保证被打包的每个HAP在配置文件(请参见"[FA模型配置文件](../application-models/application-component-configuration-fa.md)"或 "[Stage模型配置文件](../application-models/application-component-configuration-stage.md)")中配置的bundleName、versionCode、versionName、minCompatibleVersionCode、minAPIVersion, targetAPIVersion , apiReleaseType等字段相同。
- 每个HAP的moduleName唯一,同一设备Entry类型的HAP唯一。
- 对于FA模型,还需要保证json文件中配置的package唯一。
# 拆包工具
拆包工具是OpenHarmony提供的一种调测工具,支持通过命令行方式将HAP拆分为文件夹或者将App Pack(Application Package)拆分为HAP。
拆包所用的app_unpacking_tool.jar,可以在本地下载的OpenHarmony的SDK库中找到。
- HAP拆包命令
```bash
java -jar app_unpacking_tool.jar --mode <option> --hap-path <option> --out-path <option> --force <option>
```
命令参数含义及规范请见下表。
| 指令 | 是否必选项 | 描述 |
| -------- | -------- | -------- |
| --mode | 是 | 拆包类型,此处为hap。 |
| --hap-path | 是 | HAP路径。 |
| --rpcid | 否 | 是否单独将rpcid文件从HAP中提取到指定目录,如果为true,将仅提取rpcid文件,不对HAP进行拆包。 |
| --out-path | 是 | 拆包目标文件路径。 |
| --force | 否 | 默认值为false,如果为true,表示当目标文件存在时,强制删除。 |
- App包拆包命令
```bash
java -jar app_unpacking_tool.jar --mode <option> --app-path <option> --out-path <option> --force <option>
```
命令参数含义及规范请见下表。
| 指令 | 是否必选项 | 描述 |
| -------- | -------- | -------- |
| --mode | 是 | 拆包类型,此处为hap。 |
| --app-path | 是 | app包路径。 |
| --out-path | 是 | 拆包目标文件路径。 |
| --force | 否 | 默认值为false,如果为true,表示当目标文件存在时,强制删除。 |
- 从HAP中获取rpcid文件命令
```bash
java -jar app_unpacking_tool.jar --mode <option> --rpcid <option> --hap-path <option> --out-path <option> --force <option>
```
命令参数含义及规范请见下表。
| 指令 | 是否必选项 | 描述 |
| -------- | -------- | -------- |
| --mode | 是 | 拆包类型,此处为hap。 |
| --rpcid | 否 | 是否单独将rpcid文件从HAP中提取到指定目录,如果为true,将仅提取rpcid文件,不对HAP进行拆包。 |
| --out-path | 是 | 拆包rpcid目标文件路径。 |
| --hap-path | 是 | HAP路径。 |
...@@ -8,9 +8,28 @@ ...@@ -8,9 +8,28 @@
- [使用ArkTS语言开发(FA模型)](quick-start/start-with-ets-fa.md) - [使用ArkTS语言开发(FA模型)](quick-start/start-with-ets-fa.md)
- [使用JS语言开发(FA模型)](quick-start/start-with-js-fa.md) - [使用JS语言开发(FA模型)](quick-start/start-with-js-fa.md)
- 开发基础知识 - 开发基础知识
- [应用包结构配置文件的说明(FA模型)](quick-start/package-structure.md) - 应用程序包基础知识
- [应用包结构配置文件的说明(Stage模型)](quick-start/stage-structure.md) - [应用程序包概述](quick-start/application-package-overview.md)
- [SysCap说明](quick-start/syscap.md) - 应用程序包结构
- [Stage模型应用程序包结构](quick-start/application-package-structure-stage.md)
- [FA模型应用程序包结构](quick-start/application-package-structure-fa.md)
- [HAR包结构](quick-start/har-structure.md)
- 应用程序包多HAP机制
- [多HAP机制设计目标](quick-start/multi-hap-objective.md)
- [多HAP构建视图](quick-start/multi-hap-build-view.md)
- [多HAP发布部署流程](quick-start/multi-hap-release-deployment.md)
- [多HAP使用规则](quick-start/multi-hap-rules.md)
- [多HAP运行机制及数据通信方式](quick-start/multi-hap-principles.md)
- [应用程序包安装和卸载流程](quick-start/application-package-install-uninstall.md)
- 应用配置文件(Stage模型)
- [应用配置文件概述(Stage模型)](quick-start/application-configuration-file-overview-stage.md)
- [app.json5配置文件](quick-start/app-configuration-file.md)
- [module.json5配置文件](quick-start/module-configuration-file.md)
- 应用配置文件(FA模型)
- [应用配置文件概述(FA模型)](quick-start/application-configuration-file-overview-fa.md)
- [app对象内部结构](quick-start/app-structure.md)
- [deviceConfig内部结构](quick-start/deviceconfig-structure.md)
- [module对象内部结构](quick-start/module-structure.md)
- [资源分类与访问](quick-start/resource-categories-and-access.md) - [资源分类与访问](quick-start/resource-categories-and-access.md)
- 学习ArkTS语言 - 学习ArkTS语言
- [初识ArkTS语言](quick-start/arkts-get-started.md) - [初识ArkTS语言](quick-start/arkts-get-started.md)
...@@ -24,27 +43,132 @@ ...@@ -24,27 +43,132 @@
- [渲染控制](quick-start/arkts-rendering-control.md) - [渲染控制](quick-start/arkts-rendering-control.md)
- [使用限制与扩展](quick-start/arkts-restrictions-and-extensions.md) - [使用限制与扩展](quick-start/arkts-restrictions-and-extensions.md)
- 开发 - 开发
- Ability开发 - 应用模型
- [Ability框架概述](ability/ability-brief.md) - 应用模型概述
- [应用上下文Context概述](ability/context-userguide.md) - [OpenHarmony应用模型的构成要素](application-models/application-model-composition.md)
- FA模型 - [OpenHarmony应用模型解读](application-models/application-model-description.md)
- [FA模型综述](ability/fa-brief.md) - Stage模型开发指导
- [PageAbility开发指导](ability/fa-pageability.md) - [Stage模型开发概述](application-models/stage-model-development-overview.md)
- [ServiceAbility开发指导](ability/fa-serviceability.md) - Stage模型应用组件
- [DataAbility开发指导](ability/fa-dataability.md) - [应用/组件级配置](application-models/application-component-configuration-stage.md)
- [FA卡片开发指导](ability/fa-formability.md) - UIAbility组件
- Stage模型 - [UIAbility组件概述](application-models/uiability-overview.md)
- [Stage模型综述](ability/stage-brief.md) - [UIAbility组件生命周期](application-models/uiability-lifecycle.md)
- [Ability开发指导](ability/stage-ability.md) - [UIAbility组件启动模式](application-models/uiability-launch-type.md)
- [ServiceExtensionAbility开发指导](ability/stage-serviceextension.md) - [UIAbility组件基本用法](application-models/uiability-usage.md)
- [跨端迁移开发指导](ability/stage-ability-continuation.md) - [UIAbility组件与UI的数据同步](application-models/uiability-data-sync-with-ui.md)
- [Call调用开发指导](ability/stage-call.md) - [UIAbility组件间交互(设备内)](application-models/uiability-intra-device-interaction.md)
- [Stage卡片开发指导](ability/stage-formextension.md) - ExtensionAbility组件
- 其他 - [ExtensionAbility组件概述](application-models/extensionability-overview.md)
- [WantAgent开发指导](ability/wantagent.md) - [ServiceExtensionAbility](application-models/serviceextensionability.md)
- [Ability助手使用指导](ability/ability-assistant-guidelines.md) - [DataShareExtensionAbility(仅对系统应用开放)](application-models/datashareextensionability.md)
- [ContinuationManager使用指导](ability/continuationmanager.md) - [FormExtensionAbility(服务卡片)](application-models/widget-development-stage.md)
- [测试框架使用指导](ability/ability-delegator.md) - [AbilityStage组件容器](application-models/abilitystage.md)
- [应用上下文Context](application-models/application-context-stage.md)
- 信息传递载体Want
- [Want概述](application-models/want-overview.md)
- [显式Want与隐式Want匹配规则](application-models/explicit-implicit-want-mappings.md)
- [常见action与entities](application-models/actions-entities.md)
- [使用显式Want启动Ability](application-models/ability-startup-with-explicit-want.md)
- [使用隐式Want打开网址](application-models/ability-startup-with-implicit-want.md)
- [应用间使用Want分享数据](application-models/data-share-via-want.md)
- [组件启动规则](application-models/component-startup-rules.md)
- 应用组件跨设备交互(流转)
- [流转概述](application-models/inter-device-interaction-hop-overview.md)
- [跨端迁移(仅对系统应用开放)](application-models/hop-cross-device-migration.md)
- [多端协同(仅对系统应用开放)](application-models/hop-multi-device-collaboration.md)
- 进程间通信
- [进程模型](application-models/process-model-stage.md)
- 公共事件
- [公共事件简介](application-models/common-event-overview.md)
- [公共事件订阅](application-models/common-event-subscription.md)
- [公共事件发布](application-models/common-event-publish.md)
- [公共事件取消订阅](application-models/common-event-unsubscription.md)
- [后台服务](application-models/background-services.md)
- 线程间通信
- [线程模型](application-models/thread-model-stage.md)
- [使用Emitter进行线程间通信](application-models/itc-with-emitter.md)
- [使用Worker进行线程间通信](application-models/itc-with-worker.md)
- 任务管理
- [任务管理场景介绍](application-models/mission-management-overview.md)
- [任务管理与启动模式](application-models/mission-management-launch-type.md)
- [页面栈及任务链](application-models/page-mission-stack.md)
- FA模型开发指导
- [FA模型开发概述](application-models/fa-model-development-overview.md)
- FA模型应用组件
- [应用/组件级配置](application-models/application-component-configuration-fa.md)
- PageAbility组件开发指导
- [PageAbility组件概述](application-models/pageability-overview.md)
- [PageAbility组件配置](application-models/pageability-configuration.md)
- [PageAbility的生命周期](application-models/pageability-lifecycle.md)
- [PageAbility的启动模式](application-models/pageability-launch-type.md)
- [创建PageAbility](application-models/create-pageability.md)
- [启动本地PageAbility](application-models/start-local-pageability.md)
- [停止PageAbility](application-models/stop-pageability.md)
- [启动远程PageAbility(仅对系统应用开放)](application-models/start-remote-pageability.md)
- [启动指定页面](application-models/start-page.md)
- [窗口属性](application-models/window-properties.md)
- [申请授权](application-models/request-permissions.md)
- [跳转规则](application-models/redirection-rules.md)
- ServiceAbility组件开发指导
- [ServiceAbility组件概述](application-models/serviceability-overview.md)
- [ServiceAbility组件配置](application-models/serviceability-configuration.md)
- [ServiceAbility的生命周期](application-models/serviceability-lifecycle.md)
- [创建ServiceAbility](application-models/create-serviceability.md)
- [启动ServiceAbility](application-models/start-serviceability.md)
- [连接ServiceAbility](application-models/connect-serviceability.md)
- DataAbility组件开发指导
- [DataAbility组件概述](application-models/dataability-overview.md)
- [DataAbility组件配置](application-models/dataability-configuration.md)
- [DataAbility的生命周期](application-models/dataability-lifecycle.md)
- [创建DataAbility](application-models/create-dataability.md)
- [启动DataAbility](application-models/start-dataability.md)
- [访问DataAbility](application-models/access-dataability.md)
- [DataAbility权限控制](application-models/dataability-permission-control.md)
- [服务卡片开发指导](application-models/widget-development-fa.md)
- [FA模型的Context](application-models/application-context-fa.md)
- [信息传递载体Want](application-models/want-fa.md)
- 进程间通信
- [进程模型](application-models/process-model-fa.md)
- [公共事件](application-models/common-event-fa.md)
- [后台服务](application-models/rpc.md)
- 线程间通信
- [线程模型](application-models/thread-model-fa.md)
- [线程间通信](application-models/itc-fa-overview.md)
- [任务管理](application-models/mission-management-fa.md)
- FA模型与Stage模型应用组件互通指导
- [FA模型与Stage模型应用组件互通综述](application-models/fa-stage-interaction-overview.md)
- [FA模型启动Stage模型UIAbility](application-models/start-uiability-from-fa.md)
- [FA模型绑定Stage模型ServiceExtensionAbility](application-models/bind-serviceextensionability-from-fa.md)
- [FA模型访问Stage模型DataShareExtensionAbility](application-models/access-datashareextensionability-from-fa.md)
- [Stage模型启动FA模型PageAbility](application-models/start-pageability-from-stage.md)
- [Stage模型绑定FA模型ServiceAbility](application-models/bind-serviceability-from-stage.md)
- FA模型切换Stage模型指导
- [模型切换概述](application-models/model-switch-overview.md)
- 配置文件切换
- [配置文件的差异](application-models/configuration-file-diff.md)
- [app和deviceConfig的切换](application-models/app-deviceconfig-switch.md)
- [module的切换](application-models/module-switch.md)
- 组件切换
- [PageAbility切换](application-models/pageability-switch.md)
- [ServiceAbility切换](application-models/aerviceability-switch.md)
- [DataAbility切换](application-models/dataability-switch.md)
- [卡片切换](application-models/widget-switch.md)
- API切换
- [API切换概述](application-models/api-switch-overview.md)
- [Context接口切换](application-models/context-switch.md)
- [featureAbility接口切换](application-models/featureability-switch.md)
- [particleAbility接口切换](application-models/particleability-switch.md)
- [LifecycleForm接口切换](application-models/lifecycleform-switch.md)
- [LifecycleApp接口切换](application-models/lifecycleapp-switch.md)
- [LifecycleService接口切换](application-models/lifecycleservice-switch.md)
- [LifecycleData接口切换](application-models/lifecycledata-switch.md)
- [DataAbilityHelper接口切换](application-models/dataabilityhelper-switch.md)
- [mediaLibrary接口切换](application-models/medialibrary-switch.md)
- [request接口切换](application-models/request-switch.md)
- [resourceManager接口切换](application-models/resourcemanager-switch.md)
- [window接口切换](application-models/window-switch.md)
- [Storage接口切换](application-models/storage-switch.md)
- UI开发 - UI开发
- [方舟开发框架(ArkUI)概述](ui/arkui-overview.md) - [方舟开发框架(ArkUI)概述](ui/arkui-overview.md)
- 基于ArkTS的声明式开发范式 - 基于ArkTS的声明式开发范式
...@@ -145,11 +269,14 @@ ...@@ -145,11 +269,14 @@
- [动画动效](ui/ui-js-animate-dynamic-effects.md) - [动画动效](ui/ui-js-animate-dynamic-effects.md)
- [动画帧](ui/ui-js-animate-frame.md) - [动画帧](ui/ui-js-animate-frame.md)
- [自定义组件](ui/ui-js-custom-components.md) - [自定义组件](ui/ui-js-custom-components.md)
- 公共事件与通知 - 通知
- [公共事件与通知概述](notification/notification-brief.md) - [通知概述](notification/notification-overview.md)
- [公共事件开发指导](notification/common-event.md) - [订阅通知(仅对系统应用开放)](notification/notification-subscription.md)
- [通知开发指导](notification/notification-guidelines.md) - [使能通知开关](notification/notification-enable.md)
- [调试助手使用指导](notification/assistant-guidelines.md) - 发布通知
- [发布基础类型通知](notification/text-notification.md)
- [发布进度条类型通知](notification/progress-bar-notification.md)
- [为通知添加行为意图](notification/notification-with-wantagent.md)
- 窗口管理 - 窗口管理
- [窗口开发概述](windowmanager/window-overview.md) - [窗口开发概述](windowmanager/window-overview.md)
- [管理应用窗口(Stage模型)](windowmanager/application-window-stage.md) - [管理应用窗口(Stage模型)](windowmanager/application-window-stage.md)
...@@ -347,10 +474,19 @@ ...@@ -347,10 +474,19 @@
- [Neural Network Runtime对接AI推理框架开发指导](napi/neural-network-runtime-guidelines.md) - [Neural Network Runtime对接AI推理框架开发指导](napi/neural-network-runtime-guidelines.md)
- 工具 - 工具
- [DevEco Studio(OpenHarmony)使用指南](quick-start/deveco-studio-user-guide-for-openharmony.md) - [DevEco Studio(OpenHarmony)使用指南](quick-start/deveco-studio-user-guide-for-openharmony.md)
- [aa工具](tools/aa-tool.md)
- [bm工具](tools/bm-tool.md)
- 打包拆包工具
- [打包工具](tools/packing-tool.md)
- [拆包工具](tools/unpacking-tool.md)
- [anm工具](tools/anm-tool.md)
- [cem工具](tools/cem-tool.md)
- 示例教程 - 示例教程
- [示例代码](https://gitee.com/openharmony/applications_app_samples/blob/master/README_zh.md) - [示例代码](https://gitee.com/openharmony/applications_app_samples/blob/master/README_zh.md)
- [Codelabs](https://gitee.com/openharmony/codelabs/blob/master/README.md) - [Codelabs](https://gitee.com/openharmony/codelabs/blob/master/README.md)
- API参考 - API参考
- [系统能力SystemCapability使用指南](reference/syscap.md)
- [系统能力SystemCapability列表](reference/syscap-list.md)
- [Syscap列表](reference/syscap-list.md) - [Syscap列表](reference/syscap-list.md)
- 组件参考(基于ArkTS的声明式开发范式) - 组件参考(基于ArkTS的声明式开发范式)
- [组件导读](reference/arkui-ts/ts-components-summary.md) - [组件导读](reference/arkui-ts/ts-components-summary.md)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册