未验证 提交 461f1dab 编写于 作者: O openharmony_ci 提交者: Gitee

!13346 翻译完成:12090 新增应用模型文档

Merge pull request !13346 from wusongqing/TR12090
# Application Models
- Application Model Overview
- [Elements of the Application Model](application-model-composition.md)
- [Interpretation of the Application Model](application-model-description.md)
- Stage Model Development
- [Stage Model Development Overview](stage-model-development-overview.md)
- Stage Mode Application Components
- [Application- or Component-Level Configuration](application-component-configuration-stage.md)
- UIAbility Component
- [UIAbility Component Overview](uiability-overview.md)
- [UIAbility Component Lifecycle](uiability-lifecycle.md)
- [UIAbility Component Launch Type](uiability-launch-type.md)
- [UIAbility Component Usage](uiability-usage.md)
- [Data Synchronization Between UIAbility and UI](uiability-data-sync-with-ui.md)
- [Interaction Between Intra-Device UIAbility Components](uiability-intra-device-interaction.md)
- ExtensionAbility Component
- [ExtensionAbility Component Overview](extensionability-overview.md)
- [ServiceExtensionAbility](serviceextensionability.md)
- [DataShareExtensionAbility](datashareextensionability.md)
- [FormExtensionAbility (Widget)](widget-development-stage.md)
- [AbilityStage Component Container](abilitystage.md)
- [Context](application-context-stage.md)
- Want
- [Want Overview](want-overview.md)
- [Matching Rules of Explicit Want and Implicit Want](explicit-implicit-want-mappings.md)
- [Common action and entities Values](actions-entities.md)
- [Using Explicit Want to Start an Ability](ability-startup-with-explicit-want.md)
- [Using Implicit Want to Open a Website](ability-startup-with-implicit-want.md)
- [Using Want to Share Data Between Applications](data-share-via-want.md)
- [Component Startup Rules](component-startup-rules.md)
- Inter-Device Application Component Interaction (Continuation)
- [Continuation Overview](inter-device-interaction-hop-overview.md)
- [Cross-Device Migration](hop-cross-device-migration.md)
- [Multi-device Collaboration](hop-multi-device-collaboration.md)
- IPC
- [Process Model](process-model-stage.md)
- Common Events
- [Introduction to Common Events](common-event-overview.md)
- [Subscribing to Common Events](common-event-subscription.md)
- [Publishing Common Events](common-event-publish.md)
- [Unsubscribing from Common Events](common-event-unsubscription.md)
- [Background Services](background-services.md)
- Inter-Thread Communication
- [Thread Model](thread-model-stage.md)
- [Using Emitter for Inter-Thread Communication](itc-with-emitter.md)
- [Using Worker for Inter-Thread Communication](itc-with-worker.md)
- Mission Management
- [Mission Management Scenarios](mission-management-overview.md)
- [Mission Management and Launch Type](mission-management-launch-type.md)
- [Page Stack and MissionList](page-mission-stack.md)
- [Application Configuration File](config-file-stage.md)
- FA Model Development
- [FA Model Development Overview](fa-model-development-overview.md)
- FA Mode Application Components
- [Application- or Component-Level Configuration](application-component-configuration-fa.md)
- PageAbility Component Development
- [PageAbility Component Overview](pageability-overview.md)
- [PageAbility Component Configuration](pageability-configuration.md)
- [PageAbility Lifecycle](pageability-lifecycle.md)
- [PageAbility Launch Type](pageability-launch-type.md)
- [Creating a PageAbility](create-pageability.md)
- [Starting a Local PageAbility](start-local-pageability.md)
- [Stopping a PageAbility](stop-pageability.md)
- [Starting a Remote PageAbility](start-remote-pageability.md)
- [Starting a Specified Page](start-page.md)
- [Window Properties](window-properties.md)
- [Requesting Permissions](request-permissions.md)
- [Redirection Rules](redirection-rules.md)
- ServiceAbility Component Development
- [ServiceAbility Component Overview](serviceability-overview.md)
- [ServiceAbility Component Configuration](serviceability-configuration.md)
- [ServiceAbility Lifecycle](serviceability-lifecycle.md)
- [Creating a ServiceAbility](create-serviceability.md)
- [Starting a ServiceAbility](start-serviceability.md)
- [Connecting to a ServiceAbility](connect-serviceability.md)
- DataAbility Component Development
- [DataAbility Component Overview](dataability-overview.md)
- [DataAbility Component Configuration](dataability-configuration.md)
- [DataAbility Lifecycle](dataability-lifecycle.md)
- [Creating a DataAbility](create-dataability.md)
- [Starting a DataAbility](start-dataability.md)
- [Accessing a DataAbility](access-dataability.md)
- [DataAbility Permission Control](dataability-permission-control.md)
- [Widget Development](widget-development-fa.md)
- [Context](application-context-fa.md)
- [Want](want-fa.md)
- [Component Startup Rules](component-startup-rules-fa.md)
- IPC
- [Process Model](process-model-fa.md)
- [Common Events](common-event-fa.md)
- [Background Services](rpc.md)
- Inter-Thread Communication
- [Thread Model](thread-model-fa.md)
- [Inter-Thread Communication](itc-fa-overview.md)
- [Mission Management](mission-management-fa.md)
- [Application Configuration File](config-file-fa.md)
- Development of Component Interaction Between the FA Model and Stage Model
- [Component Interaction Between the FA Model and Stage Model](fa-stage-interaction-overview.md)
- [Starting a UIAbility from the FA Model](start-uiability-from-fa.md)
- [Connecting to a ServiceExtensionAbility from the FA Model](bind-serviceextensionability-from-fa.md)
- [Accessing a DataShareExtensionAbility from the FA Model](access-datashareextensionability-from-fa.md)
- [Starting a PageAbility from the Stage Model](start-pageability-from-stage.md)
- [Connecting to a ServiceAbility from the Stage Model](bind-serviceability-from-stage.md)
- Switching from the FA Model to the Stage Model
- [Model Switching Overview](model-switch-overview.md)
- Configuration File Switching
- [Differences in Configuration Files](configuration-file-diff.md)
- [Switching of app and deviceConfig](app-deviceconfig-switch.md)
- [Switching of module](module-switch.md)
- Component Switching
- [PageAbility Switching](pageability-switch.md)
- [ServiceAbility Switching](serviceability-switch.md)
- [DataAbility Switching](dataability-switch.md)
- [Widget Switching](widget-switch.md)
- API Switching
- [API Switching Overview](api-switch-overview.md)
- [Context Switching](context-switch.md)
- [featureAbility Switching](featureability-switch.md)
- [particleAbility Switching](particleability-switch.md)
- [LifecycleForm Switching](lifecycleform-switch.md)
- [LifecycleApp Switching](lifecycleapp-switch.md)
- [LifecycleService Switching](lifecycleservice-switch.md)
- [LifecycleData Switching](lifecycledata-switch.md)
- [DataAbilityHelper Switching](dataabilityhelper-switch.md)
- [mediaLibrary Switching](medialibrary-switch.md)
- [request Switching](request-switch.md)
- [resourceManager Switching](resourcemanager-switch.md)
- [window Switching](window-switch.md)
- [Storage Switching](storage-switch.md)
# Using Explicit Want to Start an Ability
When a user touches a button in an application, the application often needs to start a UIAbility component to complete a specific task. If the **abilityName** and **bundleName** parameters are specified when starting a UIAbility, the explicit Want is used. For details about how to use the explicit Want, see [Starting UIAbility in the Same Application](uiability-intra-device-interaction.md#starting-uiability-in-the-same-application).
# Using Implicit Want to Open a Website
## Prerequisites
One or more browsers are installed on your device.
The **module.json5** of a browser application is as follows:
```json
"skills": [
{
"entities": [
"entity.system.browsable"
// ...
],
"actions": [
"ohos.want.action.viewData"
// ...
],
"uris": [
{
"scheme": "https",
"host": "www.test.com",
"port": "8080",
// Prefix matching is used.
"pathStartWith": "query",
"type": "text/*"
},
{
"scheme": "http",
// ...
}
// ...
]
},
]
```
## How to Develop
1. Use the custom function **implicitStartAbility** to start an ability.
```ts
async implicitStartAbility() {
try {
let want = {
// Uncomment the line below if you want to implicitly query data 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}`)
}
}
```
The matching process is as follows:
1. If **action** in the passed **want** parameter is specified and is included in **actions** under **skills**, the matching is successful.
2. If **entities** in the passed **want** parameter is specified and is included in **entities** under **skills**, the matching is successful.
3. If **uri** in the passed **want** parameter is included in **uris** under **skills**, which is concatenated into `https://www.test.com:8080/query*` (where \* is a wildcard), the matching is successful.
4. If **type** in the passed **want** parameter is specified and is included in **type** under **skills**, the matching is successful.
2. When there are multiple matching applications, a dialog box is displayed for you to select one of them.
<img src="figures/stage-want1.png" alt="stage-want1" style="zoom:80%;" />
\ No newline at end of file
# AbilityStage Component Container
AbilityStage is a component container at the [module](../quick-start/application-package-structure-stage.md) level. When the HAP of an application is loaded for the first time, an AbilityStage instance is created. You can perform operations such as initialization on the instance.
An AbilityStage instance corresponds to a module.
AbilityStage is not automatically generated in the default project of DevEco Studio. To use AbilityStage, you can manually create an AbilityStage file. The procedure is as follows:
1. In the **ets** directory of the **Module** project, right-click and choose **New > Directory** to create a directory named **myabilitystage**.
2. In the **myabilitystage** directory, right-click and choose **New > ts File** to create a file named **MyAbilityStage.ts**.
3. Open the **MyAbilityStage.ts** file, and import the dependency package of AbilityStage. Customize a class that inherits from AbilityStage, and add the required lifecycle callbacks. The following code snippet adds the **onCreate()** lifecycle callback.
```ts
import AbilityStage from '@ohos.app.ability.AbilityStage';
export default class MyAbilityStage extends AbilityStage {
onCreate() {
// When the HAP of the application is loaded for the first time, initialize the module.
}
onAcceptWant(want) {
// Triggered only for the ability with the specified launch type.
return "MyAbilityStage";
}
}
```
[AbilityStage](../reference/apis/js-apis-app-ability-abilityStage.md) has the lifecycle callback [onCreate()](../reference/apis/js-apis-app-ability-abilityStage.md#abilitystageoncreate) and the event callbacks [onAcceptWant()](../reference/apis/js-apis-app-ability-abilityStage.md#abilitystageonacceptwant), [onConfigurationUpdated()](../reference/apis/js-apis-app-ability-abilityStage.md#abilitystageonconfigurationupdate), and [onMemoryLevel()](../reference/apis/js-apis-app-ability-abilityStage.md#abilitystageonmemorylevel).
- **onCreate()** lifecycle callback: Before the first UIAbility instance of a module is loaded, an AbilityStage instance is created. This callback is invoked when the AbilityStage instance is created. The AbilityStage module notifies you of when you can perform module initialization such as resource pre-loading and thread creation during module loading.
- **onAcceptWant()** event callback: triggered when the UIAbility is started in [specified mode](uiability-launch-type.md#specified). For details, see [UIAbility Component Launch Type](uiability-launch-type.md).
- **onConfigurationUpdated()** event callback: triggered when the global system configuration changes. The global system configuration, such as the system language and theme, are defined in the [Configuration](../reference/apis/js-apis-app-ability-configuration.md) class before project configuration.
- **onMemoryLevel()** event callback: triggered when the system adjusts the memory.
When an application is switched to the background, it is cached in the background. This adversely affects the overall system performance. When system resources are insufficient, the system reclaims memory from applications in multiple ways. For example, the system may stop applications to release memory for executing key tasks. To further maintain the balance of the system memory and prevent the system from stopping application processes, you can subscribe to the system memory changes in the **onMemoryLevel()** lifecycle callback of AbilityStage to release unnecessary resources.
```ts
import AbilityStage from '@ohos.app.ability.AbilityStage';
export default class MyAbilityStage extends AbilityStage {
onMemoryLevel(level) {
// Release unnecessary memory based on the change of available system memory.
}
}
```
<!--no_check-->
\ No newline at end of file
# Accessing a DataAbility
To access a DataAbility, import the basic dependency packages and obtain the URI string for communicating with the DataAbility.
The basic dependency packages include:
- @ohos.ability.featureAbility
- @ohos.data.dataAbility
- @ohos.data.rdb
The sample code for accessing a DataAbility is as follows:
1. Create a **DataAbilityHelper** instance.
```ts
// Different from the URI defined in the config.json file, the URI passed in the parameter has an extra slash (/), three slashes in total.
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. Construct RDB data.
```ts
let valuesBucket = {"name": "gaolu"}
let da = new ohos_data_ability.DataAbilityPredicates()
let valArray =new Array("value1");
let cars = new Array({"batchInsert1" : "value1",});
```
For details about DataAbilityPredicates, see [DataAbility Predicates](../reference/apis/js-apis-data-ability.md).
3. Use **insert** to insert data to the DataAbility.
```ts
// Callback mode:
DAHelper.insert(
urivar,
valuesBucket,
(error, data) => {
console.info("DAHelper insert result: " + data)
}
);
```
```ts
// Promise mode (await needs to be used in the asynchronous method):
let datainsert = await DAHelper.insert(urivar, valuesBucket).then((data) => {
console.info("insert success.");
}).catch((error) => {
console.error("insert failed.");
});
```
4. Use **delete** to delete data from the DataAbility.
```ts
// Callback mode:
DAHelper.delete(
urivar,
da,
(error, data) => {
console.info("DAHelper delete result: " + data)
}
);
```
```ts
// Promise mode (await needs to be used in the asynchronous method):
let datadelete = await DAHelper.delete(
urivar,
da,
);
```
5. Use **update** to update data in the DataAbility.
```ts
// Callback mode:
DAHelper.update(
urivar,
valuesBucket,
da,
(error, data) => {
console.info("DAHelper update result: " + data)
}
);
```
```ts
// Promise mode (await needs to be used in the asynchronous method):
let dataupdate = await DAHelper.update(
urivar,
valuesBucket,
da,
);
```
6. Use **query** to query data in the DataAbility.
```ts
// Callback mode:
DAHelper.query(
urivar,
valArray,
da,
(error, data) => {
console.info("DAHelper query result: " + data)
}
);
```
```ts
// Promise mode (await needs to be used in the asynchronous method):
let dataquery = await DAHelper.query(
urivar,
valArray,
da
);
```
7. Use **batchInsert** to insert data in batches to the DataAbility.
```ts
// Callback mode:
DAHelper.batchInsert(
urivar,
cars,
(error, data) => {
console.info("DAHelper batchInsert result: " + data)
}
);
```
```ts
// Promise mode (await needs to be used in the asynchronous method):
let databatchInsert = await DAHelper.batchInsert(
urivar,
cars
);
```
8. Use **executeBatch** to process data in batches in the DataAbility.
```ts
// Callback mode:
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 mode (await needs to be used in the asynchronous method):
let dataexecuteBatch = await DAHelper.executeBatch(
urivar,
[
{
uri: urivar,
type: featureAbility.DataAbilityOperationType.TYPE_INSERT,
valuesBucket:
{
"executeBatch" : "value1",
},
predicates: da,
expectedCount:0,
predicatesBackReferences: null,
interrupted:true,
}
]
);
```
The APIs for operating a DataAbility are provided by **DataAbilityHelper**. For details about the APIs, see [DataAbilityHelper](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md).
# Accessing a DataShareExtensionAbility from the FA Model
## Overview
Regardless of the FA model or stage model, the data read/write function consists of the client and server.
- In the FA model, the client uses the **DataAbilityHelper** class to provide external APIs, and the server uses the **DataAbility** class to provide database read and write services.
- In the stage model, the client uses the **DataShareHelper** class to provide external APIs, and the server uses the **DataShareExtensionAbility** class to provide database read and write services.
If the client uses the FA model whereas the server is upgraded to the stage model, the client cannot access the server.
To resolve this issue, OpenHarmony provides a solution on the framework side for smooth evolution.
## Basic Principles
A compatible method is that **DataAbilityHelper** determines whether to call the **DataShareHelper** APIs based on the URI prefix (either **DataAbility** or **DataShare**). However, this method requires modification to the URI in the original client code.
Instead of manual modification, OpenHarmony adopts the following processing:
1. The system attempts to start the DataAbility based on the URI passed in. If the startup fails, the system converts the URI prefix to **DataShare** and attempts to start the DataShareExtensionAbility.
2. If the URI does not map to any DataAbility or DataShareExtensionAbility, the startup fails. Otherwise, either the DataAbility or DataShareExtensionAbility is started.
## Constraints
1. When you switch a DataAbility to a DataShareExtensionAbility, only the URI prefix can be modified.![FAvsStage-uri](figures/FAvsStage-uri.png)
2. The **DataShareHelper** class implements only certain APIs of **DataAbilityHelper**. For details about the APIs, see the table below.
**Table 1** APIs invoked when the FA model accesses a DataShareExtensionAbility of the stage model
| API| Provided by DataAbilityHelper| Provided by DataShareHelper| Compatible|
| -------- | -------- | -------- | -------- |
| on | Yes| Yes| Yes|
| off | Yes| Yes| Yes|
| notifyChange | Yes| Yes| Yes|
| insert | Yes| Yes| Yes|
| delete | Yes| Yes| Yes|
| query | Yes| Yes| Yes|
| update | Yes| Yes| Yes|
| batchInsert | Yes| Yes| Yes|
| getType | Yes| No| No|
| getFileTypes | Yes| No| No|
| normalizeUri | Yes| Yes| Yes|
| denormalizeUri | Yes| Yes| Yes|
| openFile | Yes| No| No|
| call | Yes| No| No|
| executeBatch | Yes| No| No|
# Common action and entities Values
The [action](../reference/apis/js-apis-ability-wantConstant.md#wantconstantaction) field specifies the common operation (such as viewing, sharing, and application details) to be performed by the caller. In implicit Want, you can define this field and use it together with **uri** or **parameters** to specify the operation to be performed on the data, for example, viewing URI data. For example, if the URI is a website and the action is **ohos.want.action.viewData**, the ability that supports website viewing is matched. Declaring the **action** field in Want indicates that the invoked application should support the declared operation. The **actions** field under **skills** in the configuration file indicates the operations supported by the application.
**Common action Values**
- **ACTION_HOME**: action of starting the application entry component. It must be used together with **ENTITY_HOME**. The application icon on the home screen is an explicit entry component. Users can touch the icon to start the entry component. Multiple entry components can be configured for an application.
- **ACTION_CHOOSE**: action of selecting local resource data, such as Contacts and Gallery. Generally, the system has corresponding Picker applications for different types of data.
- **ACTION_VIEW_DATA**: action of viewing data. A website URI indicates the action for opening the website.
- **ACTION_VIEW_MULTIPLE_DATA**: action of launching the UI for sending multiple data records.
The [entities](../reference/apis/js-apis-ability-wantConstant.md#wantconstantentity) field specifies the additional category information (such as browser and video player) of the target ability. It is a supplement to **action** in implicit Want. You can define this field to filter application categories, for example, browser. Declaring the **entities** field in Want indicates that the invoked application should belong to the declared category. The **entities** field under **skills** in the configuration file indicates the categories supported by the application.
**Common entities Values**
- **ENTITY_DEFAULT**: default category, which is meaningless.
- **ENTITY_HOME**: abilities with an icon displayed on the home screen.
- **ENTITY_BROWSABLE**: browser type.
# API Switching Overview
Due to the differences in the thread model and process model, certain APIs (marked with **FAModelOnly** in the SDK) can be used only in the FA model. When switching an application from the FA model to the stage model, replace the APIs marked with **FAModelOnly** in the application with the APIs supported in the stage model. This topic uses the switching of **startAbility()** as an example.
![api-switch-overview](figures/api-switch-overview.png)
- Sample code of **startAbility()** in the FA model:
```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.');
})
```
- Sample code of **startAbility()** in the stage model:
```ts
// context is a member of the ability object and is required for invoking inside a non-ability object.
// Pass in the Context object.
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.');
})
```
# Switching of app and deviceConfig
To help you better maintain the configuration of application-level attributes, OpenHarmony has extracted the **app** and **deviceConfig** tags from the **config.json** file to the **app.json5** file and changed certain tag names in the stage model.
**Table 1** Comparison of the app tag in the configuration files
| Configuration Item| app in config.json| app in app.json5|
| -------- | -------- | -------- |
| Internal version number of an application| "version": {<br> "code": 1,<br>} | "versionCode":&nbsp;1&nbsp;, |
| Text description of the version number, which is displayed to users| "version": {<br> "name": "1.0.0",<br>} | "versionName"&nbsp;:&nbsp;"1.0.0"&nbsp;, |
| Earliest compatible version of the application| "version": {<br> "minCompatibleVersionCode": 1,<br>} | "minCompatibleVersionCode"&nbsp;:&nbsp;1&nbsp;, |
| Minimum API version required for application running| "apiVersion": {<br> "compatible": 7,<br>} | "minAPIVersion"&nbsp;:&nbsp;7&nbsp;, |
| Target API version required for application running| "apiVersion": {<br> "target": 8,<br>} | "targetApiVersion"&nbsp;:&nbsp;8&nbsp;, |
| Type of the target API version required for application running| "apiVersion": {<br> "releaseType": Release,<br>} | "apiReleaseType":&nbsp;"Release"&nbsp;, |
OpenHarmony has reconstructed the [deviceConfig](../quick-start/deviceconfig-structure.md) tag of the **config.json** file in the **app.json5** file. It has integrated the fields related to device information under **deviceConfig** into the **app** tag of the [app.json5](../quick-start/app-configuration-file.md) file.
**Table 2** Comparison of the deviceConfig tag in the configuration files
| deviceConfig in the FA Model| Description| Stage Model| Difference|
| -------- | -------- | -------- | -------- |
| deviceConfig| Device information.| / | This tag is no longer available in the stage model. In the stage model, device information is configured under the **app** tag.|
| process | Name of the process running the application or ability. If the **process** attribute is configured in the **deviceConfig** tag, all abilities of the application run in this process. You can set the **process** attribute for a specific ability in the **abilities** attribute, so that the ability can run in the particular process.| / | The stage model does not support the configuration of process names.|
| keepAlive | Whether the application is always running. This attribute applies only to system applications and does not take effect for third-party applications.| / | The stage model does not support changing of the model control mode for system applications.|
| supportBackup | Whether the application supports data backup and restore.| / | This configuration is not supported in the stage model.|
| compressNativeLibs | Whether the **libs** libraries are packaged in the HAP file after being compressed.| / | This configuration is not supported in the stage model.|
| network | Network security configuration.| / | This configuration is not supported in the stage model.|
<!--no_check-->
\ No newline at end of file
# Application- or Component-Level Configuration (FA Model)
When developing an application, you may need to configure certain tags to identify the application, such as the bundle name and application icon. This topic describes key tags that need to be configured during application development.
- **Configuring the bundle name**
The bundle name is specified by the **bundleName** field under **app** in the **config.json** file. This field uniquely identifies an application. The bundle name can contain only letters, digits, underscores (_), and periods (.). It must start with a letter. The bundle name is a string with 7 to 127 bytes of a reverse domain name, for example, **com.example.myapplication**. It is recommended that the first part is the top-level domain **"com"**, and the second part is the vendor or individual name, which can be of multiple levels. For details about the configuration, see [app](../quick-start/app-structure.md).
- **Configuring the application icon and label**
The FA model does not support direct configuration of application icons and labels. Instead, the icon and label of a PageAbility component that meet the rules are used as the application icon and label. For details about the rules, see [PageAbility Component](pageability-configuration.md). The icon is specified by the **icon** field under **abilities** in the **config.json** file. The icon must be configured in the resource file on DevEco Studio, and the path of the icon must be **/resource/base/media**. An example value is **$media:ability_icon**. The label is the index of the resource file. It identifies the name of the ability presented to users. The label value can be an ability name or a resource index to the ability name in multiple languages. In the **skills** attribute of the ability, if the **actions** value contains **action.system.home** and the **entities** value contains **entity.system.home**, the icon and label of the ability is used as the application icon and label. If multiple abilities address this condition, the icon and label of the first candidate ability is used as the application icon and label. For details about the configuration, see [abilities](../quick-start/module-structure.md).
```json
"abilities": [
"icon": "$media:icon",
"label": "$string:MainAbility_label",
"skills": [
{
"entities": ["entity.system.home"],
"actions": ["action.system.home"]
}
]
// ...
}
```
- **Configuring application version declaration**
To declare the application version, set the **version** field under **app** in the **config.json** file to specify the version number, version name, and earliest compatible version number. For details about the configuration, see [version](../quick-start/module-structure.md).
- **Configuring device types supported by the module**
To configure the device types supported by the module, set the **deviceType** field in the **config.json** file. If a certain device type is added to **deviceTypes**, the module can run on that device. For details about the configuration, see [deviceType](../quick-start/module-structure.md).
- **Configuring the component permission**
To request component permissions, set the **reqPermission** field under **module** in the **config.json** file. This field declares the name of the permission to request, the reason for requesting the permission, and the scenario where the permission is used. For details about the configuration, see [reqPermission](../quick-start/module-structure.md).
<!--no_check-->
\ No newline at end of file
# Application- or Component-Level Configuration (Stage Model)
When developing an application, you may need to configure certain tags to identify the application, such as the bundle name and application icon. This topic describes key tags that need to be configured during application development. Icons and labels are usually configured together. There is the application icon, application label, entry icon, and entry label, which correspond to the **icon** and **label** fields in the [app.json5 file](../quick-start/app-configuration-file.md) and [module.json5 file](../quick-start/module-configuration-file.md). The application icon and label are used in **Settings**. For example, they are displayed in the application list in **Settings**. The entry icon is displayed on the device's home screen after the application is installed. The entry icon maps to a [UIAbility](uiability-overview.md) component. Therefore, an application can have multiple entry icons and labels. When you touch one of them, the corresponding UIAbility page is displayed.
**Figure 1** Icons and labels
![application-component-configuration-stage](figures/application-component-configuration-stage.png)
- **Configuring the bundle name**
The bundle name is specified by the **bundleName** field in the [app.json5 file](../quick-start/app-configuration-file.md) in the **AppScope** directory of the project. This field uniquely identifies an application. You are advised to use the reverse domain name notion, for example, *com.example.demo*, where the first part is the domain suffix **com**, the second part is the vendor/individual name, and the third part is the application name, which can be of multiple levels.
- **Configuring the application icon and label**
The application icon is specified by the **icon** field in the [app.json5 file](../quick-start/app-configuration-file.md) in the **AppScope** directory of the project. The **icon** field must be set to the index of an image so that the image is displayed as the application icon. The application icon is usually displayed in an application list, for example, the application list in **Settings**.
The application label is specified by the **label** field in the [app.json5 file](../quick-start/app-configuration-file.md) in the **AppScope** module of the project. The **label** field specifies the application name displayed to users. It must be set to the index of a string resource.
The **icon** and **label** fields in the **app.json5** file are under **app**, as follows:
```json
{
"app": {
"icon": "$media:app_icon",
"label": "$string:app_name"
// ...
}
}
```
- **Configuring the entry icon and label**
The entry icon and label are configured by specifying **icon** and **label** under **abilities** in the [module.json5 file](../quick-start/module-configuration-file.md). For example, if you want to display the icon and label of the UIAbility component on the home screen, add **entity.system.home** to **entities** and **action.system.home** to **actions** under **skills**. If the preceding fields are configured for multiple UIAbility components of an application, multiple icons and labels are displayed on the home screen, corresponding to their respective UIAbility component.
```json
{
"module": {
// ...
"abilities": [
{
// The information starting with $ is the resource value.
"icon": "$media:icon",
"label": "$string:EntryAbility_label",
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
}
]
}
}
```
- **Configuring application version declaration**
To declare the application version, configure the **versionCode** and **versionName** fields in the [app.json5 file](../quick-start/app-configuration-file.md) in the **AppScope** directory of the project. **versionCode** specifies the version number of the application. The value is a 32-bit non-negative integer. It is used only to determine whether a version is later than another version. A larger value indicates a later version. **versionName** provides the text description of the version number.
- **Configuring device types supported by the module**
To configure the device types supported by the module, set the **deviceTypes** field in the [module.json5 file](../quick-start/module-configuration-file.md). If a certain device type is added to **deviceTypes**, the module can run on that device.
- **Configuring the module permission**
The **requestPermission** field in the [module.json5 file](../quick-start/module-configuration-file.md) is used to configure the permission information required by the module to access the protected part of the system or other applications. This field declares the name of the permission to request, the reason for requesting the permission, and the scenario where the permission is used.
<!--no_check-->
\ No newline at end of file
# Context (FA Model)
There is only one context in the FA model. All capabilities in the context are provided through methods. The context uses these methods to extend the capabilities of the **featureAbility** class.
## Available APIs
To use the context in the FA model, first import the **featureAbility** module.
```ts
import featureAbility from "@ohos.ability.featureAbility";
```
Then, call **getContext()** to obtain the **Context** object:
```ts
let context = featureAbility.getContext()
```
For details about the APIs, see [API Reference](../reference/apis/js-apis-inner-app-context.md).
## How to Develop
1. Query bundle information.
```ts
import featureAbility from '@ohos.ability.featureAbility'
export default {
onCreate() {
// Obtain the context and call related APIs.
let context = featureAbility.getContext();
context.getBundleName((data, bundleName)=>{
console.info("ability bundleName:" + bundleName)
});
console.info('Application onCreate')
},
onDestroy() {
console.info('Application onDestroy')
},
}
```
2. Set the display orientation of the host featureAbility.
```ts
import featureAbility from '@ohos.ability.featureAbility'
import bundle from '@ohos.bundle';
export default {
onCreate() {
// Obtain the context and call related APIs.
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 (Stage Model)
## Overview
[Context](../reference/apis/js-apis-inner-application-context.md) is the context of an object in an application. It provides basic information about the application, for example, **resourceManager**, **applicationInfo**, **dir** (application development path), and **area** (encrypted area). It also provides basic methods such as **createBundleContext()** and **getApplicationContext()**. The UIAbility component and ExtensionAbility derived class components have their own **Context** classes, for example, the base class **Context**, **ApplicationContext**, **AbilityStageContext**, **UIAbilityContext**, **ExtensionContext**, and **ServiceExtensionContext**.
- The figure below illustrates the inheritance relationship of contexts.
<img src="figures/context-inheritance.png" alt="context-inheritance" style="zoom: 50%;" />
- The figure below illustrates the holding relationship of contexts.
<img src="figures/context-holding.png" alt="context-holding" style="zoom:50%;" />
- The following describes the information provided by different contexts.
- [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md): Each UIAbility has the **Context** attribute, which provides APIs to operate the ability, obtain the ability configuration, request permissions from users, and more.
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
let uiAbilityContext = this.context;
// ...
}
}
```
- Scenario-specific [ExtensionContext](../reference/apis/js-apis-inner-application-extensionContext.md): For example, ServiceExtensionContext, inherited from ExtensionContext, provides APIs related to background services.
```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-inner-application-abilityStageContext.md): module-level context. It provides **HapModuleInfo** and **Configuration** in addition to those provided by the base class **Context**.
```ts
import AbilityStage from "@ohos.app.ability.AbilityStage";
export default class MyAbilityStage extends AbilityStage {
onCreate() {
let abilityStageContext = this.context;
// ...
}
}
```
- [ApplicationContext](../reference/apis/js-apis-inner-application-applicationContext.md): application-level context. It provides APIs for subscribing to ability lifecycle changes, system memory changes, and system environment changes. The application-level context can be obtained from UIAbility, ExtensionAbility, and AbilityStage.
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
let applicationContext = this.context.getApplicationContext();
// ...
}
}
```
## Typical Usage Scenarios of Context
This topic describes how to use the context in the following scenarios:
- [Obtaining the Application Development Path](#obtaining-the-application-development-path)
- [Obtaining and Modifying Encrypted Areas](#obtaining-and-modifying-encrypted-areas)
- [Creating Context of Another Application or Module](#creating-context-of-another-application-or-module)
- [Subscribing to Ability Lifecycle Changes in a Process](#subscribing-to-ability-lifecycle-changes-in-a-process)
- [Requesting Permissions from Users Through AbilityContext](#requesting-permissions-from-users-through-uiabilitycontext)
### Obtaining the Application Development Path
The following table describes the application development paths obtained from context.
**Table 1** Application development paths
| Name| Type| Readable| Writable| Description|
| -------- | -------- | -------- | -------- | -------- |
| cacheDir | string | Yes| No| Cache directory of the application on the internal storage.<br>It is the content of **Storage** of an application under **Settings > Apps & services > Apps**.|
| tempDir | string | Yes| No| Temporary file directory of the application.<br>Files in this directory are deleted after the application is uninstalled.|
| filesDir | string | Yes| No| File directory of the application on the internal storage.<br>Files in this directory may be synchronized to other directories during application migration or backup.|
| databaseDir | string | Yes| No| Storage directory of the local database.|
| bundleCodeDir | string | Yes| No| Installation directory of the application on the internal storage.|
| distributedFilesDir | string | Yes| No| Storage directory of distributed application data files.|
| preferencesDir | string | Yes| Yes| Preferences directory of the application.|
The capability of obtaining the application development path is provided by the base class **Context**. This capability is also provided by **ApplicationContext**, **AbilityStageContext**, **UIAbilityContext**, and **ExtensionContext**. However, the paths obtained from different contexts may differ, as shown below.
**Figure 1** Application development paths obtained from context
<img src="figures/context-dir.png" alt="context-dir" style="zoom: 50%;" />
- Obtain the application-level path through **ApplicationContext**. It is recommended that global application information be stored in this path. Files stored in this path will be deleted only when the application is uninstalled.
| Name| Path|
| -------- | -------- |
| bundleCodeDir | {Path prefix}/el1/bundle/|
| cacheDir | {Path prefix}/{Encryption level}/base/cache/|
| filesDir | {Path prefix}/{Encryption level}/base/files/|
| preferencesDir | {Path prefix}/{Encryption level}/base/preferences/|
| tempDir | {Path prefix}/{Encryption level}/base/temp/|
| databaseDir | {Path prefix}/{Encryption level}/database/|
| distributedFilesDir | {Path prefix}/el2/distributedFiles/|
- Obtain the HAP level path through **AbilityStageContext**, **UIAbilityContext**, and **ExtensionContext**. It is recommended that the HAP information be stored in this path. The file content stored in this path will be deleted when the HAP is uninstalled. The file content in the application-level path will be deleted only after all the HAPs of the application are uninstalled.
| Name| Path|
| -------- | -------- |
| bundleCodeDir | {Path prefix}/el1/bundle/|
| cacheDir | {Path prefix}/{Encryption level}/base/**haps/{moduleName}**/cache/|
| filesDir | {Path prefix}/{Encryption level}/base/**haps/{moduleName}**/files/|
| preferencesDir | {path prefix}/{encryption level}/base/**haps/{moduleName}**/preferences/|
| tempDir | {Path prefix}/{Encryption level}/base/**haps/{moduleName}**/temp/|
| databaseDir | {Path prefix}/{Encryption level}/database/**{moduleName}**/|
| distributedFilesDir | {Path prefix}/el2/distributedFiles/**{moduleName}**/|
The sample code for obtaining the application development paths is as follows:
```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;
// ...
}
}
```
### Obtaining and Modifying Encrypted Areas
You can read and write [the area attribute in the context](../reference/apis/js-apis-inner-application-context.md) to obtain and set an encrypted area. Two encryption levels are supported:
- AreaMode.EL1: device-level encryption area, which is accessible after the device is powered on.
- AreaMode.EL2: user-level encryption area, which is accessible only after the device is powered on and the password is entered (for the first time).
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
// Before storing common information, switch the encryption level to EL1.
if (this.context.area === 1) {// Obtain the area.
this.context.area = 0; // Modify the area.
}
// Store common information.
// Before storing sensitive information, switch the encryption level to EL2.
if (this.context.area === 0) { // Obtain the area.
this.context.area = 1; // Modify the area.
}
// Store sensitive information.
}
}
```
### Creating Context of Another Application or Module
The base class **Context** provides the [createBundleContext(bundleName:string)](../reference/apis/js-apis-inner-application-context.md#contextcreatebundlecontext), [createModuleContext(moduleName:string)](../reference/apis/js-apis-inner-application-context.md#contextcreatemodulecontext), and [createModuleContext(bundleName:string, moduleName:string)](../reference/apis/js-apis-inner-application-context.md#contextcreatemodulecontext-1) methods for creating the context of other applications or modules, so as to obtain the resource information, for example, [obtaining the application development paths](#obtaining-the-application-development-path) of other modules.
- Call **createBundleContext(bundleName:string)** to create the context of another application.
> **NOTE**
>
> To obtain the context of another application:
>
> - Request the **ohos.permission.GET_BUNDLE_INFO_PRIVILEGED** permission. For details, see [Permission Application Guide](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file).
>
> - This is a system API and cannot be called by third-party applications.
For example, application information displayed on the home screen includes the application name and icon. The home screen application calls the foregoing method to obtain the context information, so as to obtain the resource information including the application name and icon.
```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;
// ...
}
}
```
- Call **createModuleContext(bundleName:string, moduleName:string)** to obtain the context of a specified module of another application. After obtaining the context, you can obtain the resource information of that module.
> **NOTE**
>
> To obtain the context of a specified module of another application:
>
> - Request the **ohos.permission.GET_BUNDLE_INFO_PRIVILEGED** permission. For details, see [Permission Application Guide](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file).
>
> - This is a system API and cannot be called by third-party applications.
```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);
// ...
}
}
```
- Call **createModuleContext(moduleName:string)** to obtain the context of another module in the current application. After obtaining the context, you can obtain the resource information of that 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);
// ...
}
}
```
### Subscribing to Ability Lifecycle Changes in a Process
In the DFX statistics scenario of an application, if you need to collect statistics on the stay duration and access frequency of a page, you can subscribe to ability lifecycle changes.
When the ability lifecycle changes in a process, for example, being created or destroyed, becoming visible or invisible, or gaining or losing focus, the corresponding callback is triggered, and a listener ID is returned. The ID is incremented by 1 each time the listener is registered. When the number of listeners exceeds the upper limit (2^63-1), -1 is returned. The following uses [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) as an example.
```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. Obtain the application context through the context attribute.
let applicationContext = this.context.getApplicationContext();
// 2. Register a listener for the lifecycle changes through the application context.
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));
});
}
}
```
### Requesting Permissions from Users Through UIAbilityContext
Each ability has the **Context** attribute. The ability is used to process the lifecycle. Methods use to operate the ability (such as **startAbility()**, **connectServiceExtensionAbility()**, and **terminateSelf()**) are implemented in the corresponding context. The context also provides methods for obtaining the ability configuration and requesting permissions from users. For details about how to obtain the context, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability).
When an application needs to obtain users' privacy information or use system capabilities, for example, to obtain location information, to access the calendar, or to use the camera to take photos or record videos, the application must request permissions from users, as shown below. For details, see [Permission Application Guide](../security/accesstoken-guidelines.md).
**Figure 2** Requesting the permission to access the calendar from users
<img src="figures/application-context-stage.png" alt="application-context-stage" style="zoom:50%;" />
\ No newline at end of file
# Elements of the Application Model
The application model is the abstraction of capabilities required by OpenHarmony applications. It provides necessary components and running mechanisms for applications. With application models, you can develop applications based on a unified set of models, making application development simpler and more efficient.
The OpenHarmony application model consists of the following elements:
- Application component
An application component is the basic unit and running entry of an application. When a user starts, uses, or exits an application, the application component transits in different states. This is called the application component lifecycle. The application component provides lifecycle callback functions, through which you can detect application [status changes](uiability-lifecycle.md). When compiling an application, you needs to compile application components and their lifecycle callback functions, and configure related information in the application configuration file. In this way, the operating system creates an application component instance based on the configuration file during running, and schedules the lifecycle callback functions, so as to execute your code.
- Application process model
The application process model defines how application processes are created, destroyed, and communicate with each other.
- Application thread model
The application thread model defines how a thread in an application process is created and destroyed, how the main thread and UI thread are created, and how the threads communicate with each other.
- Application mission management model
The application mission management model defines how a mission is created and destroyed, and the relationship between missions and components. A mission is a record about the use of an application component instance. Each time a user starts an application component instance, a mission is generated. For example, when a user starts a video application, the video application mission is displayed on the **Recents** page. When the user clicks the mission, the system switches the mission to the foreground. If the video editing functionality in the video application is compiled by using an application component, an application component instance for video editing is created when the user starts video editing. In this case, both the video application mission and video editing mission are displayed on the **Recents** page.
- Application configuration file
The application configuration file contains information about the application configuration, application components, and permissions, as well as custom information. The information will be provided for the compiler, application market, and operating system in the build, distribution, and running phases.
# Interpretation of the Application Model
## Application Model Overview
Along its evolution, OpenHarmony has provided two application models:
- Feature Ability (FA) model. This model is supported by OpenHarmony API version 7 and 8. It is no longer recommended.
- Stage model. This model is supported since OpenHarmony API version 9. It is recommended and will evolve for a long time. In this model, classes such as **AbilityStage** and **WindowStage** are provided as the stage of application components and windows. That's why it is named stage model.
The stage model is designed based on the following considerations, which make it become the recommended model:
1. **Designed for complex applications**
- In the stage model, multiple application components share an ArkTS engine (VM running the programming language ArkTS) instance, making it easy for application components to share objects and status while requiring less memory.
- The object-oriented development mode makes the code of complex applications easy to read, maintain, and scale.
2. **Native support for [cross-device migration](hop-cross-device-migration.md) and [multi-device collaboration](hop-multi-device-collaboration.md) at the application component level**
The stage model decouples application components from User Interfaces (UIs).
- In cross-device migration scenarios, after the system migrates application component data or status between devices, it can use the declarative feature of ArkUI to restore the UI based on the data or status saved in the application components.
- In multi-device collaboration scenarios, application components can initiate Remote Procedure Calls (RPCs) and support interaction with cross-device application components.
3. **Support for multiple device types and window forms**
Application component management and window management are decoupled at the architecture level. This decoupling makes it:
- Easy to tailor application components. For example, windows can be tailored for devices without screens.
- Easy to extend the window forms.
- Possible for application components to use the same lifecycle on multiple devices (such as desktop devices and mobile devices).
4. **Well balanced application capabilities and system management costs**
The stage model redefines the boundary of application capabilities to well balance application capabilities and system management costs.
- Diverse application components (such as widgets and input methods) for specific scenarios.
- Standardized background process management. To deliver a better user experience, the stage model manages background application processes in a more orderly manner. Applications cannot reside in the background randomly, and their background behavior is strictly managed to minimize malicious behavior.
## Differences Between the FA Model and Stage Model
In the stage model, multiple application components share the same ArkTS engine instance. In the FA model, each application component exclusively uses an ArkTS engine instance. This is their biggest difference. In the stage model, application components can easily share objects and status while requiring less memory. Therefore, you are advised to use the stage model when developing complex applications in distributed scenarios.
The table below describes their differences in detail.
**Table 1** Differences between the FA model and stage model
| Item| FA model| Stage model|
| -------- | -------- | -------- |
| **Application component**| 1. Component classification<br>- PageAbility: has the UI and supports user interaction. For details, see [PageAbility Component Overview](pageability-overview.md).<br>- ServiceAbility: provides background services and has no UI. For details, see [ServiceAbility Component Overview](serviceability-overview.md).<br>- DataAbility: provides the data sharing capability and has no UI. For details, see [DataAbility Component Overview](dataability-overview.md).<br>2. Development mode<br>Application components are specified by exporting anonymous objects and fixed entry files. You cannot perform derivation. It is inconvenient for capability expansion.| 1. Component classification<br>- UIAbility: has the UI and supports user interaction. For details, see [UIAbility Component Overview](uiability-overview.md).<br>- ExtensionAbility: provides extension capabilities (such as widget and input methods) for specific scenarios. For details, see [ExtensionAbility Component Overview](extensionability-overview.md).<br>2. Development mode<br>The object-oriented mode is used to provide open application components as classes. You can derive application components for capability expansion.|
| **Process model**| There are two types of processes:<br>1. Main process<br>2. Rendering process<br>For details, see [Process Model (FA Model)](process-model-fa.md). | There are three types of processes:<br>1. Main process<br>2. ExtensionAbility process<br>3. Rendering process<br>For details, see [Process Model (Stage Model)](process-model-stage.md). |
| **Thread model**| 1. ArkTS engine instance creation<br>A process can run multiple application component instances, and each application component instance runs in an independent ArkTS engine instance.<br>2. Thread model<br>Each ArkTS engine instance is created on an independent thread (non-main thread). The main thread does not have an ArkTS engine instance.<br>3. Intra-process object sharing: not supported.<br>For details, see [Thread Model (FA Model)](thread-model-fa.md). | 1. ArkTS engine instance creation<br>A process can run multiple application component instances, and all application component instances share one ArkTS engine instance.<br>2. Thread model<br>The ArkTS engine instance is created on the main thread.<br>3. Intra-process object sharing: supported.<br>For details, see [Thread Model (Stage Model)](thread-model-stage.md). |
| **Mission management model**| - A mission is created for each PageAbility component instance.<br>- Missions are stored persistently until the number of missions exceeds the maximum (customized based on the product configuration) or users delete missions.<br>- PageAbility components do not form a stack structure.<br>For details, see [Mission Management Scenarios](mission-management-overview.md).| - A mission is created for each UIAbility component instance.<br>- Missions are stored persistently until the number of missions exceeds the maximum (customized based on the product configuration) or users delete missions.<br>- UIAbility components do not form a stack structure.<br>For details, see [Mission Management Scenarios](mission-management-overview.md).|
| **Application configuration file**| The **config.json** file is used to describe the application, HAP, and application component information.<br>For details, see [Application Configuration File Overview (FA Model)](../quick-start/application-configuration-file-overview-fa.md).| The **app.json5** file is used to describe the application information, and the **module.json5** file is used to describe the HAP and application component information.<br>For details, see [Application Configuration File Overview (Stage Model)](../quick-start/application-configuration-file-overview-stage.md).|
<!--no_check-->
\ No newline at end of file
# Background Services (Stage Model)
The stage model uses ServiceExtensionAbility to provide background services. A system application can implement a background service and provide external capabilities. For example, if system application A implements a background service, third-party application B can communicate with A by connecting to A's background service.
For details about ServiceExtensionAbility, see [Background Service Development](serviceextensionability.md).
# Connecting to a ServiceAbility from the Stage Model
This topic describes how the two application components of the stage model connect to the ServiceAbility component of the FA model.
## UIAbility Accessing a ServiceAbility
A UIAbility accesses a ServiceAbility in the same way as it accesses a 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 Accessing a ServiceAbility
The following uses the ServiceExtensionAbility component as an example to describe how an ExtensionAbility accesses a ServiceAbility. A ServiceExtensionAbility accesses a ServiceAbility in the same way as it accesses another 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);
}
}
```
# Connecting to a ServiceExtensionAbility from the FA Model
This topic describes how the three application components of the FA model connect to the ServiceExtensionAbility component of the stage model.
## PageAbility Accessing a ServiceExtensionAbility
A PageAbility accesses a ServiceExtensionAbility in the same way as it accesses a 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 or DataAbility Accessing a ServiceExtensionAbility
A ServiceAbility or DataAbility accesses a ServiceExtensionAbility in the same way as it accesses a 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);
```
# Common Events (FA Model)
For details, see [Common Events](common-event-overview.md) in the stage model.
# Introduction to Common Events
OpenHarmony provides Common Event Service (CES) for applications to subscribe to, publish, and unsubscribe from common events.
Common events are classified into system common events and custom common events.
- System common events: defined in CES. Only system applications and system services can publish system common events, such as HAP installation, update, and uninstall. For details about the supported system common events, see [Support](../reference/apis/js-apis-commonEventManager.md#support).
- Custom common events: customized by applications to implement cross-process event communication.
Common events are also classified into unordered, ordered, and sticky common events.
- Unordered common events: CES forwards common events based on the subscription sequence, regardless of whether subscribers receive the events.
- Ordered common event: CES forwards common events to the next subscriber only after receiving a reply from the previous subscriber.
- Sticky common event: a public event that can be sent to a subscriber before they initiate a subscription. Only system applications or system services can send sticky common event, and they must request the **ohos.permission.COMMONEVENT_STICKY** permission. For details about the configuration, see [Permission Application Guide](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file).
Each application can subscribe to common events as required. After your application subscribes to a common event, the system sends it to your application every time the event is published. Such an event may be published by the system, other applications, or your own application.
**Figure 1** Common events
![common-event](figures/common-event.png)
\ No newline at end of file
# Publishing Common Events
## When to Use
You can use [publish()](../reference/apis/js-apis-commonEventManager.md#commoneventmanagerpublish) to publish a custom common event, which can carry data for subscribers to parse and process.
> **NOTE**
>
> Subscribers can receive sticky common events that have been sent. However, they must subscribe to common events of other types before receiving them. For details about subscription, see [Subscribing to Common Events](common-event-subscription.md).
## Available APIs
For details about the APIs, see [API Reference](../reference/apis/js-apis-commonEventManager.md#commoneventmanagerpublish).
| API| Description|
| -------- | -------- |
| publish(event: string, callback: AsyncCallback) | Publishes a common event.|
| publish(event: string, options: [CommonEventPublishData](../reference/apis/js-apis-commonEventManager.md#commoneventpublishdata), callback: AsyncCallback) | Publishes a common event with given attributes.|
## Publishing a Common Event That Does Not Carry Information
Common events that do not carry information can be published only as unordered common events.
1. Import the **commonEventManager** module.
```ts
import commonEventManager from '@ohos.commonEventManager';
```
2. Pass in the common event name and callback, and publish the event.
```ts
// Publish a common event.
commonEventManager.publish("usual.event.SCREEN_OFF", (err) => {
if (err) {
console.error(`[CommonEvent] PublishCallBack err=${JSON.stringify(err)}`);
} else {
console.info(`[CommonEvent] Publish success`);
}
})
```
## Publishing a Common Event That Carries Information
Common events that carry information can be published as unordered, ordered, and sticky common events, which are specified by the **isOrdered** and **isSticky** fields of [CommonEventPublishData](../reference/apis/js-apis-commonEventManager.md#commoneventpublishdata).
1. Import the **commonEventManager** module.
```ts
import commonEventManager from '@ohos.commonEventManager';
```
2. Pass in the common event name and callback, and publish the event.
```ts
// Attributes of a common event.
let options = {
code: 1, // Result code of the common event.
data: "initial data", // Result data of the common event.
}
```
3. Pass in the common event name, attributes of the common event, and callback, and publish the event.
```ts
// Publish a common event.
commonEventManager.publish("usual.event.SCREEN_OFF", options, (err) => {
if (err) {
console.error('[CommonEvent] PublishCallBack err=' + JSON.stringify(err));
} else {
console.info('[CommonEvent] Publish success')
}
})
```
# Subscribing to Common Events
## When to Use
You can create a subscriber object to subscribe to a common event so as to obtain the parameters passed in the event. Certain system common events [require specific permissions](../security/accesstoken-guidelines.md) to subscribe to. For details, see [Required Permissions](../reference/apis/js-apis-commonEventManager.md#support).
## Available APIs
For details about the APIs, see [API Reference](../reference/apis/js-apis-commonEventManager.md#commoneventmanagersubscribe).
| API| Description|
| -------- | -------- |
| createSubscriber(subscribeInfo: [CommonEventSubscribeInfo](../reference/apis/js-apis-commonEventManager.md#commoneventsubscribeinfo), callback: AsyncCallback&lt;[CommonEventData](../reference/apis/js-apis-commonEventManager.md#commoneventdata)&gt;): void | Creates a subscriber. This API uses an asynchronous callback to return the result.|
| createSubscriber(subscribeInfo: CommonEventSubscribeInfo): Promise&lt;CommonEventSubscriber&gt; | Creates a subscriber. This API uses a promise to return the result.|
| subscribe(subscriber: CommonEventSubscriber, callback: AsyncCallback): void | Subscribes to common events.|
## How to Develop
1. Import the **commonEventManager** module.
```ts
import commonEventManager from '@ohos.commonEventManager';
```
2. Create a **subscribeInfo** object. For details about the data types and parameters of the object, see [CommonEventSubscribeInfo](../reference/apis/js-apis-commonEventManager.md#commoneventsubscribeinfo).
```ts
// Used to save the created subscriber object for subsequent subscription and unsubscription.
let subscriber = null;
// Subscriber information.
let subscribeInfo = {
events: ["usual.event.SCREEN_OFF"], // Subscribe to the common event screen-off.
}
```
3. Create a subscriber object and save the returned object for subsequent operations such as subscription and unsubscription.
```ts
// Callback for subscriber creation.
commonEventManager.createSubscriber(subscribeInfo, (err, data) => {
if (err) {
console.error(`[CommonEvent] CreateSubscriberCallBack err=${JSON.stringify(err)}`);
} else {
console.info(`[CommonEvent] CreateSubscriber success`);
subscriber = data;
// Callback for common event subscription.
}
})
```
4. Create a subscription callback, which is triggered when an event is received. The data returned in the subscription callback contains information such as the common event name and data carried by the publisher. For details about the data types and parameters of the common event data, see [CommonEventData](../reference/apis/js-apis-commonEventManager.md#commoneventdata).
```ts
// Callback for common event subscription.
if (subscriber !== null) {
commonEventManager.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`);
}
```
# Unsubscribing from Common Events
## When to Use
You can call [unsubscribe()](../reference/apis/js-apis-commonEventManager.md#commoneventmanagerunsubscribe) to unsubscribe from a common event that is no longer required.
## Available APIs
| API| Description|
| -------- | -------- |
| unsubscribe(subscriber: CommonEventSubscriber, callback?: AsyncCallback) | Unsubscribes from a common event.|
## How to Develop
1. Import the **commonEventManager** module.
```ts
import commonEventManager from '@ohos.commonEventManager';
```
2. Subscribe to an event by following the procedure described in [Subscribing to Common Events](common-event-subscription.md).
3. Call **unsubscribe** in **CommonEvent** to unsubscribe from the common event.
```ts
// The subscriber object iscreated during event subscription.
if (subscriber !== null) {
commonEventManager.unsubscribe(subscriber, (err) => {
if (err) {
console.error(`[CommonEvent] UnsubscribeCallBack err=${JSON.stringify(err)}`);
} else {
console.info(`[CommonEvent] Unsubscribe`);
subscriber = null;
}
})
}
```
# Component Startup Rules (FA Model)
Component startup refers to the behavior of starting or connecting to an application component.
- Start the PageAbility and ServiceAbility. For example, you can use **startAbility()**.
- Connect to the ServiceAbility and DataAbility. For example, you can use **connectAbility()** and **acquireDataAbilityHelper()**.
To deliver a better user experience, OpenHarmony restricts the following behavior:
- A background application randomly displays a dialog box, such as an ads pop-up.
- Background applications wake up each other. This type of behavior occupies system resources and increases power consumption, or even causes system frozen.
- A foreground application randomly redirects to another application, for example, redirecting to the payment page of another application. This type of behavior poses security risks.
In view of this, OpenHarmony formulates a set of component startup rules, as follows:
- **Before starting a component of another application, verify the visible field of the target component.**
- This rule applies only to cross-application scenarios.
- If the **visible** field of the target component is **false**, verify the **ohos.permission.START_INVISIBLE_ABILITY** permission.
- For details, see [Component Visible Configuration](../quick-start/module-configuration-file.md#abilities-tag)
- **Before starting a component of a background application, verify the BACKGROUND permission.**
- An application is considered as a foreground application only when the application process gains focus or its UIAbility component is running in the foreground.
- Verify the **ohos.permission.START_ABILITIES_FROM_BACKGROUND** permission.
- **Before starting the ServiceAbility or DataAbility component of an application, verify the AssociateWakeUp field of the target application.**
- This rule applies only to cross-application scenarios.
- This rule is valid only when the target component is ServiceAbility or DataAbility.
- The ServiceAbility and DataAbility of an application can be accessed by others only when **AssociateWakeUp** of the target application is set to **true**.
- The **AssociateWakeUp** field can be configured only for preset applications. For other applications, this field is set to **false** by default.
> **NOTE**
> 1. Component startup control has been implemented since OpenHarmony v3.2 Release.
>
> 2. The new component startup rules are more strict than the original ones. You must be familiar with the new startup rules to prevent service exceptions.
## Intra-Device Component Startup Rules
The rules for starting components on the same device vary in the following scenarios:
- Starting a PageAbility
- Starting a ServiceAbility or DataAbility
![startup-rule](figures/component-startup-inner-fa.png)
## Inter-Device Component Startup Rules
The rules for starting components on a different device vary in the following scenarios:
- Starting a PageAbility
- Starting a ServiceAbility
![component-startup-rules](figures/component-startup-inter-fa.png)
<!--no_check-->
\ No newline at end of file
# Component Startup Rules (Stage Model)
Component startup refers to the behavior of starting or connecting to an application component.
- Start the UIAbility, ServiceExtensionAbility, and DataShareExtensionAbility components. For example, you can use **startAbility()**, **startServiceExtensionAbility()**, and **startAbilityByCall()**.
- Connect to the ServiceExtensionAbility and DataShareExtensionAbility components. For example, you can use **connectServiceExtensionAbility()** and **createDataShareHelper()**.
To deliver a better user experience, OpenHarmony restricts the following behavior:
- A background application randomly displays a dialog box, such as an ads pop-up.
- Background applications wake up each other. This type of behavior occupies system resources and increases power consumption, or even causes system frozen.
- A foreground application randomly redirects to another application, for example, redirecting to the payment page of another application. This type of behavior poses security risks.
In view of this, OpenHarmony formulates a set of component startup rules, as follows:
- **Before starting a component of another application, verify the visible field of the target component.**
- If the **visible** field of the target component is **false**, verify the **ohos.permission.START_INVISIBLE_ABILITY** permission.
- For details, see [Component Visible Configuration](../quick-start/module-configuration-file.md#abilities-tag)
- **Before starting a component of a background application, verify the BACKGROUND permission.**
- An application is considered as a foreground application only when the application process gains focus or its UIAbility component is running in the foreground.
- Verify the **ohos.permission.START_ABILITIES_FROM_BACKGROUND** permission.
- **When the startAbilityByCall() method is used, verify the call permission.** For details, see [Using Ability Call to Implement UIAbility Interaction](uiability-intra-device-interaction.md#using-ability-call-to-implement-uiability-interaction) and [Using Cross-Device Ability Call](hop-multi-device-collaboration.md#using-cross-device-ability-call).
- Verify the **ohos.permission.ABILITY_BACKGROUND_COMMUNICATION** permission.
> **NOTE**
>
> - Component startup control has been implemented since OpenHarmony v3.2 Release.
>
> - The new component startup rules are more strict than the original ones. You must be familiar with the new startup rules to prevent service exceptions.
## Intra-Device Component Startup Rules
The rules for starting components on the same device vary in the following scenarios:
- Starting or connecting to the UIAbility, ServiceExtensionAbility, and DataShareExtensionAbility components
- Using **startAbilityByCall()** to start the UIAbility component
![startup-rule](figures/component-startup-inner-stage.png)
## Inter-Device Component Startup Rules
The rules for starting components on a different device vary in the following scenarios:
- Starting or connecting to the UIAbility, ServiceExtensionAbility, and DataShareExtensionAbility components
- Using **startAbilityByCall()** to start the UIAbility component
![component-startup-rules](figures/component-startup-inter-stage.png)
<!--no_check-->
\ No newline at end of file
# Application Configuration File (FA Model)
The application configuration file contains information about the application configuration, application components, and permissions, as well as custom information. The information will be provided for the compiler, application market, and operating system in the build, distribution, and running phases.
The application project code developed based on the FA model contains a **config.json** file. For details about common configuration items, see [Application- or Component-Level Configuration](application-component-configuration-fa.md). For details about the file, see [Application Configuration File Overview (FA Model)](../quick-start/application-configuration-file-overview-fa.md).
<!--no_check-->
\ No newline at end of file
# Application Configuration File (Stage Model)
The application configuration file contains information about the application configuration, application components, and permissions, as well as custom information. The information will be provided for the compiler, application market, and operating system in the build, distribution, and running phases.
The application project code developed based on the stage model contains one **app.json5** file and one or more **module.json5** files. For details about common configuration items, see [Application- or Component-Level Configuration (Stage Model)](application-component-configuration-stage.md). For details about the two files, see [Application Configuration File Overview (Stage Model)](../quick-start/application-configuration-file-overview-stage.md).
<!--no_check-->
\ No newline at end of file
# Differences in Configuration Files
The FA model uses the [config.json file](../quick-start/application-configuration-file-overview-fa.md) to describe the basic information about an application. An application can have multiple modules, and each module has a **config.json** file. The **config.json** file consists of three parts: **app**, **deviceConfig**, and **module**. The **app** tag is used to configure application-level attributes. If an application has multiple modules, the **app** configuration in each **config.json** file must be consistent.
The stage model uses the [app.json5](../quick-start/app-configuration-file.md) and [module.json](../quick-start/module-configuration-file.md) files to describe the basic information about an application. An application can have multiple modules but only one **app.json5** file. This file is used to configure application-level attributes and takes effect for all the modules. Each module has a **module.json5** file, which is used to configure module-level attributes and takes effect only for the current module.
**Figure 1** Configuration file differences
![comparison-of-configuration-file](figures/comparison-of-configuration-file.png)
<!--no_check-->
\ No newline at end of file
# Connecting to a ServiceAbility
If a ServiceAbility wants to interact with a PageAbility or a ServiceAbility in another application, you must first create a connection by calling **connectAbility()**. This method is defined in the **featureAbility** class for the PageAbility and in the **particleAbility** class for the ServiceAbility. For details about the connection rules, see [Component Startup Rules](component-startup-rules.md). When calling **connectAbility()**, you should pass in a **Want** object containing information about the target ServiceAbility and an **IAbilityConnection** object. **IAbilityConnection** provides the following APIs that you need to implement.
**Table 1** IAbilityConnection APIs
| API| Description|
| -------- | -------- |
| onConnect() | Callback invoked when the ServiceAbility is connected.|
| onDisconnect() | Callback invoked when the ServiceAbility is disconnected.|
| onFailed() | Callback invoked when the connection to the ServiceAbility fails.|
The following sample code enables the PageAbility to create connection callback instances and connect to the local 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)
```
When the ServiceAbility is connected, the **onConnect()** callback is invoked and returns an **IRemoteObject** defining the proxy used for communicating with the ServiceAbility. OpenHarmony provides a default implementation of **IRemoteObject**. You can extend **rpc.RemoteObject** to implement your own class of **IRemoteObject**.
The following sample code shows how the ServiceAbility returns itself to the caller:
```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 Switching
| API in the FA Model| Corresponding d.ts File in the Stage Model| Corresponding API or Field in the Stage Model|
| -------- | -------- | -------- |
| [getOrCreateLocalDir(callback:AsyncCallback&lt;string&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextgetorcreatelocaldir7)<br>[getOrCreateLocalDir():Promise&lt;string&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetorcreatelocaldir7-1) | There is no corresponding API in the stage model.| Applications developed on the stage model do not have the operation permission in the application root directory. Therefore, no corresponding API is provided.|
| [verifyPermission(permission:string,options:PermissionOptions,callback:AsyncCallback&lt;number&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextverifypermission7)<br>[verifyPermission(permission:string,callback:AsyncCallback&lt;number&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextverifypermission7-1)<br>[verifyPermission(permission:string,options?:PermissionOptions):Promise&lt;number&gt;;](../reference/apis/js-apis-inner-app-context.md#contextverifypermission7-2) | \@ohos.abilityAccessCtrl.d.ts | [verifyAccessTokenSync(tokenID: number, permissionName: Permissions): GrantStatus;](../reference/apis/js-apis-abilityAccessCtrl.md#verifyaccesstokensync9)<br>[verifyAccessToken(tokenID: number, permissionName: Permissions): Promise&lt;GrantStatus&gt;;](../reference/apis/js-apis-abilityAccessCtrl.md#verifyaccesstoken9) |
| [requestPermissionsFromUser(permissions:Array&lt;string&gt;,requestCode:number,resultCallback:AsyncCallback&lt;PermissionRequestResult&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextrequestpermissionsfromuser7)<br>[requestPermissionsFromUser(permissions:Array&lt;string&gt;,requestCode:number):Promise&lt;PermissionRequestResult&gt;;](../reference/apis/js-apis-inner-app-context.md#contextrequestpermissionsfromuser7-1) | application\UIAbilityContext.d.ts | [requestPermissionsFromUser(permissions: Array&lt;string&gt;, requestCallback: AsyncCallback&lt;PermissionRequestResult&gt;) : void;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextrequestpermissionsfromuser)<br>[requestPermissionsFromUser(permissions: Array&lt;string&gt;) : 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-inner-app-context.md#contextgetapplicationinfo7)<br>[getApplicationInfo():Promise&lt;ApplicationInfo&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetapplicationinfo7-1) | application\Context.d.ts | [applicationInfo: ApplicationInfo;](../reference/apis/js-apis-inner-application-context.md#attributes)|
| [getBundleName(callback : AsyncCallback&lt;string&gt;): void;](../reference/apis/js-apis-inner-app-context.md#contextgetbundlename7)<br>[getBundleName(): Promise&lt;string&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetbundlename7-1) | application\UIAbilityContext.d.ts | [abilityInfo.bundleName: string;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#attributes)|
| [getDisplayOrientation(callback : AsyncCallback&lt;bundle.DisplayOrientation&gt;): void;](../reference/apis/js-apis-inner-app-context.md#contextgetdisplayorientation7)<br>[getDisplayOrientation(): Promise&lt;bundle.DisplayOrientation&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetdisplayorientation7-1) | \@ohos.screen.d.ts | [readonly orientation: Orientation;](../reference/apis/js-apis-screen.md#orientation) |
| [setDisplayOrientation(orientation:bundle.DisplayOrientation, callback:AsyncCallback&lt;void&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextsetdisplayorientation7)<br>[setDisplayOrientation(orientation:bundle.DisplayOrientation):Promise&lt;void&gt;;](../reference/apis/js-apis-inner-app-context.md#contextsetdisplayorientation7-1) | \@ohos.screen.d.ts | [setOrientation(orientation: Orientation, callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-screen.md#setorientation)<br>[setOrientation(orientation: Orientation): Promise&lt;void&gt;;](../reference/apis/js-apis-screen.md#setorientation-1) |
| [setShowOnLockScreen(show:boolean, callback:AsyncCallback&lt;void&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextsetshowonlockscreen7)<br>[setShowOnLockScreen(show:boolean):Promise&lt;void&gt;;](../reference/apis/js-apis-inner-app-context.md#contextsetshowonlockscreen7-1) | \@ohos.window.d.ts | [setShowOnLockScreen(showOnLockScreen: boolean): void;](../reference/apis/js-apis-window.md#setshowonlockscreen9) |
| [setWakeUpScreen(wakeUp:boolean, callback:AsyncCallback&lt;void&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextsetwakeupscreen7)<br>[setWakeUpScreen(wakeUp:boolean):Promise&lt;void&gt;;](../reference/apis/js-apis-inner-app-context.md#contextsetwakeupscreen7-1) | \@ohos.window.d.ts | [setWakeUpScreen(wakeUp: boolean): void;](../reference/apis/js-apis-window.md#setwakeupscreen9) |
| [getProcessInfo(callback:AsyncCallback&lt;ProcessInfo&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextgetprocessinfo7)<br>[getProcessInfo():Promise&lt;ProcessInfo&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetprocessinfo7-1) | \@ohos.app.ability.abilityManager.d.ts | [getAbilityRunningInfos(callback: AsyncCallback&lt;Array&lt;AbilityRunningInfo&gt;&gt;): void;](../reference/apis/js-apis-app-ability-abilityManager.md#getabilityrunninginfos)<br>[getAbilityRunningInfos(): 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-inner-app-context.md#contextgetelementname7)<br>[getElementName():Promise&lt;ElementName&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetelementname7-1) | application\UIAbilityContext.d.ts | [abilityInfo.name: string;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#attributes)<br>[abilityInfo.bundleName: string;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#attributes)|
| [getProcessName(callback:AsyncCallback&lt;string&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextgetprocessname7)<br>[getProcessName():Promise&lt;string&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetprocessname7-1) | \@ohos.app.ability.abilityManager.d.ts | [getAbilityRunningInfos(callback: AsyncCallback&lt;Array&lt;AbilityRunningInfo&gt;&gt;): void;](../reference/apis/js-apis-app-ability-abilityManager.md#getabilityrunninginfos)<br>[getAbilityRunningInfos(): 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-inner-app-context.md#contextgetcallingbundle7)<br>[getCallingBundle():Promise&lt;string&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetcallingbundle7-1) | There is no corresponding API in the stage model.| Applications developed on the stage model can use the **ohos.aafwk.param.callerUid** parameter of **Want.parameters** to obtain the application information of the caller.|
| [getFilesDir(callback:AsyncCallback&lt;string&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextgetfilesdir)<br>[getFilesDir():Promise&lt;string&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetfilesdir-1) | application\Context.d.ts | [filesDir: string;](../reference/apis/js-apis-inner-application-context.md#attributes)|
| [getCacheDir(callback:AsyncCallback&lt;string&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextgetcachedir)<br>[getCacheDir():Promise&lt;string&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetcachedir-1) | application\Context.d.ts | [cacheDir: string;](../reference/apis/js-apis-inner-application-context.md#attributes)|
| [getOrCreateDistributedDir(callback:AsyncCallback&lt;string&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextgetorcreatedistributeddir7)<br>[getOrCreateDistributedDir():Promise&lt;string&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetorcreatedistributeddir7-1) | application\Context.d.ts | [distributedFilesDir: string;](../reference/apis/js-apis-inner-application-context.md#attributes)|
| [getAppType(callback:AsyncCallback&lt;string&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextgetapptype7)<br>[getAppType():Promise&lt;string&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetapptype7-1) | application\UIAbilityContext.d.ts | The stage model obtains the application type through the **type** attribute of the **abilityInfo** field.<br>[abilityInfo.type: bundleManager.AbilityType;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#attributes)|
| [getHapModuleInfo(callback:AsyncCallback&lt;HapModuleInfo&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextgethapmoduleinfo7)<br>[getHapModuleInfo():Promise&lt;HapModuleInfo&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgethapmoduleinfo7-1) | application\UIAbilityContext.d.ts | [currentHapModuleInfo: HapModuleInfo;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#attributes)|
| [getAppVersionInfo(callback:AsyncCallback&lt;AppVersionInfo&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextgetappversioninfo7)<br>[getAppVersionInfo():Promise&lt;AppVersionInfo&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetappversioninfo7-1) | bundle\bundleInfo.d.ts | [readonly name: string;](../reference/apis/js-apis-bundleManager-bundleInfo.md#bundleinfo-1)<br>[readonly versionCode: number;](../reference/apis/js-apis-bundleManager-bundleInfo.md#bundleinfo-1)<br>[readonly versionName: string;](../reference/apis/js-apis-bundleManager-bundleInfo.md#bundleinfo-1) |
| [getApplicationContext():Context;](../reference/apis/js-apis-inner-app-context.md#contextgetapplicationcontext7) | application\Context.d.ts | [getApplicationContext(): ApplicationContext;](../reference/apis/js-apis-inner-application-context.md#contextgetapplicationcontext) |
| [getAbilityInfo(callback:AsyncCallback&lt;AbilityInfo&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextgetabilityinfo7)<br>[getAbilityInfo():Promise&lt;AbilityInfo&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetabilityinfo7-1) | application\UIAbilityContext.d.ts | [abilityInfo: AbilityInfo;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#attributes)|
| [isUpdatingConfigurations(callback:AsyncCallback&lt;boolean&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextisupdatingconfigurations7)<br>[isUpdatingConfigurations():Promise&lt;boolean&gt;;](../reference/apis/js-apis-inner-app-context.md#contextisupdatingconfigurations7-1) | There is no corresponding API in the stage model.| OpenHarmony applications do not restart when the system environment changes. The **onConfigurationUpdated** callback is invoked to notify the applications of the changes. This API provides an empty implementation in the FA model, and the stage model does not provide a corresponding API.|
| [printDrawnCompleted(callback:AsyncCallback&lt;void&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextprintdrawncompleted7)<br>[printDrawnCompleted():Promise&lt;void&gt;;](../reference/apis/js-apis-inner-app-context.md#contextprintdrawncompleted7-1) | There is no corresponding API in the stage model.| This API provides an empty implementation in the FA model. The stage model does not provide a corresponding API.|
# Creating a DataAbility
To meet the basic requirements of the database storage service, implement the **Insert**, **Query**, **Update**, and **Delete** methods for a DataAbility. The **BatchInsert** and **ExecuteBatch** methods have already implemented the traversal logic, but not batch data processing.
The following sample code shows how to create a 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)
}
};
```
# Creating a PageAbility
When you create a PageAbility on DevEco Studio, DevEco Studio automatically generates the **onCreate()** and **onDestroy()** callbacks in **app.js** and **app.ets**. You need to implement the other lifecycle callbacks in **app.js** and **app.ets**. The following code snippet shows how to create a 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')
},
}
```
After the PageAbility is created, its abilities-related configuration items are displayed in the **config.json** file. The following is an example **config.json** file of an ability named MainAbility:
```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"
}
]
}
```
In the FA model, you can call **getContext** of **featureAbility** to obtain the application context and then use the capabilities provided by the context.
**Table 1** featureAbility APIs
| API| Description|
| -------- | -------- |
| getContext() | Obtains the application context.|
The following code snippet shows how to use **getContext()** to obtain the application context and distributed directory:
```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);
})()
```
# Creating a ServiceAbility
1. Create a ServiceAbility.
Override the ServiceAbility lifecycle callbacks to implement your own logic for processing interaction requests.
```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. Register the ServiceAbility.
Declare the ServiceAbility in the **config.json** file by setting its **type** attribute to **service**. The **visible** attribute specifies whether the ServiceAbility can be called by other applications. The value **true** means that the ServiceAbility can be called by other applications, and **false** means that the ServiceAbility can be called only within the application. To enable the ServiceAbility to be called by other applications, set **visible** to **true** when registering the ServiceAbility and enable associated startup. For details about the startup rules, see [Component Startup Rules](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
}
]
}
}
```
# Using Want to Share Data Between Applications
Users often need to share data (such as a text or an image) from one application to another. The following uses PDF file sharing as an example to describe how to use Want to share data between applications.
## Prerequisites
1. There are two UIAbility components (one for the sharing party and the other for the shared party) and one system component (used as the application selector). When the sharing party initiates data sharing through **startAbility()**, the application selector is started. The system implicitly matches and displays all applications that support the type of data to share. After the user selects an application, the system starts that application to complete data sharing.
2. In this section, data sharing is triggered by touching a button. You can use other ways to trigger data sharing during application development. This section focuses on the Want configuration used for data sharing.
3. The following actions are involved in this section:
- **ACTION_SELECT (ohos.want.action.select)**: action of displaying the application selector.
- **ACTION_SEND_DATA (ohos.want.action.sendData)**: action of launching the UI for sending a single data record. It is used to transfer data to the shared party.
## How to Develop
- Sharing party
1. In the stage mode, the [File Descriptor (FD)](../reference/apis/js-apis-fileio.md#fileioopensync) is used for file transfer. This example assumes that the path of the file to share is obtained.
```ts
import fileIO from '@ohos.fileio';
// let path = ...
// Open the file whose path is a variable.
let fileFd = fileIO.openSync(path, 0o102, 0o666);
```
2. As described in the prerequisites, the sharing party starts an application selector and shares the data to the selector, and the selector transfers the data to the shared party. Want of the sharing party must be nested at two layers. At the first layer, implicit Want is used together with the **ohos.want.action.select** action to display the application selector. At the second layer, complete Want is declared in the custom field **parameters** to transfer the data to share.
```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 selector.
action: wantConstant.Action.ACTION_SELECT,
// This is the custom parameter in the first layer of Want,
/ which is intended to add information to the application selector.
parameters: {
// MIME type of PDF.
"ability.picker.type": "application/pdf",
"ability.picker.fileNames": [path],
"ability.picker.fileSizes": [fileSize],
// This nested Want ,which will be directly sent to the selected application.
"ability.want.params.INTENT": {
"action": "ohos.want.action.sendData",
"type": "application/pdf",
"parameters": {
"keyFd": {"type": "FD", "value": fileFd}
}
}
}
}
```
In the preceding code, the custom field **parameters** is used. The **ability.picker.\*** fields in the first-layer **parameters** are used to pass the information to be displayed on the application selector. The following fields are involved:
- **"ability.picker.type"**: The application selector renders the file type icon based on this field.
- **"ability.picker.fileNames"**: The application selector displays the file name based on this field.
- **"ability.picker.fileSizes"**: The application selector displays the file size based on this field. The unit is byte.
- **"ability.picker.fileNames"** and **"ability.picker.fileSizes"** are arrays and have a one-to-one mapping.
For example, when **"ability.picker.type"** is **"application/pdf"**, **"ability.picker.fileNames"** is **"["APIs.pdf"]"**, and **"ability.picker.fileSizes"** is **"[350 \* 1024]"**, the application selector is displayed as follows:
<img src="figures/stage-want2.png" alt="stage-want2" style="zoom:50%;" />
In the preceding code, the **ability.want.params.INTENT** field is nested Want. In this field, **action** and **type** are used for implicit matching by the application selector. For details about implicit matching, see [Implicit Want Matching Rules](explicit-implicit-want-mappings.md#interpretation-of-implicit-want-matching-rules). After the user selects an application, the nested Want of the **ability.want.params.INTENT** field is passed to that application.
- Shared party
1. As mentioned above, the application selector performs implicit matching based on the **ability.want.params.INTENT** field. Therefore, you must set **skills** in the ability configuration file (**module.json5** file in the stage model) of the shared party as follows:
```ts
"skills": [
{
"entities": [
// ...
],
"actions": [
"ohos.want.action.sendData"
// ...
],
"uris": [
{
"type": "application/pdf"
},
// ...
]
},
]
```
The **actions** and **type** fields in **uris** match the **action** and **type** fields in **ability.want.params.INTENT**, respectively.
Files can be transferred in FD mode, but not URI mode. In implicit matching, the **type** field in Want must match the **type** field in **uris** under **skills** of the shared party. Therefore, specify only the **type** field in **uris**. If **host** and **port** are specified, the matching fails. The application selector initiates implicit matching based on **ability.want.params.INTENT**. Therefore, when the **uri** field added to **ability.want.params.INTENT** matches the **uris** field under **skills**, the matching is successful and additional data can be transferred.
2. After the application selector starts the shared party, the system calls **onCreate** and passes **ability.want.params.INTENT** to the **want** parameter.
```ts
onCreate(want, launchParam) {
// When keyFd is undefined, the application crashes.
if (want["parameters"]["keyFd"] !== undefined) {
// Receive the file descriptor.
let fd = want["parameters"]["keyFd"].value;
// ...
}
}
```
# DataAbility Component Configuration
## URI Introduction
A Uniform Resource Identifier (URI) is used to identify a specific data item, such as a table in the database or a file on the disk. URIs used in OpenHarmony comply with the commonly used URI standard. A URI consists of the components:
![fa-dataability-uri](figures/fa-dataability-uri.png)
- **scheme**: name of the scheme used by the DataAbility. The value is fixed at **dataability**.
- **authority**: device ID. To access data on a remote device, set this component to the ID of the remote device. To access data on the local device, leave this component empty.
- **path**: location of the specific resource to access.
- **query**: query parameters.
- **fragment**: subordinate resources to access.
Example URIs:
- Cross-device communication: dataability://*device*id_/*com.domainname.dataability.persondata*/*person*/*10*
- Local-device communication: dataability:///*com.domainname.dataability.persondata*/*person*/*1*
> **NOTE**
>
> In the case of local-device communication, **device_id** is empty, and therefore, there are three slashes (/) after **dataability:**.
## Introduction to Certain Configuration Items
Similar to a PageAbility, a DataAbility is configured in **abilities** under **module** of the **config.json** file. The difference between a DataAbility and PageAbility lies in the **type** and **uri** fields.
**Table 1** DataAbility configuration items
| Name| Description|
| -------- | -------- |
| "name" | Ability name.|
| "type" | Type of the ability. The value **data** indicates a DataAbility.|
| "uri" | URI used for communication.|
| "visible" | Whether the ability is visible to other applications. Data sharing is allowed only when the value is **true**.|
The following is an example **config.json** file:
```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"
}]
```
For details about the configuration items, see [Internal Structure of module](../quick-start/module-structure.md).
<!--no_check-->
\ No newline at end of file
# DataAbility Lifecycle
You can override lifecycle callbacks (described in the table below) for a DataAbility based on service requirements.
**Table 1** DataAbility lifecycle APIs
| API| Description|
| -------- | -------- |
| onInitialized?(info: AbilityInfo): void | Called during ability initialization to initialize the relational database (RDB).|
| update?(uri: string, valueBucket: rdb.ValuesBucket, predicates: dataAbility.DataAbilityPredicates, callback: AsyncCallback&lt;number&gt;): void | Updates data in the database.|
| query?(uri: string, columns: Array&lt;string&gt;, predicates: dataAbility.DataAbilityPredicates, callback: AsyncCallback&lt;ResultSet&gt;): void | Queries data in the database.|
| delete?(uri: string, predicates: dataAbility.DataAbilityPredicates, callback: AsyncCallback&lt;number&gt;): void | Deletes one or more data records from the database.|
| normalizeUri?(uri: string, callback: AsyncCallback&lt;string&gt;): void | Normalizes the URI. A normalized URI applies to cross-device use, persistence, backup, and restore. When the context changes, it ensures that the same data item can be referenced.|
| batchInsert?(uri: string, valueBuckets: Array&lt;rdb.ValuesBucket&gt;, callback: AsyncCallback&lt;number&gt;): void | Inserts multiple data records into the database.|
| denormalizeUri?(uri: string, callback: AsyncCallback&lt;string&gt;): void | Converts a normalized URI generated by **normalizeUri** into a denormalized URI.|
| insert?(uri: string, valueBucket: rdb.ValuesBucket, callback: AsyncCallback&lt;number&gt;): void | Inserts a data record into the database.|
| openFile?(uri: string, mode: string, callback: AsyncCallback&lt;number&gt;): void | Opens a file.|
| getFileTypes?(uri: string, mimeTypeFilter: string, callback: AsyncCallback&lt;Array&lt;string&gt;&gt;): void | Obtains the MIME type of a file.|
| getType?(uri: string, callback: AsyncCallback&lt;string&gt;): void | Obtains the MIME type matching the data specified by the URI.|
| executeBatch?(ops: Array&lt;DataAbilityOperation&gt;, callback: AsyncCallback&lt;Array&lt;DataAbilityResult&gt;&gt;): void | Operates data in the database in batches.|
| call?(method: string, arg: string, extras: PacMap, callback: AsyncCallback&lt;PacMap&gt;): void | Calls a custom API.|
# DataAbility Component Overview
A DataAbility is an ability that uses the Data template. It provides unified data access for external systems, but not a UI for user interaction. A DataAbility can be started by a PageAbility, a ServiceAbility, or other applications. It remains to run in the background even after the user switches to another application.
A DataAbility helps applications manage access to data stored by themselves and other applications, and provides methods for sharing data with other applications, either on the same device or across devices.
Data can be stored in a database or files on disks. The DataAbility provide methods for inserting, deleting, updating, and querying data, and opening files. You should implement these methods.
# DataAbility Permission Control
The DataAbility uses permission control to determine whether an ability can access the data service it provides. There are static and dynamic permission controls.
## Static Permission Control
The DataAbility functions as the server. When being started, the DataAbility verifies the client permissions against the settings of the optional fields **readPermission**, **writePermission**, and **Permission** fields in the **config.json** file. The following is an example:
```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"
}]
```
The client permission is configured in **reqPermissions** under **module** in the **config.json** file. The following is an example:
```json
{
"module": {
"reqPermissions":{
{
"name":"ohos.permission.READ_CONTACTS"
},
{
"name":"ohos.permission.WRITE_CONTACTS"
}
}
}
}
```
## Dynamic Permission Control
Static permission control determines whether a DataAbility can be started by another ability or application. It does not verify the permission of each read/write interface.
Dynamic permission control verifies whether the client has the corresponding permission for every read/write interface. The table below lists the permissions required for calling these interfaces.
**Table 1** Permission configuration for data read/write interfaces
| Interface with the Read Permission| Interface with the Write Permission| Interface with the Read/Write Permission Based on Actual Requirements|
| -------- | -------- | -------- |
| query, normalizeUri, denormalizeUri, openfile (with **mode** set to **'r'**)| insert, batchInsert, delete, update, openfile (with **mode** set to **'w'**)| executeBatch |
For interfaces that require the read permission, the server must have **readPermission** specified, and the client must obtain the read permission before calling them.
For interfaces that require the write permission, the server must have **writePermission** specified, and the client must obtain the write permission before calling them.
# DataAbility Switching
The DataAbility component in the FA model corresponds to the DataShareExtensionAbility component in the stage model.
The DataShareExtensionAbility class provides system APIs. Only system applications can create DataShareExtensionAbility instances. Therefore, DataAbility switching adopts different policies for system applications and third-party applications.
## Switching a DataAbility of a System Application
The procedure for switching a DataAbility of a system application is similar to the procedure of PageAbility switching.
1. Create a DataShareExtensionAbility in the stage model.
2. Migrate the DataAbility code to the DataShareExtensionAbility.
The table below describes the lifecycle comparison of the DataAbility and DataShareExtensionAbility.
| DataAbility| DataShareExtensionAbility| Comparison Description|
| -------- | -------- | -------- |
| onInitialized?(info: AbilityInfo): void | onCreate?(want: Want, callback: AsyncCallback&lt;void&gt;): void<br> | The two methods have the same invoking time but different input parameters. In the stage model, the **want** parameter is added so that you can obtain parameters during creation.|
| update?(uri: string, valueBucket: rdb.ValuesBucket, predicates: dataAbility.DataAbilityPredicates, callback: AsyncCallback&lt;number&gt;): void | update?(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket, callback: AsyncCallback&lt;number&gt;): void | The two methods have the same meaning and invoking time, but slightly different parameter sequence and parameter type. A simple reconstruction is required.|
| query?(uri: string, columns: Array&lt;string&gt;, predicates: dataAbility.DataAbilityPredicates, callback: AsyncCallback&lt;ResultSet&gt;): void | query?(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array&lt;string&gt;, callback: AsyncCallback&lt;Object&gt;): void;| The two methods have the same meaning and invoking time, but slightly different parameter sequence and parameter type. A simple reconstruction is required.|
| delete?(uri: string, predicates: dataAbility.DataAbilityPredicates, callback: AsyncCallback&lt;number&gt;): void | delete?(uri: string, predicates: dataSharePredicates.DataSharePredicates, callback: AsyncCallback&lt;number&gt;):| The two methods have the same meaning and invoking time, but slightly different parameter type. A simple reconstruction is required.|
| normalizeUri?(uri: string, callback: AsyncCallback&lt;string&gt;): void | normalizeUri?(uri: string, callback: AsyncCallback&lt;string&gt;): void| The two methods have the same meaning, invoking time, and parameters.|
| batchInsert?(uri: string, valueBuckets: Array&lt;rdb.ValuesBucket&gt;, callback: AsyncCallback&lt;number&gt;): void | batchInsert?(uri: string, values: Array&lt;ValuesBucket&gt;, callback: AsyncCallback&lt;number&gt;): void| The two methods have the same meaning and invoking time, but slightly different parameter type. A simple reconstruction is required.|
| denormalizeUri?(uri: string, callback: AsyncCallback&lt;string&gt;): void | denormalizeUri?(uri: string, callback: AsyncCallback&lt;string&gt;): void | The two methods have the same meaning, invoking time, and parameters.|
| insert?(uri: string, valueBucket: rdb.ValuesBucket, callback: AsyncCallback&lt;number&gt;): void | insert?(uri: string, value: ValuesBucket, callback: AsyncCallback&lt;number&gt;): void | The two methods have the same meaning and invoking time, but slightly different parameter type. A simple reconstruction is required.|
| openFile?(uri: string, mode: string, callback: AsyncCallback&lt;number&gt;): void | NA | The stage model does not support cross-process URI access. You are advised to use [the **want** parameter to carry the file descriptor and file information](data-share-via-want.md) for cross-process file access.|
| getFileTypes?(uri: string, mimeTypeFilter: string, callback: AsyncCallback&lt;Array&lt;string&gt;&gt;): void | NA | The stage model does not support cross-process URI access. You are advised to use [the **want** parameter to carry the file descriptor and file information](data-share-via-want.md) for cross-process file access.|
| getType?(uri: string, callback: AsyncCallback&lt;string&gt;): void | NA | The stage model does not support cross-process URI access. You are advised to use [the **want** parameter to carry the file descriptor and file information](data-share-via-want.md) for cross-process file access.|
| executeBatch?(ops: Array&lt;DataAbilityOperation&gt;, callback: AsyncCallback&lt;Array&lt;DataAbilityResult&gt;&gt;): void | NA | This method is not provided in the stage model. You need to implement the functionality based on service functions.|
| call?(method: string, arg: string, extras: PacMap, callback: AsyncCallback&lt;PacMap&gt;): void | NA | This method is not provided in the stage model. You need to implement the functionality based on service functions.|
## Switching a DataAbility of a Third-Party Application
In the stage model, third-party applications cannot provide data services for other third-party applications. You can select a switching solution based on your service requirements.
| Service Type| Switching Solution|
| -------- | -------- |
| Providing data for third-party applications| Match a scenario-specific [ExtensionAbility](../reference/apis/js-apis-bundleManager.md#extensionabilitytype).|
| Providing data within the application| Extract the component code as a common module for other components to use.|
# DataAbilityHelper Switching
| API in the FA Model| Corresponding d.ts File in the Stage Model| Corresponding API in the Stage Model|
| -------- | -------- | -------- |
| [openFile(uri: string, mode: string, callback: AsyncCallback&lt;number&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperopenfile)<br>[openFile(uri: string, mode: string): Promise&lt;number&gt;;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperopenfile-1) | \@ohos.data.fileAccess.d.ts | [openFile(uri: string, flags: OPENFLAGS) : Promise&lt;number&gt;;](../reference/apis/js-apis-fileAccess.md#fileaccesshelperopenfile)<br>[openFile(uri: string, flags: OPENFLAGS, callback: AsyncCallback&lt;number&gt;) : void;](../reference/apis/js-apis-fileAccess.md#fileaccesshelperopenfile) |
| [on(type: 'dataChange', uri: string, callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperon) | \@ohos.data.dataShare.d.ts | [on(type: 'dataChange', uri: string, callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-data-dataShare.md#ondatachange) |
| [off(type: 'dataChange', uri: string, callback?: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperoff) | \@ohos.data.dataShare.d.ts | [off(type: 'dataChange', uri: string, callback?: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-data-dataShare.md#offdatachange) |
| [getType(uri: string, callback: AsyncCallback&lt;string&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelpergettype)<br>[getType(uri: string): Promise&lt;string&gt;;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelpergettype-1) | There is no corresponding API in the stage model.| The stage model does not support cross-process URI access. You are advised to use [the want parameter to carry the file descriptor and file information](data-share-via-want.md) for cross-process file access.|
| [getFileTypes(uri: string, mimeTypeFilter: string, callback: AsyncCallback&lt;Array&lt;string&gt;&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelpergetfiletypes)<br>[getFileTypes(uri: string, mimeTypeFilter: string): Promise&lt;Array&lt;string&gt;&gt;;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelpergetfiletypes-1) | There is no corresponding API in the stage model.| The stage model does not support cross-process URI access. You are advised to use [the want parameter to carry the file descriptor and file information](data-share-via-want.md) for cross-process file access.|
| [normalizeUri(uri: string, callback: AsyncCallback&lt;string&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelpernormalizeuri)<br>[normalizeUri(uri: string): Promise&lt;string&gt;;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelpernormalizeuri-1) | \@ohos.data.dataShare.d.ts | [normalizeUri(uri: string, callback: AsyncCallback&lt;string&gt;): void;](../reference/apis/js-apis-data-dataShare.md#normalizeuri)<br>[normalizeUri(uri: string): Promise&lt;string&gt;;](../reference/apis/js-apis-data-dataShare.md#normalizeuri-1) |
| [denormalizeUri(uri: string, callback: AsyncCallback&lt;string&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperdenormalizeuri)<br>[denormalizeUri(uri: string): Promise&lt;string&gt;;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperdenormalizeuri-1) | \@ohos.data.dataShare.d.ts | [denormalizeUri(uri: string, callback: AsyncCallback&lt;string&gt;): void;](../reference/apis/js-apis-data-dataShare.md#denormalizeuri)<br>[denormalizeUri(uri: string): Promise&lt;string&gt;;](../reference/apis/js-apis-data-dataShare.md#denormalizeuri-1) |
| [notifyChange(uri: string, callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelpernotifychange)<br>[notifyChange(uri: string): Promise&lt;void&gt;;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelpernotifychange-1) | \@ohos.data.dataShare.d.ts | [notifyChange(uri: string, callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-data-dataShare.md#notifychange)<br>[notifyChange(uri: string): Promise&lt;void&gt;;](../reference/apis/js-apis-data-dataShare.md#notifychange-1) |
| [insert(uri: string, valuesBucket: rdb.ValuesBucket, callback: AsyncCallback&lt;number&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperinsert)<br>[insert(uri: string, valuesBucket: rdb.ValuesBucket): Promise&lt;number&gt;;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperinsert-1) | \@ohos.data.dataShare.d.ts | [insert(uri: string, value: ValuesBucket, callback: AsyncCallback&lt;number&gt;): void;](../reference/apis/js-apis-data-dataShare.md#insert)<br>[insert(uri: string, value: ValuesBucket): Promise&lt;number&gt;;](../reference/apis/js-apis-data-dataShare.md#insert-1) |
| [batchInsert(uri: string, valuesBuckets: Array&lt;rdb.ValuesBucket&gt;, callback: AsyncCallback&lt;number&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperbatchinsert)<br>[batchInsert(uri: string, valuesBuckets: Array&lt;rdb.ValuesBucket&gt;): Promise&lt;number&gt;;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperbatchinsert-1) | \@ohos.data.dataShare.d.ts | [batchInsert(uri: string, values: Array&lt;ValuesBucket&gt;, callback: AsyncCallback&lt;number&gt;): void;](../reference/apis/js-apis-data-dataShare.md#batchinsert)<br>[batchInsert(uri: string, values: Array&lt;ValuesBucket&gt;): Promise&lt;number&gt;;](../reference/apis/js-apis-data-dataShare.md#batchinsert-1) |
| [delete(uri: string, predicates: dataAbility.DataAbilityPredicates, callback: AsyncCallback&lt;number&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperdelete)<br>[delete(uri: string, predicates?: dataAbility.DataAbilityPredicates): Promise&lt;number&gt;;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperdelete-1)<br>[delete(uri: string, callback: AsyncCallback&lt;number&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperdelete) | \@ohos.data.dataShare.d.ts | [delete(uri: string, predicates: dataSharePredicates.DataSharePredicates, callback: AsyncCallback&lt;number&gt;): void;](../reference/apis/js-apis-data-dataShare.md#delete)<br>[delete(uri: string, predicates: dataSharePredicates.DataSharePredicates): Promise&lt;number&gt;;](../reference/apis/js-apis-data-dataShare.md#delete-1) |
| [update(uri: string, valuesBucket: rdb.ValuesBucket, predicates: dataAbility.DataAbilityPredicates, callback: AsyncCallback&lt;number&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperupdate)<br>[update(uri: string, valuesBucket: rdb.ValuesBucket, predicates?: dataAbility.DataAbilityPredicates): Promise&lt;number&gt;;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperupdate-1)<br>[update(uri: string, valuesBucket: rdb.ValuesBucket, callback: AsyncCallback&lt;number&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperupdate) | \@ohos.data.dataShare.d.ts | [update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket, callback: AsyncCallback&lt;number&gt;): void;](../reference/apis/js-apis-data-dataShare.md#update)<br>[update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket): Promise&lt;number&gt;;](../reference/apis/js-apis-data-dataShare.md#update-1) |
| [query(uri: string, columns: Array&lt;string&gt;, predicates: dataAbility.DataAbilityPredicates, callback: AsyncCallback&lt;ResultSet&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperquery)<br>[query(uri: string, callback: AsyncCallback&lt;ResultSet&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperquery)<br>[query(uri: string, columns: Array&lt;string&gt;, callback: AsyncCallback&lt;ResultSet&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperquery)<br>[query(uri: string, predicates: dataAbility.DataAbilityPredicates, callback: AsyncCallback&lt;ResultSet&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperquery)<br>[query(uri: string, columns?: Array&lt;string&gt;, predicates?: dataAbility.DataAbilityPredicates): Promise&lt;ResultSet&gt;;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperquery-1) | \@ohos.data.dataShare.d.ts | [query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array&lt;string&gt;, callback: AsyncCallback&lt;DataShareResultSet&gt;): void;](../reference/apis/js-apis-data-dataShare.md#query)<br>[query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array&lt;string&gt;): Promise&lt;DataShareResultSet&gt;;](../reference/apis/js-apis-data-dataShare.md#query-1) |
| [call(uri: string, method: string, arg: string, extras: PacMap, callback: AsyncCallback&lt;PacMap&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelpercall-1)<br>[call(uri: string, method: string, arg: string, extras: PacMap): Promise&lt;PacMap&gt;;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelpercall) | There is no corresponding API in the stage model.| No corresponding API is provided.|
| [executeBatch(uri: string, operations: Array&lt;DataAbilityOperation&gt;, callback: AsyncCallback&lt;Array&lt;DataAbilityResult&gt;&gt;): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperexecutebatch)<br>[executeBatch(uri: string, operations: Array&lt;DataAbilityOperation&gt;): Promise&lt;Array&lt;DataAbilityResult&gt;&gt;;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperexecutebatch-1) | There is no corresponding API in the stage model.| No corresponding API is provided.|
# DataShareExtensionAbility
DataShareExtensionAbility is available only for system application. It provides the data sharing capability. System applications can implement a DataShareExtensionAbility or access an existing DataShareExtensionAbility in the system. Third-party applications can only access an existing DataShareExtensionAbility. For details, see [DataShare Development](../database/database-datashare-guidelines.md).
# Matching Rules of Explicit Want and Implicit Want
Both explicit Want and implicit Want can be used to match an ability to start based on certain rules. These rules determine how the parameters set in Want match the configuration file declared by the target ability.
- **Matching rules of explicit Want**
| Name| Type| Matching Item| Mandatory| Rule Description|
| -------- | -------- | -------- | -------- | -------- |
| deviceId | string | Yes| No| If this field is unspecified, only abilities on the local device are matched.|
| bundleName | string | Yes| Yes| If **abilityName** is specified but **bundleName** is unspecified, the matching fails.|
| moduleName | string | Yes| No| If this field is unspecified and multiple modules with the same ability name exist in the application, the first ability is matched by default.|
| abilityName | string | Yes| Yes| To use explicit Want, this field must be specified.|
| uri | string | No| No| This field is not used for matching. It is passed to the target ability as a parameter.|
| type | string | No| No| This field is not used for matching. It is passed to the target ability as a parameter.|
| action | string | No| No| This field is not used for matching. It is passed to the target ability as a parameter.|
| entities | Array&lt;string&gt; | No| No| This field is not used for matching. It is passed to the target ability as a parameter.|
| flags | number | No| No| This field is not used for matching and is directly transferred to the system for processing. It is generally used to set runtime information, such as URI data authorization.|
| parameters | {[key:&nbsp;string]:&nbsp;any} | No| No| This field is not used for matching. It is passed to the target ability as a parameter.|
- **Matching rules for implicit Want**
| Name| Type| Matching Item| Mandatory| Rule Description|
| -------- | -------- | -------- | -------- | -------- |
| deviceId | string | Yes| No| Implicit invoking is not supported across devices.|
| abilityName | string | No| No| To use implicit Want, this field must be left unspecified.|
| bundleName | string | Yes| No| - When only **bundleName** is specified, matching is limited to that application.<br>- When both **bundleName** and **moduleName** are specified, matching is limited to that module in that application.<br>- When only **moduleName** is specified, the setting is invalid.<br>For details, see [Interpretation of Implicit Want Matching Rules](#interpretation-of-implicit-want-matching-rules). |
| moduleName | string | Yes| No||
| uri | string | Yes| No||
| type | string | Yes| No||
| action | string | Yes| No||
| entities | Array&lt;string&gt; | Yes| No||
| flags | number | No| No| This field is not used for matching and is directly transferred to the system for processing. It is generally used to set runtime information, such as URI data authorization.|
| parameters | {[key:&nbsp;string]:&nbsp;any} | No| No| This field is not used for matching. It is passed to the target ability as a parameter.|
## Interpretation of Implicit Want Matching Rules
Get familiar with the following about implicit Want:
- The **want** parameter passed by the caller indicates the operation to be performed by the caller. It also provides data and application type restrictions.
- The **skills** field declares the capabilities of the target ability. For details, see [the skills tag](../quick-start/module-configuration-file.md#skills-tag) in the [module.json5 file](../quick-start/module-configuration-file.md).
The system matches the **want** parameter (including the **action**, **entities**, **uri**, and **type** attributes) passed by the caller against the **skills** configuration (including the **actions**, **entities**, **uris**, and **type** attributes) of the abilities one by one. When all the four attributes are matched, a dialog box is displayed for users to select a matched application.
### Matching Rules of action in the want Parameter
The system matches the [action](../reference/apis/js-apis-ability-wantConstant.md#wantconstantaction) attribute in the **want** parameter passed by the caller against **actions** under **skills** of the abilities.
- If **action** in the passed **want** parameter is specified but **actions** under **skills** of an ability is unspecified, the matching fails.
- If **action** in the passed **want** parameter is unspecified but **actions** under **skills** of an ability is specified, the matching is successful.
- If **action** in the passed **want** parameter is specified, and **actions** under **skills** of an ability is specified and contains **action** in the passed **want** parameter, the matching is successful.
- If **action** in the passed **want** parameter is specified, and **actions** under **skills** of an ability is specified but does not contain **action** in the passed **want** parameter, the matching fails.
Figure 1 Matching rules of action in the want parameter
<img src="figures/want-action.png" alt="want-action" style="zoom:80%;" />
### Matching Rules of entities in the want Parameter
The system matches the [entities](../reference/apis/js-apis-ability-wantConstant.md#wantconstantentity) attribute in the **want** parameter passed by the caller against **entities** under **skills** of the abilities.
- If **entities** in the passed **want** parameter is unspecified but **entities** under **skills** of an ability is specified, the matching is successful.
- If **entities** in the passed **want** parameter is unspecified but **entities** under **skills** of an ability is unspecified, the matching is successful.
- If **entities** in the passed **want** parameter is specified but **entities** under **skills** of an ability is unspecified, the matching fails.
- If **entities** in the passed **want** parameter is specified, and **entities** under **skills** of an ability is specified and contains **entities** in the passed **want** parameter, the matching is successful.
- If **entities** in the passed **want** parameter is specified, and **entities** under **skills** of an ability is specified but does not contain **entities** in the passed **want** parameter, the matching fails.
Figure 2 Matching rule of entities in the want parameter
<img src="figures/want-entities.png" alt="want-entities" style="zoom:80%;" />
### Matching Rules of uri and type in the want Parameter
When the **uri** and **type** parameters are specified in the **want** parameter to initiate a component startup request, the system traverses the list of installed components and matches the **uris** array under **skills** of the abilities one by one. If one of the **uris** arrays under **skills** matches the **uri** and **type** in the passed **want**, the matching is successful.
Figure 3 Matching rules when uri and type are specified in the want parameter
<img src="figures/want-uri-type1.png" alt="want-uri-type1" style="zoom: 80%;" />
There are four combinations of **uri** and **type** settings. The matching rules are as follows:
- Neither **uri** or **type** is specified in the **want** parameter.
- If the **uris** array under **skills** of an ability is unspecified, the matching is successful.
- If the **uris** array under **skills** of an ability contains an URI element whose **scheme** and **type** are unspecified, the matching is successful.
- In other cases, the matching fails.
- Only **uri** is specified in the **want** parameter.
- If the **uris** array under **skills** of an ability is unspecified, the matching fails.
- If the **uris** array under **skills** of an ability contains an element whose [uri is matched](#matching-rules-of-uri) and **type** is unspecified, the matching is successful. Otherwise, the matching fails.
- Only **type** is specified in the **want** parameter.
- If the **uris** array under **skills** of an ability is unspecified, the matching fails.
- If the **uris** array under **skills** of an ability contains an URI element whose **scheme** is unspecified and [type is matched](#matching-rules-of-type), the matching is successful. Otherwise, the matching fails.
- Both **uri** and **type** are specified in the **want** parameter, as shown in Figure 3.
- If the **uris** array under **skills** of an ability is unspecified, the matching fails.
- If the **uris** array under **skills** of an ability contains an element whose [uri is matched](#matching-rules-of-uri) and [type is matched](#matching-rules-of-type), the matching is successful. Otherwise, the matching fails.
To simplify the description, **uri** and **type** passed in the **want** parameter are called **w_uri** and **w_type**, respectively; the **uris** array under **skills** of an ability to match is called **s_uris**; each element in the array is called **s_uri**. Matching is performed from top to bottom.
Figure 4 Matching rules of uri and type in the want parameter
<img src="figures/want-uri-type2.png" alt="want-uri-type2" style="zoom:80%;" />
### Matching Rules of uri
To simplify the description, **uri** in the passed **want** parameter is called **w_uri**; **uri** under **skills** of an ability to match is called **s_uri**. The matching rules are as follows:
- If **scheme** of **s_uri** is unspecified and **w_uri** is unspecified, the matching is successful. Otherwise, the matching fails.
- If **host** of **s_uri** is unspecified and **scheme** of **w_uri** and **scheme** of **s_uri** are the same, the matching is successful. Otherwise, the matching fails.
- If **path**, **pathStartWith**, and **pathRegex** of **s_uri** are unspecified and **w_uri** and **s_uri** are the same, the matching is successful. Otherwise, the matching fails.
- If **path** of **s_uri** is specified and the **full path expressions** of **w_uri** and **s_uri** are the same, the matching is successful. Otherwise, the matching of **pathStartWith** continues.
- If **pathStartWith** of **s_uri** is specified and **w_uri** contains the prefix expression of **s_uri**, the matching is successful. Otherwise, **pathRegex** matching continues.
- If **pathRegex** of **s_uri** is specified and **w_uri** meets the regular expression of **s_uri**, the matching is successful. Otherwise, the matching fails.
> **NOTE**
>
> The **scheme**, **host**, **port**, **path**, **pathStartWith**, and **pathRegex** attributes of **uris** under **skills** of an ability are concatenated. If **path**, **pathStartWith**, and **pathRegex** are declared in sequence, **uris** can be concatenated into the following expressions:
>
> - **Full path expression**: `scheme://host:port/path`
>
> - **Prefix expression**: `scheme://host:port/pathStartWith`
>
> - **Regular expression**: `scheme://host:port/pathRegex`
### Matching Rules of type
> **NOTE**
>
> The matching rules of **type** described in this section are based on the fact that **type** in the **want** parameter is specified. If **type** is unspecified, follow the [matching rules of uri and type in the want parameter](#matching-rules-of-uri-and-type-in-the-want-parameter).
To simplify the description, **uri** in the passed **want** parameter is called **w_type**, and **type** of **uris** under **skills** of an ability to match is called **s_type**. The matching rules are as follows:
- If **s_type** is unspecified, the matching fails.
- If **s_type** or **w_type** contains the wildcard `*/*`, the matching is successful.
- If the last character of **s_type** is the wildcard `*`, for example, `prefixType/*`, the matching is successful only when **w_type** contains `prefixType/`.
- If the last character of **w_type** is the wildcard `*`, for example, `prefixType/*`, the matching is successful only when **s_type** contains `prefixType/`.
<!--no_check-->
\ No newline at end of file
# ExtensionAbility Component Overview
The ExtensionAbility component is used for specific scenarios such as widgets and input methods.
An [ExtensionAbilityType](../reference/apis/js-apis-bundleManager.md#extensionabilitytype) is provided for every specific scenario. All types of ExtensionAbility components are managed by the corresponding system services in a unified manner. For example, the InputMethodExtensionAbility component is managed by the input method management service. The following ExtensionAbility types are supported:
- [FormExtensionAbility](../reference/apis/js-apis-app-form-formExtensionAbility.md): ExtensionAbility component of the form type, which provides APIs related to widgets.
- [WorkSchedulerExtensionAbility](../reference/apis/js-apis-resourceschedule-workScheduler.md): ExtensionAbility component of the work_scheduler type, which provides APIs for registering, canceling, and querying Work Scheduler tasks.
- [InputMethodExtensionAbility](../reference/apis/js-apis-inputmethod.md): ExtensionAbility component of the input_method type, which provides an input method framework that can be used to hide the keyboard, obtain the list of installed input methods, display the dialog box for input method selection, and more.
- [ServiceExtensionAbility](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md): ExtensionAbility component of the service type, which provides APIs related to background service scenarios.
- [AccessibilityExtensionAbility](../reference/apis/js-apis-application-accessibilityExtensionAbility.md): ExtensionAbility component of the accessibility type, which provides APIs related to the accessibility feature.
- [DataShareExtensionAbility](../reference/apis/js-apis-application-dataShareExtensionAbility.md): ExtensionAbility component of the data_share type, which provides APIs for data sharing.
- [StaticSubscriberExtensionAbility](../reference/apis/js-apis-application-staticSubscriberExtensionAbility.md): ExtensionAbility component of the static_subscriber type, which provides APIs for static broadcast.
- [WindowExtensionAbility](../reference/apis/js-apis-application-windowExtensionAbility.md): ExtensionAbility component of the window type, which allows system applications to display UIs of other applications.
- [EnterpriseAdminExtensionAbility](../reference/apis/js-apis-EnterpriseAdminExtensionAbility.md): ExtensionAbility component of the enterprise_admin type, which provides APIs for processing enterprise management events, such as application installation events on devices and events indicating too many incorrect screen-lock password attempts.
## Using ExtensionAbility of the Specified Type
All types of ExtensionAbility components are started by the corresponding system management service, rather than applications, so that their lifecycles are under control by the system. The caller of the ExtensionAbility component does not need to care about its lifecycle.
The following uses [InputMethodExtensionAbility](../reference/apis/js-apis-inputmethod.md) as an example. As shown in the figure below, when an application calls the InputMethodExtensionAbility component, the input method management service is called first. The input method management service starts the InputMethodExtensionAbility component, returns the component to the application, and starts to manage its lifecycle.
**Figure 1** Using the InputMethodExtensionAbility component
![ExtensionAbility-start](figures/ExtensionAbility-start.png)
## Implementing ExtensionAbility of the Specified Type
The following uses [FormExtensionAbility](../reference/apis/js-apis-app-form-formExtensionAbility.md) as an example. The widget framework provides the base class [FormExtensionAbility](../reference/apis/js-apis-app-form-formExtensionAbility.md). You derive this base class to create your own class (such as **MyFormExtensionAbility**), implement the callbacks, such as **onCreate()** and **onUpdateForm()**, to provide specific widget functionalities. For details, see [FormExtensionAbility](Widget-development-stage.md).
You do not need to care when to add or delete a widget. The lifecycle of the FormExtensionAbility instance and the lifecycle of the ExtensionAbility process where the FormExtensionAbility instance is located are scheduled and managed by FormManagerService.
![form_extension](figures/form_extension.png)
> **NOTE**
>
> For an application, all ExtensionAbility components of the same type run in an independent process, whereas UIAbility, ServiceExtensionAbility, and DataShareExtensionAbility run in another independent process. For details, see [Process Model (Stage Model)](process-model-stage.md).
>
> For example, an application has one UIAbility component, one ServiceExtensionAbility, one DataShareExtensionAbility, two FormExtensionAbility, and one ImeExtensionAbility. When the application is running, there are three processes:
>
> - UIAbility, ServiceExtensionAbility, and DataShareExtensionAbility run in an independent process.
>
> - The two FormExtensionAbility components run in an independent process.
>
> - The two ImeExtensionAbility components run in an independent process.
# FA Model Development Overview
During application development based on the Feature Ability (FA) model, the following tasks are involved in the application model.
**Table 1** FA model development process
| Task| Introduction| Guide|
| -------- | -------- | -------- |
| Application component development| Use the PageAbility, ServiceAbility, DataAbility, and widgets of the FA model to develop applications.| - [Application- or Component-Level Configuration](application-component-configuration-fa.md)<br>- [PageAbility Component](pageability-overview.md)<br>- [ServiceAbility Component](serviceability-overview.md)<br>- [DataAbility Component](dataability-overview.md)<br>- [Widget Development](Widget-development-fa.md)<br>- [Context](application-context-fa.md)<br>- [Want](want-fa.md) |
| Inter-process communication (IPC)| Learn the process model and common IPC modes of the FA model.| [Common Events](common-event-fa.md)<br>[Background Services](rpc.md) |
| Inter-thread communication| Learn the thread model and common inter-thread communication modes of the FA model.| [Inter-Thread Communication](itc-fa-overview.md)|
| Mission management| Learn the basic concepts and typical scenarios of mission management in the FA model.| [Mission Management](mission-management-fa.md)|
| Application configuration file| Learn the requirements for developing application configuration files in the FA model.| [Application Configuration File](config-file-fa.md) |
# Component Interaction Between the FA Model and Stage Model
The FA model is supported by API version 8 and earlier versions, and the stage model is recommended since API version 9. The FA model and stage model have their respective components. The FA model provides three types of application components: PageAbility, ServiceAbility, and DataAbility. The stage model provides two types of application components: UIAbility and ExtensionAbility.
You cannot use both models for the development of an application (see the figure below). However, a device (system) can contain applications developed on both models (scenario 3 in the figure below). In this case, their components may interact with each other.
Figure 1 Coexistent application components of the FA model and stage model
![coexistence-of-FAandStage](figures/coexistence-of-FAandStage.png)
The following table lists the possible interaction scenarios. You must pay attention to the concerns listed below during your application development.
Table 1 Application component interaction scenarios
| Interaction Scenario| Concerns|
| -------- | -------- |
| [Starting a UIAbility from the FA Model](start-uiability-from-fa.md) | Set **bundleName** and **abilityName** in the **want** parameter to the bundle name and ability name of the UIAbility in the stage model.|
| [Connecting to a ServiceExtensionAbility from the FA Model](bind-serviceextensionability-from-fa.md) | Set **bundleName** and **abilityName** in the **want** parameter to the bundle name and ability name of the ServiceExtensionAbility in the stage model.|
| [Accessing a DataShareExtensionAbility from the FA Model](access-datashareextensionability-from-fa.md) | No code modification is required. However, you need to understand the API compatibility of **DataShareHelper** and **DataAbilityHelper**.|
| [Starting a PageAbility from the Stage Model](start-pageability-from-stage.md) | Set **bundleName** and **abilityName** in the **want** parameter to the bundle name and ability name of the PageAbility in the FA model.|
| [Connecting to a ServiceAbility from the Stage Model](bind-serviceability-from-stage.md) | Set **bundleName** and **abilityName** in the **want** parameter to the bundle name and ability name of the ServiceAbility in the FA model.|
| Accessing a DataAbility from the Stage Model | This type of access is not supported.|
# featureAbility Switching
| API in the FA Model| Corresponding d.ts File in the Stage Model| Corresponding API in the Stage Model|
| -------- | -------- | -------- |
| [getWant(callback: AsyncCallback&lt;Want&gt;): void;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitygetwant)<br>[getWant(): Promise&lt;Want&gt;;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitygetwant-1) | \@ohos.app.ability.UIAbility.d.ts | [launchWant: Want;](../reference/apis/js-apis-app-ability-uiAbility.md#attributes)|
| [startAbility(parameter: StartAbilityParameter, callback: AsyncCallback&lt;number&gt;): void;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitystartability)<br>[startAbility(parameter: StartAbilityParameter): Promise&lt;number&gt;;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitystartability-1) | application\UIAbilityContext.d.ts | [startAbility(want: Want, callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartability)<br>[startAbility(want: Want, options: StartOptions, callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartability-1)<br>[startAbility(want: Want, options?: StartOptions): Promise&lt;void&gt;;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartability-2) |
| [getContext(): Context;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitygetcontext) | \@ohos.app.ability.UIAbility.d.ts | [context: UIAbilityContext;](../reference/apis/js-apis-app-ability-uiAbility.md#attributes)|
| [startAbilityForResult(parameter: StartAbilityParameter, callback: AsyncCallback&lt;AbilityResult&gt;): void;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitystartabilityforresult7)<br>[startAbilityForResult(parameter: StartAbilityParameter): Promise&lt;AbilityResult&gt;;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitystartabilityforresult7-1) | application\UIAbilityContext.d.ts | [startAbilityForResult(want: Want, callback: AsyncCallback&lt;AbilityResult&gt;): void;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartabilityforresult)<br>[startAbilityForResult(want: Want, options: StartOptions, callback: AsyncCallback&lt;AbilityResult&gt;): void;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartabilityforresult-1)<br>[startAbilityForResult(want: Want, options?: StartOptions): Promise&lt;AbilityResult&gt;;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartabilityforresult-2) |
| [terminateSelfWithResult(parameter: AbilityResult, callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-ability-featureAbility.md#featureabilityterminateselfwithresult7)<br>[terminateSelfWithResult(parameter: AbilityResult): Promise&lt;void&gt;;](../reference/apis/js-apis-ability-featureAbility.md#featureabilityterminateselfwithresult7-1) | application\UIAbilityContext.d.ts | [terminateSelfWithResult(parameter: AbilityResult, callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextterminateselfwithresult)<br>[terminateSelfWithResult(parameter: AbilityResult): Promise&lt;void&gt;;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextterminateselfwithresult-1) |
| [terminateSelf(callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-ability-featureAbility.md#featureabilityterminateself7)<br>[terminateSelf(): Promise&lt;void&gt;;](../reference/apis/js-apis-ability-featureAbility.md#featureabilityterminateself7-1) | application\UIAbilityContext.d.ts | [terminateSelf(callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextterminateself)<br>[terminateSelf(): Promise&lt;void&gt;;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextterminateself-1) |
| [acquireDataAbilityHelper(uri: string): DataAbilityHelper;](../reference/apis/js-apis-ability-featureAbility.md#featureabilityacquiredataabilityhelper7) | \@ohos.data.dataShare.d.ts<br>\@ohos.data.fileAccess.d.ts | [createDataShareHelper(context: Context, uri: string, callback: AsyncCallback&lt;DataShareHelper&gt;): void;](../reference/apis/js-apis-data-dataShare.md#datasharecreatedatasharehelper)<br>[createDataShareHelper(context: Context, uri: string): Promise&lt;DataShareHelper&gt;;](../reference/apis/js-apis-data-dataShare.md#datasharecreatedatasharehelper-1)<br>[createFileAccessHelper(context: Context): FileAccessHelper;](../reference/apis/js-apis-fileAccess.md#fileaccesscreatefileaccesshelper-1)<br>[createFileAccessHelper(context: Context, wants: Array&lt;Want&gt;): FileAccessHelper;](../reference/apis/js-apis-fileAccess.md#fileaccesscreatefileaccesshelper) |
| [hasWindowFocus(callback: AsyncCallback&lt;boolean&gt;): void;](../reference/apis/js-apis-ability-featureAbility.md#featureabilityhaswindowfocus7)<br>[hasWindowFocus(): Promise&lt;boolean&gt;;](../reference/apis/js-apis-ability-featureAbility.md#featureabilityhaswindowfocus7-1) | \@ohos.window.d.ts | [on(eventType: 'windowStageEvent', callback: Callback&lt;WindowStageEventType&gt;): void;](../reference/apis/js-apis-window.md#onwindowstageevent9)<br>Checks whether the [active window](../reference/apis/js-apis-window.md#windowstageeventtype9) has the focus.|
| [connectAbility(request: Want, options:ConnectOptions ): number;](../reference/apis/js-apis-ability-featureAbility.md#featureabilityconnectability7) | application\UIAbilityContext.d.ts | [connectServiceExtensionAbility(want: Want, options: ConnectOptions): number;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextconnectserviceextensionability) |
| [disconnectAbility(connection: number, callback:AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitydisconnectability7)<br>[disconnectAbility(connection: number): Promise&lt;void&gt;;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitydisconnectability7-1) | application\UIAbilityContext.d.ts | [disconnectAbility(connection: number, callback:AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextdisconnectserviceextensionability-1)<br>[disconnectAbility(connection: number): Promise&lt;void&gt;;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextdisconnectserviceextensionability) |
| [getWindow(callback: AsyncCallback&lt;window.Window&gt;): void;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitygetwindow7)<br>[getWindow(): Promise&lt;window.Window&gt;;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitygetwindow7-1) | \@ohos.window.d.ts | [getLastWindow(ctx: BaseContext, callback: AsyncCallback&lt;Window&gt;): void;](../reference/apis/js-apis-window.md#windowgetlastwindow9)<br>[getLastWindow(ctx: BaseContext): 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.
先完成此消息的编辑!
想要评论请 注册