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

!3226 同步最新英文内容到3.1 Release,涉及元能力、通知、包管理的内容(无需翻译)

Merge pull request !3226 from 时睿/OpenHarmony-3.1-Release
......@@ -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)
......@@ -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.
......
# 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 <key><value> | 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");
});
```
# 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
......
# 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.
......
# 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:<br>**normal**: indicates that the JavaScript component is an application instance.<br>**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.<br>**true**: The widget is the default one.<br>**false**: The widget is not the default one.| Boolean | No |
| type | Type of the widget. Available values are as follows:<br>**Java**: indicates a Java-programmed widget.<br>**JS**: indicates a JavaScript-programmed widget.| String | No |
| type | Type of the widget. Available values are as follows:<br>**JS**: indicates a JavaScript-programmed widget. | String | No |
| colorMode | Color mode of the widget. Available values are as follows:<br>**auto**: The widget adopts the auto-adaptive color mode.<br>**dark**: The widget adopts the dark color mode.<br>**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:<br>1 * 2: indicates a grid with one row and two columns.<br>2 * 2: indicates a grid with two rows and two columns.<br>2 * 4: indicates a grid with two rows and four columns.<br>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:<br>**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.<br>**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.<br>If the value is **0**, this field does not take effect.<br>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.
......@@ -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<string> = ["ohos.permission.DISTRIBUTED_DATASYNC"];
let bundleFlag = 0;
let tokenID = undefined;
let userID = 100;
let appInfo = await bundle.getApplicationInfo('ohos.samples.etsDemo', bundleFlag, userID);
tokenID = appInfo.accessTokenId;
let atManager = abilityAccessCtrl.createAtManager();
let requestPermissions: Array<string> = [];
for (let i = 0;i < array.length; i++) {
let result = await atManager.verifyAccessToken(tokenID, array[i]);
console.info("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.
# 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\<WantAgent\>) | Creates a **WantAgent** object. This API uses an asynchronous callback to return the result.|
| wantAgent.getWantAgent(info: WantAgentInfo): Promise\<WantAgent\>; | Creates a **WantAgent** object. This API uses a promise to return the result.|
| commonEvent.trigger(agent: WantAgent, triggerInfo: TriggerInfo, callback?: Callback\<CompleteData\>) | 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))
})
```
......@@ -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&lt;void&gt;): void;<br>function stopBackgroundRunning(context: Context): Promise&lt;void&gt;; | 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
......
......@@ -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.
......
# 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)
# 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 [<options>]`
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 [<options>]`
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 [<options>]`
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)
# 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.
# 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)
# 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<boolean>): void | Checks whether notification is enabled.|
| enableNotification(bundle: BundleOption, enable: boolean, callback: AsyncCallback<void>): 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>): void | Subscribes to a notification with the subscription information specified.|
| subscribe(subscriber: NotificationSubscriber, callback: AsyncCallback<void>): void | Subscribes to all notifications. |
| unsubscribe(subscriber: NotificationSubscriber, callback: AsyncCallback<void>): 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>): void | Publishes a notification. |
| publish(request: NotificationRequest, userId: number, callback: AsyncCallback<void>): void | Publishes a notification to the specified user. |
| cancel(id: number, label: string, callback: AsyncCallback<void>): void | Cancels a specified notification. |
| cancelAll(callback: AsyncCallback<void>): 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)
```
......@@ -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 |
## 开发步骤
......
......@@ -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 | 计算任务 | 正在运行计算任务 | 仅在特定设备生效 |
### 长时任务使用约束
- 如果用户选择可感知业务(如播音、导航等),触发对应后台模式,在任务启动时,系统会强制弹出通知提醒用户。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册