提交 832ea7b1 编写于 作者: Z zengyawen

application-models

Signed-off-by: Nzengyawen <zengyawen1@huawei.com>
上级 055176c4
# 应用模型
- 应用模型概述
- [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切换](aerviceability-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&gt;app.json5文件内获取;abilityName可在对应模块内的“yourModuleName &gt; src &gt; main &gt; 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按钮时,应看到页面的跳转。
![startAbilityWtExplicitWant](figures/startAbilityWtExplicitWant.PNG)
# 使用隐式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. 当有多个匹配应用时,会被应用选择器展示给用户进行选择。![stage-want1](figures/stage-want1.png)
# 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)
# 应用/组件级配置
在开发应用时,需要配置应用的一些标签,例如应用的包名、图标等标识特征的属性。本文描述了在开发应用需要配置的一些关键标签。图标和标签通常一起配置,可以分为应用图标、应用标签和入口图标、入口标签,分别对应[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的继承关系
![context-inheritance](figures/context-inheritance.png)
- 各类Context的持有关系
![context-holding](figures/context-holding.png)
- 各类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中获取的应用开发路径  
![context-dir](figures/context-dir.png)
- 通过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%E6%A8%A1%E5%9E%8B)。
>
> - 接口为系统接口,三方应用不支持调用。
例如在桌面上显示的应用信息,包括应用名称和应用图标等,桌面应用可以通过调用上述的方法获取相应应用的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%E6%A8%A1%E5%9E%8B)。
>
> - 接口为系统接口,三方应用不支持调用。
```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** 向用户申请日历访问授权
![application-context-stage](figures/application-context-stage.png)
\ 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%E6%A8%A1%E5%9E%8B)
每个应用都可以按需订阅公共事件,订阅成功,当公共事件发布时,系统会将其发送给对应的应用。这些公共事件可能来自系统、其他应用和应用自身。
**图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#%E6%9D%83%E9%99%90%E5%88%97%E8%A1%A8)
## 接口说明
详细接口见[接口文档](../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:&nbsp;number,&nbsp;permissionName:&nbsp;Permissions):&nbsp;GrantStatus;](../reference/apis/js-apis-abilityAccessCtrl.md#verifyaccesstokensync9)<br/>[verifyAccessToken(tokenID:&nbsp;number,&nbsp;permissionName:&nbsp;Permissions):&nbsp;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:&nbsp;Array&lt;string&gt;,&nbsp;requestCallback:&nbsp;AsyncCallback&lt;PermissionRequestResult&gt;)&nbsp;:&nbsp;void;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextrequestpermissionsfromuser)<br/>[requestPermissionsFromUser(permissions:&nbsp;Array&lt;string&gt;)&nbsp;:&nbsp;Promise&lt;PermissionRequestResult&gt;;](../reference/apis/js-apis-inner-application-uiAbilityContext.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:&nbsp;ApplicationInfo;](../reference/apis/js-apis-inner-application-context.md#属性) |
| [getBundleName(callback&nbsp;:&nbsp;AsyncCallback&lt;string&gt;):&nbsp;void;](../reference/apis/js-apis-Context.md#contextgetbundlename7)<br/>[getBundleName():&nbsp;Promise&lt;string&gt;;](../reference/apis/js-apis-Context.md#contextgetbundlename7-1) | application\UIAbilityContext.d.ts | [abilityInfo.bundleName:&nbsp;string;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#属性) |
| [getDisplayOrientation(callback&nbsp;:&nbsp;AsyncCallback&lt;bundle.DisplayOrientation&gt;):&nbsp;void;](../reference/apis/js-apis-Context.md#contextgetdisplayorientation7)<br/>[getDisplayOrientation():&nbsp;Promise&lt;bundle.DisplayOrientation&gt;;](../reference/apis/js-apis-Context.md#contextgetdisplayorientation7-1) | \@ohos.screen.d.ts | [readonly&nbsp;orientation:&nbsp;Orientation;](../reference/apis/js-apis-screen.md#orientation) |
| [setDisplayOrientation(orientation:bundle.DisplayOrientation,&nbsp;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:&nbsp;Orientation,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-screen.md#setorientation)<br/>[setOrientation(orientation:&nbsp;Orientation):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-screen.md#setorientation-1) |
| [setShowOnLockScreen(show:boolean,&nbsp;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:&nbsp;boolean):&nbsp;void;](../reference/apis/js-apis-window.md#setshowonlockscreen9) |
| [setWakeUpScreen(wakeUp:boolean,&nbsp;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:&nbsp;boolean):&nbsp;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:&nbsp;AsyncCallback&lt;Array&lt;AbilityRunningInfo&gt;&gt;):&nbsp;void;](../reference/apis/js-apis-app-ability-abilityManager.md#getabilityrunninginfos)<br/>[getAbilityRunningInfos():&nbsp;Promise&lt;Array&lt;AbilityRunningInfo&gt;&gt;;](../reference/apis/js-apis-app-ability-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:&nbsp;string;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#属性)<br/>[abilityInfo.bundleName:&nbsp;string;](../reference/apis/js-apis-inner-application-uiAbilityContext.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:&nbsp;AsyncCallback&lt;Array&lt;AbilityRunningInfo&gt;&gt;):&nbsp;void;](../reference/apis/js-apis-app-ability-abilityManager.md#getabilityrunninginfos)<br/>[getAbilityRunningInfos():&nbsp;Promise&lt;Array&lt;AbilityRunningInfo&gt;&gt;;](../reference/apis/js-apis-app-ability-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:&nbsp;string;](../reference/apis/js-apis-inner-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:&nbsp;string;](../reference/apis/js-apis-inner-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:&nbsp;string;](../reference/apis/js-apis-inner-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:&nbsp;bundleManager.AbilityType;](../reference/apis/js-apis-inner-application-uiAbilityContext.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:&nbsp;HapModuleInfo;](../reference/apis/js-apis-inner-application-uiAbilityContext.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&nbsp;name:&nbsp;string;](../reference/apis/js-apis-bundleManager-bundleInfo.md#bundleinfo-1)<br/>[readonly&nbsp;versionCode:&nbsp;number;](../reference/apis/js-apis-bundleManager-bundleInfo.md#bundleinfo-1)<br/>[readonly&nbsp;versionName:&nbsp;string;](../reference/apis/js-apis-bundleManager-bundleInfo.md#bundleinfo-1) |
| [getApplicationContext():Context;](../reference/apis/js-apis-Context.md#contextgetapplicationcontext7) | application\Context.d.ts | [getApplicationContext():&nbsp;ApplicationContext;](../reference/apis/js-apis-inner-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:&nbsp;AbilityInfo;](../reference/apis/js-apis-inner-application-uiAbilityContext.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]”时,应用选择器将以下形式展示。![stage-want2](figures/stage-want2.png)
示例代码中“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-Bundle.md#extensionabilitytype9)。 |
| 应用内使用的数据 | 对应用内其他组件提供数据,建议提取公共模块。 |
# 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匹配规则  
![want-action](figures/want-action.png)
### 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匹配规则  
![want-entities](figures/want-entities.png)
### want参数的uri和type匹配规则
调用方传入的want参数中设置uri和type参数发起组件启动请求,系统会遍历当前系统已安装的组件列表,并逐个匹配待匹配Ability的skills配置中的uris数组,如果待匹配Ability的skills配置中的uris数组中只要有一个可以匹配调用方传入的want参数中设置的uri和type即为匹配成功。
**图3** want参数中uri和type皆不为空时的匹配规则  
![want-uri-type1](figures/want-uri-type1.png)
实际应用中,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的具体匹配规则  
![want-uri-type2](figures/want-uri-type2.png)
### 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-app-ability-uiAbility.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-inner-application-uiAbilityContext.md#abilitycontextstartability)<br/>[startAbility(want:&nbsp;Want,&nbsp;options:&nbsp;StartOptions,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartability-1)<br/>[startAbility(want:&nbsp;Want,&nbsp;options?:&nbsp;StartOptions):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-inner-application-uiAbilityContext.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-app-ability-uiAbility.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-inner-application-uiAbilityContext.md#abilitycontextstartabilityforresult)<br/>[startAbilityForResult(want:&nbsp;Want,&nbsp;options:&nbsp;StartOptions,&nbsp;callback:&nbsp;AsyncCallback&lt;AbilityResult&gt;):&nbsp;void;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartabilityforresult-1)<br/>[startAbilityForResult(want:&nbsp;Want,&nbsp;options?:&nbsp;StartOptions):&nbsp;Promise&lt;AbilityResult&gt;;](../reference/apis/js-apis-inner-application-uiAbilityContext.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-inner-application-uiAbilityContext.md#abilitycontextterminateselfwithresult)<br/>[terminateSelfWithResult(parameter:&nbsp;AbilityResult):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-inner-application-uiAbilityContext.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-inner-application-uiAbilityContext.md#abilitycontextterminateself)<br/>[terminateSelf():&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-inner-application-uiAbilityContext.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-inner-application-uiAbilityContext.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-inner-application-uiAbilityContext.md#abilitycontextdisconnectserviceextensionability-1)<br/>[disconnectAbility(connection:&nbsp;number):&nbsp;Promise&lt;void&gt;;](../reference/apis/js-apis-inner-application-uiAbilityContext.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) |
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册