diff --git a/en/application-dev/ability/Readme-EN.md b/en/application-dev/ability/Readme-EN.md index 8be4858131c0b947639fdeed77bf4f99b3dfb10c..f32b4f7c02be64ac5839f23b77665889130e4a4d 100644 --- a/en/application-dev/ability/Readme-EN.md +++ b/en/application-dev/ability/Readme-EN.md @@ -6,4 +6,7 @@ - [FA Widget Development](fa-formability.md) - Other + - [WantAgent Development](wantagent.md) - [Ability Assistant Usage](ability-assistant-guidelines.md) + - [Test Framework Usage](ability-delegator.md) + diff --git a/en/application-dev/ability/ability-assistant-guidelines.md b/en/application-dev/ability/ability-assistant-guidelines.md index de9f35adbce1e77603fa1a15ba8db8512c0fc8c0..09feb5e590a67df877035069f0d80d8765831fd5 100644 --- a/en/application-dev/ability/ability-assistant-guidelines.md +++ b/en/application-dev/ability/ability-assistant-guidelines.md @@ -28,13 +28,13 @@ The ability assistant is pre-installed in the device environment. You can direct Starts an ability. - | Name | Description | - | --------- | ---------------------- | - | -h/--help | Help information. | + | Name | Description | + | --------- | -------------------------- | + | -h/--help | Help information. | | -d | Device ID. This parameter is optional. | | -a | Ability name. This parameter is mandatory.| | -b | Bundle name. This parameter is mandatory. | - | -D | Debugging mode. This parameter is optional. | + | -D | Debugging mode. This parameter is optional. | **Return value** @@ -82,13 +82,20 @@ The ability assistant is pre-installed in the device environment. You can direct | -i/--ability | AbilityRecord ID | Prints detailed information about a specified ability. | | -c/--client | | Prints detailed ability information. This parameter must be used together with other parameters. Example commands: **aa dump -a -c** and **aa dump -i 21 -c**.| - **Method** - + ``` aa dump -a ``` - + ![aa-dump-a](figures/aa-dump-a.PNG) + ``` + aa dump -l + ``` + ![aa-dump-l](figures/aa-dump-l.PNG) + ``` + aa dump -i 12 + ``` + ![aa-dump-i](figures/aa-dump-i.PNG) - **force-stop** Forcibly stops a process based on the bundle name. diff --git a/en/application-dev/ability/ability-delegator.md b/en/application-dev/ability/ability-delegator.md new file mode 100644 index 0000000000000000000000000000000000000000..cbf823bacad7b9781d90c8a86224893740444f35 --- /dev/null +++ b/en/application-dev/ability/ability-delegator.md @@ -0,0 +1,139 @@ +# Test Framework Usage + +## Overview +The delegator test framework provides a self-test framework (environment) for OpenHarmony applications. Using this framework, you can start an ability, schedule its lifecycle, listen for its state changes, run a shell command, and print the test result. + +## Constraints + +The APIs provided by the test framework can be used only in the test HAP. They take effect only after the test framework is started by running the **aa test** command or using the Integrated Development Environment (IDE). + + +## Starting the Test Framework + +The test framework can be started using either of the following methods: + +- Method 1: Run the **aa test** command. +- Method 2: Use the IDE. + +### Running aa test + +You can run the **aa test** command to start the test framework. You can specify the **TestRunner** to be used and the package name or module name of the HAP where the **TestRunner** is located. + +An example command in the FA model is as follows: + +```javascript +aa test -p com.example.myapplicationfaets -s unittest OpenHarmonyTestRunner -s class ActsAbilityTest -w 20 +``` + +An example command in the stage model is as follows: +```javascript +aa test -m com.example.myapplicationfaets -s unittest OpenHarmonyTestRunner -s class ActsAbilityTest -w 20 +``` +| Parameter | Mandatory| Description | +| --------------- | -------- | ------------------------------------------------------------ | +| -p | Yes | Package name of the HAP where the **TestRunner** is located. This parameter is used by the FA model. | +| -m | Yes | Module name of the HAP where the **TestRunner** is located. This parameter is used by the stage model. | +| -s unittest | Yes | Name of the **TestRunner** to be used. The TestRunner name must be the same as the file name. | +| -w | No | Timeout interval of a test case, in seconds. If this parameter is not specified, the test framework exits only after **finishTest** is invoked.| +| -s | No | It can be any parameter in the key-value format. The entered parameters can be obtained in key-value mode through **AbilityDelegatorArgs.parameters**. For example, in **-s classname myTest**, **classname** is the key and **myTest** is the value.| + +### Using the IDE + +For details about how to start the IDE, see [IDE Guide](https://developer.harmonyos.com/en/docs/documentation/doc-guides/ohos-openharmony-test-framework-0000001263160453#section1034420367508). + +## Introduction to TestRunner + +**TestRunner** is the entry class of the test framework test process. When the test process is started, the system calls related APIs in **TestRunner**. You need to inherit this class and override the **onPrepare** and **onRun** APIs. When creating an application template, the IDE initializes the default **TestRunner** and starts the default **TestAbility** in the **onRun** API. You can modify the test code of **TestAbility** or override **onPrepare** and **onRun** in **TestRunner** to implement your own test code. For details, see [TestRunner](../reference/apis/js-apis-testRunner.md). + +## Introduction to AbilityMonitor + +**AbilityMonitor** is provided by the test framework for binding to and listening for abilities. You can use **AbilityMonitor** to bind to an **Ability** instance and add **AbilityMonitor** to the listening list. After an ability is bound, the creation and lifecycle changes of the ability will trigger the related callback in **AbilityMonitor**. You can test and verify the ability in these callbacks. For details, see [AbilityMonitor](../reference/apis/js-apis-application-abilityMonitor.md). + +**Example** + +```javascript +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' + +function onAbilityCreateCallback() { + console.info("onAbilityCreateCallback"); +} + +var monitor = { + abilityName: "abilityname", + onAbilityCreate: onAbilityCreateCallback +} + +var abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); +abilityDelegator.addAbilityMonitor(monitor).then((void) => { + console.info("addAbilityMonitor promise"); +}); +``` + +## Introduction to AbilityDelegator + +**AbilityDelegator** is a main function class of the test framework. It provides the functions of starting an ability, obtaining an **Ability** instance, scheduling the ability lifecycle, listening for the ability state, and printing test results. + +**Modules to Import** + +```javascript +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' +``` + +```javascript +var abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() +``` + +### Starting an Ability and Listening for the Ability State + +Use **AbilityDelegator** and **AbilityMonitor** to start an ability, obtain an **Ability** instance, and listen for the ability state. + +**Example** + +```javascript +var abilityDelegator; +var ability; +var timeout = 100; + +function onAbilityCreateCallback() { + console.info("onAbilityCreateCallback"); +} + +var monitor = { + abilityName: "abilityname", + onAbilityCreate: onAbilityCreateCallback +} + +abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); +abilityDelegator.waitAbilityMonitor(monitor, timeout, (err, data) => { + ability = data; + console.info("waitAbilityMonitor callback"); +}); + +var want = { + bundleName: "bundleName", + abilityName: "abilityName" +}; + +abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); +abilityDelegator.startAbility(want, (err, data) => { + console.info("startAbility callback"); +}); +``` + +### Scheduling the Ability Lifecycle + +**AbilityDelegator** provides APIs to display and schedule the ability lifecycle and supports the foreground and background. It works with **AbilityMonitor** to listen for the ability lifecycle. For details, see [AbilityDelegator](../reference/apis/js-apis-application-abilityDelegator.md). + +### Running a Shell Command + +**AbilityDelegator** provides APIs to run shell commands. You can run a shell command in the test code. This feature takes effect only in the test environment. +**Example** + +```javascript + var abilityDelegator; + var cmd = "cmd"; + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + abilityDelegator.executeShellCommand(cmd, (err,data) => { + console.info("executeShellCommand callback"); + }); +``` diff --git a/en/application-dev/ability/fa-brief.md b/en/application-dev/ability/fa-brief.md index baf58d144162435b5a7834c88440777ef84621a6..db7346a6f4723cdf5589a8e5671944d95ea3878f 100644 --- a/en/application-dev/ability/fa-brief.md +++ b/en/application-dev/ability/fa-brief.md @@ -1,19 +1,32 @@ # FA Model Overview ## Overall Architecture -The development of an OpenHarmony application is essentially the development of one or more abilities. By scheduling abilities and managing their lifecycle, OpenHarmony implements application scheduling. In the FA model, three types of abilities are provided: Page, Service, and Data. The Page ability has the ArkUI and therefore provides the capability of interacting with users. The Service ability does not have a UI. It runs in the background and provides custom services for other abilities to invoke. The Data ability does not have a UI. It also runs in the background and enables other abilities to insert, delete, and query data. +The development of an OpenHarmony application is essentially the development of one or more abilities. By scheduling abilities and managing their lifecycle, OpenHarmony implements application scheduling. + +The Feature Ability (FA) model applies to application development using API 8 and earlier versions. In this model, there are Page, Service, Data, and Form abilities. +- The Page ability implements the ArkUI and provides the capability of interacting with users. +- The Service ability does not have a UI. It runs in the background and provides custom services for other abilities to invoke. +- The Data ability does not have a UI. It also runs in the background and enables other abilities to insert, delete, and query data. +- The Form ability provides a widget, which is a UI display mode. ## Application Package Structure **The following figure shows the application package structure.** + ![fa-package-info](figures/fa-package-info.png) +For details about the application package structure, see [Description of the Application Package Structure Configuration File](../quick-start/package-structure.md). + ## Lifecycle +Among all abilities, the Page ability has the most complex lifecycle, because it has a UI and is the interaction entry of applications. **The following figure shows the lifecycle of the Page ability.** ![fa-pageAbility-lifecycle](figures/fa-pageAbility-lifecycle.png) -You can override lifecycle functions in **app.js/app.ets** to process application logic. +The other abilities do not involve the foreground/background switchover and the **onShow** callback. +You can override the lifecycle callbacks in **app.js/app.ets** to process application logic. + +Currently, the **app.js** file provides only the **onCreate** and **onDestroy** callbacks, and the **app.ets** file provides the full lifecycle callbacks. ## Process and Thread Model diff --git a/en/application-dev/ability/fa-dataability.md b/en/application-dev/ability/fa-dataability.md index fc8cc8da0850badaaf1f8c8cfe9984dadb7d9420..4b098d095df7ca0bec73c485f1a83d70ae43fb3d 100644 --- a/en/application-dev/ability/fa-dataability.md +++ b/en/application-dev/ability/fa-dataability.md @@ -1,138 +1,94 @@ # Data Ability Development - -## Basic Concepts +## When to Use A Data ability helps applications manage access to data stored by themselves and other applications. It also provides APIs for sharing data with other applications either on the same device or across devices. Data ability providers can customize data access-related APIs such as data inserting, deleting, updating, and querying, as well as file opening, and share data with other applications through these open APIs. -## Creating a Data Ability -### 1. Implementation of the Data Subsystem -1. To meet the basic requirements of the database storage service, implement the **Insert**, **Query**, **Update**, and **Delete** APIs in the **Data** class to provide batch data processing. The traversal logic has been implemented by the **BatchInsert** and **ExecuteBatch** APIs. -2. The APIs used in the lifecycle of the Data ability are as follows: - - - onInitialized - - Called during ability initialization to initialize the relational database (RDB). - - - update - - Updates data in the database. - - - query - - Queries data in the database. - - - delete - - Deletes one or multiple data records from the database. - - - normalizeUri - - 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 - - Inserts multiple data records into the database. - - - denormalizeUri +## Available APIs + +**Table 1** Data ability lifecycle callbacks +|API|Description| +|:------|:------| +|onInitialized|Called during ability initialization to initialize the relational database (RDB).| +|update|Updates data in the database.| +|query|Queries data in the database.| +|delete|Deletes one or multiple data records from the database.| +|normalizeUri|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|Inserts multiple data records into the database.| +|denormalizeUri|Converts a normalized URI generated by **normalizeUri** into a denormalized URI.| +|insert|Inserts a data record into the database.| +|openFile|Opens a file.| +|getFileTypes|Obtains the MIME type of a file.| +|getType|Obtains the MIME type matching the data specified by the URI.| +|executeBatch|Operates data in the database in batches.| +|call|A customized API.| + + +## How to Develop +### Creating a Data Ability - Converts a normalized URI generated by **normalizeUri** into a denormalized URI. - - - insert - - Inserts a data record into the database. - - - openFile - - Opens a file. - - - getFileTypes - - Obtains the MIME type of a file. - - - getType - - Obtains the MIME type matching the data specified by the URI. - - - executeBatch - - Operates data in the database in batches. - - - call - - A customized API. - +1. To meet the basic requirements of the database storage service, implement the **Insert**, **Query**, **Update**, and **Delete** APIs in the **Data** class to provide batch data processing. The traversal logic has been implemented by the **BatchInsert** and **ExecuteBatch** APIs. - The following code snippet shows how to create a Data ability: + The following code snippet shows how to create a Data ability: ```javascript - import dataAbility from '@ohos.data.dataability' - import dataRdb from '@ohos.data.rdb' - - const TABLE_NAME = 'book' - const STORE_CONFIG = { name: 'book.db', encryptKey: new Uint8Array([]) } - const SQL_CREATE_TABLE = 'CREATE TABLE IF NOT EXISTS book(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, introduction TEXT NOT NULL)' - let rdbStore = undefined - export default { - onInitialized(abilityInfo) { - console.info('DataAbility onInitialized, abilityInfo:' + abilityInfo.bundleName) - dataRdb.getRdbStore(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], (num: number) => { - console.info('DataAbility batch insert ret=' + num) - }) - } else { - rdbStore.insert(TABLE_NAME, valueBuckets[i], callback) - } + onInitialized(abilityInfo) { + console.info('DataAbility onInitialized, abilityInfo:' + abilityInfo.bundleName) + dataRdb.getRdbStore(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], (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) } + }, + 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) + } }; - ``` +2. Submodule Configuration -### 2. Subsystem Configuration - -| JSON Field | Description | -| ------------- | ------------------------------------------------------------ | -| "name" | Ability name, corresponding to the **Data** class name derived from **Ability**. | -| "type" | Ability type, which is **Data** for a Data ability. | -| "uri" | URI used for communication. | -| "visible" | Whether the Data ability is visible to other applications. When this parameter is set to **true**, the Data ability can communicate with other applications.| + | JSON Field| Description | + | ------------ | ------------------------------------------------------------ | + | "name" | Ability name, corresponding to the **Data** class name derived from **Ability**. | + | "type" | Ability type, which is **Data** for a Data ability. | + | "uri" | URI used for communication. | + | "visible" | Whether the Data ability is visible to other applications. When this parameter is set to **true**, the Data ability can communicate with other applications.| -**config.json configuration example** + **config.json configuration example** -```json -"abilities":[{ + ```json + "abilities":[{ "srcPath": "DataAbility", "name": ".DataAbility", "icon": "$media:icon", @@ -141,121 +97,142 @@ Data ability providers can customize data access-related APIs such as data inser "type": "data", "visible": true, "uri": "dataability://ohos.samples.etsdataability.DataAbility" -}] -``` + }] + ``` + +### Accessing a Data ability +#### Development Preparations + +Import the basic dependency packages and obtain the URI string for communicating with the Data submodule. + +The basic dependency packages include: +- @ohos.ability.featureAbility +- @ohos.data.dataability +- @ohos.data.rdb + +#### Data Ability API Development -## Accessing a Data ability -### 1. Preparing for JS Application Development -Basic dependency packages: - 1. @ohos.ability.featureAbility - 2. @ohos.data.dataability - 3. @ohos.data.rdb -URI string used for communication with the Data ability. -### 2. JS Application Development APIs -Create a utility API object. -```js -// Different from the URI defined in the config.json file, the URI passed in the parameter has an extra slash (/), because there is a DeviceID parameter between the second and the third slash (/). -var urivar = "dataability:///com.ix.DataAbility" -var DAHelper = featureAbility.acquireDataAbilityHelper( +1. Create a Data ability helper. + + For details about the APIs provided by **DataAbilityHelper**, see [DataAbilityHelper Module](../reference/apis/js-apis-dataAbilityHelper.md). + ```js + // Different from the URI defined in the config.json file, the URI passed in the parameter has an extra slash (/), because there is a DeviceID parameter between the second and the third slash (/). + var urivar = "dataability:///com.ix.DataAbility" + var DAHelper = featureAbility.acquireDataAbilityHelper( urivar -); -``` -Construct RDB data. -```js -var valuesBucket = {"name": "gaolu"} -var da = new ohos_data_ability.DataAbilityPredicates() -var valArray =new Array("value1"); -var cars = new Array({"batchInsert1" : "value1",}); -``` -Use **insert** to insert data to the Data subsystem. -```js -// Callback mode: -DAHelper.insert( + ); + ``` +2. Construct RDB data. + ```js + var valuesBucket = {"name": "gaolu"} + var da = new ohos_data_ability.DataAbilityPredicates() + var valArray =new Array("value1"); + var cars = new Array({"batchInsert1" : "value1",}); + ``` +3. Use **insert** to insert data to the Data submodule. + ```js + // Callback mode: + DAHelper.insert( urivar, valuesBucket, (error, data) => { expect(typeof(data)).assertEqual("number") } -); -// Promise mode: -var datainsert = await DAHelper.insert( + ); + ``` + + ```js + // Promise mode: + var datainsert = await DAHelper.insert( urivar, valuesBucket -); -``` -Use **delete** to delete data from the Data subsystem. -```js -// Callback mode: -DAHelper.delete( + ); + ``` +4. Use **delete** to delete data from the Data submodule. + ```js + // Callback mode: + DAHelper.delete( urivar, da, (error, data) => { expect(typeof(data)).assertEqual("number") } -); -// Promise mode: -var datadelete = await DAHelper.delete( + ); + ``` + + ```js + // Promise mode: + var datadelete = await DAHelper.delete( urivar, da, -); -``` -Use **update** to update data in the Data subsystem. -```js -// Callback mode: -DAHelper.update( + ); + ``` +5. Use **update** to update data in the Data submodule. + ```js + // Callback mode: + DAHelper.update( urivar valuesBucket, da, (error, data) => { expect(typeof(data)).assertEqual("number") } -); -// Promise mode: -var dataupdate = await DAHelper.update( + ); + ``` + + ```js + // Promise mode: + var dataupdate = await DAHelper.update( urivar, valuesBucket, da, -); -``` -Use **query** to query data in the Data subsystem. -```js -// Callback mode: -DAHelper.query( + ); + ``` +6. Use **query** to query data in the Data submodule. + ```js + // Callback mode: + DAHelper.query( urivar, valArray, da, (error, data) => { expect(typeof(data)).assertEqual("object") } -); -// Promise mode: -var dataquery = await DAHelper.query( + ); + ``` + + ```js + // Promise mode: + var dataquery = await DAHelper.query( urivar, valArray, da -); -``` -Use **batchInsert** to insert data in batches to the Data subsystem. -```js -// Callback mode: -DAHelper.batchInsert( + ); + ``` +7. Use **batchInsert** to insert data in batches to the Data submodule. + ```js + // Callback mode: + DAHelper.batchInsert( urivar, cars, (error, data) => { expect(typeof(data)).assertEqual("number") } -); -// Promise mode: -var databatchInsert = await DAHelper.batchInsert( + ); + ``` + + ```js + // Promise mode: + var databatchInsert = await DAHelper.batchInsert( urivar, cars -); -``` -Use **executeBatch** to process data in batches in the Data subsystem. -```js -// Callback mode: -DAHelper.executeBatch( + ); + ``` +8. Use **executeBatch** to process data in batches in the Data submodule. + ```js + // Callback mode: + DAHelper.executeBatch( urivar, [ { @@ -271,9 +248,12 @@ DAHelper.executeBatch( (error, data) => { expect(typeof(data)).assertEqual("object") } -); -// Promise mode: -var dataexecuteBatch = await DAHelper.executeBatch( + ); + ``` + + ```js + // Promise mode: + var dataexecuteBatch = await DAHelper.executeBatch( urivar, [ { @@ -289,16 +269,16 @@ var dataexecuteBatch = await DAHelper.executeBatch( interrupted:true, } ] -); -``` + ); + ``` ## Development Example The following sample is provided to help you better understand how to develop a Data ability: -- [eTSDataAbility](https://gitee.com/openharmony/app_samples/tree/master/ability/eTSDataAbility) +- [DataAbility](https://gitee.com/openharmony/app_samples/tree/master/ability/DataAbility) -This **eTSDataAbility** sample shows how to: +This sample shows how to: Create a Data ability in the **data.ts** file in the **DataAbility** directory. diff --git a/en/application-dev/ability/fa-formability.md b/en/application-dev/ability/fa-formability.md index 89a110ed2fefaedb379bc7adffaa132dd6548721..49f2cf96d7d515fe60c9b8d85e793e7c9fbb9111 100644 --- a/en/application-dev/ability/fa-formability.md +++ b/en/application-dev/ability/fa-formability.md @@ -1,39 +1,39 @@ # FA Widget Development ## Widget Overview -A Form ability presents a widget, which is a set of UI components used to display important information or operations for an application. It provides users with direct access to a desired application service, without requiring them to open the application. +A widget is a set of UI components used to display important information or operations for an application. It provides users with direct access to a desired application service, without requiring them to open the application. -A widget displays brief information about an application on the UI of another application (host application, currently system applications only) and provides basic interactive features such as opening a UI page or sending a message. The widget client is responsible for displaying the service widget. +A widget displays brief information about an application on the UI of another application (host application, currently system applications only) and provides basic interactive features such as opening a UI page or sending a message. The widget host is responsible for displaying the widget. Basic concepts: - Widget provider The widget provider is an atomic service that provides the content to be displayed. It controls the display content, component layout, and component click events of a widget. -- Widget client - The widget client is an application that displays the widget content and controls the position where the widget is displayed in the host application. +- Widget host + The widget host is an application that displays the widget content and controls the position where the widget is displayed in the host application. - Widget Manager The Widget Manager is a resident agent that manages widgets added to the system and provides functions such as periodic widget update. > ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE** -> The widget client and provider do not keep running all the time. The Widget Manager starts the widget provider to obtain widget information when a widget is added, deleted, or updated. +> The widget host and provider do not keep running all the time. The Widget Manager starts the widget provider to obtain widget information when a widget is added, deleted, or updated. -You only need to develop widget content as the widget provider. The system automatically handles the work done by the widget client and Widget Manager. +You only need to develop widget content as the widget provider. The system automatically handles the work done by the widget host and Widget Manager. The widget provider controls the widget content to display, component layout, and click events bound to components. ## Scenario -Form ability development refers to the development conducted by the widget provider based on the Feature Ability (FA) model(fa-brief.md). As a widget provider, you need to carry out the following operations: +Form ability development refers to the development conducted by the widget provider based on the [Feature Ability (FA) model](fa-brief.md). As a widget provider, you need to carry out the following operations: -- Develop the lifecycle callback functions in **FormAbility**. +- Develop the lifecycle callbacks in **LifecycleForm**. - Create a **FormBindingData** object. - Update a widget through **FormProvider**. - Develop the widget UI page. ## Available APIs -The table below describes the lifecycle callback functions provided **FormAbility**. +The table below describes the lifecycle callbacks provided **LifecycleForm**. -**Table 1** FormAbility APIs +**Table 1** LifecycleForm APIs | API | Description | | :----------------------------------------------------------- | :------------------------------------------- | @@ -43,7 +43,7 @@ The table below describes the lifecycle callback functions provided **FormAbilit | onVisibilityChange(newStatus: { [key: string]: number }): void | Called to notify the widget provider of the change of widget visibility. | | onEvent(formId: string, message: string): void | Called to instruct the widget provider to receive and process the widget event. | | onDestroy(formId: string): void | Called to notify the widget provider that a **Form** instance (widget) has been destroyed. | -| onConfigurationUpdated(config: Configuration): void; | Called when the configuration of the environment where the ability is running is updated. | +| onAcquireFormState?(want: Want): formInfo.FormState | Called when the widget provider receives the status query result of a specified widget. | For details about the **FormProvider** APIs, see [FormProvider](../reference/apis/js-apis-formprovider.md). @@ -58,9 +58,9 @@ For details about the **FormProvider** APIs, see [FormProvider](../reference/api ## How to Develop -### Creating a Form Ability +### Creating LifecycleForm -To create a widget in the FA model, you need to implement the lifecycle callback functions of **FormAbility**. The sample code is as follows: +To create a widget in the FA model, you need to implement the lifecycles of **LifecycleForm**. The sample code is as follows: 1. Import the required modules. @@ -70,7 +70,7 @@ To create a widget in the FA model, you need to implement the lifecycle callback import formProvider from '@ohos.application.formProvider' ``` -2. Implement the lifecycle callback functions of **FormAbility**. +2. Implement the lifecycle callbacks of **LifecycleForm**. ```javascript export default { @@ -85,11 +85,11 @@ To create a widget in the FA model, you need to implement the lifecycle callback return formData; }, onCastToNormal(formId) { - // Called when the widget client converts the temporary widget into a normal one. The widget provider should do something to respond to the conversion. + // Called when the widget host converts the temporary widget into a normal one. The widget provider should do something to respond to the conversion. console.log('FormAbility onCastToNormal'); }, onUpdate(formId) { - // To support scheduled update, periodic update, or update requested by the widget client for a widget, override this method for data update. + // To support scheduled update, periodic update, or update requested by the widget host for a widget, override this method for data update. console.log('FormAbility onUpdate'); let obj = { "title": "titleOnUpdate", @@ -101,7 +101,7 @@ To create a widget in the FA model, you need to implement the lifecycle callback }); }, onVisibilityChange(newStatus) { - // Called when the widget client initiates an event about visibility changes. The widget provider should do something to respond to the notification. + // Called when the widget host initiates an event about visibility changes. The widget provider should do something to respond to the notification. console.log('FormAbility onVisibilityChange'); }, onEvent(formId, message) { @@ -129,7 +129,7 @@ Configure the **config.json** file for the **Form** ability. | -------- | ------------------------------------------------------------ | -------- | ------------------------ | | name | Name of a JavaScript component. The default value is **default**. | String | No | | pages | Route information about all pages in the JavaScript component, including the page path and page name. The value is an array, in which each element represents a page. The first element in the array represents the home page of the JavaScript FA.| Array | No | - | window | Window-related configurations. This field applies only to phones, tablets, smart TVs, head units, and wearable devices.| Object | Yes | + | window | Window-related configurations. | Object | Yes | | type | Type of the JavaScript component. Available values are as follows:
**normal**: indicates that the JavaScript component is an application instance.
**form**: indicates that the JavaScript component is a widget instance.| String | Yes (initial value: **normal**)| | mode | Development mode of the JavaScript component. | Object | Yes (initial value: left empty) | @@ -147,28 +147,26 @@ Configure the **config.json** file for the **Form** ability. }] ``` -- The **abilities** module in the **config.json** file corresponds to the **Form** ability. The internal field structure is described as follows: +- The **abilities** module in the **config.json** file corresponds to the **LifecycleForm** of the widget. The internal field structure is described as follows: | Field | Description | Data Type | Default | | ------------------- | ------------------------------------------------------------ | ---------- | ------------------------ | | name | Class name of the widget. The value is a string with a maximum of 127 bytes. | String | No | | description | Description of the widget. The value can be a string or a resource index to descriptions in multiple languages. The value is a string with a maximum of 255 bytes.| String | Yes (initial value: left empty) | | isDefault | Whether the widget is a default one. Each ability has only one default widget.
**true**: The widget is the default one.
**false**: The widget is not the default one.| Boolean | No | - | type | Type of the widget. Available values are as follows:
**Java**: indicates a Java-programmed widget.
**JS**: indicates a JavaScript-programmed widget.| String | No | + | type | Type of the widget. Available values are as follows:
**JS**: indicates a JavaScript-programmed widget. | String | No | | colorMode | Color mode of the widget. Available values are as follows:
**auto**: The widget adopts the auto-adaptive color mode.
**dark**: The widget adopts the dark color mode.
**light**: The widget adopts the light color mode.| String | Yes (initial value: **auto**)| | supportDimensions | Grid styles supported by the widget. Available values are as follows:
1 * 2: indicates a grid with one row and two columns.
2 * 2: indicates a grid with two rows and two columns.
2 * 4: indicates a grid with two rows and four columns.
4 * 4: indicates a grid with four rows and four columns.| String array| No | | defaultDimension | Default grid style of the widget. The value must be available in the **supportDimensions** array of the widget.| String | No | - | landscapeLayouts | Landscape layouts for the grid styles. Values in this array must correspond to the values in the **supportDimensions** array. This field is required only by Java-programmed widgets.| String array| No | - | portraitLayouts | Portrait layouts for the grid styles. Values in this array must correspond to the values in the **supportDimensions** array. This field is required only by Java-programmed widgets.| String array| No | | updateEnabled | Whether the widget can be updated periodically. Available values are as follows:
**true**: The widget can be updated periodically, depending on the update way you select, either at a specified interval (**updateDuration**) or at the scheduled time (**scheduledUpdateTime**). **updateDuration** is preferentially recommended.
**false**: The widget cannot be updated periodically.| Boolean | No | | scheduledUpdateTime | Scheduled time to update the widget. The value is in 24-hour format and accurate to minute. | String | Yes (initial value: **0:0**) | | updateDuration | Interval to update the widget. The value is a natural number, in the unit of 30 minutes.
If the value is **0**, this field does not take effect.
If the value is a positive integer ***N***, the interval is calculated by multiplying ***N*** and 30 minutes.| Number | Yes (initial value: **0**) | - | formConfigAbility | Name of the facility or activity used to adjust a widget. | String | Yes (initial value: left empty) | - | formVisibleNotify | Whether the widget is allowed to use the widget visibility notification. | String | Yes (initial value: left empty) | - | jsComponentName | Component name of the widget. The value is a string with a maximum of 127 bytes. This field is required only by JavaScript-programmed widgets.| String | No | + | formConfigAbility | Indicates the link to a specific page of the application. The value is a URI. | String | Yes (initial value: left empty) | + | formVisibleNotify | Whether the widget is allowed to use the widget visibility notification. | String | Yes (initial value: left empty) | + | jsComponentName | Component name of the widget. The value is a string with a maximum of 127 bytes. | String | No | | metaData | Metadata of the widget. This field contains the array of the **customizeData** field. | Object | Yes (initial value: left empty) | | customizeData | Custom information about the widget. | Object array | Yes (initial value: left empty) | - + A configuration example is as follows: ```json @@ -180,10 +178,12 @@ Configure the **config.json** file for the **Form** ability. "label": "$string:form_FormAbility_label", "srcPath": "FormAbility", "type": "service", + "srcLanguage": "ets", + "formsEnabled": true, "forms": [{ "colorMode": "auto", "defaultDimension": "2*2", - "description": "This is a service widget.", + "description": "This is a widget.", "formVisibleNotify": true, "isDefault": true, "jsComponentName": "widget", @@ -233,13 +233,13 @@ You should override **onDestroy** to delete widget data. For details about the persistence method, see [Lightweight Data Store Development](../database/database-preference-guidelines.md). -Note that the **Want** passed by the widget client to the widget provider contains a temporary flag, indicating whether the requested widget is a temporary one. +Note that the **Want** passed by the widget host to the widget provider contains a temporary flag, indicating whether the requested widget is a temporary one. -Normal widget: a widget that will be persistently used by the widget client +Normal widget: a widget that will be persistently used by the widget host -Temporary widget: a widget that is temporarily used by the widget client +Temporary widget: a widget that is temporarily used by the widget host -Data of a temporary widget is not persistently stored. If the widget framework is killed and restarted, data of a temporary widget will be deleted. However, the widget provider is not notified of which widget is deleted, and still keeps the data. Therefore, the widget provider should implement data clearing. In addition, the widget client may convert a temporary widget into a normal one. If the conversion is successful, the widget provider should process the widget ID and store the data persistently. This prevents the widget provider from deleting persistent data when clearing temporary widgets. +Data of a temporary widget is not persistently stored. If the widget framework is killed and restarted, data of a temporary widget will be deleted. However, the widget provider is not notified of which widget is deleted, and still keeps the data. Therefore, the widget provider should implement data clearing. In addition, the widget host may convert a temporary widget into a normal one. If the conversion is successful, the widget provider should process the widget ID and store the data persistently. This prevents the widget provider from deleting persistent data when clearing temporary widgets. ### Developing the Widget UI Page You can use HML, CSS, and JSON to develop the UI page for a JavaScript-programmed widget. @@ -325,3 +325,11 @@ You can use HML, CSS, and JSON to develop the UI page for a JavaScript-programme Now you've got a widget shown below. ![fa-form-example](figures/fa-form-example.png) + +## Development Example + +The following sample is provided to help you better understand how to develop a widget on the FA model: + +[FormAbility](https://gitee.com/openharmony/app_samples/tree/master/ability/FormAbility) + +This sample provides a widget. Users can create, update, and delete widgets on the home screen of their phones or by using their own widget host. This sample also implements widget information persistence by using lightweight data storage. diff --git a/en/application-dev/ability/fa-pageability.md b/en/application-dev/ability/fa-pageability.md index 1fe34335238f17e3318128b9c52cf59ba00b12e8..9d26c220e5f691e29d03c8ab4a9ad6c3752c99d4 100644 --- a/en/application-dev/ability/fa-pageability.md +++ b/en/application-dev/ability/fa-pageability.md @@ -2,11 +2,13 @@ ## Overview ### Concepts -The Page ability has the ArkUI and therefore provides the capability of interacting with users. When you create an ability in the integrated development environment (IDE), the IDE automatically creates template code. The capabilities related to the Page ability are exposed through the singleton **featureAbility**, and the lifecycle callbacks are exposed through the callback functions in **app.js/app.ets**. +The Page ability implements the ArkUI and provides the capability of interacting with developers. When you create an ability in the integrated development environment (IDE), the IDE automatically creates template code. The capabilities related to the Page ability are implemented through the **featureAbility**, and the lifecycle callbacks are implemented through the callbacks in **app.js/app.ets**. ### Page Ability Lifecycle -The ability lifecycle is a general term for all states of an ability (either a Page or a Service ability), such as **INACTIVE**, **ACTIVE**, and **BACKGROUND**. +**Ability lifecycle** + +The Page ability lifecycle is a general term for all states of a Page ability, such as **INACTIVE**, **ACTIVE**, and **BACKGROUND**. The following figure shows the lifecycle state transition of the Page ability. @@ -15,21 +17,34 @@ The following figure shows the lifecycle state transition of the Page ability. Description of ability lifecycle states: - - **UNINITIALIZED**: The ability is not initialized. This is a temporary state. An ability changes directly to the **INITIAL** state upon its creation. + - **UNINITIALIZED**: The Page ability is not initialized. This is a temporary state. A Page ability changes directly to the **INITIAL** state upon its creation. - - **INITIAL**: This state refers to the initial or stopped state. The ability in this state is not running. The ability enters the **INACTIVE** state after it is started. + - **INITIAL**: This state refers to the initial or stopped state. The Page ability in this state is not running. The Page ability enters the **INACTIVE** state after it is started. - **INACTIVE**: The ability is visible but does not gain focus. - **ACTIVE**: The ability runs in the foreground and gains focus. - - **BACKGROUND**: The ability returns to the background. After being re-activated, the ability enters the **ACTIVE** state. After being destroyed, the ability enters the **INITIAL** state. + - **BACKGROUND**: The Page ability returns to the background. After being re-activated, the Page ability enters the **ACTIVE** state. After being destroyed, the Page ability enters the **INITIAL** state. -**The following figure shows the lifecycle of the Page ability.** +**The following figure shows the relationship between lifecycle callbacks and lifecycle states of the Page ability.** ![fa-pageAbility-lifecycle](figures/fa-pageAbility-lifecycle.png) -You can override the lifecycle callback functions provided by the Page ability in **app.js/app.ets**. +You can override the lifecycle callbacks provided by the Page ability in the **app.js/app.ets** file. Currently, the **app.js** file provides only the **onCreate** and **onDestroy** callbacks, and the **app.ets** file provides the full lifecycle callbacks. + +### Launch Type +The ability supports three launch types: singleton, multi-instance, and instance-specific. +The **launchType** item in the **config.json** file is used to specify the launch type. + +| Launch Type | Description |Description | +| ----------- | ------- |---------------- | +| standard | Multi-instance | A new instance is started each time an ability starts.| +| singleton | Singleton | Only one instance exists in the system. If an instance already exists when an ability is started, that instance is reused.| +| specified | Instance-specific| The internal service of an ability determines whether to create multiple instances during running.| + +By default, **standard** is used. + ## Development Guidelines ### Available APIs @@ -46,48 +61,48 @@ You can override the lifecycle callback functions provided by the Page ability i ### Starting a Local Page Ability -* Modules to Import +**Modules to Import** +```js + import featureAbility from '@ohos.ability.featureAbility' ``` -import featureAbility from '@ohos.ability.featureAbility' -``` -* Example + +**Example** ```javascript -import featureAbility from '@ohos.ability.featureAbility' -featureAbility.startAbility({ + import featureAbility from '@ohos.ability.featureAbility' + featureAbility.startAbility({ want: { action: "", entities: [""], type: "", options: { - // Grant the permission to read the URI. + // Grant the permission to perform read operations on the URI. authReadUriPermission: true, - // Grant the permission to write the URI. + // Grant the permission to perform write operations on the URI. authWriteUriPermission: true, - // Forward the intent result to the origin ability. + // Support forwarding the Want result to the ability. abilityForwardResult: true, - // Mark the ability start-up triggered by continuation. + // Enable abiligy continuation. abilityContinuation: true, // Specify that a component does not belong to ohos. notOhosComponent: true, - // Specify whether an ability is started. + // Specify that an ability is started. abilityFormEnabled: true, - // Grant the permission to persist the URI. + // Grant the permission for possible persisting on the URI. authPersistableUriPermission: true, - // Grant the permission to persist the URI. + // Grant the permission for possible persisting on the prefix URI. authPrefixUriPermission: true, - // Support distributed scheduling and start-up across multiple devices. + // Support distributed scheduling system startup on multiple devices. abilitySliceMultiDevice: true, - // An ability using the Service template is started regardless of whether the - // host application has been started. + // A service ability is started regardless of whether the host application has been started. startForegroundAbility: true, // Install the specified ability if it is not installed. installOnDemand: true, - // Return the result to the origin ability slice. + // Return the result to the ability slice. abilitySliceForwardResult: true, - // Install the specified ability with the background mode if it is not installed. + // Install the specified ability with background mode if it is not installed. installWithBackgroundMode: true }, deviceId: "", @@ -95,14 +110,17 @@ featureAbility.startAbility({ abilityName: "com.example.startability.MainAbility", uri: "" }, -}, -); + }, + ); ``` + You can also include **parameters** in the **want** parameter and set its value in the key-value format. -* Example + +**Example** + ```javascript -import featureAbility from '@ohos.ability.featureAbility' -featureAbility.startAbility({ + import featureAbility from '@ohos.ability.featureAbility' + featureAbility.startAbility({ want: { bundleName: "com.example.startability", @@ -111,44 +129,115 @@ featureAbility.startAbility({ abilityName: "com.example.startability.MainAbility" } }, -}, -); + }, + ); ``` -### Starting a Remote Page Ability +### Starting a Remote Page Ability (Applying only to System Applications) +>Note: The **getTrustedDeviceListSync** API of the **DeviceManager** class is open only to system applications. Therefore, remote Page ability startup applies only to system applications. -* Modules to Import +**Modules to Import** ``` -import featureAbility from '@ohos.ability.featureAbility' + import featureAbility from '@ohos.ability.featureAbility' + import deviceManager from '@ohos.distributedHardware.deviceManager'; ``` -* Example +**Example** +```ts + function onStartRemoteAbility() { + console.info('onStartRemoteAbility begin'); + let params; + let wantValue = { + bundleName: 'ohos.samples.etsDemo', + abilityName: 'ohos.samples.etsDemo.RemoteAbility', + deviceId: getRemoteDeviceId(), + parameters: params + }; + console.info('onStartRemoteAbility want=' + JSON.stringify(wantValue)); + featureAbility.startAbility({ + want: wantValue + }).then((data) => { + console.info('onStartRemoteAbility finished, ' + JSON.stringify(data)); + }); + console.info('onStartRemoteAbility end'); + } +``` -```javascript -var promise = await featureAbility.startAbility({ - want: - { - deviceId: this.deviceId, - bundleName: "com.example.test", - abilityName: "com.example.test.MainAbility", - }, -} -); +Obtain **deviceId** from **DeviceManager**. The sample code is as follows: + +```ts + import deviceManager from '@ohos.distributedHardware.deviceManager'; + let dmClass; + function getRemoteDeviceId() { + if (typeof dmClass === 'object' && dmClass != null) { + let list = dmClass.getTrustedDeviceListSync(); + if (typeof (list) == 'undefined' || typeof (list.length) == 'undefined') { + console.log("MainAbility onButtonClick getRemoteDeviceId err: list is null"); + return; + } + console.log("MainAbility onButtonClick getRemoteDeviceId success:" + list[0].deviceId); + return list[0].deviceId; + } else { + console.log("MainAbility onButtonClick getRemoteDeviceId err: dmClass is null"); + } + } +``` + +In the cross-device scenario, the application must also apply for the data synchronization permission from end users. The sample code is as follows: + +```ts + import abilityAccessCtrl from "@ohos.abilityAccessCtrl"; + import bundle from '@ohos.bundle'; + async function RequestPermission() { + console.info('RequestPermission begin'); + let array: Array = ["ohos.permission.DISTRIBUTED_DATASYNC"]; + let bundleFlag = 0; + let tokenID = undefined; + let userID = 100; + let appInfo = await bundle.getApplicationInfo('ohos.samples.etsDemo', bundleFlag, userID); + tokenID = appInfo.accessTokenId; + let atManager = abilityAccessCtrl.createAtManager(); + let requestPermissions: Array = []; + for (let i = 0;i < array.length; i++) { + let result = await atManager.verifyAccessToken(tokenID, array[i]); + console.info("verifyAccessToken result:" + JSON.stringify(result)); + if (result == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) { + } else { + requestPermissions.push(array[i]); + } + } + console.info("requestPermissions:" + JSON.stringify(requestPermissions)); + if (requestPermissions.length == 0 || requestPermissions == []) { + return; + } + let context = featureAbility.getContext(); + context.requestPermissionsFromUser(requestPermissions, 1, (data)=>{ + console.info("data:" + JSON.stringify(data)); + console.info("data requestCode:" + data.requestCode); + console.info("data permissions:" + data.permissions); + console.info("data authResults:" + data.authResults); + }); + console.info('RequestPermission end'); + } ``` + ### Lifecycle APIs -**Table 2** Lifecycle callback functions + +**Table 2** Lifecycle callbacks | API | Description | | ------------ | ------------------------------------------------------------ | -| onShow() | Invoked when the ability is switched from the background to the foreground. In this case, the ability is visible to users.| -| onHide() | Invoked when the ability is switched from the foreground to the background. In this case, the ability is invisible.| -| onDestroy() | Invoked when the ability is destroyed. In this callback, you can make preparations for app exit, such as recycling resources and clearing the cache.| -| onCreate() | Invoked when the ability is created for the first time. You can initialize the application in this callback.| -| onInactive() | Invoked when the ability loses focus. An ability loses focus before entering the background state.| -| onActive() | Invoked when the ability is switched to the foreground and gains focus. | - -* Example -You need to override the lifecycle callback functions in **app.js/app.ets**. The IDE template generates **onCreate()** and **onDestroy()** by default. You need to override the other functions. +| onShow() | Called when the ability is switched from the background to the foreground. In this case, the ability is visible to users.| +| onHide() | Called when the ability is switched from the foreground to the background. In this case, the ability is invisible.| +| onDestroy() | Called when the ability is destroyed. In this callback, you can make preparations for app exit, such as recycling resources and clearing the cache.| +| onCreate() | Called when the ability is created for the first time. You can initialize the application in this callback.| +| onInactive() | Called when the ability loses focus. An ability loses focus before entering the background state.| +| onActive() | Called when the ability is switched to the foreground and gains focus. | + +**Example** + +You need to override the lifecycle callbacks in **app.js/app.ets**. The IDE template generates **onCreate()** and **onDestroy()** by default. You need to override the other callbacks. + ```javascript export default { onCreate() { @@ -174,6 +263,6 @@ export default { ### Development Example The following sample is provided to help you better understand how to develop a Page ability: -- [DMS](https://gitee.com/openharmony/app_samples/tree/master/ability/DMS) +[DMS](https://gitee.com/openharmony/app_samples/tree/master/ability/DMS) This sample describes how to start a local ability and remote ability. diff --git a/en/application-dev/ability/fa-serviceability.md b/en/application-dev/ability/fa-serviceability.md index 41811571ccd7bc2b48bead35cd5c8c77a6e0a516..1d3ffc44f8402225a5dbdea0df7c89531abaa5c5 100644 --- a/en/application-dev/ability/fa-serviceability.md +++ b/en/application-dev/ability/fa-serviceability.md @@ -1,34 +1,27 @@ # Service Ability Development -## Basic Concepts +## When to Use A Service ability is used to run tasks in the background, such as playing music or downloading files. It does not provide a UI for user interaction. Service abilities can be started by other applications or abilities and can remain running in the background even after the user switches to another application. -## Creating a Service Ability +## Available APIs -1. Create a child class of the **Ability** class and override the following Service ability-related lifecycle callbacks to implement your own logic for processing requests to interact with your Service ability: - - - onStart() - - This callback is invoked for initializing a Service ability when the Service ability is being created. This callback is invoked only once in the entire lifecycle of a Service ability. The **Want** object passed to this callback must be null. - - - onCommand() - - This callback is invoked every time a Service ability is created on a client. You can calculate calling statistics and perform initialization operations in this callback. - - - onConnect() - - This callback is invoked when another ability is connected to the Service ability. It returns an **IRemoteObject**. You can use this callback to generate a channel for the other ability to interact with the Service ability during inter-process communication (IPC). An ability can connect to the same Service ability for multiple times. When the first client is connected to a Service ability, the system calls **onConnect()** to generate an **IRemoteObject** for the Service ability, and the generated **IRemoteObject** will then be cached and used for all clients that are connected to this Service ability without having to call **onConnect()** again. - - - onDisconnect() - - This callback is invoked when another ability is disconnected from the Service ability. +**Table 1** Service ability lifecycle callbacks +|API|Description| +|:------|:------| +|onStart|Called to initialize a Service ability when the Service ability is being created. This callback is invoked only once in the entire lifecycle of a Service ability. The **Want** object passed to this callback must be null.| +|onCommand|Called every time a Service ability is created on a client. You can calculate calling statistics and perform initialization operations in this callback.| +|onConnect|Called when another ability is connected to the Service ability.| +|onDisconnect|Called when another ability is disconnected from the Service ability.| +|onStop|Called when the Service ability is being destroyed. You should override this callback for your Service ability to clear its resources, such as threads and registered listeners.| - - onStop() +## How to Develop - This callback is invoked when a Service ability is being destroyed. You should override this callback for your Service ability to clear its resources, such as threads and registered listeners. +### Creating a Service Ability +1. Create a child class of the **Ability** class and override the following Service ability-related lifecycle callbacks to implement your own logic for processing requests to interact with your Service ability: + The following code snippet shows how to create a Service ability: - + ```javascript export default { onStart(want) { @@ -49,11 +42,11 @@ A Service ability is used to run tasks in the background, such as playing music } ``` -2. Register a Service ability. - - You must declare your Service ability in the **config.json** file by setting its **type** attribute to **service**. +2. Register a Service ability. - ```javascript + You must declare your Service ability in the **config.json** file by setting its **type** attribute to **service**. + + ```javascript { "module": { "abilities": [ @@ -68,14 +61,13 @@ A Service ability is used to run tasks in the background, such as playing music } ... } - ``` + ``` - -## Starting the Service Ability +### Starting a Service ability -The **Ability** class provides the **startAbility()** method for you to start another Service ability by passing a **Want** object. +The **Ability** class provides the **startAbility()** API for you to start another Service ability by passing a **Want** object. To set information about the target Service ability, you can first construct a **Want** object with the **bundleName** and **abilityName** parameters specified. The meanings of the parameters are as follows: @@ -86,7 +78,7 @@ The following code snippet shows how to start a Service ability running on the l ```javascript import featureAbility from '@ohos.ability.featureability'; -var promise = await featureAbility.startAbility( +let promise = await featureAbility.startAbility( { want: { @@ -97,29 +89,49 @@ var promise = await featureAbility.startAbility( ); ``` -- After the preceding code is executed, the **startAbility()** method is called to start the Service ability. - - If the Service ability is not running, the system calls **onStart()** to initialize the Service ability, and then calls **onCommand()** on the Service ability. - - If the Service ability is running, the system directly calls **onCommand()** on the Service ability. +After the preceding code is executed, the **startAbility()** API is called to start the Service ability. +- If the Service ability is not running, the system calls **onStart()** to initialize the Service ability, and then calls **onCommand()** on the Service ability. +- If the Service ability is running, the system directly calls **onCommand()** on the Service ability. -- Stopping a Service ability - Once created, the Service ability keeps running in the background. The system does not stop or destroy it unless memory resources must be reclaimed. You can call **terminateAbility()** on a Service ability to stop it or call **stopAbility()** on another ability to stop the specified Service ability. + +### Stopping a Service ability + + Once created, the Service ability keeps running in the background. The system does not stop or destroy it unless memory resources must be reclaimed. You can call **terminateSelf()** on a Service ability to stop it or call **stopAbility()** on another ability to stop the specified Service ability. -## Connecting to a Local Service Ability +### Connecting to a Local Service Ability If you need to connect a Service ability to a Page ability or to a Service ability in another application, you must first implement the **IAbilityConnection** API for the connection. A Service ability allows other abilities to connect to it through **connectAbility()**. -When calling **connectAbility()**, you should pass a **Want** object containing information about the target Service ability and an **IAbilityConnection** object to the method. **IAbilityConnection** provides the following callbacks that you should implement: **onConnect()**, **onDisconnect()**, and **onFailed()**. The **onConnect()** callback is invoked when a Service ability is connected, **onDisconnect()** is invoked when a Service ability is unexpectedly disconnected, and **onFailed()** is invoked when a connection to a Service ability fails. +When calling **connectAbility()**, you should pass a **Want** object containing information about the target Service ability and an **IAbilityConnection** object to the API. **IAbilityConnection** provides the following callbacks that you should implement: **onConnect()**, **onDisconnect()**, and **onFailed()**. The **onConnect()** callback is invoked when a Service ability is connected, **onDisconnect()** is invoked when a Service ability is unexpectedly disconnected, and **onFailed()** is invoked when a connection to a Service ability fails. The following code snippet shows how to implement the callbacks: ```javascript -var mRemote; +let mRemote; function onConnectCallback(element, remote){ - console.log('ConnectAbility onConnect Callback') + console.log('onConnectLocalService onConnectDone element: ' + element); + console.log('onConnectLocalService onConnectDone remote: ' + remote); mRemote = remote; + if (mRemote == null) { + prompt.showToast({ + message: "onConnectLocalService not connected yet" + }); + return; + } + let option = new rpc.MessageOption(); + let data = new rpc.MessageParcel(); + let reply = new rpc.MessageParcel(); + data.writeInt(1); + data.writeInt(99); + await mRemote.sendRequest(1, data, reply, option); + let msg = reply.readInt(); + prompt.showToast({ + message: "onConnectLocalService connect result: " + msg, + duration: 3000 + }); } function onDisconnectCallback(element){ @@ -135,7 +147,7 @@ The following code snippet shows how to connect to a local Service ability: ```javascript import featureAbility from '@ohos.ability.featureability'; -var connId = featureAbility.connectAbility( +let connId = featureAbility.connectAbility( { bundleName: "com.jstest.serviceability", abilityName: "com.jstest.serviceability.MainAbility", @@ -155,7 +167,7 @@ The following code snippet shows how the Service ability instance returns itself ```javascript import rpc from "@ohos.rpc"; -var mMyStub; +let mMyStub; export default { onStart(want) { class MyStub extends rpc.RemoteObject{ @@ -166,6 +178,16 @@ export default { return null; } onRemoteRequest(code, message, reply, option) { + console.log("ServiceAbility onRemoteRequest called"); + if (code === 1) { + let op1 = data.readInt(); + let op2 = data.readInt(); + console.log("op1 = " + op1 + ", op2 = " + op2); + reply.writeInt(op1 + op2); + } else { + console.log("ServiceAbility unknown request code"); + } + return true; } } mMyStub = new MyStub("ServiceAbility-test"); @@ -186,19 +208,38 @@ export default { } ``` -## Connecting to a Remote Service Ability +### Connecting to a Remote Service Ability (Applying only to System Applications) +>Note: The **getTrustedDeviceListSync** API of the **DeviceManager** class is open only to system applications. Therefore, remote Service ability startup applies only to system applications. If you need to connect a Service ability to a Page ability on another device or to a Service ability in another application on another device, you must first implement the **IAbilityConnection** interface for the connection. A Service ability allows other abilities on another device to connect to it through **connectAbility()**. -When calling **connectAbility()**, you should pass a **Want** object containing information about the target Service ability and an **IAbilityConnection** object to the method. **IAbilityConnection** provides the following callbacks that you should implement: **onConnect()**, **onDisconnect()**, and **onFailed()**. The **onConnect()** callback is invoked when a Service ability is connected, **onDisconnect()** is invoked when a Service ability is unexpectedly disconnected, and **onFailed()** is invoked when a connection to a Service ability fails. +When calling **connectAbility()**, you should pass a **Want** object containing information about the target Service ability and an **IAbilityConnection** object to the API. **IAbilityConnection** provides the following callbacks that you should implement: **onConnect()**, **onDisconnect()**, and **onFailed()**. The **onConnect()** callback is invoked when a Service ability is connected, **onDisconnect()** is invoked when a Service ability is unexpectedly disconnected, and **onFailed()** is invoked when a connection to a Service ability fails. The following code snippet shows how to implement the callbacks: -```javascript -var mRemote; +```ts +let mRemote; function onConnectCallback(element, remote){ - console.log('ConnectRemoteAbility onConnect Callback') + console.log('onConnectLocalService onConnectDone element: ' + element); + console.log('onConnectLocalService onConnectDone remote: ' + remote); mRemote = remote; + if (mRemote == null) { + prompt.showToast({ + message: "onConnectLocalService not connected yet" + }); + return; + } + let option = new rpc.MessageOption(); + let data = new rpc.MessageParcel(); + let reply = new rpc.MessageParcel(); + data.writeInt(1); + data.writeInt(99); + await mRemote.sendRequest(1, data, reply, option); + let msg = reply.readInt(); + prompt.showToast({ + message: "onConnectLocalService connect result: " + msg, + duration: 3000 + }); } function onDisconnectCallback(element){ @@ -210,17 +251,35 @@ function onFailedCallback(code){ } ``` -The **Want** of the target Service ability must contain the remote **deviceId**, which can be obtained through **deviceManager**. +The **Want** of the target Service ability must contain the remote **deviceId**, which can be obtained from **DeviceManager**. The sample code is as follows: + +```ts +import deviceManager from '@ohos.distributedHardware.deviceManager'; +let dmClass; +function getRemoteDeviceId() { + if (typeof dmClass === 'object' && dmClass != null) { + let list = dmClass.getTrustedDeviceListSync(); + if (typeof (list) == 'undefined' || typeof (list.length) == 'undefined') { + console.log("MainAbility onButtonClick getRemoteDeviceId err: list is null"); + return; + } + console.log("MainAbility onButtonClick getRemoteDeviceId success:" + list[0].deviceId); + return list[0].deviceId; + } else { + console.log("MainAbility onButtonClick getRemoteDeviceId err: dmClass is null"); + } +} +``` The following code snippet shows how to connect to a remote Service ability: -```javascript +```ts import featureAbility from '@ohos.ability.featureability'; -var connId = featureAbility.connectAbility( +let connId = featureAbility.connectAbility( { - deviceId: deviceId, - bundleName: "com.jstest.serviceability", - abilityName: "com.jstest.serviceability.MainAbility", + deviceId: getRemoteDeviceId(), + bundleName: "ohos.samples.etsDemo", + abilityName: "ohos.samples.etsDemo.ServiceAbility", }, { onConnect: onConnectCallback, @@ -229,53 +288,124 @@ var connId = featureAbility.connectAbility( }, ); ``` +In the cross-device scenario, the application must also apply for the data synchronization permission from end users. The sample code is as follows: + +```ts +import abilityAccessCtrl from "@ohos.abilityAccessCtrl"; +import bundle from '@ohos.bundle'; +async function RequestPermission() { + console.info('RequestPermission begin'); + let array: Array = ["ohos.permission.DISTRIBUTED_DATASYNC"]; + let bundleFlag = 0; + let tokenID = undefined; + let userID = 100; + let appInfo = await bundle.getApplicationInfo('ohos.samples.etsDemo', bundleFlag, userID); + tokenID = appInfo.accessTokenId; + let atManager = abilityAccessCtrl.createAtManager(); + let requestPermissions: Array = []; + for (let i = 0;i < array.length; i++) { + let result = await atManager.verifyAccessToken(tokenID, array[i]); + console.info("verifyAccessToken result:" + JSON.stringify(result)); + if (result == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) { + } else { + requestPermissions.push(array[i]); + } + } + console.info("requestPermissions:" + JSON.stringify(requestPermissions)); + if (requestPermissions.length == 0 || requestPermissions == []) { + return; + } + let context = featureAbility.getContext(); + context.requestPermissionsFromUser(requestPermissions, 1, (data)=>{ + console.info("data:" + JSON.stringify(data)); + console.info("data requestCode:" + data.requestCode); + console.info("data permissions:" + data.permissions); + console.info("data authResults:" + data.authResults); + }); + console.info('RequestPermission end'); +} +``` When a Service ability is connected, the **onConnect()** callback is invoked and returns an **IRemoteObject** defining the proxy used for communicating with the Service ability. OpenHarmony provides a default implementation of the **IRemoteObject** interface. You can inherit **rpc.RemoteObject** to implement your own class of **IRemoteObject**. The following code snippet shows how the Service ability instance returns itself to the calling ability: -```javascript +```ts import rpc from "@ohos.rpc"; -var mMyStub; -export default { - onStart(want) { - class MyStub extends rpc.RemoteObject{ - constructor(des) { - if (typeof des === 'string') { - super(des); - } - return null; - } - onRemoteRequest(code, message, reply, option) { - } +class FirstServiceAbilityStub extends rpc.RemoteObject{ + constructor(des) { + if (typeof des === 'string') { + super(des); + } else { + return null; } - mMyStub = new MyStub("ServiceAbility-test"); + } + onRemoteRequest(code, data, reply, option) { + console.log("ServiceAbility onRemoteRequest called"); + if (code === 1) { + let op1 = data.readInt(); + let op2 = data.readInt(); + console.log("op1 = " + op1 + ", op2 = " + op2); + reply.writeInt(op1 + op2); + } else { + console.log("ServiceAbility unknown request code"); + } + return true; + } +} + +export default { + onStart() { + console.info('ServiceAbility onStart'); }, - onCommand(want, restart, startId) { - console.log('ServiceAbility onCommand'); + onStop() { + console.info('ServiceAbility onStop'); }, onConnect(want) { - console.log('ServiceAbility OnConnect'); - return mMyStub; - }, - onDisconnect() { - console.log('ServiceAbility OnDisConnect'); + console.log("ServiceAbility onConnect"); + try { + let value = JSON.stringify(want); + console.log("ServiceAbility want:" + value); + } catch(error) { + console.log("ServiceAbility error:" + error); + } + return new FirstServiceAbilityStub("first ts service stub"); }, - onStop() { - console.log('ServiceAbility onStop'); + onDisconnect(want) { + console.log("ServiceAbility onDisconnect"); + let value = JSON.stringify(want); + console.log("ServiceAbility want:" + value); }, -} + onCommand(want, startId) { + console.info('ServiceAbility onCommand'); + let value = JSON.stringify(want); + console.log("ServiceAbility want:" + value); + console.log("ServiceAbility startId:" + startId); + } +}; ``` ## Development Example -The following sample is provided to help you better understand how to develop a Service ability: +### The following sample is provided to help you better understand how to develop a Service ability: + +- [ServiceAbility](https://gitee.com/openharmony/app_samples/tree/master/ability/ServiceAbility) -- [eTSServiceAbility](https://gitee.com/openharmony/app_samples/tree/master/ability/eTSServiceAbility) -This **eTSServiceAbility** sample shows how to: +This sample shows how to: Create a local Service ability in the **service.ts** file in the **ServiceAbility** directory. Encapsulate the process of starting and connecting to the local Service ability in the **MainAbility** directory. + + +### The following sample is provided to help you better understand how to develop a remote Service ability: + +- [DMS](https://gitee.com/openharmony/app_samples/tree/master/ability/DMS) + +This **DMS** sample shows how to: + +Create a remote Service ability in the **service.ts** file in the **ServiceAbility** directory. + +Encapsulate the process of connecting to the remote Service ability in the **RemoteAbility** directory. diff --git a/en/application-dev/ability/figures/AbilityComponentInstanceMission.png b/en/application-dev/ability/figures/AbilityComponentInstanceMission.png new file mode 100644 index 0000000000000000000000000000000000000000..ce349b7a3544739dd2d3314d35f5b8e3ee68357c Binary files /dev/null and b/en/application-dev/ability/figures/AbilityComponentInstanceMission.png differ diff --git a/en/application-dev/ability/figures/aa-dump-a.PNG b/en/application-dev/ability/figures/aa-dump-a.PNG new file mode 100644 index 0000000000000000000000000000000000000000..ae8d41f65f68d73895be5bbbb539c0d220b2a9a5 Binary files /dev/null and b/en/application-dev/ability/figures/aa-dump-a.PNG differ diff --git a/en/application-dev/ability/figures/aa-dump-i.PNG b/en/application-dev/ability/figures/aa-dump-i.PNG new file mode 100644 index 0000000000000000000000000000000000000000..12998c5ba3e7d667d1147b6e825f8d110d5c5c5e Binary files /dev/null and b/en/application-dev/ability/figures/aa-dump-i.PNG differ diff --git a/en/application-dev/ability/figures/aa-dump-l.PNG b/en/application-dev/ability/figures/aa-dump-l.PNG new file mode 100644 index 0000000000000000000000000000000000000000..a6797eef284990e3fa25e71562ac8afbddf0821d Binary files /dev/null and b/en/application-dev/ability/figures/aa-dump-l.PNG differ diff --git a/en/application-dev/ability/figures/fa-package-info.png b/en/application-dev/ability/figures/fa-package-info.png index 20f01625eed79a95962fdc0d8105e62c29d9dbb0..86da707408da8fdb149ea62d92298fed605132ca 100644 Binary files a/en/application-dev/ability/figures/fa-package-info.png and b/en/application-dev/ability/figures/fa-package-info.png differ diff --git a/en/application-dev/ability/figures/fa-pageAbility-lifecycle.png b/en/application-dev/ability/figures/fa-pageAbility-lifecycle.png index 3093a7765a9055a28527edd4280c4f476adf6d33..ab6e01af0cf96f852c37696fe0c23425219eca39 100644 Binary files a/en/application-dev/ability/figures/fa-pageAbility-lifecycle.png and b/en/application-dev/ability/figures/fa-pageAbility-lifecycle.png differ diff --git a/en/application-dev/ability/wantagent.md b/en/application-dev/ability/wantagent.md new file mode 100644 index 0000000000000000000000000000000000000000..d092ea537ec46bd0c380549cbbf67364f57ff311 --- /dev/null +++ b/en/application-dev/ability/wantagent.md @@ -0,0 +1,72 @@ +# WantAgent Development +### Introduction +The **WantAgent** class encapsulates a **Want** object that specifies a particular action. To trigger a **WantAgent**, you can either call **wantAgent.trigger** to trigger it directly or add it to a notification so that it will be triggered when users tap the notification. + +You can use a **WantAgent** in a notification to start an ability or publish a common event. + +### When to Use +Start another ability through a **WantAgent**. + +### Available APIs +| API | Description| +| ---------------------------------------------------------------------------------------------- | ----------- | +| wantAgent.getWantAgentInfo(info: WantAgentInfo, callback: AsyncCallback\) | Creates a **WantAgent** object. This API uses an asynchronous callback to return the result.| +| wantAgent.getWantAgent(info: WantAgentInfo): Promise\; | Creates a **WantAgent** object. This API uses a promise to return the result.| +| commonEvent.trigger(agent: WantAgent, triggerInfo: TriggerInfo, callback?: Callback\) | Triggers a **WantAgent**.| + +### How to Develop +1. Import the **WantAgent** module. + +```javascript +import wantAgent from '@ohos.wantAgent'; +``` + +2. Create a **WantAgentInfo** object. For details about the data types and parameters of **WantAgentInfo**, see [WantAgent Module](../reference/apis/js-apis-wantAgent.md#wantagentinfo). + +```javascript +private wantAgentObj = null // Save the WantAgent object created. It will be used to complete the trigger operations. + +//wantAgentInfo +var wantAgentInfo = { + wants: [ + { + deviceId: "", + bundleName: "com.example.test", + abilityName: "com.example.test.MainAbility", + action: "", + entities: [], + uri: "", + parameters: {} + } + ], + operationType: OperationType.START_ABILITY, + requestCode: 0, + wantAgentFlags:[WantAgentFlags.CONSTANT_FLAG] +} +``` + +3. Create a **WantAgent** object and save the returned **wantAgentObj** for subsequent trigger operations. + +```javascript +// Create a WantAgent object. +wantAgent.getWantAgent(wantAgentInfo, (err, wantAgentObj) => { + if (err.code) { + console.error("[WantAgent]getWantAgent err=" + JSON.stringify(err)) + } else { + console.log("[WantAgent]getWantAgent success") + this.wantAgentObj = wantAgentObj + } +}) +``` + +4. Trigger the **WantAgent**. + +``` +// Trigger the WantAgent. +var triggerInfo = { + code:0 +} +wantAgent.trigger(wantAgentObj, triggerInfo, (completeData) => { + console.log("[WantAgent]getWantAgent success, completeData: ", + JSON.stringify(completeData)) +}) +``` diff --git a/en/application-dev/background-task-management/background-task-dev-guide.md b/en/application-dev/background-task-management/background-task-dev-guide.md index c504299cc8de51b6a992545fb939154cb5365a82..c96dfca665cf33065c35a7351786fec35a02654b 100644 --- a/en/application-dev/background-task-management/background-task-dev-guide.md +++ b/en/application-dev/background-task-management/background-task-dev-guide.md @@ -36,12 +36,12 @@ import backgroundTaskManager from '@ohos.backgroundTaskManager'; ```js import backgroundTaskManager from '@ohos.backgroundTaskManager'; - + let myReason = 'test requestSuspendDelay'; let delayInfo = backgroundTaskManager.requestSuspendDelay(myReason, () => { console.info("Request suspension delay will time out."); }); - + var id = delayInfo.requestId;console.info("requestId is: " + id); ``` @@ -106,36 +106,53 @@ ohos.permission.KEEP_BACKGROUND_RUNNING | function stopBackgroundRunning(context: Context, callback: AsyncCallback<void>): void;
function stopBackgroundRunning(context: Context): Promise<void>; | Cancels the continuous task.| -For details about **WantAgent**, see [WantAgent](../reference/apis/js-apis-notification.md#WantAgent). - +For details about **wantAgent**, see [WantAgent](../reference/apis/js-apis-wantAgent.md). **Table 4** Background modes -| Name| ID Value| Description| -| -------- | -------- | -------- | -| DATA_TRANSFER | 1 | Data transfer.| -| AUDIO_PLAYBACK | 2 | Audio playback.| -| AUDIO_RECORDING | 3 | Audio recording.| -| LOCATION | 4 | Positioning and navigation.| -| BLUETOOTH_INTERACTION | 5 | Bluetooth-related task.| -| MULTI_DEVICE_CONNECTION | 6 | Multi-device connection.| -| WIFI_INTERACTION | 7 | WLAN-related task (reserved).| -| VOIP | 8 | Voice and video call (reserved).| -| TASK_KEEPING | 9 | Computing task (for PC only).| + +| Name| ID Value| Description| Item| +| -------- | -------- | -------- | -------- | +| DATA_TRANSFER | 1 | Data transfer.| dataTransfer | +| AUDIO_PLAYBACK | 2 | Audio playback.| audioPlayback | +| AUDIO_RECORDING | 3 | Audio recording.| audioRecording | +| LOCATION | 4 | Positioning and navigation.| location | +| BLUETOOTH_INTERACTION | 5 | Bluetooth-related task.| bluetoothInteraction | +| MULTI_DEVICE_CONNECTION | 6 | Multi-device connection.| multiDeviceConnection | +| WIFI_INTERACTION | 7 | WLAN-related task (reserved).| wifiInteraction | +| VOIP | 8 | Voice and video call (reserved).| voip | +| TASK_KEEPING | 9 | Computing task (for specific devices only).| taskKeeping | ## How to Develop -1. Declare the continuous task permission in the **config.json** file. +1. Configure the continuous task permission and background mode type in the **config.json** file, with the ability type set to **service**. ```json "module": { - "package": "com.example.myapplication", - ..., - "reqPermissions": [ - { - "name": "ohos.permission.KEEP_BACKGROUND_RUNNING" - } - ] + "package": "com.example.myapplication", + + "abilities": [ + + { + "backgroundModes": [ + "dataTransfer", + "location", + + ], + + "type": "service" + } + ], + "defPermissions": [ + { + "name": "ohos.permission.KEEP_BACKGROUND_RUNNING" + } + ], + "reqPermissions": [ + { + "name": "ohos.permission.KEEP_BACKGROUND_RUNNING" + } + ] } ``` @@ -174,13 +191,13 @@ For details about **WantAgent**, see [WantAgent](../reference/apis/js-apis-notif ```js import backgroundTaskManager from '@ohos.backgroundTaskManager'; import featureAbility from '@ohos.ability.featureAbility'; - + backgroundTaskManager.stopBackgroundRunning(featureAbility.getContext()).then(() => { console.info("Operation succeeded"); }).catch((err) => { console.error("Operation failed Cause: " + err); }); - + ``` ## Development Examples diff --git a/en/application-dev/background-task-management/background-task-overview.md b/en/application-dev/background-task-management/background-task-overview.md index 37db9e3dbbb04532b2a724d07d1f75b54ea89628..5062447a9c9491ee0854963f4360c610fb2815f6 100644 --- a/en/application-dev/background-task-management/background-task-overview.md +++ b/en/application-dev/background-task-management/background-task-overview.md @@ -28,9 +28,9 @@ Adhere to the following constraints and rules when using transient tasks: - **When to request**: An application can request a transient task only when it is running in the foreground or before it is suspended in the background. Otherwise, the application may be suspended, resulting in request failure. By default, an application has 6–12 seconds of running time (subject to the application scenario) before it is suspended in the background. -- **Timeout**: The system notifies the application of the suspension delay timeout by using a callback. The application must then cancel the delayed suspension or apply for delayed suspension again. Otherwise, the application will be forcibly suspended. +- **Timeout**: If a suspension delay is about to time out, the system notifies the application of the timeout by using a callback. The application must then cancel the delayed suspension. Otherwise, the application will be forcibly terminated. -- **When to cancel**: The requesting application shall cancel the request when the transient task is complete. If the request is forcibly canceled by the system, the time frame allowed for the application to run in the background will be affected. +- **When to cancel**: The requesting application shall proactively cancel the request when the transient task is complete, rather than waiting for a system callback. Otherwise, the time frame allowed for the application to run in the background will be affected. - **Quota mechanism**: To prevent abuse of the keepalive, each application has a certain quota every day (dynamically adjusted based on user habits). After using up the quota, an application cannot request transient tasks. Therefore, applications should cancel their request immediately after the transient tasks are complete, to avoid quota consumption. (Note: The quota refers to the requested duration and does not include the time when the application runs in the background.) @@ -52,7 +52,7 @@ OpenHarmony provides 9 background modes for services that require continuous tas | multiDeviceConnection | Distributed interconnection| A distributed task is running.| | | wifiInteraction | WLAN transmission| A WLAN-related task is running.| System API, which is available only to system applications| | voip | Voice and video calls over VoIP| A call-related task is running.| System API, which is available only to system applications| -| taskKeeping | Computing task| A computing task is running| PC-specific, valid only on PCs| +| taskKeeping | Computing task| A computing task is running| Effective only for specific devices| ### Restrictions on Using Continuous Tasks - If a user triggers a perceivable task, such as broadcasting and navigation, the corresponding background mode is triggered. When the task is started, the system forcibly displays a notification to the user. diff --git a/en/application-dev/notification/Readme-EN.md b/en/application-dev/notification/Readme-EN.md new file mode 100644 index 0000000000000000000000000000000000000000..2a0df0e3a4f6f2bbc27739a97b44df5f72569de5 --- /dev/null +++ b/en/application-dev/notification/Readme-EN.md @@ -0,0 +1,17 @@ +# Common Event and Notification + +[Common Event and Notification Overview](notification-brief.md) + +### Common Event + +* [Common Event Development](common-event.md) + +### Notification + +* [Notification Development](notification.md) + + + +### Debugging Tools + +* [Debugging Assistant Usage](assistant-guidelines.md) diff --git a/en/application-dev/notification/assistant-guidelines.md b/en/application-dev/notification/assistant-guidelines.md new file mode 100644 index 0000000000000000000000000000000000000000..35d3eaeaaddd023861056fe819fbe4016c59bb01 --- /dev/null +++ b/en/application-dev/notification/assistant-guidelines.md @@ -0,0 +1,134 @@ +# Debugging Assistant Usage + +The common event and notification module provides debugging tools to facilitate your application development. With these tools, you can view common event and notification information, publish common events, and more. These tools have been integrated with the system. You can run related commands directly in the shell. + +### cem Debugging Assistant + +##### publish + +* Functionality + + Publishes a common event. + +* Usage + + `cem publish []` + + The table below describes the available options. + + | Option | Description | + | ------------ | ------------------------------------------ | + | -e/--event | Indicates the name of the common event to publish. Mandatory. | + | -s/--sticky | Indicates that the common event to publish is sticky. Optional. By default, non-sticky events are published.| + | -o/--ordered | Indicates that the common event to publish is ordered. Optional. By default, non-ordered events are published. | + | -c/--code | Indicates the result code of the common event. Optional. | + | -d/--data | Indicates the data carried in the common event. Optional. | + | -h/--help | Indicates the help Information | + +* Example + + `cem publish --event "testevent"` + + Publish a common event named **testevent**. + + ![cem-publish-event](figures/cem-publish-event.png) + + + + `cem publish -e "testevent" -s -o -c 100 -d "this is data" ` + + Publish a sticky, ordered common event named **testevent**. The result code of the event is **100** and the data carried is **this is data**. + + ![cem-publish-all](figures/cem-publish-all.png) + +##### dump + +* Functionality + + Displays information about common events. + +* Usage + + `cem dump []` + + The table below describes the available options. + + | Option | Description | + | ---------- | -------------------------------------------- | + | -a/--all | Displays information about all common events that have been sent since system startup.| + | -e/--event | Displays information about a specific event. | + | -h/--help | Displays the help information. | + +* Example + +​ `cem dump -e "testevent"` + +​ Display information about the common event testevent. + +​ ![cem-dump-e](figures/cem-dump-e.png) + +##### help + +* Functionality + + Displays the help information. + +* Usage + + `cem help` + +* Example + + ![cem-help](figures/cem-help.png) + + + +### anm Debugging Assistant + +##### dump + +* Functionality + + Displays information about notifications. + +* Usage + + `anm dump []` + + The table below describes the available options. + + | Option | Description | + | ---------------- | ---------------------------------------- | + | -A/--active | Displays information about all active notifications. | + | -R/--recent | Displays information about the recent notifications. | + | -D/--distributed | Displays information about distributed notifications from other devices. | + | --setRecentCount | Indicates the number of the cached recent notifications to be displayed. Optional.| + | -h/--help | Displays the help information. | + +* Example + + `anm dump -A` + + Displays information about all active notifications. + + ![anm-dump-A](figures/anm-dump-A.png) + + + + `anm dump --setRecentCount 10` + + Set the number of the cached recent notifications to be displayed to 10. + +##### help + +* Functionality + + Displays the help information. + +* Usage + + `anm help` + +* Example + + ![anm-help](figures/anm-help.png) diff --git a/en/application-dev/notification/common-event.md b/en/application-dev/notification/common-event.md new file mode 100644 index 0000000000000000000000000000000000000000..cd139f0700d01475ad7f6fb358744e52ffafb913 --- /dev/null +++ b/en/application-dev/notification/common-event.md @@ -0,0 +1,179 @@ +# Common Event Development +### Introduction +OpenHarmony provides a 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: The system sends an event based on system policies to the apps that have subscribed to this event when it occurs. This type of event is typically system events published by key system services, such as HAP installation, update, and uninstallation. + ++ Custom common event: customized by applications to implement cross-application event communication. + +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. + +## Common Event Subscription Development + +### When to Use +You can create a subscriber object to subscribe to a common event to obtain the parameters passed in the event. Certain system common events require specific permissions to subscribe to. For details, see [Required Permissions](../reference/apis/js-apis-commonEvent.md). + +### Available APIs +| API | Description| +| ---------------------------------------------------------------------------------------------- | ----------- | +| commonEvent.createSubscriber(subscribeInfo: CommonEventSubscribeInfo, callback: AsyncCallback) | Creates a subscriber. This API uses a callback to return the result.| +| commonEvent.createSubscriber(subscribeInfo: CommonEventSubscribeInfo) | Creates a subscriber. This API uses a promise to return the result. | +| commonEvent.subscribe(subscriber: CommonEventSubscriber, callback: AsyncCallback) | Subscribes to common events.| + +### How to Develop +1. Import the **commonEvent** module. + +```javascript +import commonEvent from '@ohos.commonEvent'; +``` + +2. Create a **subscribeInfo** object. For details about the data types and parameters of the object, see [CommonEventSubscribeInfo](../reference/apis/js-apis-commonEvent.md#commoneventsubscribeinfo). + +```javascript +private subscriber = null // Used to save the created subscriber object for subsequent subscription and unsubscription. + +// Subscriber information +var subscribeInfo = { + events: ["event"], +} +``` + +3. Create a subscriber object and save the returned object for subsequent operations such as subscription and unsubscription. + +```javascript +// Callback for subscriber creation. +commonEvent.createSubscriber(subscribeInfo, (err, subscriber) => { + if (err.code) { + console.error("[CommonEvent]CreateSubscriberCallBack err=" + JSON.stringify(err)) + } else { + console.log("[CommonEvent]CreateSubscriber") + this.subscriber = subscriber + this.result = "Create subscriber succeed" + } +}) +``` + +4. Create a subscription callback, which is triggered when an event is received. The data returned by 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-commonEvent.md#commoneventdata). + +```javascript +// Callback for common event subscription. +if (this.subscriber != null) { + commonEvent.subscribe(this.subscriber, (err, data) => { + if (err.code) { + console.error("[CommonEvent]SubscribeCallBack err=" + JSON.stringify(err)) + } else { + console.log("[CommonEvent]SubscribeCallBack data=" + JSON.stringify(data)) + this.result = "receive, event = " + data.event + ", data = " + data.data + ", code = " + data.code + } + }) + this.result = "Subscribe succeed" +} else { + prompt.showToast({ message: "Need create subscriber" }) +} +``` + +## Public Event Publishing Development + +### When to Use +You can use the **publish** APIs to publish a custom common event, which can carry data for subscribers to parse and process. + +### Available APIs +| API | Description| +| ---------------------------------- | ------ | +| commonEvent.publish(event: string, callback: AsyncCallback) | Publishes a common event.| +| commonEvent.publish(event: string, options: CommonEventPublishData, callback: AsyncCallback) | Publishes a common event with given attributes.| + +### How to Develop +#### Development for Publishing a Common Event +1. Import the **commonEvent** module. + +```javascript +import commonEvent from '@ohos.commonEvent'; +``` + +2. Pass in the common event name and callback, and publish the event. + +```javascript +// Publish a common event. +commonEvent.publish("event", (err) => { + if (err.code) { + console.error("[CommonEvent]PublishCallBack err=" + JSON.stringify(err)) + } else { + console.info("[CommonEvent]Publish1") + } +}) +``` + +#### Development for Publishing a Common Event with Given Attributes +1. Import the **commonEvent** module. + +```javascript +import commonEvent from '@ohos.commonEvent' +``` + +2. Define attributes of the common event to publish. For details about the data types and parameters in the data to publish, see [CommonEventPublishData](../reference/apis/js-apis-commonEvent.md#commoneventpublishdata). + +```javascript +// Attributes of a common event. +var 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. + +```javascript +// Publish a common event. +commonEvent.publish("event", options, (err) => { + if (err.code) { + console.error("[CommonEvent]PublishCallBack err=" + JSON.stringify(err)) + } else { + console.info("[CommonEvent]Publish2") + } +}) +``` + +## Common Event Unsubscription Development + +### When to Use +You can use the **unsubscribe** API to unsubscribe from a common event. + +### Available APIs +| API | Description| +| ---------------------------------- | ------ | +| commonEvent.unsubscribe(subscriber: CommonEventSubscriber, callback?: AsyncCallback) | Unsubscribes from a common event.| + +### How to Develop +1. Import the **commonEvent** module. + +```javascript +import commonEvent from '@ohos.commonEvent'; +``` + +2. Subscribe to a common event by following instructions in [Common Event Subscription Development](#Common-Event-Subscription-Development). +3. Invoke the **unsubscribe** API in **CommonEvent** to unsubscribe from the common event. + +```javascript +if (this.subscriber != null) { + commonEvent.unsubscribe(this.subscriber, (err) => { + if (err.code) { + console.error("[CommonEvent]UnsubscribeCallBack err=" + JSON.stringify(err)) + } else { + console.log("[CommonEvent]Unsubscribe") + this.subscriber = null + this.result = "Unsubscribe succeed" + } + }) +} +``` + +## Development Example + +The following sample is provided to help you better understand how to use the common event functionality: + +- [CommonEvent](https://gitee.com/openharmony/app_samples/tree/master/ability/CommonEvent) + +This sample shows how to use **CommonEvent** APIs in Extended TypeScript (eTS) to create subscribers and subscribe to, publish, and unsubscribe from common events. diff --git a/en/application-dev/notification/figures/anm-dump-A.png b/en/application-dev/notification/figures/anm-dump-A.png new file mode 100644 index 0000000000000000000000000000000000000000..368e6f2d810976486e786a4c8f0603a87ad48540 Binary files /dev/null and b/en/application-dev/notification/figures/anm-dump-A.png differ diff --git a/en/application-dev/notification/figures/anm-help.png b/en/application-dev/notification/figures/anm-help.png new file mode 100644 index 0000000000000000000000000000000000000000..d80ac8e76a70c2be383f0a05a12e3e707dcf242b Binary files /dev/null and b/en/application-dev/notification/figures/anm-help.png differ diff --git a/en/application-dev/notification/figures/ans.png b/en/application-dev/notification/figures/ans.png new file mode 100644 index 0000000000000000000000000000000000000000..8be552d2acedbef962326365fb2d19ded3838c14 Binary files /dev/null and b/en/application-dev/notification/figures/ans.png differ diff --git a/en/application-dev/notification/figures/cem-dump-e.png b/en/application-dev/notification/figures/cem-dump-e.png new file mode 100644 index 0000000000000000000000000000000000000000..c2422ba0e51011174c333985ad7647f170e0f126 Binary files /dev/null and b/en/application-dev/notification/figures/cem-dump-e.png differ diff --git a/en/application-dev/notification/figures/cem-help.png b/en/application-dev/notification/figures/cem-help.png new file mode 100644 index 0000000000000000000000000000000000000000..8ca4bc0605f9c1f75a8cb45f8ab77c9c5d6f04e4 Binary files /dev/null and b/en/application-dev/notification/figures/cem-help.png differ diff --git a/en/application-dev/notification/figures/cem-publish-all.png b/en/application-dev/notification/figures/cem-publish-all.png new file mode 100644 index 0000000000000000000000000000000000000000..99526e1f7245d101914354e2a89d5e97d710c27f Binary files /dev/null and b/en/application-dev/notification/figures/cem-publish-all.png differ diff --git a/en/application-dev/notification/figures/cem-publish-event.png b/en/application-dev/notification/figures/cem-publish-event.png new file mode 100644 index 0000000000000000000000000000000000000000..f0ca7e73093f1be72c743bd7c08467f11e2a0e05 Binary files /dev/null and b/en/application-dev/notification/figures/cem-publish-event.png differ diff --git a/en/application-dev/notification/figures/ces.png b/en/application-dev/notification/figures/ces.png new file mode 100644 index 0000000000000000000000000000000000000000..b1aa5438a19ac79899e0f45791f3e1a79e4242dc Binary files /dev/null and b/en/application-dev/notification/figures/ces.png differ diff --git a/en/application-dev/notification/figures/notification.png b/en/application-dev/notification/figures/notification.png new file mode 100644 index 0000000000000000000000000000000000000000..93029e29a91d6dd435a9a768cb79c5fc48184565 Binary files /dev/null and b/en/application-dev/notification/figures/notification.png differ diff --git a/en/application-dev/notification/notification-brief.md b/en/application-dev/notification/notification-brief.md new file mode 100644 index 0000000000000000000000000000000000000000..8be39b2cc823398e4572a77469909f9fd06e2a5f --- /dev/null +++ b/en/application-dev/notification/notification-brief.md @@ -0,0 +1,23 @@ +# Common Event and Notification Overview + +The common event and notification module enables applications to publish messages to other applications, and receive messages from the system or other applications. These messages can be news push messages, advertisement notifications, or warning information. + +Common Event Service (CES) enables applications to publish, subscribe to, and unsubscribe from common events. Based on the sender type, common events are classified into system common events and custom common events. + +![ces](figures/ces.png) + +- System common event: sent by the system based on system policies to the applications that have subscribed to the event. This type of event includes the screen-on/off events that the users are aware of and the system events published by key system services, such as USB device attachment or detachment, network connection, and system update events. + +- Custom common event: customized by applications to be received by specific subscribers. This type of event is usually related to the service logic of the sender applications. + + The Advanced Notification Service (ANS) enables applications to publish notifications. Below are some typical use cases for publishing notifications: + + - Display received SMS messages and instant messages. + + - Display push messages of applications, such as advertisements, version updates, and news notifications. + + - Display ongoing events, such as music playback, navigation information, and download progress. + +Notifications are displayed in the notification panel. Uses can delete a notification or click the notification to trigger predefined actions. + +![ans](figures/ans.png) diff --git a/en/application-dev/notification/notification.md b/en/application-dev/notification/notification.md new file mode 100644 index 0000000000000000000000000000000000000000..a8822563cd639844817b860fb5760ee605edb307 --- /dev/null +++ b/en/application-dev/notification/notification.md @@ -0,0 +1,248 @@ + + +# Notification Development + +## When to Use + +OpenHarmony uses the Advanced Notification Service (ANS) to manage notifications, with support for various notification types, including text, long text, multi-text, image, social, and media. All system services and applications can send notifications through the notification API. Users can view all notifications on the system UI. + +Below are some typical use cases for notifications: + +- Display received SMS messages and instant messages. +- Display push messages of applications, such as advertisements and version updates. +- Display ongoing events, such as navigation information and download progress. + + + +## Notification Service Process + +The notification service process involves the ANS subsystem, notification sender, and notification subscriber. + +A notification is generated by the notification sender and sent to the ANS through inter-process communication (IPC). The ANS then distributes the notification to the notification subscriber. + +System applications also support notification-related configuration options, such as switches. The system configuration initiates a configuration request and sends the request to the ANS for storage in the memory and database. + +![1648113187545](figures/notification.png) + + + +## Available APIs + +Certain APIs can be invoked only by system applications that have been granted the **SystemCapability.Notification.Notification** permission. The APIs use either a callback or promise to return the result. The tables below list the APIs that use a callback, which provide same functions as their counterparts that use a promise. For details about the APIs, see the [API document](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-notification.md). + +**Table 1** APIs for notification enabling + +| API | Description | +| ------------------------------------------------------------ | ---------------- | +| isNotificationEnabled(bundle: BundleOption, callback: AsyncCallback): void | Checks whether notification is enabled.| +| enableNotification(bundle: BundleOption, enable: boolean, callback: AsyncCallback): void | Sets whether to enable notification. | + +If the notification function of an application is disabled, it cannot send notifications. + + + +**Table 2** APIs for notification subscription + +| API | Description | +| ------------------------------------------------------------ | ---------------- | +| subscribe(subscriber: NotificationSubscriber, info: NotificationSubscribeInfo, callback: AsyncCallback): void | Subscribes to a notification with the subscription information specified.| +| subscribe(subscriber: NotificationSubscriber, callback: AsyncCallback): void | Subscribes to all notifications. | +| unsubscribe(subscriber: NotificationSubscriber, callback: AsyncCallback): void | Unsubscribes from a notification. | + +The subscription APIs support subscription to all notifications or notifications from specific applications. + + + +**Table 3** Notification subscription callbacks + +| API | Description | +| ------------------------------------------------ | ---------------- | +| onConsume?:(data: SubscribeCallbackData) => void | Callback for receiving notifications. | +| onCancel?:(data: SubscribeCallbackData) => void | Callback for canceling notifications. | +| onUpdate?:(data: NotificationSortingMap) => void | Callback for notification sorting updates.| +| onConnect?:() => void; | Callback for subscription. | +| onDisconnect?:() => void; | Callback for unsubscription. | + + + +**Table 4** APIs for notification sending + +| API | Description | +| ------------------------------------------------------------ | ------------------------ | +| publish(request: NotificationRequest, callback: AsyncCallback): void | Publishes a notification. | +| publish(request: NotificationRequest, userId: number, callback: AsyncCallback): void | Publishes a notification to the specified user. | +| cancel(id: number, label: string, callback: AsyncCallback): void | Cancels a specified notification. | +| cancelAll(callback: AsyncCallback): void; | Cancels all notifications published by the application.| + +The **publish** API that carries **userId** can be used to publish notifications to subscribers of a specified user. + + + +## Development Guidelines + +The notification development process generally involves three aspects: subscribing to notifications, enabling the notification feature, and publishing notifications. + +### Modules to Import + +```js +import Notification from '@ohos.notification'; +``` + + + +### Subscribing to Notifications + +The notification recipient preferentially initiates a notification subscription request to the notification subsystem. + +```js +var subscriber = { + onConsume: function (data) { + let req = data.request; + console.info('===>onConsume callback req.id: ' + req.id); + }, + onCancel: function (data) { + let req = data.request; + console.info('===>onCancel callback req.id: : ' + req.id); + }, + onUpdate: function (data) { + console.info('===>onUpdate in test===>'); + }, + onConnect: function () { + console.info('===>onConnect in test===>'); + }, + onDisconnect: function () { + console.info('===>onDisConnect in test===>'); + }, + onDestroy: function () { + console.info('===>onDestroy in test===>'); + }, + }; + + Notification.subscribe(subscriber, (err, data) => { // This API uses an asynchronous callback to return the result. + if (err.code) { + console.error('===>failed to subscribe because ' + JSON.stringify(err)); + return; + } + console.info('===>subscribeTest success : ' + JSON.stringify(data)); + }); +``` + + + +### Publishing Notifications + +Before publishing a notification, make sure the notification feature is enabled for your application. This feature is disabled by default and can be enabled in the notification settings. + +##### Publishing Notifications + +To publish a notification, create a **NotificationRequest** object and set attributes such as the notification type, title, and content. In the following examples, a normal text notification and a notification containing a **WantAgent** are being published. + +Normal Text Notification + +```js +// Create a NotificationRequest object. +var notificationRequest = { + id: 1, + content: { + contentType: Notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT, + normal: { + title: "test_title", + text: "test_text", + additionalText: "test_additionalText" + } + } +} + +// Publish the notification. +Notification.publish(notificationRequest) .then((data) => { + console.info('===>publish promise success req.id : ' + notificationRequest.id); +}).catch((err) => { + console.error('===>publish promise failed because ' + JSON.stringify(err)); +}); +``` + + + +Notification Containing WantAgent. + +For details about how to use **WantAgent**, see [WantAgent Development](https://gitee.com/openharmony/docs/blob/master/en/application-dev/ability/wantagent.md). + +- Create a **WantAgent** object. + +```js +import wantAgent from '@ohos.wantAgent'; + +// WantAgentInfo object +var wantAgentInfo = { + wants: [ + { + bundleName: 'ohos.samples.eTSNotification', + abilityName: 'ohos.samples.eTSNotification.MainAbility', + } + ], + operationType: wantAgent.OperationType.START_ABILITY, + requestCode: 0, + wantAgentFlags:[wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG] +} + +// WantAgent object +var WantAgent; + +// getWantAgent callback +function getWantAgentCallback(err, data) { + console.info("===>getWantAgentCallback===>"); + if (err.code == 0) { + WantAgent = data; + } else { + console.info('----getWantAgent failed!----'); + } +} + +// Obtain the WantAgent object. +wantAgent.getWantAgent(wantAgentInfo, getWantAgentCallback) +``` + +- Publish the notification. + +```js +// Create a NotificationRequest object. +var notificationRequest = { + content: { + contentType: Notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT, + normal: { + title: "AceApplication_Title", + text: "AceApplication_Text", + additionalText: "AceApplication_AdditionalText" + }, + }, + id: 1, + label: 'TEST', + wantAgent: WantAgent, + slotType: Notification.SlotType.OTHER_TYPES, + deliveryTime: new Date().getTime() +} + +// Publish the notification. +Notification.publish(notificationRequest) .then((data) => { + console.info('===>publish promise success req.id : ' + notificationRequest.id); +}).catch((err) => { + console.error('===>publish promise failed because ' + JSON.stringify(err)); +}); +``` + + + +- Cancel the notification. + +An application can cancel a single notification or all notifications. An application can cancel only the notifications published by itself. + +```js +// cancel callback +function cancelCallback(err) { + console.info("===>cancelCallback===>"); +} + +Notification.cancel(1, "label", cancelCallback) +``` + + diff --git a/en/application-dev/notification/public_sys-resources/icon-caution.gif b/en/application-dev/notification/public_sys-resources/icon-caution.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 Binary files /dev/null and b/en/application-dev/notification/public_sys-resources/icon-caution.gif differ diff --git a/en/application-dev/notification/public_sys-resources/icon-danger.gif b/en/application-dev/notification/public_sys-resources/icon-danger.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 Binary files /dev/null and b/en/application-dev/notification/public_sys-resources/icon-danger.gif differ diff --git a/en/application-dev/notification/public_sys-resources/icon-note.gif b/en/application-dev/notification/public_sys-resources/icon-note.gif new file mode 100644 index 0000000000000000000000000000000000000000..6314297e45c1de184204098efd4814d6dc8b1cda Binary files /dev/null and b/en/application-dev/notification/public_sys-resources/icon-note.gif differ diff --git a/en/application-dev/notification/public_sys-resources/icon-notice.gif b/en/application-dev/notification/public_sys-resources/icon-notice.gif new file mode 100644 index 0000000000000000000000000000000000000000..86024f61b691400bea99e5b1f506d9d9aef36e27 Binary files /dev/null and b/en/application-dev/notification/public_sys-resources/icon-notice.gif differ diff --git a/en/application-dev/notification/public_sys-resources/icon-tip.gif b/en/application-dev/notification/public_sys-resources/icon-tip.gif new file mode 100644 index 0000000000000000000000000000000000000000..93aa72053b510e456b149f36a0972703ea9999b7 Binary files /dev/null and b/en/application-dev/notification/public_sys-resources/icon-tip.gif differ diff --git a/en/application-dev/notification/public_sys-resources/icon-warning.gif b/en/application-dev/notification/public_sys-resources/icon-warning.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 Binary files /dev/null and b/en/application-dev/notification/public_sys-resources/icon-warning.gif differ diff --git a/en/application-dev/quick-start/package-structure.md b/en/application-dev/quick-start/package-structure.md index b9e4caa013ad468f43ca0a7a3ee486623018a028..1b3d88f8b378aa84ce9d571c97320b5b6c861494 100644 --- a/en/application-dev/quick-start/package-structure.md +++ b/en/application-dev/quick-start/package-structure.md @@ -1,10 +1,24 @@ -# Directory Structure -In an application development project, you need to declare the package structure of the application in the **config.json** file. -The following is an example of the configuration file: +# Application Package Structure Configuration File -``` +In an application development project, you need to declare the package structure of the application in the **config.json** file. + +## Internal Structure of the config.json File + +The **config.json** file consists of three mandatory tags, namely, **app**, **deviceConfig**, and ***module***. See Table 1 for details. + +Table 1 Internal structure of the config.json file + +| Tag | Description | Data Type| Default| +| ------------ | ------------------------------------------------------------ | -------- | ---------- | +| app | Global configuration of an application. Different HAP files of the same application must use the same **app** configuration. For details, see [Internal Structure of the app Tag](#Internal-structure-of-the-app-tag).| Object | No | +| deviceConfig | Application configuration applied to a specific type of device. For details, see [Internal Structure of the deviceconfig Tag](#Internal-structure-of-the-deviceconfig-tag).| Object | No | +| module | Configuration of a HAP file. The ***module*** configuration is valid only for the current HAP file. For details, see [Internal Structure of the module Tag](#Internal-structure-of-the-module-tag).| Object | No | + +Example of config.json: + +```json { "app": { "bundleName": "com.example.myapplication", @@ -27,7 +41,6 @@ The following is an example of the configuration file: "default" ], "distro": { - "deliveryWithInstall": true, "moduleName": "entry", "moduleType": "entry" }, @@ -67,9 +80,681 @@ The following is an example of the configuration file: } ``` -Note the following when declaring the package structure: +### Internal Structure of the app Tag + +The **app** tag contains the global configuration information of the application. For details about the internal structure, see Table 2. + +Table 2 Internal structure of the app tag + +| Attribute | Description | Data Type| Default | +| ---------- | ------------------------------------------------------------ | -------- | ------------------ | +| bundleName | Bundle name of the application. It uniquely identifies the application. The bundle name can contain only letters, digits, underscores (_), and periods (.). It must start with a letter. The value is a string with 7 to 127 bytes of a reverse domain name, for example, **com.example.myapplication**. It is recommended that the first level be the domain name suffix "com" and the second level be the vendor/individual name. More levels are also accepted.| String | No | +| vendor | Description of the application vendor. The value is a string with a maximum of 255 bytes. | String | Yes (initial value: left empty)| +| version | Version information of the application. For details, see Table 3. | Object | No | +| apiVersion | OpenHarmony API version on which the application depends. For details, see Table 4. | Object | Yes (initial value: left empty)| + +Table 3 Internal structure of version + +| Attribute | Description | Data Type| Default | +| ------------------------ | ------------------------------------------------------------ | -------- | -------------------------- | +| name | Application version number visible to users. The value can be customized and cannot exceed 127 bytes. The customization rules are as follows:
API 5 and earlier versions: A three-segment version number is recommended, for example, A.B.C (also compatible with A.B). In the version number, A, B, and C are integers ranging from 0 to 999. Other formats are not supported.
A indicates the major version number.
B indicates the minor version number.
C indicates the patch version number.
API 6 and later versions: A four-segment version number is recommended, for example, A.B.C.D. In the version number, A, B, and C are integers ranging from 0 to 99, and D is an integer ranging from 0 to 999.
A indicates the major version number.
B indicates the minor version number.
C indicates the feature version number.
D indicates the patch version number.| Number | No | +| code | Application version number used only for application management by OpenHarmony. This version number is not visible to users of the application. The value rules are as follows:
API 5 and earlier versions: It is a non-negative integer less than 32 bits in binary mode, converted from the value of version.name as follows: The conversion rules are as follows:
Value of **code** = A * 1,000,000 + B * 1,000 + C. For example, if the value of **version.name** is 2.2.1, the value of **code** is 2002001.
API 6 and later versions: The value of **code** is not associated with the value of **version.name** and can be customized. The value is a non-negative integer ranging from 2 to 31. Note that the value must be updated each time the application version is updated. The value for a later version must be greater than that for an earlier version.| Number | No | +| minCompatibleVersionCode | Minimum compatible version of the application. It is used to check whether the application is compatible with the version on other devices in the cross-device scenario.
The value rules are the same as those of **version.code**.| Number | No (initial value: **code** attribute value)| + +Table 4 Internal structure of apiVersion + +| Attribute | Description | Data Type| Default| +| ----------- | ----------------------------------------------------------- | -------- | ---------- | +| compatible | Minimum API version required for running the application. The value ranges from 0 to 2147483647. | Integer | Yes | +| target | Target API version required for running the application. The value ranges from 0 to 2147483647.| Integer | Yes | +| releaseType | Type of the target API version required for running the application. | String | Yes | + +Example of the app tag structure: + +```json +"app": { + "bundleName": "com.example.myapplication", + "vendor": "example", + "version": { + "code": 1, + "name": "1.0" + }, + "apiVersion": { + "compatible": 4, + "target": 5, + "releaseType": "Beta1" + } + } +``` + +### Internal Structure of the deviceConfig Tag + +The **deviceConfig** tag contains the application configuration information on the device, including attributes such as **default**, **tv**, **car**, **wearable**, and **liteWearable**. The **default** configuration applies to all types of devices. You need to declare the peculiar configuration of a specific device type in the associated sub-tag of this type. For details about the internal structure, see Table 5. + +Table 5 Internal structure of the deviceConfig tag + +| Attribute | Description | Data Type| Default | +| ------------ | ----------------------------------------------- | -------- | ------------------ | +| default | Application configuration applied to all types of devices. See Table 6. | Object | No | +| tablet | Application configuration specific to tablets. See Table 6. | Object | Yes (initial value: left empty)| +| tv | Application configuration specific to smart TVs. See Table 6. | Object | Yes (initial value: left empty)| +| car | Application configuration specific to head units. See Table 6. | Object | Yes (initial value: left empty)| +| wearable | Application configuration specific to wearables. See Table 6. | Object | Yes (initial value: left empty)| +| liteWearable | Application configuration specific to lite wearables. See Table 6.| Object | Yes (initial value: left empty)| + +For details about the internal structures of device attributes, see Table 6. + +Table 6 Internal structure of device attributes + +| Attribute | Description | Data Type| Default | +| ------------------ | ------------------------------------------------------------ | -------- | ----------------------- | +| 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. This attribute applies only to the default, tablet, smart TV, head unit, and wearable device types. The value can contain a maximum of 31 characters. | String | Yes | +| supportBackup | Whether the application supports backup and restoration. If this attribute is set to **false**, backup or restoration will not be performed for the application.
This attribute applies only to the default, tablet, smart TV, head unit, and wearable device type types. | Boolean | Yes (initial value: **false**)| +| compressNativeLibs | Whether the **libs** libraries are packaged in the HAP file after being compressed. If this attribute is set to **false**, the **libs** libraries are stored without being compressed and will be directly loaded during the installation of the HAP file.
This attribute applies only to the default, tablet, smart TV, head unit, and wearable device type types. | Boolean | Yes (initial value: **true**) | +| directLaunch | Whether the application can be started when the device is locked. If you want to start the application without unlocking the device, set this attribute to **true**. Devices running OpenHarmony do not support this attribute.| Boolean | Yes (initial value: **false**)| +| ark | Maple configuration. See Table 7. | Object | Yes (initial value: left empty) | +| network | Network security configuration. You can customize the network security settings of the application in the security statement of the configuration file without modifying the application code. See Table 9.| Object | Yes (initial value: left empty) | + +Table 7 Internal structure of the **ark** attribute + +| Attribute | Description | Data Type| Default | +| ---------- | -------------------------------- | -------- | ------------------------------ | +| reqVersion | Maple version required for the application. For details, see Table 8.| Object | No | +| flag | Type of the Maple application. | String | No (available options: **m**, **mo**, **z**).| + +Table 8 Internal structure of the reqVersion attribute + +| Attribute | Description | Data Type| Default| +| ---------- | --------------------------------------------------------- | -------- | ---------- | +| compatible | Minimum Maple version required for the application. The value is a 32-bit unsigned integer.| Integer | No | +| target | Type of the Maple application. The value is a 32-bit unsigned integer. | Integer | No | + +Table 9 Internal structure of the network attribute + +| Attribute | Description | Data Type| Default | +| ---------------- | ------------------------------------------------------------ | -------- | ----------------------- | +| cleartextTraffic | Whether to allow the application to use plaintext traffic, for example, plaintext HTTP traffic.
**true**: The application is allowed to use plaintext traffic.
**false**: The application is not allowed to use plaintext traffic.| Boolean | Yes (initial value: **false**)| +| securityConfig | Network security configuration of the application. For details, see Table 10. | Object | Yes (initial value: left empty) | + +Table 10 Internal structure of the securityConfig attribute + +| Attribute | Sub-attribute | Description | Data Type| Default | +| -------------- | ------------------ | ------------------------------------------------------------ | -------- | ---------------- | +| domainSettings | - | Security settings of the custom network domain. This attribute allows nested domains. To be more specific, the **domainSettings** object of a large domain can be nested with the **domainSettings** objects of small network domains.| Object| Yes (initial value: left empty)| +| | cleartextPermitted | Whether plaintext traffic can be transmitted in the custom network domain. If both **cleartextTraffic** and **security** are declared, whether plaintext traffic can be transmitted in the custom network domain is determined by the **cleartextPermitted** attribute.
**true**: Plaintext traffic can be transmitted.
**false**: Plaintext traffic cannot be transmitted.| Boolean| No | +| | domains | Domain name configuration. This attribute consists of the **subdomains** and **name** sub-attributes.
**subdomains** (boolean): specifies whether the domain name contains subdomains. If this sub-attribute is set to **true**, the domain naming convention applies to all related domains and subdomains (including the lower-level domains of the subdomains). Otherwise, the convention applies only to exact matches.
**name** (string): indicates the domain name.| Object array| No | + +Example of the deviceConfig tag structure: + +```json +"deviceConfig": { + "default": { + "process": "com.example.test.example", + "supportBackup": false, + "network": { + "cleartextTraffic": true, + "securityConfig": { + "domainSettings": { + "cleartextPermitted": true, + "domains": [ + { + "subdomains": true, + "name": "example.ohos.com" + } + ] + } + } + } + } +} +``` + +### Internal Structure of the module Tag + +The **module** tag contains the configuration information of the HAP file. For details about the internal structure, see Table 11. + +Table 11 Internal structure of the module tag + +| Attribute | Description | Data Type | Default | +| --------------- | ------------------------------------------------------------ | ---------- | ------------------------------------------------------------ | +| mainAbility | Ability displayed on the Service Center icon. When the resident process is started, the **mainAbility** is started.| String | No if any ability using the Page template exists | +| package | Structure name of the HAP file. The value must be unique in the application. The value is a string with a maximum of 127 bytes, in the reverse domain name notation. It is recommended that the value be the same as the project directory of the HAP file. This attribute applies only to the default, tablet, smart TV, head unit, and wearable device type types. | String | No | +| name | Class name of the HAP file. The value is in the reverse domain name notation. The prefix must be the same as the package name specified by the **package** label at the same level. The value can also start with a period (.). The value is a string with a maximum of 255 bytes.
This attribute applies only to the default, tablet, smart TV, head unit, and wearable device type types. | String | No | +| description | Description of the HAP file. The value is a string with a maximum of 255 bytes. If the value exceeds the limit or needs to support multiple languages, you can use a resource index to the description. This attribute applies only to the default, tablet, smart TV, head unit, and wearable device type types. | String | Yes (initial value: left empty) | +| supportedModes | Mode supported by the application. Currently, only the **drive** mode is defined. This attribute applies only to head units.| String array| Yes (initial value: left empty) | +| deviceType | Type of device on which the abilities can run. The device types predefined in the system include **tablet**, **tv**, **car**, **wearable**, and **liteWearable**. | String array| No | +| distro | Distribution description of the current HAP file. This attribute applies only to the default, tablet, smart TV, head unit, and wearable device type types. For details, see Table 12. | Object | No | +| metaData | Metadata of the HAP file. For details, see Table 13. | Object | Yes (initial value: left empty) | +| abilities | All abilities in the current module. The value is an array of objects, each of which represents a shortcut object. For details, see Table 17.| Object array | Yes (initial value: left empty) | +| js | A set of JS modules developed using the ArkUI framework. Each element in the set represents the information about a JS module. For details, see Table 22.| Object array | Yes (initial value: left empty) | +| shortcuts | Shortcut information of the application. The value is an array of objects, each of which represents a shortcut object. For details, see Table 25.| Object array | Yes (initial value: left empty) | +| reqPermissions | Permissions that the application applies for from the system before its running. For details, see Table 21. | Object array | Yes (initial value: left empty) | +| colorMode | Color mode of the application.
**dark**: Resources applicable for the dark mode are selected.
**light**: Resources applicable for the light mode are selected.
**auto**: Resources are selected based on the color mode of the system.
This attribute applies only to the default, tablet, smart TV, head unit, and wearable device type types. | String | Yes (initial value: **auto**) | +| distroFilter | Application distribution rules.
This attribute defines the rules for distributing HAP files based on different device specifications, so that precise matching can be performed when AppGallery distributes applications. Applications can be distributed by API version, screen shape, or screen resolution. During distribution, a unique HAP is determined based on the mapping between **deviceType** and these three factors. For details, see Table 29. | Object | Yes (initial value: left empty) Configure this attribute when an application has multiple entry modules.| +| reqCapabilities | Device capabilities required for running the application. | String array| Yes (initial value: left empty) | +| commonEvents | Static broadcast. For details, see Table 35. | Object array | Yes (initial value: left empty) | +| allowClassMap | Metadata of the HAP file. The value can be **true** or **false**. If the value is **true**, the HAP file uses the Java object proxy mechanism provided by the OpenHarmony framework. | Boolean | No (initial value: **false**) | +| entryTheme | Keyword of an OpenHarmony internal topic. Set it to the resource index of the name.| String | Yes (initial value: left empty) | + +Example of the module tag structure: + +```json +"module": { + "mainAbility": "MainAbility", + "package": "com.example.myapplication.rntry", + "name": ".MyOHOSAbilityPackage", + "description": "$string:description_application", + "supportModes": [ + "drive" + ], + "deviceType": [ + "car" + ], + "distro": { + "moduleName": "ohos_entry", + "moduleType": "entry" + }, + "abilities": [ + ... + ], + "shortcuts": [ + ... + ], + "js": [ + ... + ], + "reqPermissions": [ + ... + ], + "colorMode": "light" +} +``` + +Table 12 Internal structure of the distro attribute + +| Attribute | Description | Data Type| Default| +| ---------------- | ------------------------------------------------------------ | -------- | ---------- | +| moduleName | Name of the current HAP file. The maximum length is 31 characters. | String | No | +| moduleType | Type of the current HAP file. The value can be **entry** or **feature**. For the HAR type, set this attribute to **har**.| String | No | +| installationFree | Whether the HAP file supports the installation-free feature.
**true**: The HAP file supports the installation-free feature and meets installation-free constraints.
**false**: The HAP file does not support the installation-free feature.
Pay attention to the following:
When **entry.hap** is set to **true**, all **feature.hap** fields related to **entry.hap **must be **true**.
When **entry.hap** is set to **false**, **feature.hap** related to **entry.hap** can be set to **true** or **false** based on service requirements.| Boolean | No | + +Example of the distro attribute structure: + +```json +"distro": { + "moduleName": "ohos_entry", + "moduleType": "entry", + "installationFree": true +} +``` + +Table 13 Internal structure of the metaData attribute + +| Attribute | Description | Data Type| Default | +| ------------- | ------------------------------------------------------------ | -------- | -------------------- | +| parameters | Metadata of the parameters to be passed for calling the ability. The metadata of each parameter consists of the **description**, **name**, and **type** sub-attributes. For details, see Table 14.| Object array| Yes (initial value: left empty) | +| results | Metadata of the ability return value. The metadata of each return value consists of the **description**, **name**, and **type** sub-attributes. For details, see Table 15.| Object array| Yes (initial value: left empty)| +| customizeData | Custom metadata of the parent component. **parameters** and **results** cannot be configured in **application**. For details, see Table 16.| Object array| Yes (initial value: left empty)| + +Table 14 Internal structure of the parameters attribute + +| Attribute | Description | Data Type| Default | +| ----------- | ------------------------------------------------------------ | -------- | ------------------ | +| description | Description of the parameter. The value can be a string or a resource index to descriptions in multiple languages. The value can contain a maximum of 255 characters.| String | Yes (initial value: left empty)| +| name | Name of the parameter. The value can contain a maximum of 255 characters. | String | Yes (initial value: left empty)| +| type | Type of the parameter, for example, **Integer**. | String | No | + +Table 15 Internal structure of the results attribute + +| Attribute | Description | Data Type| Default | +| ----------- | ------------------------------------------------------------ | -------- | -------------------- | +| description | Description of the return value. The value can be a string or a resource index to descriptions in multiple languages. The value can contain a maximum of 255 characters.| String | Yes (initial value: left empty)| +| name | Name of the return value. The value can contain a maximum of 255 characters. | String | Yes (initial value: left empty)| +| type | Type of the return value, for example, **Integer**. | String | No | + +Table 16 Internal structure of the customizeData attribute + +| Attribute| Description | Data Type| Default | +| -------- | ---------------------------------------------------------- | -------- | -------------------- | +| name | Key of a data element. The value is a string with a maximum of 255 bytes. | String | Yes (initial value: left empty)| +| value | Value of a data element. The value is a string with a maximum of 255 bytes. | String | Yes (initial value: left empty)| +| extra | Custom format of the data element. The value is an index to the resource that identifies the data.| String | Yes (initial value: left empty)| + +Example of the metaData attribute structure: + +```json +"metaData": { + "parameters" : [{ + "name" : "string", + "type" : "Float", + "description" : "$string:parameters_description" + }], + "results" : [{ + "name" : "string", + "type" : "Float", + "description" : "$string:results_description" + }], + "customizeData" : [{ + "name" : "string", + "value" : "string", + "extra" : "$string:customizeData_description" + }] +} +``` + +Table 17 Internal structure of the abilities attribute + +| Attribute | Description | Data Type | Default | +| ---------------- | ------------------------------------------------------------ | ---------- | -------------------------------------------------------- | +| 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. If this attribute is set to the name of the process running other applications, all these applications can run in the same process, provided they have the same unified user ID and the same signature. Devices running OpenHarmony do not support this attribute.| String | Yes (initial value: left empty) | +| name | Name of the ability. The value is a reverse domain name, in the format of "*Bundle name*.*Class name*", for example, **"com.example.myapplication.MainAbility"**. Alternatively, the value can start with a period (.) followed by the class name, for example, **".MainAbility"**.
The ability name must be unique in an application. This attribute applies only to the default, tablet, smart TV, head unit, and wearable device type types.
Note: When you use DevEco Studio to create a project, the configuration of the first ability is generated by default, including the **MainAbility.java** file and the class name **MainAbility** defaulted in the **name** string for the **abilities** attribute in **config.json**. The value of this attribute can be customized if you use other IDE tools. The value can contain a maximum of 127 characters. | String | No | +| description | Description of the ability. The value can be a string or a resource index to descriptions in multiple languages. The value can contain a maximum of 255 characters.| String | Yes (initial value: left empty) | +| icon | Index to the ability icon file. Example value: **$media:ability_icon**. 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 of the ability is also used as the icon of the application. If multiple abilities address this condition, the icon of the first candidate ability is used as the application icon.
Note: The **icon** and **label** values of an application are visible to users. Ensure that at least one of them is different from any existing icons or labels.| String | Yes (initial value: left empty) | +| label | Ability name visible to users. The value can be a name string or a resource index to names 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 label of the ability is also used as the label of the application. If multiple abilities address this condition, the label of the first candidate ability is used as the application label.
Note: The **icon** and **label** values of an application are visible to users. Ensure that at least one of them is different from any existing icons or labels. The value can be a reference to a string defined in a resource file or a string enclosed in brackets ({}). The value can contain a maximum of 255 characters.| String | Yes (initial value: left empty) | +| uri | Uniform Resource Identifier (URI) of the ability. The value can contain a maximum of 255 characters. | String | Yes (No for abilities using the Data template) | +| launchType | Startup type of the ability. The value can be **standard**, **singleMission**, or **singleton**.
**standard**: Multiple **Ability** instances can be created during startup.
Most abilities can use this type.
**singleMission**: Only a single **Ability** instance can be created in each task stack during startup.
**singleton**: Only a single **Ability** instance can be created across all task stacks during startup. For example, a globally unique incoming call screen uses the singleton startup type. This attribute applies only to the default, tablet, smart TV, head unit, and wearable device type types. | String | Yes (initial value: **standard**) | +| visible | Whether the ability can be called by other applications.
**true**: The ability can be called by other applications.
**false**: The ability cannot be called by other applications.| Boolean | Yes (initial value: **false**) | +| permissions | Permissions required for abilities of another application to call the current ability, generally in the format of a reverse domain name. The value can be either the permissions predefined in the OS or your custom permissions.| String array| Yes (initial value: left empty) | +| skills | Types of the **want** that can be accepted by the ability. | Object array | Yes (initial value: left empty) | +| deviceCapability | Device capabilities required to run the ability.| String array| Yes (initial value: left empty) | +| metaData | Metadata. For details, see Table 13. | Object | Yes (initial value: left empty) | +| type | Type of the ability. Available values are as follows:
**page**: FA developed using the Page template to provide the capability of interacting with users.
**service**: PA developed using the Service template to provide the capability of running tasks in the background.
**data**: PA developed using the Data template to provide unified data access for external systems.
**CA**: ability that can be started by other applications as a window.| String | No | +| orientation | Display orientation of the ability. This attribute applies only to the ability using the Page template. Available values are as follows:
unspecified: indicates that the system automatically determines the display orientation of the ability.
**landscape**: indicates the landscape orientation.
**portrait**: indicates the portrait orientation.
**followRecent**: indicates that the orientation follows the most recent application in the stack.| String | Yes (initial value: **unspecified**) | +| backgroundModes | Background service type of the ability. You can assign multiple background service types to a specific ability. This attribute applies only to the ability using the Service template. Available values are as follows:
**dataTransfer**: service for downloading, backing up, sharing, or transferring data from the network or peer devices
**audioPlayback**: audio playback service
**audioRecording**: audio recording service
**pictureInPicture**: picture in picture (PiP) and small-window video playback services
**voip**: voice/video call and VoIP services
**location**: location and navigation services
**bluetoothInteraction**: Bluetooth scanning, connection, and transmission services
**wifiInteraction**: WLAN scanning, connection, and transmission services
**screenFetch**: screen recording and screenshot services
**multiDeviceConnection**: multi-device interconnection service| String array| Yes (initial value: left empty) | +| grantPermission | Whether permissions can be granted for any data in the ability. | Boolean | Yes (initial value: left empty) | +| readPermission | Permission required for reading data in the ability. This attribute applies only to the ability using the Data template. The value is a string with a maximum of 255 bytes. This attribute applies only to the default, tablet, smart TV, head unit, and wearable device type types. | String | Yes (initial value: left empty) | +| writePermission | Permission required for writing data to the ability. This attribute applies only to the ability using the Data template. The value is a string with a maximum of 255 bytes. This attribute applies only to the default, tablet, smart TV, head unit, and wearable device type types. | String | Yes (initial value: left empty) | +| configChanges | System configurations that the ability concerns. Upon any changes on the concerned configurations, the **onConfigurationUpdated** callback will be invoked to notify the ability. Available values are as follows:
**mcc**: indicates that the mobile country code (MCC) of the IMSI is changed. Typical scenario: A SIM card is detected, and the MCC is updated.
**mnc**: indicates that the mobile network code (MNC) of the IMSI is changed. Typical scenario: A SIM card is detected, and the MNC is updated.
**locale**: indicates that the locale is changed. Typical scenario: The user has selected a new language for the text display of the device.
**layout**: indicates that the screen layout is changed. Typical scenario: Currently, different display forms are all in the active state.
**fontSize**: indicates that font size is changed. Typical scenario: A new global font size is set.
**orientation**: indicates that the screen orientation is changed. Typical scenario: The user rotates the device.
**density**: indicates that the display density is changed. Typical scenario: The user may specify different display ratios, or different display forms are active at the same time.
**size**: indicates that the size of the display window is changed.
**smallestSize**: indicates that the length of the shorter side of the display window is changed.
**colorMode**: indicates that the color mode is changed.| String array| Yes (initial value: left empty) | +| mission | Task stack of the ability. This attribute applies only to the ability using the Page template. By default, all abilities in an application belong to the same task stack. This attribute applies only to the default, tablet, smart TV, head unit, and wearable device type types. | String | Yes (initial value: bundle name of the application) | +| targetAbility | Target ability that this ability alias points to. This attribute applies only to the ability using the Page template. If the **targetAbility** attribute is set, only **name**, **icon**, **label**, **visible**, **permissions**, and **skills** take effect in the current ability (ability alias). Other attributes use the values of the **targetAbility** attribute. The target ability must belong to the same application as the alias and must be declared in **config.json** ahead of the alias. This attribute applies only to the default, tablet, smart TV, head unit, and wearable device type types. | String | Yes (initial value: left empty, indicating that the current ability is not an alias)| +| multiUserShared | Whether the ability supports data sharing among multiple users. This attribute applies only to the ability using the Data template. If this attribute is set to **true**, only one copy of data is stored for multiple users. Note that this attribute will invalidate the **visible** attribute. This attribute applies only to the default, tablet, smart TV, head unit, and wearable device type types. | Boolean | Yes (initial value: **false**) | +| supportPipMode | Whether the ability allows the user to enter the Picture in Picture (PiP) mode. The PiP mode enables the user to watch a video in a small window that hovers on top of a full screen window (main window). This attribute applies only to the ability using the Page template. This attribute applies only to the default, tablet, smart TV, head unit, and wearable device type types. | Boolean | Yes (initial value: **false**) | +| formsEnabled | Whether the ability can provide forms. This attribute applies only to the ability using the Page template.
**true**: This ability can provide forms.
**false**: This ability cannot provide forms.| Boolean | Yes (initial value: **false**) | +| forms | Details about the forms used by the ability. This attribute is valid only when **formsEnabled** is set to **true**. For details, see Table 27.| Object array | Yes (initial value: left empty) | +| srcLanguage | Programming language used to develop the ability. | String | The value can be **java**, **js**, or **ets**. | +| srcPath | Path of the JS code and components corresponding to the ability. | String | Yes (initial value: left empty) | +| uriPermission | Application data that the ability can access. This attribute consists of the **mode** and **path** sub-attributes. This attribute is valid only for the capability of the type provider. Devices running OpenHarmony do not support this attribute. For details, see Table 18.| Object | Yes (initial value: left empty) | + +Table 18 Internal structure of the uriPermission attribute + +| Attribute| Description | Data Type| Default | +| -------- | ----------------------- | -------- | ------------------------- | +| path | Path identified by **uriPermission**.| String | No | +| mode | Mode matching the **uriPeimission**.| String | Yes (initial value: *default***)| + +Example of the abilities attribute structure: + +```json +"abilities": [ + { + "name": ".MainAbility", + "description": "test main ability", + "icon": "$media:ic_launcher", + "label": "$media:example", + "launchType": "standard", + "orientation": "unspecified", + "permissions": [ + ], + "visible": true, + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ], + "configChanges": [ + "locale", + "layout", + "fontSize", + "orientation" + ], + "type": "page" + }, + { + "name": ".PlayService", + "description": "example play ability", + "icon": "$media:ic_launcher", + "label": "$media:example", + "launchType": "standard", + "orientation": "unspecified", + "visible": false, + "skills": [ + { + "actions": [ + "action.play.music", + "action.stop.music" + ], + "entities": [ + "entity.audio" + ] + } + ], + "type": "service", + "backgroundModes": [ + "audioPlayback" + ] + }, + { + "name": ".UserADataAbility", + "type": "data", + "uri": "dataability://com.example.world.test.UserADataAbility", + "visible": true + } +] +``` + +Table 19 Internal structure of the skills attribute + +| Attribute| Description | Data Type | Default | +| -------- | ------------------------------------------------------------ | ---------- | -------------------- | +| actions | Actions of the **want** that can be accepted by the ability. Generally, the value is an **action** value predefined in the system.| String array| Yes (initial value: left empty)| +| entities | Entities of the **want** that can be accepted by the ability, such as video and Home application.| String array| Yes (initial value: left empty)| +| uris | URIs of the **want** that can be accepted by the ability. For details, see Table 20.| Object array | Yes (initial value: left empty)| + +Table 20 Internal structure of the uris attribute + +| Attribute | Description | Data Type| Default | +| ------------- | -------------------------- | -------- | -------------------- | +| scheme | Scheme in the URI. | String | No | +| host | Host in the URI. | String | Yes (initial value: left empty)| +| port | Port number in the URI. | String | Yes (initial value: left empty)| +| pathStartWith | **pathStartWith** value in the URI.| String | String | +| path | Path in the URI. | String | Yes (initial value: left empty)| +| pathRegx | **pathRegx** value in the URI. | String | Yes (initial value: left empty)| +| type | Type of the URI. | String | Yes (initial value: left empty)| + +Example of the skills attribute structure: + +```json +"skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ], + "uris": [ + { + "scheme": "http", + "host": "www.example.com", + "port": "8080", + "path": "query/student/name", + "type": "text/*" + } + ] + } +] +``` + +Table 21 reqPermissions + +| Attribute | Description | **Type**| **Value Range** | **Default Value** | **Restrictions** | +| --------- | ------------------------------------------------------------ | -------- | ----------------------------------------------------------- | ---------------------- | ------------------------------------------------------------ | +| name | Permission name, which is mandatory. | String | Custom | None | Parsing will fail if this field is not set. | +| reason | Reason for applying for the permission, which is mandatory only when applying for the **user_grant** permission.| String | The displayed text cannot exceed 256 bytes. | Empty | This field is mandatory for the **user_grant** permission. If it is left empty, application release will be rejected. Multi-language adaptation is required.| +| usedScene | Description of the application scenario and timing for using the permission, which is mandatory only when applying for the **user_grant** permission. This attribute consists of the **ability** and **when** sub-attributes. Multiple abilities can be configured.| Object | **ability**: ability name; **when**: **inuse** or **always**| **ability**: left empty; **when**: **inuse**| The **ability** sub-attribute is mandatory for the **user_grant** permission, and the **when** field is optional. | + +Table 22 Internal structure of the js attribute + +| Attribute| Description | Data Type| Default | +| -------- | ------------------------------------------------------------ | -------- | ------------------------ | +| name | Name of a JavaScript component. The default value is **default**. | String | No | +| pages | Route information about all pages in the JavaScript component, including the page path and page name. The value is an array, in which each element represents a page. The first element in the array represents the home page of the JavaScript FA.| Array | No | +| window | Window-related configurations. This attribute applies only to the default, tablet, smart TV, head unit, and wearable device type types. For details, see Table 23. | Object | Yes | +| type | Type of the JavaScript component. Available values are as follows:
**normal**: indicates that the JavaScript component is an application instance.
**form**: indicates that the JavaScript component is a widget instance.| String | Yes (initial value: **normal**)| +| mode | Development mode of the JavaScript component. For details, see Table 24. | Object | Yes (initial value: left empty) | + +Table 23 Internal structure of the window attribute + +| Attribute | Description | Data Type| Default | +| --------------- | ------------------------------------------------------------ | -------- | ----------------------- | +| designWidth | Baseline width for page design, in pixels. The size of an element is scaled by the actual device width.| Number | Yes (initial value: 720px) | +| autoDesignWidth | Whether to automatically calculate the baseline width for page design. If it is set to **true**, the **designWidth** attribute becomes invalid. The baseline width is calculated based on the device width and screen density.| Boolean| Yes (initial value: **false**)| + +Table 24 Internal structure of the **mode** attribute + +| Attribute| Description | Data Type | Default | +| -------- | -------------------- | ----------------------------------- | --------------------------- | +| type | Type of the JavaScript component.| String. The value can be **pageAbility** or **form**.| Yes (initial value: **pageAbility**)| +| syntax | Syntax type of the JavaScript component.| String. The value can be **hml** or **ets**. | Yes (initial value: **hml**) | + +Example of the js attribute structure: + +```json +"js": [ + { + "name": "default", + "pages": [ + "pages/index/index", + "pages/detail/detail" + ], + "window": { + "designWidth": 720, + "autoDesignWidth": false + }, + "type": "form" + } +] +``` + +Table 25 Internal structure of the shortcuts attribute + +| Attribute | Description | Data Type| Default | +| ---------- | ------------------------------------------------------------ | -------- | ------------------ | +| shortcutId | Shortcut ID. The value is a string with a maximum of 63 bytes. | String | No | +| label | Label of the shortcut, that is, the text description displayed by the shortcut. The value can be a string or a resource index to the description. The value is a string with a maximum of 63 bytes.| String | Yes (initial value: left empty)| +| icon | Icon of the shortcut. The value is a resource index to the description. | String | Yes (initial value: left empty)| +| intents | Intents to which the shortcut points. The attribute consists of the **targetClass** and **targetBundle** sub-attributes. For details, see Table 26.| Object array| Yes (initial value: left empty)| + +Table 26 Internal structure of the intents attribute + +| Attribute | Description | Data Type| Default | +| ------------ | --------------------------------------- | -------- | -------------------- | +| targetClass | Class name for the target ability of the shortcut. | String | Yes (initial value: left empty)| +| targetBundle | Application bundle name for the target ability of the shortcut.| String | Yes (initial value: left empty)| + +Example of the shortcuts attribute structure: + +```json +"shortcuts": [ + { + "shortcutId": "id", + "label": "$string:shortcut", + "intents": [ + { + "targetBundle": "com.example.world.test", + "targetClass": "com.example.world.test.entry.MainAbility" + } + ] + } +] +``` + +Table 27 Internal structure of the forms attribute + +| Attribute | Description | Data Type | Default | +| ------------------- | ------------------------------------------------------------ | ---------- | ------------------------ | +| name | Class name of the widget. The value is a string with a maximum of 127 bytes. | String | No | +| description | Description of the widget. The value can be a string or a resource index to descriptions in multiple languages. The value is a string with a maximum of 255 bytes.| String | Yes (initial value: left empty) | +| isDefault | Whether the widget is a default one. Each ability has only one default widget.
**true**: The widget is the default one.
**false**: The widget is not the default one.| Boolean | No | +| type | Type of the widget. Available values are as follows:
**Java**: indicates a Java-programmed widget.
**JS**: indicates a JavaScript-programmed widget.| String | No | +| colorMode | Color mode of the widget. Available values are as follows:
**auto**: The widget adopts the auto-adaptive color mode.
**dark**: The widget adopts the dark color mode.
**light**: The widget adopts the light color mode.| String | Yes (initial value: **auto**)| +| supportDimensions | Grid styles supported by the widget. Available values are as follows:
1 * 2: indicates a grid with one row and two columns.
2 * 2: indicates a grid with two rows and two columns.
2 * 4: indicates a grid with two rows and four columns.
4 * 4: indicates a grid with four rows and four columns.| String array| No | +| defaultDimension | Default grid style of the widget. The value must be available in the **supportDimensions** array of the widget.| String | No | +| landscapeLayouts | Landscape layouts for the grid styles. Values in this array must correspond to the values in the **supportDimensions** array. This field is required only by Java-programmed widgets.| String array| No | +| portraitLayouts | Portrait layouts for the grid styles. Values in this array must correspond to the values in the **supportDimensions** array. This field is required only by Java-programmed widgets.| String array| No | +| updateEnabled | Whether the widget can be updated periodically. Available values are as follows:
**true**: The widget can be updated periodically, depending on the update way you select, either at a specified interval (**updateDuration**) or at the scheduled time (**scheduledUpdateTime**). **updateDuration** is preferentially recommended.
**false**: The widget cannot be updated periodically.| Boolean | No | +| scheduledUpdateTime | Scheduled time to update the widget. The value is in 24-hour format and accurate to minute. | String | Yes (initial value: **0:0**) | +| updateDuration | Interval to update the widget. The value is a natural number, in the unit of 30 minutes.
If the value is **0**, this field does not take effect.
If the value is a positive integer ***N***, the interval is calculated by multiplying ***N*** and 30 minutes.| Number | Yes (initial value: **0**) | +| formConfigAbility | Link to a specific page of the application. The value is a URI. | String | Yes (initial value: left empty) | +| formVisibleNotify | Whether the widget is allowed to use the widget visibility notification. | String | Yes (initial value: left empty) | +| jsComponentName | Component name of the widget. The value is a string with a maximum of 127 bytes. This attribute is required only by JavaScript-programmed widgets.| String | No | +| metaData | Metadata of the widget. This attribute contains the array of the **customizeData** attribute. For details, see Table 13. | Object | Yes (initial value: left empty) | +| customizeData | Custom information about the widget. For details, see Table 28. | Object array | Yes (initial value: left empty) | + +Table 28 Internal structure of the customizeData attribute + +| Attribute| Description | Data Type| Default | +| -------- | --------------------------------------------------- | -------- | -------------------- | +| name | Name in the custom name-value pair. The value is a string with a maximum of 255 bytes. | String | Yes (initial value: left empty)| +| value | Value in the custom name-value pair. The value is a string with a maximum of 255 bytes. | String | Yes (initial value: left empty)| +| extra | Format of the current custom data. The value is the resource value of **extra**.| String | Yes (initial value: left empty)| + +Example of the forms attribute structure: + +```json +"forms": [ + { + "name": "Form_Js", + "description": "It's Js Form", + "type": "JS", + "jsComponentName": "card", + "colorMode": "auto", + "isDefault": true, + "updateEnabled": true, + "scheduledUpdateTime": "11:00", + "updateDuration": 1, + "defaultDimension": "2*2", + "supportDimensions": [ + "2*2", + "2*4", + "4*4" + ] + }, + { + "name": "Form_Java", + "description": "It's Java Form", + "type": "Java", + "colorMode": "auto", + "isDefault": false, + "updateEnabled": true, + "scheduledUpdateTime": "21:05", + "updateDuration": 1, + "defaultDimension": "1*2", + "supportDimensions": [ + "1*2" + ], + "landscapeLayouts": [ + "$layout:ability_form" + ], + "portraitLayouts": [ + "$layout:ability_form" + ], + "formConfigAbility": "ability://com.example.myapplication.fa/.MainAbility", + "metaData": { + "customizeData": [ + { + "name": "originWidgetName", + "value": "com.example.weather.testWidget" + } + ] + } + } +] +``` + +Table 29 Internal structure of the distroFilter attribute + +| Attribute | Description | Data Type| Default| +| ------------- | ------------------------------------------------------------ | -------- | ---------- | +| apiVersion | Supported API versions. For details, see Table 30. | Object | No | +| screenShape | Supported screen shapes. For details, see Table 31. | Object array| No | +| screenWindow | Supported window resolutions when the application is running. This attribute applies only to the lite wearables. For details, see Table 32.| Object array| No | +| screenDensity | Pixel density of the screen, in dots per inch (DPI). For details, see Table 33. | Object array| No | +| countryCode | Country code used during application distribution. For details, see the ISO-3166-1 standard. Multiple enumerated values of countries and regions are supported. For details, see Table 34.| Object array| No | + +Table 30 Internal structure of the apiVersion attribute + +| Attribute| Description | Data Type| Default | +| -------- | ------------------------------------------------------------ | -------- | -------------------- | +| policy | Blocklist and trustlist rule of the sub-attribute value. Set this attribute to **exclude** or **include**.**include** indicates that the sub-attribute value is in the trustlist. If the value matches any of the **value** enums, it matches this attribute.| String | Yes (initial value: left empty)| +| value | An integer of the existing API version, for example, 4, 5, or 6. Example: If an application uses two software versions developed using API 5 and API 6 for the same device model, two installation packages of the entry type can be released.| Array | Yes (initial value: left empty)| + +Table 31 Internal structure of the screenShape attribute + +| Attribute| Description | Data Type| Default | +| -------- | ------------------------------------------------------------ | -------- | -------------------- | +| policy | Blocklist and trustlist rule of the sub-attribute value. Set this attribute to **exclude** or **include**.**include** indicates that the sub-attribute value is in the trustlist. If the value matches any of the **value** enums, it matches this attribute.| String | Yes (initial value: left empty)| +| value | The value can be **circle** or **rect**. Example: Different HAPs can be provided for a smart watch with a circular face and that with a rectangular face.| Array | Yes (initial value: left empty)| + +Table 32 Internal structure of the screenWindow attribute + +| Attribute| Description | Data Type| Default | +| -------- | ------------------------------------------------------------ | -------- | -------------------- | +| policy | Blocklist and trustlist rule of the sub-attribute value. Set this attribute to **exclude** or **include**.**include** indicates that the sub-attribute value is in the trustlist. If the value matches any of the **value** enums, it matches this attribute.| String | Yes (initial value: left empty)| +| value | Width and height of the screen. The value of a single string is in the format of Width x Height in pixels, for example, **454*454**.| Array | Yes (initial value: left empty)| + +Table 33 Internal structure of the screenDensity attribute + +| Attribute| Description | Data Type| Default | +| -------- | ------------------------------------------------------------ | -------- | -------------------- | +| policy | Blocklist and trustlist rule of the sub-attribute value. Set this attribute to **exclude** or **include**.**include** indicates that the sub-attribute value is in the trustlist. If the value matches any of the **value** enums, it matches this attribute.| String | Yes (initial value: left empty)| +| value | Available values are as follows:
**sdpi**: screen density with small-scale dots per inch (SDPI). This value is applicable for devices with a DPI range of (0, 120].
**mdpi**: screen density with medium-scale dots per inch (MDPI). This value is applicable for devices with a DPI range of (120, 160].
**ldpi**: screen density with large-scale dots per inch (LDPI). This value is applicable for devices with a DPI range of (160, 240].
**xldpi**: screen density with extra-large-scale dots per inch (XLDPI). This value is applicable for devices with a DPI range of (240, 320].
**xxldpi**: screen density with extra-extra-large-scale dots per inch (XXLDPI). This value is applicable for devices with a DPI range of (320, 480].
**xxxldpi**: screen density with extra-extra-extra-large-scale dots per inch (XXXLDPI). This value is applicable for devices with a DPI range of (480, 640].| Array | Yes (initial value: left empty)| + +Table 34 Internal structure of the countryCode attribute + +| Attribute| Description | Data Type | Default | +| -------- | ------------------------------------------------------------ | ---------- | -------------------- | +| policy | Blocklist and trustlist rule of the sub-attribute value. Set this attribute to **exclude** or **include**.**include** indicates that the sub-attribute value is in the trustlist. If the value matches any of the **value** enums, it matches this attribute.| String | Yes (initial value: left empty)| +| value | Country code of the area to which the application is to be distributed. The value is a string array, of which each substring indicates a country or region. The substring consists of two uppercase letters.| String array| Yes (initial value: left empty)| + +Example of the distroFilter attribute structure: + +```json +"distroFilter": { + "apiVersion": { + "policy": "include", + "value": [4,5] + }, + "screenShape": { + "policy": "include", + "value": ["circle","rect"] + }, + "screenWindow": { + "policy": "include", + "value": ["454*454","466*466"] + }, + "screenDensity":{ + "policy": "exclude", + "value": ["ldpi","xldpi"] + }, + "countryCode": { + "policy":"include", + "value":["CN", "HK"] + } +} +``` + +Table 35 Internal structure of the commonEvents attribute -- The value of **package** must be unique for the applications with the same **bundleName**. -- Only one ability can be declared in the **abilities** field. -- The **name** field under **abilities** must be unique for the applications with the same **bundleName**. +| Attribute | Description | Data Type | Default | +| ---------- | ------------------------------------------------------------ | ---------- | ------------------ | +| name | Name of a static broadcast. | String | No | +| permission | Permission that needs to be applied for to implement the static common event. | String array| Yes (initial value: left empty)| +| data | Additional data array to be carried by the current static common event. | String array| Yes (initial value: left empty)| +| type | Type array of the current static common event. | String array| Yes (initial value: left empty)| +| events | A set of events for the wants that can be received. The value can be system predefined or custom.| String array| No | +Example of the commonEvents attribute structure: + +```json +"commonEvents": [ + { + "name":"MainAbility", + "permission": "string", + "data":[ + "string", + "string" + ], + "events": [ + "string", + "string" + ] + } +] +``` diff --git a/zh-cn/application-dev/background-task-management/background-task-dev-guide.md b/zh-cn/application-dev/background-task-management/background-task-dev-guide.md index 4635a0b01afad6bab922ea70c688b97bd3f158ca..92e3d3c99b700a391ab38e8fbe9d40d6388198ee 100644 --- a/zh-cn/application-dev/background-task-management/background-task-dev-guide.md +++ b/zh-cn/application-dev/background-task-management/background-task-dev-guide.md @@ -120,7 +120,7 @@ ohos.permission.KEEP_BACKGROUND_RUNNING | MULTI_DEVICE_CONNECTION | 6 | 多设备互联 | multiDeviceConnection | | WIFI_INTERACTION | 7 | WLAN相关(系统保留) | wifiInteraction | | VOIP | 8 | 音视频通话(系统保留) | voip | -| TASK_KEEPING | 9 | 计算任务(仅供PC使用) | taskKeeping | +| TASK_KEEPING | 9 | 计算任务(仅供特定设备使用) | taskKeeping | ## 开发步骤 diff --git a/zh-cn/application-dev/background-task-management/background-task-overview.md b/zh-cn/application-dev/background-task-management/background-task-overview.md index 7ade1cd9041a74287722f3d3ce3efcdb052e114e..78cf56ca90901323f2e37e5ff305bceddb4c5095 100644 --- a/zh-cn/application-dev/background-task-management/background-task-overview.md +++ b/zh-cn/application-dev/background-task-management/background-task-overview.md @@ -28,11 +28,11 @@ - **申请时机**:允许应用在前台时,或退后台在被挂起之前(应用退到后台默认有6~12秒的运行时长,具体时长由系统根据具体场景决定)申请延迟挂起,否则可能被挂起(Suspend),导致申请失败。 -- **超时**:延迟挂起超时(Timeout),系统通过回调知会应用,应用需要取消对应的延迟挂起,或再次申请延迟挂起。超期不取消或不处理,该应用会被强制取消延迟挂起。 +- **超时**:延迟挂起即将超时(Timeout),系统通过回调知会应用,应用需要取消对应的延迟挂起。如果超时不取消,该应用会被强制杀掉。 -- **取消时机**:任务完成后申请方应用主动取消延时申请,不要等到超时后被系统取消,否则会影响该应用的后台允许运行时长配额。 +- **取消时机**:任务完成后申请方应用应该主动取消延迟挂起,不要等到系统回调后再取消,否则会影响该应用的后台允许运行时长配额。 -- **配额机制**:为了防止应用滥用保活,或者申请后不取消,每个应用每天都会有一定配额(会根据用户的使用习惯动态调整),配额消耗完就不再允许申请短时任务,所以应用完成短时任务后立刻取消延时申请,避免消耗配额。(注,这个配额指的是申请的时长,系统默认应用在后台运行的时间不计算在内)。 +- **配额机制**:为了防止应用滥用保活,或者申请后不取消,每个应用每天都会有一定配额(会根据用户的使用习惯动态调整),配额消耗完就不再允许申请短时任务,所以应用完成短时任务后立刻取消延迟挂起,避免消耗配额。(注,这个配额指的是申请的时长,系统默认应用在后台运行的时间不计算在内)。 ## 长时任务 长时任务给用户能够直观感受到的且需要一直在后台运行的业务提供后台运行生命周期的保障。比如:业务需要在后台播放声音、需要在后台持续导航定位等。此类用户可以直观感知到的后台业务行为,可以通过使用长时任务对应的后台模式保障业务在后台的运行,支撑应用完成在后台的业务。 @@ -52,7 +52,7 @@ OpenHarmony提供了九种后台模式,供需要在后台做长时任务的业 | multiDeviceConnection | 分布式互联任务 | 正在运行分布式任务 | | | wifiInteraction | WLAN传输 | 正在运行WLAN相关任务 | SystemApi,仅对System权限应用开放 | | voip | 音视频电话、VOIP | 正在运行通话相关任务 | SystemApi,仅对System权限应用开放 | -| taskKeeping | 计算任务 | 正在运行计算任务 | PC特有,仅在PC申请生效 | +| taskKeeping | 计算任务 | 正在运行计算任务 | 仅在特定设备生效 | ### 长时任务使用约束 - 如果用户选择可感知业务(如播音、导航等),触发对应后台模式,在任务启动时,系统会强制弹出通知提醒用户。