提交 3e1a248d 编写于 作者: H hunili 提交者: Gitee

Merge branch 'OpenHarmony-3.1-Release' of gitee.com:openharmony/docs into OpenHarmony-3.1-Release

...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
- [Application Development Overview](application-dev-guide.md) - [Application Development Overview](application-dev-guide.md)
- About OpenHarmony - About OpenHarmony
- [OpenHarmony Project](../OpenHarmony-Overview.md) - [OpenHarmony Project](../OpenHarmony-Overview.md)
- [Glossary](../device-dev/glossary/glossary.md) - [Glossary](../glossary.md)
- [OpenHarmony Release Notes](../release-notes/Readme.md) - [OpenHarmony Release Notes](../release-notes/Readme.md)
- Getting Started - Getting Started
- [Getting Started with Application Development](quick-start/Readme-EN.md) - [Getting Started with Application Development](quick-start/Readme-EN.md)
......
...@@ -6,4 +6,7 @@ ...@@ -6,4 +6,7 @@
- [FA Widget Development](fa-formability.md) - [FA Widget Development](fa-formability.md)
- Other - Other
- [WantAgent Development](wantagent.md)
- [Ability Assistant Usage](ability-assistant-guidelines.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 ...@@ -28,13 +28,13 @@ The ability assistant is pre-installed in the device environment. You can direct
Starts an ability. Starts an ability.
| Name | Description | | Name | Description |
| --------- | ---------------------- | | --------- | -------------------------- |
| -h/--help | Help information. | | -h/--help | Help information. |
| -d | Device ID. This parameter is optional. | | -d | Device ID. This parameter is optional. |
| -a | Ability name. This parameter is mandatory.| | -a | Ability name. This parameter is mandatory.|
| -b | Bundle 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** **Return value**
...@@ -82,13 +82,20 @@ The ability assistant is pre-installed in the device environment. You can direct ...@@ -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. | | -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**.| | -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** **Method**
``` ```
aa dump -a 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** - **force-stop**
Forcibly stops a process based on the bundle name. 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 # FA Model Overview
## Overall Architecture ## 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 ## Application Package Structure
**The following figure shows the application package structure.** **The following figure shows the application package structure.**
![fa-package-info](figures/fa-package-info.png) ![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 ## 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.** **The following figure shows the lifecycle of the Page ability.**
![fa-pageAbility-lifecycle](figures/fa-pageAbility-lifecycle.png) ![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 ## Process and Thread Model
......
# Data Ability Development # Data Ability Development
## When to Use
## Basic Concepts
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. 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. 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 ## Available APIs
### 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. **Table 1** Data ability lifecycle callbacks
2. The APIs used in the lifecycle of the Data ability are as follows: |API|Description|
|:------|:------|
- onInitialized |onInitialized|Called during ability initialization to initialize the relational database (RDB).|
|update|Updates data in the database.|
Called during ability initialization to initialize the relational database (RDB). |query|Queries data in the database.|
|delete|Deletes one or multiple data records from the database.|
- update |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.|
Updates data in the database. |denormalizeUri|Converts a normalized URI generated by **normalizeUri** into a denormalized URI.|
|insert|Inserts a data record into the database.|
- query |openFile|Opens a file.|
|getFileTypes|Obtains the MIME type of a file.|
Queries data in the database. |getType|Obtains the MIME type matching the data specified by the URI.|
|executeBatch|Operates data in the database in batches.|
- delete |call|A customized API.|
Deletes one or multiple data records from the database.
## How to Develop
- normalizeUri ### Creating a Data Ability
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. 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.
- 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.
The following code snippet shows how to create a Data ability: The following code snippet shows how to create a Data ability:
```javascript ```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 { export default {
onInitialized(abilityInfo) { onInitialized(abilityInfo) {
console.info('DataAbility onInitialized, abilityInfo:' + abilityInfo.bundleName) console.info('DataAbility onInitialized, abilityInfo:' + abilityInfo.bundleName)
dataRdb.getRdbStore(STORE_CONFIG, 1, (err, store) => { dataRdb.getRdbStore(STORE_CONFIG, 1, (err, store) => {
console.info('DataAbility getRdbStore callback') console.info('DataAbility getRdbStore callback')
store.executeSql(SQL_CREATE_TABLE, []) store.executeSql(SQL_CREATE_TABLE, [])
rdbStore = store rdbStore = store
}); });
}, },
insert(uri, valueBucket, callback) { insert(uri, valueBucket, callback) {
console.info('DataAbility insert start') console.info('DataAbility insert start')
rdbStore.insert(TABLE_NAME, valueBucket, callback) rdbStore.insert(TABLE_NAME, valueBucket, callback)
}, },
batchInsert(uri, valueBuckets, callback) { batchInsert(uri, valueBuckets, callback) {
console.info('DataAbility batch insert start') console.info('DataAbility batch insert start')
for (let i = 0;i < valueBuckets.length; i++) { for (let i = 0;i < valueBuckets.length; i++) {
console.info('DataAbility batch insert i=' + i) console.info('DataAbility batch insert i=' + i)
if (i < valueBuckets.length - 1) { if (i < valueBuckets.length - 1) {
rdbStore.insert(TABLE_NAME, valueBuckets[i], (num: number) => { rdbStore.insert(TABLE_NAME, valueBuckets[i], (num: number) => {
console.info('DataAbility batch insert ret=' + num) console.info('DataAbility batch insert ret=' + num)
}) })
} else { } else {
rdbStore.insert(TABLE_NAME, valueBuckets[i], callback) 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 |
| ------------ | ------------------------------------------------------------ |
| 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. |
| "name" | Ability name, corresponding to the **Data** class name derived from **Ability**. | | "uri" | URI used for communication. |
| "type" | Ability type, which is **Data** for a Data ability. | | "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.|
| "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 ```json
"abilities":[{ "abilities":[{
"srcPath": "DataAbility", "srcPath": "DataAbility",
"name": ".DataAbility", "name": ".DataAbility",
"icon": "$media:icon", "icon": "$media:icon",
...@@ -141,121 +97,142 @@ Data ability providers can customize data access-related APIs such as data inser ...@@ -141,121 +97,142 @@ Data ability providers can customize data access-related APIs such as data inser
"type": "data", "type": "data",
"visible": true, "visible": true,
"uri": "dataability://ohos.samples.etsdataability.DataAbility" "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 1. Create a Data ability helper.
Create a utility API object.
```js For details about the APIs provided by **DataAbilityHelper**, see [DataAbilityHelper Module](../reference/apis/js-apis-dataAbilityHelper.md).
// 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 (/). ```js
var urivar = "dataability:///com.ix.DataAbility" // 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 DAHelper = featureAbility.acquireDataAbilityHelper( var urivar = "dataability:///com.ix.DataAbility"
var DAHelper = featureAbility.acquireDataAbilityHelper(
urivar urivar
); );
``` ```
Construct RDB data. 2. Construct RDB data.
```js ```js
var valuesBucket = {"name": "gaolu"} var valuesBucket = {"name": "gaolu"}
var da = new ohos_data_ability.DataAbilityPredicates() var da = new ohos_data_ability.DataAbilityPredicates()
var valArray =new Array("value1"); var valArray =new Array("value1");
var cars = new Array({"batchInsert1" : "value1",}); var cars = new Array({"batchInsert1" : "value1",});
``` ```
Use **insert** to insert data to the Data subsystem. 3. Use **insert** to insert data to the Data submodule.
```js ```js
// Callback mode: // Callback mode:
DAHelper.insert( DAHelper.insert(
urivar, urivar,
valuesBucket, valuesBucket,
(error, data) => { (error, data) => {
expect(typeof(data)).assertEqual("number") expect(typeof(data)).assertEqual("number")
} }
); );
// Promise mode: ```
var datainsert = await DAHelper.insert(
```js
// Promise mode:
var datainsert = await DAHelper.insert(
urivar, urivar,
valuesBucket valuesBucket
); );
``` ```
Use **delete** to delete data from the Data subsystem. 4. Use **delete** to delete data from the Data submodule.
```js ```js
// Callback mode: // Callback mode:
DAHelper.delete( DAHelper.delete(
urivar, urivar,
da, da,
(error, data) => { (error, data) => {
expect(typeof(data)).assertEqual("number") expect(typeof(data)).assertEqual("number")
} }
); );
// Promise mode: ```
var datadelete = await DAHelper.delete(
```js
// Promise mode:
var datadelete = await DAHelper.delete(
urivar, urivar,
da, da,
); );
``` ```
Use **update** to update data in the Data subsystem. 5. Use **update** to update data in the Data submodule.
```js ```js
// Callback mode: // Callback mode:
DAHelper.update( DAHelper.update(
urivar urivar
valuesBucket, valuesBucket,
da, da,
(error, data) => { (error, data) => {
expect(typeof(data)).assertEqual("number") expect(typeof(data)).assertEqual("number")
} }
); );
// Promise mode: ```
var dataupdate = await DAHelper.update(
```js
// Promise mode:
var dataupdate = await DAHelper.update(
urivar, urivar,
valuesBucket, valuesBucket,
da, da,
); );
``` ```
Use **query** to query data in the Data subsystem. 6. Use **query** to query data in the Data submodule.
```js ```js
// Callback mode: // Callback mode:
DAHelper.query( DAHelper.query(
urivar, urivar,
valArray, valArray,
da, da,
(error, data) => { (error, data) => {
expect(typeof(data)).assertEqual("object") expect(typeof(data)).assertEqual("object")
} }
); );
// Promise mode: ```
var dataquery = await DAHelper.query(
```js
// Promise mode:
var dataquery = await DAHelper.query(
urivar, urivar,
valArray, valArray,
da da
); );
``` ```
Use **batchInsert** to insert data in batches to the Data subsystem. 7. Use **batchInsert** to insert data in batches to the Data submodule.
```js ```js
// Callback mode: // Callback mode:
DAHelper.batchInsert( DAHelper.batchInsert(
urivar, urivar,
cars, cars,
(error, data) => { (error, data) => {
expect(typeof(data)).assertEqual("number") expect(typeof(data)).assertEqual("number")
} }
); );
// Promise mode: ```
var databatchInsert = await DAHelper.batchInsert(
```js
// Promise mode:
var databatchInsert = await DAHelper.batchInsert(
urivar, urivar,
cars cars
); );
``` ```
Use **executeBatch** to process data in batches in the Data subsystem. 8. Use **executeBatch** to process data in batches in the Data submodule.
```js ```js
// Callback mode: // Callback mode:
DAHelper.executeBatch( DAHelper.executeBatch(
urivar, urivar,
[ [
{ {
...@@ -271,9 +248,12 @@ DAHelper.executeBatch( ...@@ -271,9 +248,12 @@ DAHelper.executeBatch(
(error, data) => { (error, data) => {
expect(typeof(data)).assertEqual("object") expect(typeof(data)).assertEqual("object")
} }
); );
// Promise mode: ```
var dataexecuteBatch = await DAHelper.executeBatch(
```js
// Promise mode:
var dataexecuteBatch = await DAHelper.executeBatch(
urivar, urivar,
[ [
{ {
...@@ -289,16 +269,16 @@ var dataexecuteBatch = await DAHelper.executeBatch( ...@@ -289,16 +269,16 @@ var dataexecuteBatch = await DAHelper.executeBatch(
interrupted:true, interrupted:true,
} }
] ]
); );
``` ```
## Development Example ## Development Example
The following sample is provided to help you better understand how to develop a Data ability: 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. Create a Data ability in the **data.ts** file in the **DataAbility** directory.
......
# FA Widget Development # FA Widget Development
## Widget Overview ## 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: Basic concepts:
- Widget provider - 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. 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 - Widget host
The widget client is an application that displays the widget content and controls the position where the widget is displayed in the host application. 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 - Widget Manager
The Widget Manager is a resident agent that manages widgets added to the system and provides functions such as periodic widget update. 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** > ![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. The widget provider controls the widget content to display, component layout, and click events bound to components.
## Scenario ## 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. - Create a **FormBindingData** object.
- Update a widget through **FormProvider**. - Update a widget through **FormProvider**.
- Develop the widget UI page. - Develop the widget UI page.
## Available APIs ## 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 | | API | Description |
| :----------------------------------------------------------- | :------------------------------------------- | | :----------------------------------------------------------- | :------------------------------------------- |
...@@ -43,7 +43,7 @@ The table below describes the lifecycle callback functions provided **FormAbilit ...@@ -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. | | 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. | | 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. | | 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). 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 ...@@ -58,9 +58,9 @@ For details about the **FormProvider** APIs, see [FormProvider](../reference/api
## How to Develop ## 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. 1. Import the required modules.
...@@ -70,7 +70,7 @@ To create a widget in the FA model, you need to implement the lifecycle callback ...@@ -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' import formProvider from '@ohos.application.formProvider'
``` ```
2. Implement the lifecycle callback functions of **FormAbility**. 2. Implement the lifecycle callbacks of **LifecycleForm**.
```javascript ```javascript
export default { export default {
...@@ -85,11 +85,11 @@ To create a widget in the FA model, you need to implement the lifecycle callback ...@@ -85,11 +85,11 @@ To create a widget in the FA model, you need to implement the lifecycle callback
return formData; return formData;
}, },
onCastToNormal(formId) { 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'); console.log('FormAbility onCastToNormal');
}, },
onUpdate(formId) { 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'); console.log('FormAbility onUpdate');
let obj = { let obj = {
"title": "titleOnUpdate", "title": "titleOnUpdate",
...@@ -101,7 +101,7 @@ To create a widget in the FA model, you need to implement the lifecycle callback ...@@ -101,7 +101,7 @@ To create a widget in the FA model, you need to implement the lifecycle callback
}); });
}, },
onVisibilityChange(newStatus) { 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'); console.log('FormAbility onVisibilityChange');
}, },
onEvent(formId, message) { onEvent(formId, message) {
...@@ -129,7 +129,7 @@ Configure the **config.json** file for the **Form** ability. ...@@ -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 | | 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 | | 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**)| | 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) | | 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. ...@@ -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 | | Field | Description | Data Type | Default |
| ------------------- | ------------------------------------------------------------ | ---------- | ------------------------ | | ------------------- | ------------------------------------------------------------ | ---------- | ------------------------ |
| name | Class name of the widget. The value is a string with a maximum of 127 bytes. | String | No | | 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) | | 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 | | 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**)| | 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 | | 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 | | 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 | | 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**) | | 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**) | | 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) | | 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) | | 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 | | 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) | | 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) | | customizeData | Custom information about the widget. | Object array | Yes (initial value: left empty) |
A configuration example is as follows: A configuration example is as follows:
```json ```json
...@@ -180,10 +178,12 @@ Configure the **config.json** file for the **Form** ability. ...@@ -180,10 +178,12 @@ Configure the **config.json** file for the **Form** ability.
"label": "$string:form_FormAbility_label", "label": "$string:form_FormAbility_label",
"srcPath": "FormAbility", "srcPath": "FormAbility",
"type": "service", "type": "service",
"srcLanguage": "ets",
"formsEnabled": true,
"forms": [{ "forms": [{
"colorMode": "auto", "colorMode": "auto",
"defaultDimension": "2*2", "defaultDimension": "2*2",
"description": "This is a service widget.", "description": "This is a widget.",
"formVisibleNotify": true, "formVisibleNotify": true,
"isDefault": true, "isDefault": true,
"jsComponentName": "widget", "jsComponentName": "widget",
...@@ -233,13 +233,13 @@ You should override **onDestroy** to delete widget data. ...@@ -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). 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 ### Developing the Widget UI Page
You can use HML, CSS, and JSON to develop the UI page for a JavaScript-programmed widget. 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 ...@@ -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. Now you've got a widget shown below.
![fa-form-example](figures/fa-form-example.png) ![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 @@ ...@@ -2,11 +2,13 @@
## Overview ## Overview
### Concepts ### 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 ### 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. 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. ...@@ -15,21 +17,34 @@ The following figure shows the lifecycle state transition of the Page ability.
Description of ability lifecycle states: 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. - **INACTIVE**: The ability is visible but does not gain focus.
- **ACTIVE**: The ability runs in the foreground and gains 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) ![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 ## Development Guidelines
### Available APIs ### Available APIs
...@@ -46,48 +61,48 @@ You can override the lifecycle callback functions provided by the Page ability i ...@@ -46,48 +61,48 @@ You can override the lifecycle callback functions provided by the Page ability i
### Starting a Local Page Ability ### 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 ```javascript
import featureAbility from '@ohos.ability.featureAbility' import featureAbility from '@ohos.ability.featureAbility'
featureAbility.startAbility({ featureAbility.startAbility({
want: want:
{ {
action: "", action: "",
entities: [""], entities: [""],
type: "", type: "",
options: { options: {
// Grant the permission to read the URI. // Grant the permission to perform read operations on the URI.
authReadUriPermission: true, authReadUriPermission: true,
// Grant the permission to write the URI. // Grant the permission to perform write operations on the URI.
authWriteUriPermission: true, authWriteUriPermission: true,
// Forward the intent result to the origin ability. // Support forwarding the Want result to the ability.
abilityForwardResult: true, abilityForwardResult: true,
// Mark the ability start-up triggered by continuation. // Enable abiligy continuation.
abilityContinuation: true, abilityContinuation: true,
// Specify that a component does not belong to ohos. // Specify that a component does not belong to ohos.
notOhosComponent: true, notOhosComponent: true,
// Specify whether an ability is started. // Specify that an ability is started.
abilityFormEnabled: true, abilityFormEnabled: true,
// Grant the permission to persist the URI. // Grant the permission for possible persisting on the URI.
authPersistableUriPermission: true, authPersistableUriPermission: true,
// Grant the permission to persist the URI. // Grant the permission for possible persisting on the prefix URI.
authPrefixUriPermission: true, authPrefixUriPermission: true,
// Support distributed scheduling and start-up across multiple devices. // Support distributed scheduling system startup on multiple devices.
abilitySliceMultiDevice: true, abilitySliceMultiDevice: true,
// An ability using the Service template is started regardless of whether the // A service ability is started regardless of whether the host application has been started.
// host application has been started.
startForegroundAbility: true, startForegroundAbility: true,
// Install the specified ability if it is not installed. // Install the specified ability if it is not installed.
installOnDemand: true, installOnDemand: true,
// Return the result to the origin ability slice. // Return the result to the ability slice.
abilitySliceForwardResult: true, 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 installWithBackgroundMode: true
}, },
deviceId: "", deviceId: "",
...@@ -95,14 +110,17 @@ featureAbility.startAbility({ ...@@ -95,14 +110,17 @@ featureAbility.startAbility({
abilityName: "com.example.startability.MainAbility", abilityName: "com.example.startability.MainAbility",
uri: "" uri: ""
}, },
}, },
); );
``` ```
You can also include **parameters** in the **want** parameter and set its value in the key-value format. You can also include **parameters** in the **want** parameter and set its value in the key-value format.
* Example
**Example**
```javascript ```javascript
import featureAbility from '@ohos.ability.featureAbility' import featureAbility from '@ohos.ability.featureAbility'
featureAbility.startAbility({ featureAbility.startAbility({
want: want:
{ {
bundleName: "com.example.startability", bundleName: "com.example.startability",
...@@ -111,44 +129,115 @@ featureAbility.startAbility({ ...@@ -111,44 +129,115 @@ featureAbility.startAbility({
abilityName: "com.example.startability.MainAbility" 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 Obtain **deviceId** from **DeviceManager**. The sample code is as follows:
var promise = await featureAbility.startAbility({
want: ```ts
{ import deviceManager from '@ohos.distributedHardware.deviceManager';
deviceId: this.deviceId, let dmClass;
bundleName: "com.example.test", function getRemoteDeviceId() {
abilityName: "com.example.test.MainAbility", 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 ### Lifecycle APIs
**Table 2** Lifecycle callback functions
**Table 2** Lifecycle callbacks
| API | Description | | API | Description |
| ------------ | ------------------------------------------------------------ | | ------------ | ------------------------------------------------------------ |
| onShow() | Invoked when the ability is switched from the background to the foreground. In this case, the ability is visible to users.| | onShow() | Called 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.| | onHide() | Called 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.| | 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() | Invoked when the ability is created for the first time. You can initialize the application in this callback.| | onCreate() | Called 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.| | onInactive() | Called 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. | | onActive() | Called when the ability is switched to the foreground and gains focus. |
* Example **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.
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 ```javascript
export default { export default {
onCreate() { onCreate() {
...@@ -174,6 +263,6 @@ export default { ...@@ -174,6 +263,6 @@ export default {
### Development Example ### Development Example
The following sample is provided to help you better understand how to develop a Page ability: 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. 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'; ...@@ -36,12 +36,12 @@ import backgroundTaskManager from '@ohos.backgroundTaskManager';
```js ```js
import backgroundTaskManager from '@ohos.backgroundTaskManager'; import backgroundTaskManager from '@ohos.backgroundTaskManager';
let myReason = 'test requestSuspendDelay'; let myReason = 'test requestSuspendDelay';
let delayInfo = backgroundTaskManager.requestSuspendDelay(myReason, () => { let delayInfo = backgroundTaskManager.requestSuspendDelay(myReason, () => {
console.info("Request suspension delay will time out."); console.info("Request suspension delay will time out.");
}); });
var id = delayInfo.requestId;console.info("requestId is: " + id); var id = delayInfo.requestId;console.info("requestId is: " + id);
``` ```
...@@ -106,36 +106,53 @@ ohos.permission.KEEP_BACKGROUND_RUNNING ...@@ -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.| | 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 **Table 4** Background modes
| Name| ID Value| Description|
| -------- | -------- | -------- | | Name| ID Value| Description| Item|
| DATA_TRANSFER | 1 | Data transfer.| | -------- | -------- | -------- | -------- |
| AUDIO_PLAYBACK | 2 | Audio playback.| | DATA_TRANSFER | 1 | Data transfer.| dataTransfer |
| AUDIO_RECORDING | 3 | Audio recording.| | AUDIO_PLAYBACK | 2 | Audio playback.| audioPlayback |
| LOCATION | 4 | Positioning and navigation.| | AUDIO_RECORDING | 3 | Audio recording.| audioRecording |
| BLUETOOTH_INTERACTION | 5 | Bluetooth-related task.| | LOCATION | 4 | Positioning and navigation.| location |
| MULTI_DEVICE_CONNECTION | 6 | Multi-device connection.| | BLUETOOTH_INTERACTION | 5 | Bluetooth-related task.| bluetoothInteraction |
| WIFI_INTERACTION | 7 | WLAN-related task (reserved).| | MULTI_DEVICE_CONNECTION | 6 | Multi-device connection.| multiDeviceConnection |
| VOIP | 8 | Voice and video call (reserved).| | WIFI_INTERACTION | 7 | WLAN-related task (reserved).| wifiInteraction |
| TASK_KEEPING | 9 | Computing task (for PC only).| | VOIP | 8 | Voice and video call (reserved).| voip |
| TASK_KEEPING | 9 | Computing task (for specific devices only).| taskKeeping |
## How to Develop ## 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 ```json
"module": { "module": {
"package": "com.example.myapplication", "package": "com.example.myapplication",
...,
"reqPermissions": [ "abilities": [
{
"name": "ohos.permission.KEEP_BACKGROUND_RUNNING" {
} "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 ...@@ -174,13 +191,13 @@ For details about **WantAgent**, see [WantAgent](../reference/apis/js-apis-notif
```js ```js
import backgroundTaskManager from '@ohos.backgroundTaskManager'; import backgroundTaskManager from '@ohos.backgroundTaskManager';
import featureAbility from '@ohos.ability.featureAbility'; import featureAbility from '@ohos.ability.featureAbility';
backgroundTaskManager.stopBackgroundRunning(featureAbility.getContext()).then(() => { backgroundTaskManager.stopBackgroundRunning(featureAbility.getContext()).then(() => {
console.info("Operation succeeded"); console.info("Operation succeeded");
}).catch((err) => { }).catch((err) => {
console.error("Operation failed Cause: " + err); console.error("Operation failed Cause: " + err);
}); });
``` ```
## Development Examples ## Development Examples
......
...@@ -28,9 +28,9 @@ Adhere to the following constraints and rules when using transient tasks: ...@@ -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. - **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.) - **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 ...@@ -52,7 +52,7 @@ OpenHarmony provides 9 background modes for services that require continuous tas
| multiDeviceConnection | Distributed interconnection| A distributed task is running.| | | 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| | 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| | 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 ### 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. - 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.
......
...@@ -15,7 +15,7 @@ Call **createDistributedObject()** to create a distributed data object instance. ...@@ -15,7 +15,7 @@ Call **createDistributedObject()** to create a distributed data object instance.
**Table 1** API for creating a distributed data object instance **Table 1** API for creating a distributed data object instance
| Package| API| Description| | Package| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
| ohos.data.distributedDataObject| createDistributedObject(source: object): DistributedObject | Creates a distributed data object instance for data operations.| | ohos.data.distributedDataObject| createDistributedObject(source: object): DistributedObject | Creates a distributed data object instance for data operations.<br>- &nbsp;**source**: attributes of the **distributedObject** set.<br>- &nbsp;**DistributedObject**: returns the distributed object created.|
### Generating a Session ID ### Generating a Session ID
...@@ -33,7 +33,7 @@ Call setSessionId() to set the session ID for a distributed data object. The ses ...@@ -33,7 +33,7 @@ Call setSessionId() to set the session ID for a distributed data object. The ses
**Table 3** API for setting a session ID **Table 3** API for setting a session ID
| Class| API| Description| | Class| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
| DistributedDataObject | setSessionId(sessionId?: string): boolean | Sets a session ID for distributed data objects.| | DistributedDataObject | setSessionId(sessionId?: string): boolean | Sets a session ID for distributed data objects.<br>&nbsp;**sessionId**: ID of a distributed object in a trusted network. To remove a distributed data object from the network, set this parameter to "" or leave it empty.|
### Observing Data Changes ### Observing Data Changes
...@@ -43,7 +43,7 @@ Call **on()** to subscribe to data changes of a distributed data object. When th ...@@ -43,7 +43,7 @@ Call **on()** to subscribe to data changes of a distributed data object. When th
| Class| API| Description| | Class| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
| DistributedDataObject| on(type: 'change', callback: Callback<{ sessionId: string, fields: Array&lt;string&gt; }>): void | Subscribes to data changes.| | DistributedDataObject| on(type: 'change', callback: Callback<{ sessionId: string, fields: Array&lt;string&gt; }>): void | Subscribes to data changes.|
| DistributedDataObject| off(type: 'change', callback?: Callback<{ sessionId: string, fields: Array&lt;string&gt; }>): void | Unsubscribes from data changes.| | DistributedDataObject| off(type: 'change', callback?: Callback<{ sessionId: string, fields: Array&lt;string&gt; }>): void | Unsubscribes from data changes. Callback used to return changes of the distributed object. If this parameter is not specified, all callbacks related to data changes will be unregistered.|
### Observing Online or Offline Status ### Observing Online or Offline Status
...@@ -72,6 +72,7 @@ The following example shows how to implement a distributed data object synchroni ...@@ -72,6 +72,7 @@ The following example shows how to implement a distributed data object synchroni
```js ```js
var local_object = distributedObject.createDistributedObject({name:undefined, age:undefined, isVis:true, var local_object = distributedObject.createDistributedObject({name:undefined, age:undefined, isVis:true,
parent:undefined, list:undefined}); parent:undefined, list:undefined});
var sessionId = distributedObject.genSessionId();
``` ```
...@@ -82,13 +83,13 @@ The following example shows how to implement a distributed data object synchroni ...@@ -82,13 +83,13 @@ The following example shows how to implement a distributed data object synchroni
```js ```js
// Local object // Local object
var local_object = distributedObject.createDistributedObject({name:"jack", age:18, isVis:true, var local_object = distributedObject.createDistributedObject({name:"jack", age:18, isVis:true,
parent:{mother:"jack mom",father:"jack Dad"},[{mother:"jack mom"}, {father:"jack Dad"}]}; parent:{mother:"jack mom",father:"jack Dad"},list:[{mother:"jack mom"}, {father:"jack Dad"}]});
local_object.setsessionId(sessionId); local_object.setSessionId(sessionId);
// Remote object // Remote object
var remote_object = distributedObject.createDistributedObject({name:undefined, age:undefined, isVis:true, var remote_object = distributedObject.createDistributedObject({name:undefined, age:undefined, isVis:true,
parent:undefined, list:undefined}); parent:undefined, list:undefined});
remote_object.setsessionId(sessionId); remote_object.setSessionId(sessionId);
// After obtaining that the device status goes online, the remote object synchronizes data. That is, name changes to jack and age to 18. // After obtaining that the device status goes online, the remote object synchronizes data. That is, name changes to jack and age to 18.
``` ```
...@@ -97,7 +98,7 @@ The following example shows how to implement a distributed data object synchroni ...@@ -97,7 +98,7 @@ The following example shows how to implement a distributed data object synchroni
The sample code is as follows: The sample code is as follows:
```js ```js
changeCallback : function (sessionId, changeData) { function changeCallback(sessionId, changeData) {
console.info("change" + sessionId); console.info("change" + sessionId);
if (changeData != null && changeData != undefined) { if (changeData != null && changeData != undefined) {
...@@ -147,22 +148,22 @@ The following example shows how to implement a distributed data object synchroni ...@@ -147,22 +148,22 @@ The following example shows how to implement a distributed data object synchroni
8. Subscribe to the status (online/offline) changes of the distributed data object. A callback will be invoked to report the status change when the target distributed data object goes online or offline. 8. Subscribe to the status (online/offline) changes of the distributed data object. A callback will be invoked to report the status change when the target distributed data object goes online or offline.
The sample code is as follows: The sample code is as follows:
```js ```js
statusCallback : function (sessionId, networkid, status) { function statusCallback(sessionId, networkId, status) {
this.response += "status changed " + sessionId + " " + status + " " + networkId; this.response += "status changed " + sessionId + " " + status + " " + networkId;
} }
local_object.on("status", this.changeCallback); local_object.on("status", this.statusCallback);
``` ```
9. Unsubscribe from the status changes of the distributed data object. You can specify the callback to unsubscribe from. If you do not specify the callback, all status change callbacks will be unsubscribe from. 9. Unsubscribe from the status changes of the distributed data object. You can specify the callback to unsubscribe from. If you do not specify the callback, all status change callbacks will be unsubscribe from.
The sample code is as follows: The sample code is as follows:
```js ```js
// Unsubscribe from changeCallback. // Unsubscribe from statusCallback.
local_object.off("status", changeCallback); local_object.off("status", statusCallback);
// unsubscribe from all status change callbacks. // unsubscribe from all status change callbacks.
local_object.off("status"); local_object.off("status");
``` ```
10. Remove the distributed data object from the synchronization network. After the distributed data object is removed from the network, the data changes on the local end will not be synchronized to the remote end. 10. Remove a distributed data object from the synchronization network. After the distributed data object is removed from the network, the data changes on the local end will not be synchronized to the remote end.
The sample code is as follows: The sample code is as follows:
```js ```js
......
...@@ -7,7 +7,7 @@ On the basis of the SQLite database, the relational database (RDB) allows you to ...@@ -7,7 +7,7 @@ On the basis of the SQLite database, the relational database (RDB) allows you to
## Available APIs ## Available APIs
**Creating and Deleting an RDB Store** ### Creating or Deleting an RDB Store
The following table describes the APIs available for creating and deleting an RDB store. The following table describes the APIs available for creating and deleting an RDB store.
...@@ -17,51 +17,55 @@ The following table describes the APIs available for creating and deleting an RD ...@@ -17,51 +17,55 @@ The following table describes the APIs available for creating and deleting an RD
| -------- | -------- | | -------- | -------- |
|getRdbStore(config:&nbsp;StoreConfig,&nbsp;version:&nbsp;number,&nbsp;callback:&nbsp;AsyncCallback&lt;RdbStore&gt;):&nbsp;void | Obtains an RDB store. This method uses a callback to return the result. You can set parameters for the RDB store based on service requirements, and then call APIs to perform data operations.<br>-&nbsp;**config**: configuration of the RDB store.<br>-&nbsp;**version**: RDB version.<br>-&nbsp;**callback**: callback invoked to return the RDB store obtained.| |getRdbStore(config:&nbsp;StoreConfig,&nbsp;version:&nbsp;number,&nbsp;callback:&nbsp;AsyncCallback&lt;RdbStore&gt;):&nbsp;void | Obtains an RDB store. This method uses a callback to return the result. You can set parameters for the RDB store based on service requirements, and then call APIs to perform data operations.<br>-&nbsp;**config**: configuration of the RDB store.<br>-&nbsp;**version**: RDB version.<br>-&nbsp;**callback**: callback invoked to return the RDB store obtained.|
|getRdbStore(config:&nbsp;StoreConfig,&nbsp;version:&nbsp;number):&nbsp;Promise&lt;RdbStore&gt; | Obtains an RDB store. This method uses a promise to return the result. You can set parameters for the RDB store based on service requirements, and then call APIs to perform data operations.<br>-&nbsp;**config**: configuration of the RDB store.<br>-&nbsp;**version**: RDB version.| |getRdbStore(config:&nbsp;StoreConfig,&nbsp;version:&nbsp;number):&nbsp;Promise&lt;RdbStore&gt; | Obtains an RDB store. This method uses a promise to return the result. You can set parameters for the RDB store based on service requirements, and then call APIs to perform data operations.<br>-&nbsp;**config**: configuration of the RDB store.<br>-&nbsp;**version**: RDB version.|
|deleteRdbStore(name:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void | Deletes an RDB store. This method uses a callback to return the result. <br>-&nbsp;**name**: RDB store to delete.<br>-&nbsp;**callback**: callback invoked to return the result. If the RDB store is deleted, **true** will be returned. Otherwise, **false** will be returned.| |deleteRdbStore(name:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void | Deletes an RDB store. This method uses a callback to return the result. <br>-&nbsp;**name**: RDB store to delete.<br>-&nbsp;**callback**: callback invoked to return the result.|
| deleteRdbStore(name:&nbsp;string):&nbsp;Promise&lt;void&gt; | Deletes an RDB store. This method uses a promise to return the result.<br>-&nbsp;**name**: RDB store to delete.| | deleteRdbStore(name:&nbsp;string):&nbsp;Promise&lt;void&gt; | Deletes an RDB store. This method uses a promise to return the result.<br>-&nbsp;**name**: RDB store to delete.|
**Managing Data in an RDB Store** ### Managing Data in an RDB Store
The RDB provides APIs for inserting, deleting, updating, and querying data in the local RDB store. The RDB provides APIs for inserting, deleting, updating, and querying data in the local RDB store.
- **Inserting data**<br/> - **Inserting data**
The RDB provides APIs for inserting data through a **ValuesBucket** in a data table. If the data is inserted, the row ID of the data inserted will be returned; otherwise, **-1** will be returned. The RDB provides APIs for inserting data through a **ValuesBucket** in a data table. If the data is inserted, the row ID of the data inserted will be returned; otherwise, **-1** will be returned.
**Table 2** APIs for inserting data **Table 2** APIs for inserting data
| Class| API| Description| | Class| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
| RdbStore | insert(name:&nbsp;string,&nbsp;values:&nbsp;ValuesBucket,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):void | Inserts a row of data into a table. This method uses a callback to return the result.<br>-&nbsp;**name**: name of the target table.<br>-&nbsp;**values**: data to be inserted into the table.<br>-&nbsp;**callback**: callback invoked to return the result. If the operation is successful, the row ID will be returned. Otherwise, **-1** will be returned.| | RdbStore | insert(name:&nbsp;string,&nbsp;values:&nbsp;ValuesBucket,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):void | Inserts a row of data into a table. This method uses a callback to return the result.<br>-&nbsp;**name**: name of the target table.<br>-&nbsp;**values**: data to be inserted into the table.<br>-&nbsp;**callback**: callback invoked to return the result. If the operation is successful, the row ID will be returned. Otherwise, **-1** will be returned.|
| RdbStore | insert(name:&nbsp;string,&nbsp;values:&nbsp;ValuesBucket):&nbsp;Promise&lt;number&gt; | Inserts a row of data into a table. This method uses a promise to return the result.<br>-&nbsp;**name**: name of the target table.<br>-&nbsp;**values**: data to be inserted into the table.| | RdbStore | insert(name:&nbsp;string,&nbsp;values:&nbsp;ValuesBucket):&nbsp;Promise&lt;number&gt; | Inserts a row of data into a table. This method uses a promise to return the result.<br>-&nbsp;**name**: name of the target table.<br>-&nbsp;**values**: data to be inserted into the table.|
- **Updating data**<br/> - **Updating data**
Call the **update()** method to pass new data and specify the update conditions by using **RdbPredicates**. If the data is updated, the number of rows of the updated data will be returned; otherwise, **0** will be returned. Call the **update()** method to pass new data and specify the update conditions by using **RdbPredicates**. If the data is updated, the number of rows of the updated data will be returned; otherwise, **0** will be returned.
**Table 3** APIs for updating data **Table 3** APIs for updating data
| Class| API| Description| | Class| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
| RdbStore | update(values:&nbsp;ValuesBucket,&nbsp;rdbPredicates:&nbsp;RdbPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):void | Updates data in the RDB store based on the specified **RdbPredicates** object. This method uses a callback to return the result.<br>-&nbsp;**values**: data to update, which is stored in a **ValuesBucket**.<br>-&nbsp;**rdbPredicates**: conditions for updating data.<br>-&nbsp;**callback**: callback invoked to return the number of rows updated.| | RdbStore | update(values:&nbsp;ValuesBucket,&nbsp;rdbPredicates:&nbsp;RdbPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):void | Updates data in the RDB store based on the specified **RdbPredicates** object. This method uses a callback to return the result.<br>-&nbsp;**values**: data to update, which is stored in a **ValuesBucket**.<br>-&nbsp;**rdbPredicates**: conditions for updating data.<br>-&nbsp;**callback**: callback invoked to return the number of rows updated.|
| RdbStore | update(values:&nbsp;ValuesBucket,&nbsp;rdbPredicates:&nbsp;RdbPredicates):&nbsp;Promise | Updates data in the RDB store based on the specified **RdbPredicates** object. This method uses a promise to return the result.<br>-&nbsp;**values**: data to update, which is stored in a **ValuesBucket**.<br>-&nbsp;**rdbPredicates**: conditions for updating data.| | RdbStore | update(values:&nbsp;ValuesBucket,&nbsp;rdbPredicates:&nbsp;RdbPredicates):&nbsp;Promise | Updates data in the RDB store based on the specified **RdbPredicates** object. This method uses a promise to return the result.<br>-&nbsp;**values**: data to update, which is stored in a **ValuesBucket**.<br>-&nbsp;**rdbPredicates**: conditions for updating data.|
- **Deleting data**<br/> - **Deleting data**
Call the **delete()** method to delete data meeting the conditions specified by **RdbPredicates**. If the data is deleted, the number of rows of the deleted data will be returned; otherwise, **0** will be returned. Call the **delete()** method to delete data meeting the conditions specified by **RdbPredicates**. If the data is deleted, the number of rows of the deleted data will be returned; otherwise, **0** will be returned.
**Table 4** APIs for deleting data **Table 4** APIs for deleting data
| Class| API| Description| | Class| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
| RdbStore | delete(rdbPredicates:&nbsp;RdbPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):void | Deletes data from the RDB store based on the specified **RdbPredicates** object. This method uses a callback to return the result.<br>-&nbsp;**rdbPredicates**: conditions for deleting data.<br>-&nbsp;**callback**: callback invoked to return the number of rows deleted.| | RdbStore | delete(rdbPredicates:&nbsp;RdbPredicates,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):void | Deletes data from the RDB store based on the specified **RdbPredicates** object. This method uses a callback to return the result.<br>-&nbsp;**rdbPredicates**: conditions for deleting data.<br>-&nbsp;**callback**: callback invoked to return the number of rows deleted.|
| RdbStore | delete(rdbPredicates:&nbsp;RdbPredicates):&nbsp;Promise | Deletes data from the RDB store based on the specified **RdbPredicates** object. This method uses a promise to return the result.<br>-&nbsp;**rdbPredicates**: conditions for deleting data.| | RdbStore | delete(rdbPredicates:&nbsp;RdbPredicates):&nbsp;Promise | Deletes data from the RDB store based on the specified **RdbPredicates** object. This method uses a promise to return the result.<br>-&nbsp;**rdbPredicates**: conditions for deleting data.|
- **Querying data**
- **Querying data**<br/>
You can query data in an RDB store in either of the following ways: You can query data in an RDB store in either of the following ways:
- Call the **query()** method to query data based on the predicates, without passing any SQL statement. - Call the **query()** method to query data based on the predicates, without passing any SQL statement.
- Run the native SQL statement. - Run the native SQL statement.
**Table 5** APIs for querying data **Table 5** APIs for querying data
| Class| API| Description| | Class| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
| RdbStore | query(rdbPredicates:&nbsp;RdbPredicates,&nbsp;columns:&nbsp;Array,&nbsp;callback:&nbsp;AsyncCallback&lt;ResultSet&gt;):&nbsp;void | Queries data in the RDB store based on the specified **RdbPredicates** object. This method uses a callback to return the result.<br>-&nbsp;**rdbPredicates**: conditions for querying data.<br>-&nbsp;**columns**: columns to query. If this parameter is not specified, the query applies to all columns.<br>-&nbsp;**callback**: callback invoked to return the result. If the operation is successful, a **ResultSet** object will be returned.| | RdbStore | query(rdbPredicates:&nbsp;RdbPredicates,&nbsp;columns:&nbsp;Array,&nbsp;callback:&nbsp;AsyncCallback&lt;ResultSet&gt;):&nbsp;void | Queries data in the RDB store based on the specified **RdbPredicates** object. This method uses a callback to return the result.<br>-&nbsp;**rdbPredicates**: conditions for querying data.<br>-&nbsp;**columns**: columns to query. If this parameter is not specified, the query applies to all columns.<br>-&nbsp;**callback**: callback invoked to return the result. If the operation is successful, a **ResultSet** object will be returned.|
...@@ -69,7 +73,7 @@ The RDB provides APIs for inserting, deleting, updating, and querying data in th ...@@ -69,7 +73,7 @@ The RDB provides APIs for inserting, deleting, updating, and querying data in th
| RdbStore | querySql(sql:&nbsp;string,&nbsp;bindArgs:&nbsp;Array&lt;ValueType&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;ResultSet&gt;):void | Queries data in the RDB store using the specified SQL statement. This method uses a callback to return the result.<br>-&nbsp;**sql**: SQL statement.<br>-&nbsp;**bindArgs**: arguments in the SQL statement.<br>-&nbsp;**callback**: callback invoked to return the result. If the operation is successful, a **ResultSet** object will be returned.| | RdbStore | querySql(sql:&nbsp;string,&nbsp;bindArgs:&nbsp;Array&lt;ValueType&gt;,&nbsp;callback:&nbsp;AsyncCallback&lt;ResultSet&gt;):void | Queries data in the RDB store using the specified SQL statement. This method uses a callback to return the result.<br>-&nbsp;**sql**: SQL statement.<br>-&nbsp;**bindArgs**: arguments in the SQL statement.<br>-&nbsp;**callback**: callback invoked to return the result. If the operation is successful, a **ResultSet** object will be returned.|
| RdbStore | querySql(sql:&nbsp;string,&nbsp;bindArgs?:&nbsp;Array&lt;ValueType&gt;):Promise&lt;ResultSet&gt; | Queries data in the RDB store using the specified SQL statement. This method uses a promise to return the result.<br>-&nbsp;**sql**: SQL statement.<br>-&nbsp;**bindArgs**: arguments in the SQL statement.| | RdbStore | querySql(sql:&nbsp;string,&nbsp;bindArgs?:&nbsp;Array&lt;ValueType&gt;):Promise&lt;ResultSet&gt; | Queries data in the RDB store using the specified SQL statement. This method uses a promise to return the result.<br>-&nbsp;**sql**: SQL statement.<br>-&nbsp;**bindArgs**: arguments in the SQL statement.|
**Using Predicates** ### Using Predicates
The RDB provides **RdbPredicates** for you to set database operation conditions. The RDB provides **RdbPredicates** for you to set database operation conditions.
...@@ -108,12 +112,12 @@ The RDB provides **RdbPredicates** for you to set database operation conditions. ...@@ -108,12 +112,12 @@ The RDB provides **RdbPredicates** for you to set database operation conditions.
| RdbPredicates | in(field:&nbsp;string,&nbsp;value:&nbsp;Array&lt;ValueType&gt;):&nbsp;RdbPredicates | Sets the **RdbPredicates** to match the field with data type **Array&#60;ValueType&#62;** and value within the specified range.<br>-&nbsp;**field**: column name in the database table.<br>-&nbsp;**value**: array of **ValueType** to match.<br>-&nbsp;**RdbPredicates**: returns a **RdbPredicates** object that matches the specified field.| | RdbPredicates | in(field:&nbsp;string,&nbsp;value:&nbsp;Array&lt;ValueType&gt;):&nbsp;RdbPredicates | Sets the **RdbPredicates** to match the field with data type **Array&#60;ValueType&#62;** and value within the specified range.<br>-&nbsp;**field**: column name in the database table.<br>-&nbsp;**value**: array of **ValueType** to match.<br>-&nbsp;**RdbPredicates**: returns a **RdbPredicates** object that matches the specified field.|
| RdbPredicates | notIn(field:&nbsp;string,&nbsp;value:&nbsp;Array&lt;ValueType&gt;):&nbsp;RdbPredicates | Sets the **RdbPredicates** to match the field with data type **Array&#60;ValueType&#62;** and value out of the specified range.<br>-&nbsp;**field**: column name in the database table.<br>-&nbsp;**value**: array of **ValueType** to match.<br>-&nbsp;**RdbPredicates**: returns a **RdbPredicates** object that matches the specified field.| | RdbPredicates | notIn(field:&nbsp;string,&nbsp;value:&nbsp;Array&lt;ValueType&gt;):&nbsp;RdbPredicates | Sets the **RdbPredicates** to match the field with data type **Array&#60;ValueType&#62;** and value out of the specified range.<br>-&nbsp;**field**: column name in the database table.<br>-&nbsp;**value**: array of **ValueType** to match.<br>-&nbsp;**RdbPredicates**: returns a **RdbPredicates** object that matches the specified field.|
**Using the Result Set** ### Using the Result Set
A result set can be regarded as a row of data in the queried results. It allows you to traverse and access the data you have queried. The following table describes the external APIs of **ResultSet**. A result set can be regarded as a row of data in the queried results. It allows you to traverse and access the data you have queried. The following table describes the external APIs of **ResultSet**.
> ![icon-notice.gif](../public_sys-resources/icon-notice.gif) **NOTICE**<br/> > ![icon-notice.gif](../public_sys-resources/icon-notice.gif) **NOTICE**<br/>
> After a result set is used, you must call the **close()** method to close it explicitly. > After a result set is used, you must call the **close()** method to close it explicitly.**
**Table 7** APIs for using the result set **Table 7** APIs for using the result set
...@@ -133,26 +137,13 @@ A result set can be regarded as a row of data in the queried results. It allows ...@@ -133,26 +137,13 @@ A result set can be regarded as a row of data in the queried results. It allows
| ResultSet | isColumnNull(columnIndex:&nbsp;number):&nbsp;boolean | Checks whether the value in the specified column of the current row is null.| | ResultSet | isColumnNull(columnIndex:&nbsp;number):&nbsp;boolean | Checks whether the value in the specified column of the current row is null.|
| ResultSet | close():&nbsp;void | Closes the result set.| | ResultSet | close():&nbsp;void | Closes the result set.|
**Changing the Encryption Key for an RDB Store**
You can encrypt an RDB store.
When creating an RDB store, you can add a key for security purposes. After that, the RDB store can be accessed only with the correct key. You can change the key but cannot delete it.
Once an RDB store is created without a key, you can no longer add a key for it.
**Table 8** APIs for changing the encryption key ### Setting Distributed Tables
| Class| API| Description|
| -------- | -------- | -------- |
| RdbStore | changeEncryptKey(newEncryptKey:Uint8Array,&nbsp;callback:&nbsp;AsyncCallback&lt;number&gt;):void; | Changes the encryption key for this RDB store. This method uses a callback to return the result. If the operation is successful, **0** will be returned. Otherwise, a non-zero value will be returned.|
| RdbStore | changeEncryptKey(newEncryptKey:Uint8Array):&nbsp;Promise&lt;number&gt;; | Changes the encryption key for this RDB store. This method uses a promise to return the result. If the operation is successful, **0** will be returned. Otherwise, a non-zero value will be returned.|
**Setting Distributed Tables** **Setting Distributed Tables**
You can set a list of distributed tables for data operations across devices. **Table 8** APIs for setting distributed tables
**Table 9** APIs for setting distributed tables
| Class| API| Description| | Class| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
...@@ -163,7 +154,7 @@ You can set a list of distributed tables for data operations across devices. ...@@ -163,7 +154,7 @@ You can set a list of distributed tables for data operations across devices.
You can obtain the distributed table name for a remote device based on the local table name. The distributed table name can be used to query the RDB store of the remote device. You can obtain the distributed table name for a remote device based on the local table name. The distributed table name can be used to query the RDB store of the remote device.
**Table 10** API for obtaining the distributed table name of a remote device **Table 9** APIs for obtaining the distributed table name of a remote device
| Class| API| Description| | Class| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
...@@ -172,17 +163,16 @@ You can obtain the distributed table name for a remote device based on the local ...@@ -172,17 +163,16 @@ You can obtain the distributed table name for a remote device based on the local
**Synchronizing Data Between Devices** **Synchronizing Data Between Devices**
**Table 11** APIs for synchronizing data between devices **Table 10** APIs for synchronizing data between devices
| Class| API| Description| | Class| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
| RdbStore | sync(mode: SyncMode, predicates: RdbPredicates, callback: AsyncCallback<Array<[string, number]>>): void;| Synchronizes data between devices. This method uses a callback to return the result.<br>-&nbsp;**mode**: data synchronization mode. **SYNC\_MODE\_PUSH** means to push data from the local device to a remote device. **SYNC\_MODE\_PULL** means to pull data from a remote device to the local device.<br>-&nbsp;**predicates**: data and devices to be synchronized.<br>-&nbsp;**callback**: callback invoked to return the result. In the result, **string** indicates the device ID, and **number** indicates the synchronization status of each device. The value **0** indicates a success, and other values indicate a failure.| | RdbStore | sync(mode: SyncMode, predicates: RdbPredicates, callback: AsyncCallback<Array<[string, number]>>): void;| Synchronizes data between devices. This method uses a callback to return the result.<br>-&nbsp;**mode**: data synchronization mode. **SYNC\_MODE\_PUSH** means to push data from the local device to a remote device. **SYNC\_MODE\_PULL** means to pull data from a remote device to the local device.<br>-&nbsp;**predicates**: data and devices to be synchronized.<br>-&nbsp;**callback**: callback invoked to return the result. In the result, **string** indicates the device ID, and **number** indicates the synchronization status of each device. The value **0** indicates a success, and other values indicate a failure.|
| RdbStore | sync(mode: SyncMode, predicates: RdbPredicates): Promise<Array<[string, number]>>;| Synchronizes data between devices. This method uses a promise to return the result.<br>-&nbsp;**mode**: data synchronization mode. **SYNC\_MODE\_PUSH** means to push data from the local device to a remote device. **SYNC\_MODE\_PULL** means to pull data from a remote device to the local device.<br>-&nbsp;**predicates**: data and devices to be synchronized. | | RdbStore | sync(mode: SyncMode, predicates: RdbPredicates): Promise<Array<[string, number]>>;| Synchronizes data between devices. This method uses a promise to return the result.<br>-&nbsp;**mode**: data synchronization mode. **SYNC\_MODE\_PUSH** means to push data from the local device to a remote device. **SYNC\_MODE\_PULL** means to pull data from a remote device to the local device.<br>-&nbsp;**predicates**: data and devices to be synchronized. |
**Registering an RDB Store Observer** **Registering an RDB Store Observer**
**Table 12** API for registering an observer **Table 11** API for registering an observer
| Class| API| Description| | Class| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
...@@ -190,7 +180,7 @@ You can obtain the distributed table name for a remote device based on the local ...@@ -190,7 +180,7 @@ You can obtain the distributed table name for a remote device based on the local
**Unregistering an RDB Store Observer** **Unregistering an RDB Store Observer**
**Table 13** API for unregistering an observer **Table 12** API for unregistering an observer
| Class| API| Description| | Class| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
...@@ -211,9 +201,10 @@ You can obtain the distributed table name for a remote device based on the local ...@@ -211,9 +201,10 @@ You can obtain the distributed table name for a remote device based on the local
const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)";
const STORE_CONFIG = {name: "rdbstore.db",} const STORE_CONFIG = {name: "rdbstore.db",}
data_rdb.getRdbStore(STORE_CONFIG, 1, function (err, rdbStore) {
let rdbStore = await data_rdb.getRdbStore(STORE_CONFIG, 1); rdbStore.executeSql(SQL_CREATE_TABLE)
await rdbStore.executeSql(CREATE_TABLE_TEST); console.info('create table done.')
})
``` ```
2. Insert data. 2. Insert data.
...@@ -238,16 +229,16 @@ You can obtain the distributed table name for a remote device based on the local ...@@ -238,16 +229,16 @@ You can obtain the distributed table name for a remote device based on the local
``` ```
let predicates = new data_rdb.RdbPredicates("test"); let predicates = new data_rdb.RdbPredicates("test");
predicates.equalTo("name", "Tom") predicates.equalTo("name", "Tom")
let resultSet = await rdbStore.query(predicates) let promisequery = rdbStore.query(predicates)
promisequery.then((resultSet) => {
resultSet.goToFirstRow() resultSet.goToFirstRow()
const id = await resultSet.getLong(resultSet.getColumnIndex("id")) const id = resultSet.getLong(resultSet.getColumnIndex("id"))
const name = await resultSet.getString(resultSet.getColumnIndex("name")) const name = resultSet.getString(resultSet.getColumnIndex("name"))
const age = await resultSet.getLong(resultSet.getColumnIndex("age")) const age = resultSet.getLong(resultSet.getColumnIndex("age"))
const salary = await resultSet.getDouble(resultSet.getColumnIndex("salary")) const salary = resultSet.getDouble(resultSet.getColumnIndex("salary"))
const blobType = await resultSet.getBlob(resultSet.getColumnIndex("blobType")) const blobType = resultSet.getBlob(resultSet.getColumnIndex("blobType"))
resultSet.close()
resultSet.close() })
``` ```
4. Set the distributed tables to be synchronized. 4. Set the distributed tables to be synchronized.
...@@ -261,7 +252,7 @@ You can obtain the distributed table name for a remote device based on the local ...@@ -261,7 +252,7 @@ You can obtain the distributed table name for a remote device based on the local
promise.then(() => { promise.then(() => {
console.info("setDistributedTables success.") console.info("setDistributedTables success.")
}).catch((err) => { }).catch((err) => {
console.info("setDistributedTables failed."") console.info("setDistributedTables failed.")
}) })
``` ```
...@@ -276,7 +267,7 @@ You can obtain the distributed table name for a remote device based on the local ...@@ -276,7 +267,7 @@ You can obtain the distributed table name for a remote device based on the local
let predicate = new data_rdb.RdbPredicates('test') let predicate = new data_rdb.RdbPredicates('test')
predicate.inDevices(['12345678abcde']) predicate.inDevices(['12345678abcde'])
let promise = rdbStore.sync(rdb.SyncMode.SYNC_MODE_PUSH, predicate) let promise = rdbStore.sync(rdb.SyncMode.SYNC_MODE_PUSH, predicate)
promise.then(result) { promise.then((result) => {
console.log('sync done.') console.log('sync done.')
for (let i = 0; i < result.length; i++) { for (let i = 0; i < result.length; i++) {
console.log('device=' + result[i][0] + ' status=' + result[i][1]) console.log('device=' + result[i][0] + ' status=' + result[i][1])
......
...@@ -22,16 +22,16 @@ ...@@ -22,16 +22,16 @@
## Available APIs ## Available APIs
| Module | API | Description | | Module| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
| ohos.sensor | sensor.on(sensorType,callback:AsyncCallback&lt;Response&gt;):void | Subscribes to data changes of a type of sensor. | | ohos.sensor | sensor.on(sensorType, callback:AsyncCallback&lt;Response&gt;): void | Subscribes to data changes of a type of sensor.|
| ohos.sensor | sensor.once(sensorType,callback:AsyncCallback&lt;Response&gt;):void | Subscribes to only one data change of a type of sensor. | | ohos.sensor | sensor.once(sensorType, callback:AsyncCallback&lt;Response&gt;): void | Subscribes to only one data change of a type of sensor.|
| ohos.sensor | sensor.off(sensorType,callback:AsyncCallback&lt;void&gt;):void | Unsubscribes from sensor data changes. | | ohos.sensor | sensor.off(sensorType, callback:AsyncCallback&lt;void&gt;): void | Unsubscribes from sensor data changes.|
## How to Develop ## How to Develop
1. To obtain data from a type of sensor, configure the request permissions in the **config.json** file. 1. To obtain data from a type of sensor, configure the request permissions in the **config.json** file.
``` ```
"reqPermissions":[ "reqPermissions":[
...@@ -67,67 +67,59 @@ ...@@ -67,67 +67,59 @@
"when":"inuse" "when":"inuse"
} }
}, },
{
"name":"ohos.permission.VIBRATE",
"reason"":"",
"usedScene":{
"ability": [".MainAbility"],
"when":"inuse"
}
},
] ]
``` ```
2. Subscribe to data changes of a type of sensor. 2. Subscribe to data changes of a type of sensor.
``` ```
import sensor from "@ohos.sensor" import sensor from "@ohos.sensor"
sensor.on(type:sensorType,function(error,data){ sensor.on(sensor.sensorType.SENSOR_TYPE_ACCELEROMETER,function(data){
if (error) {// The call fails, and error.code and error.message are printed.
console.error("Subscription failed. Error code: " + error.code + "; message: " + error.message);
return;
};
console.info("Subscription succeeded. data = "+ data);// The call is successful, and the obtained sensor data is printed. console.info("Subscription succeeded. data = "+ data);// The call is successful, and the obtained sensor data is printed.
} }
); );
``` ```
The following figure shows the successful call result when **SensorType** is **SENSOR_TYPE_ID_ACCELEROMETER**. The following figure shows the successful call result when **SensorType** is **SENSOR_TYPE_ID_ACCELEROMETER**.
![en-us_image_0000001241693881](figures/en-us_image_0000001241693881.png) ![en-us_image_0000001241693881](figures/en-us_image_0000001241693881.png)
3. Unsubscribe from sensor data changes. 3. Unsubscribe from sensor data changes.
``` ```
import sensor from "@ohos.sensor" import sensor from "@ohos.sensor"
sensor.off(type:sensorType,function(error) { sensor.off(sensor.sensorType.SENSOR_TYPE_ACCELEROMETER,function() {
if (error) {// The unsubscription fails, and error.code and error.message are printed.
console.error("Failed to unsubscribe from acceleration sensor data. Error code: " + error.code + "; message: " + error.message);
return;
};
console.info("Succeeded in unsubscribing from acceleration sensor data.");// The unsubscription is successful, and the result is printed. console.info("Succeeded in unsubscribing from acceleration sensor data.");// The unsubscription is successful, and the result is printed.
} }
); );
``` ```
The following figure shows the successful call result when **SensorType** is **SENSOR_TYPE_ID_ACCELEROMETER**. The following figure shows the successful call result when **SensorType** is **SENSOR_TYPE_ID_ACCELEROMETER**.
![en-us_image_0000001196654004](figures/en-us_image_0000001196654004.png) ![en-us_image_0000001196654004](figures/en-us_image_0000001196654004.png)
4. Subscribe to only one data change of a type of sensor. 4. Subscribe to only one data change of a type of sensor.
``` ```
import sensor from "@ohos.sensor" import sensor from "@ohos.sensor"
sensor.once(tyep:sensorType,function(error, data) { sensor.once(sensor.sensorType.SENSOR_TYPE_ACCELEROMETER,function(data) {
if (error) {// The call fails, and error.code and error.message are printed. console.info("Data obtained successfully. data=" + data);// The call is successful, and the obtained sensor data is printed.
console.error("Failed to obtain data. Error code: " + error.code + "; message: " + error.message);
return;
};
console.info("Data obtained successfully. data="+data);// The call is successful, and the obtained sensor data is printed.
} }
); );
``` ```
The following figure shows the successful call result when **SensorType** is **SENSOR_TYPE_ID_ACCELEROMETER**. The following figure shows the successful call result when **SensorType** is **SENSOR_TYPE_ID_ACCELEROMETER**.
![en-us_image_0000001241733907](figures/en-us_image_0000001241733907.png) ![en-us_image_0000001241733907](figures/en-us_image_0000001241733907.png)
If the API fails to be called, you are advised to use the **try/catch** statement to capture error information that may occur in the code. Example:
```
try {
sensor.once(sensor.sensorType.SENSOR_TYPE_ACCELEROMETER,function(data) {
console.info("Data obtained successfully. data=" + data);// The call is successful, and the obtained sensor data is printed.
});
} catch (error) {
console.error(error);
}
```
...@@ -170,9 +170,9 @@ You can set a USB device as a host to connect to a device for data transfer. The ...@@ -170,9 +170,9 @@ You can set a USB device as a host to connect to a device for data transfer. The
var pipe = usb.connectDevice(deviceList[0]); var pipe = usb.connectDevice(deviceList[0]);
/* /*
Claim the corresponding interface from deviceList. Claim the corresponding interface from deviceList.
interface must be one present in the device configuration. interface1 must be one present in the device configuration.
*/ */
usb.claimInterface(pipe , interface, true); usb.claimInterface(pipe , interface1, true);
``` ```
4. Perform data transfer. 4. Perform data transfer.
......
...@@ -8,20 +8,20 @@ You can set different vibration effects as needed, for example, customizing vibr ...@@ -8,20 +8,20 @@ You can set different vibration effects as needed, for example, customizing vibr
## Available APIs ## Available APIs
| Module | API | Description | | Module| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
| ohos.vibrator | vibrate(duration:&nbsp;number):&nbsp;Promise&lt;void&gt; | Triggers&nbsp;vibration&nbsp;with&nbsp;the&nbsp;specified&nbsp;duration.&nbsp;This&nbsp;API&nbsp;uses&nbsp;a&nbsp;promise&nbsp;to&nbsp;return&nbsp;the&nbsp;result. | | ohos.vibrator | vibrate(duration:&nbsp;number):&nbsp;Promise&lt;void&gt; | Triggers vibration with the specified duration. This API uses a promise to return the result.|
| ohos.vibrator | vibrate(duration:&nbsp;number,&nbsp;callback?:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void | Triggers&nbsp;vibration&nbsp;with&nbsp;the&nbsp;specified&nbsp;duration.&nbsp;This&nbsp;API&nbsp;uses&nbsp;a&nbsp;callback&nbsp;to&nbsp;return&nbsp;the&nbsp;result. | | ohos.vibrator | vibrate(duration:&nbsp;number,&nbsp;callback?:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void | Triggers vibration with the specified duration. This API uses a callback to return the result.|
| ohos.vibrator | vibrate(effectId:&nbsp;EffectId):&nbsp;Promise&lt;void&gt; | Triggers&nbsp;vibration&nbsp;with&nbsp;the&nbsp;specified&nbsp;effect.&nbsp;This&nbsp;API&nbsp;uses&nbsp;a&nbsp;promise&nbsp;to&nbsp;return&nbsp;the&nbsp;result. | | ohos.vibrator | vibrate(effectId:&nbsp;EffectId):&nbsp;Promise&lt;void&gt; | Triggers vibration with the specified effect. This API uses a promise to return the result.|
| ohos.vibrator | vibrate(effectId:&nbsp;EffectId,&nbsp;callback?:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void | Triggers&nbsp;vibration&nbsp;with&nbsp;the&nbsp;specified&nbsp;effect.&nbsp;This&nbsp;API&nbsp;uses&nbsp;a&nbsp;callback&nbsp;to&nbsp;return&nbsp;the&nbsp;result. | | ohos.vibrator | vibrate(effectId:&nbsp;EffectId,&nbsp;callback?:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void | Triggers vibration with the specified effect. This API uses a callback to return the result.|
| ohos.vibrator | stop(stopMode:&nbsp;VibratorStopMode):&nbsp;Promise&lt;void&gt; | Stops&nbsp;vibration.&nbsp;This&nbsp;API&nbsp;uses&nbsp;a&nbsp;promise&nbsp;to&nbsp;return&nbsp;the&nbsp;result. | | ohos.vibrator | stop(stopMode:&nbsp;VibratorStopMode):&nbsp;Promise&lt;void&gt; | Stops vibration. This API uses a promise to return the result.|
| ohos.vibrator | stop(stopMode:&nbsp;VibratorStopMode,&nbsp;callback?:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void | Stops&nbsp;vibration.&nbsp;This&nbsp;API&nbsp;uses&nbsp;a&nbsp;callback&nbsp;to&nbsp;return&nbsp;the&nbsp;result. | | ohos.vibrator | stop(stopMode:&nbsp;VibratorStopMode,&nbsp;callback?:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void | Stops vibration. This API uses a callback to return the result.|
## How to Develop ## How to Develop
1. Declare the permissions required for controlling vibrators on the hardware device in the **config.json** file. 1. Declare the permissions required for controlling vibrators on the hardware device in the **config.json** file.
``` ```
"reqPermissions":[ "reqPermissions":[
{ {
...@@ -58,26 +58,26 @@ You can set different vibration effects as needed, for example, customizing vibr ...@@ -58,26 +58,26 @@ You can set different vibration effects as needed, for example, customizing vibr
``` ```
2. Trigger the device to vibrate. 2. Trigger the device to vibrate.
``` ```
import vibrator from "@ohos.vibrator" import vibrator from "@ohos.vibrator"
vibrator.vibrate(duration: number).then((error)=>{ vibrator.vibrate(1000).then((error)=>{
if(error){// The call fails, and error.code and error.message are printed. if (error) {// The call fails, and error.code and error.message are printed.
console.log("Promise return failed.error.code"+error.code+"error.message"+error.message); Console.log("Promise return failed.error.code"+error.code+"error.message"+error.message);
}else{// The call succeeded. The device starts to vibrate. }else{// The call is successful, and the device starts to vibrate.
console.log("Promise returned to indicate a successful vibration.") Console.log("Promise returned to indicate a successful vibration.")
}; };
}) })
``` ```
3. Stop the vibration. 3. Stop the vibration.
``` ```
import vibrator from "@ohos.vibrator" import vibrator from "@ohos.vibrator"
vibrator.stop(stopMode: VibratorStopMode).then((error)=>{ vibrator.stop(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_PRESET).then((error)=>{
if(error){// The call fails, and error.code and error.message are printed. if (error) {// The call fails, and error.code and error.message are printed.
console.log("Promise return failed. error.code"+error.code+"error.message"+error.message); Console.log("Promise return failed.error.code"+error.code+"error.message"+error.message);
}else{// The call succeeded. The device stops vibration. }else{// The call is successful, and the device stops vibration.
Console.log("Promise returned to indicate a successful stop."); Console.log("Promise returned to indicate a successful stop.");
}; };
}) })
......
...@@ -6,10 +6,11 @@ The vibrator service opens up the latest capabilities of the vibrator hardware t ...@@ -6,10 +6,11 @@ The vibrator service opens up the latest capabilities of the vibrator hardware t
## Working Principles ## Working Principles
The vibrator is a Misc device that consists of four modules: Vibrator API, Vibrator Framework, Vibrator Service, and HD_IDL. The vibrator is a Misc device that consists of four modules: Vibrator API, Vibrator Framework, Vibrator Service, and HDF layer.
**Figure1** Vibrator in Misc devices **Figure 1** Vibrator in Misc devices
![en-us_image_0000001180249428](figures/en-us_image_0000001180249428.png)
![0752d302-aeb9-481a-bb8f-e5524eb61eeb](figures/0752d302-aeb9-481a-bb8f-e5524eb61eeb.png)
- Vibrator API: provides basic vibrator APIs, including the APIs for querying the vibrator list, querying the vibrator by effect, and triggering and stopping vibration. - Vibrator API: provides basic vibrator APIs, including the APIs for querying the vibrator list, querying the vibrator by effect, and triggering and stopping vibration.
...@@ -17,9 +18,9 @@ The vibrator is a Misc device that consists of four modules: Vibrator API, Vibra ...@@ -17,9 +18,9 @@ The vibrator is a Misc device that consists of four modules: Vibrator API, Vibra
- Vibrator Service: manages services of vibrators. - Vibrator Service: manages services of vibrators.
- HD_IDL: adapts to different devices. - HDF layer: adapts to different devices.
## Constraints ## Constraints
When using a vibrator, you need to declare and obtain the **ohos.permission.VIBRATE** permission first so that you can control the vibration effect. When using a vibrator, you must declare the **ohos.permission.VIBRATE** permission before you can control the vibration effect. The sensitivity level of this permission is **system_grant**.
...@@ -8,69 +8,21 @@ The event logging function helps applications log various information generated ...@@ -8,69 +8,21 @@ The event logging function helps applications log various information generated
JS application event logging APIs are provided by the **hiAppEvent** module. JS application event logging APIs are provided by the **hiAppEvent** module.
**APIs for event logging:** **APIs for Event Logging**
| API | Return Value | Description | | API | Return Value | Description |
| ------------------------------------------------------------ | -------------- | ------------------------------------------------------------ | | ------------------------------------------------------------ | -------------- | ------------------------------------------------------------ |
| write(string eventName, EventType type, object keyValues, AsyncCallback\<void> callback): void | void | Logs application events in asynchronous mode. This method uses an asynchronous callback to return the result. | | write(string eventName, EventType type, object keyValues, AsyncCallback\<void> callback): void | void | Logs application events in asynchronous mode. This method uses an asynchronous callback to return the result. |
| write(string eventName, EventType type, object keyValues): Promise\<void> | Promise\<void> | Logs application events in asynchronous mode. This method uses a promise to return the result. | | write(string eventName, EventType type, object keyValues): Promise\<void> | Promise\<void> | Logs application events in asynchronous mode. This method uses a promise to return the result. |
- **eventName**: event name you customized. The event name can contain a maximum of 48 characters, including digits (0 to 9), letters (a to z), and underscores (\_). It must start with a letter.
- **type**: event type enumerated by **EventType**.
| Type | Description |
| --------- | ----------------- |
| FAULT | Fault event |
| STATISTIC | Statistical event |
| SECURITY | Security event |
| BEHAVIOR | Behavior event |
- **keyValues**: event parameter key-value pair. For a variable-length parameter, enter each pair of parameter name and value in sequence. For a JSON parameter, enter the parameter name as the key and parameter value as the value.
- A parameter name must be a string, and a parameter value must be a string, number, boolean, or array (which is a basic element).
- The number of event parameters must be less than or equal to 32.
- The parameter name can contain a maximum of 16 characters, including digits (0 to 9), letters (a to z), and underscores (\_). It must start with a letter and cannot end with an underscore (\_).
- A string value can contain a maximum of 8*1024 characters.
- An array value can contain a maximum of 100 elements. Excess elements will be truncated.
- **callback**: callback function used to process the received return value. The value **0** indicates that the event parameter verification is successful, and the event will be written to the event file asynchronously. A value greater than **0** indicates that invalid parameters are present in the event, and the event will be written to the event file asynchronously after the invalid parameters are ignored. A value smaller than **0** indicates that the event parameter verification fails, and the event will not be written to the event file asynchronously.
When an asynchronous callback is used, the return value can be processed directly in the callback. When a promise is used, the return value can also be processed in the promise in a similar way. For details about the result codes, see [Event Verification Result Codes](hiappevent-overview.md#Event Verification Result Codes). When an asynchronous callback is used, the return value can be processed directly in the callback. When a promise is used, the return value can also be processed in the promise in a similar way. For details about the result codes, see [Event Verification Result Codes](hiappevent-overview.md#Event Verification Result Codes).
**APIs for event logging configuration:** **APIs for Event Logging Configuration**
| API | Return Value | Description | | API | Return Value | Description |
| ------------------------------ | ------------ | ------------------------------------------------------------ | | ------------------------------ | ------------ | ------------------------------------------------------------ |
| configure(ConfigOption config) | boolean | Sets the configuration options for application event logging.<br/>The value **true** indicates that the operation is successful, and value **false** indicates the opposite. | | configure(ConfigOption config) | boolean | Sets the configuration options for application event logging.<br/>The value **true** indicates that the operation is successful, and value **false** indicates the opposite. |
- **config**: configuration options for application event logging.
Configuration options for application event logging (**ConfigOption**)
| Name | Type | Mandatory | Description |
| ---------- | ------- | --------- | ------------------------------------------------------------ |
| disable | boolean | No | Sets the application event logging switch. The value **true** means to disable the application event logging function, and value **false** means the opposite. |
| maxStorage | string | No | Specifies the maximum size of the event file storage directory. The default value is 10M. |
**Predefined event name constants (Event)**:
| Constant | Type | Description |
| ------------------------- | ------ | ---------------------------------------------- |
| USER_LOGIN | string | Name of the user login event. |
| USER_LOGOUT | string | Name of the user logout event. |
| DISTRIBUTED_SERVICE_START | string | Name of the distributed service startup event. |
**Predefined parameter name constants (Param):**
| Constant | Type | Description |
| ------------------------------- | ------ | -------------------------------- |
| USER_ID | string | Custom user ID. |
| DISTRIBUTED_SERVICE_NAME | string | Distributed service name. |
| DISTRIBUTED_SERVICE_INSTANCE_ID | string | Distributed service instance ID. |
## How to Develop ## How to Develop
In this example, an application event is logged after the application startup execution page is loaded. In this example, an application event is logged after the application startup execution page is loaded.
...@@ -103,8 +55,7 @@ In this example, an application event is logged after the application startup ex ...@@ -103,8 +55,7 @@ In this example, an application event is logged after the application startup ex
}).catch((err) => { }).catch((err) => {
console.error(`failed to write event because ${err.code}`); console.error(`failed to write event because ${err.code}`);
}); });
});
// 3. Set the application event logging switch. // 3. Set the application event logging switch.
hiAppEvent.configure({ hiAppEvent.configure({
disable: true disable: true
...@@ -118,6 +69,4 @@ In this example, an application event is logged after the application startup ex ...@@ -118,6 +69,4 @@ In this example, an application event is logged after the application startup ex
} }
``` ```
2. Tap the run button on the application UI to run the project. 2. Tap the run button on the application UI to run the project.
\ No newline at end of file
...@@ -6,9 +6,7 @@ HiAppEvent provides event logging APIs for applications to log the fault, statis ...@@ -6,9 +6,7 @@ HiAppEvent provides event logging APIs for applications to log the fault, statis
The HiAppEvent module of OpenHarmony can be used to develop application event services and provide functions related to application events, including flushing application events to a disk and querying historical application event data. The HiAppEvent module of OpenHarmony can be used to develop application event services and provide functions related to application events, including flushing application events to a disk and querying historical application event data.
- **Logging** **Logging**: Logs changes caused by user operations to provide service data for development, product, and O&M analysis.
Logs changes caused by user operations to provide service data for development, product, and O&M analysis.
## Event Verification Result Codes ## Event Verification Result Codes
......
...@@ -6,18 +6,14 @@ ...@@ -6,18 +6,14 @@
- [Audio Playback Development](audio-playback.md) - [Audio Playback Development](audio-playback.md)
- [Audio Playback Development Using AudioRenderer](audio-renderer.md) - [Audio Rendering Development](audio-renderer.md)
- [Audio Recording Development](audio-recorder.md) - [Audio Recording Development](audio-recorder.md)
- [Audio Recorder Development Using AudioCapturer](audio-capturer) - [Audio Capture Development](audio-capturer)
- Video - Video
- [Video Playback Development](video-playback.md) - [Video Playback Development](video-playback.md)
- [Video Recording Development](video-recorder.md)
- Image - Image
- [Image Development](image.md) - [Image Development](image.md)
# Audio Recorder Development Using AudioCapturer # Audio Capture Development
--- ---
## ***Note***: ## ***Note***:
...@@ -41,7 +41,7 @@ Here's an example of how to use AudioCapturer to capture a raw audio file. ...@@ -41,7 +41,7 @@ Here's an example of how to use AudioCapturer to capture a raw audio file.
2. (Optional) Subscribe to audio capturer state change events using the **on('stateChange')** API. 2. (Optional) Subscribe to audio capturer state change events using the **on('stateChange')** API.
If an application wants to take some action based on the state updates in capturer, the application can subscribe to the state change event. If an application wants to take some action based on the state updates in capturer, the application can subscribe to the state change event.
There are more events that applications can subscribe to, such as 'markReach' and 'periodReach'. Refer to [**js-apis-audio.md**](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-audio.md) for more details. There are more events that applications can subscribe to, such as 'markReach' and 'periodReach'. Refer to [Audio](../reference/apis/js-apis-audio.md) for more details.
``` ```
audioCapturer.on('stateChange',(state) => { audioCapturer.on('stateChange',(state) => {
console.info('AudioCapturerLog: Changed State to : ' + state) console.info('AudioCapturerLog: Changed State to : ' + state)
...@@ -149,4 +149,4 @@ That is, the AudioCapturer has an internal state that the application must alway ...@@ -149,4 +149,4 @@ That is, the AudioCapturer has an internal state that the application must alway
The system may throw an error/exception or generate other undefined behaviour if the application performs an operation while capturer is in an improper state. The system may throw an error/exception or generate other undefined behaviour if the application performs an operation while capturer is in an improper state.
## **Other APIs** ## **Other APIs**
See [**js-apis-audio.md**](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-audio.md) for more useful APIs like **getAudioTime**, **getCapturerInfo** and **getStreamInfo**. See [AudioCapturer in the Audio API](../reference/apis/js-apis-audio.md) for more useful APIs like **getAudioTime**, **getCapturerInfo** and **getStreamInfo**.
...@@ -16,7 +16,7 @@ You can use audio playback APIs to convert audio data into audible analog signal ...@@ -16,7 +16,7 @@ You can use audio playback APIs to convert audio data into audible analog signal
## How to Develop ## How to Develop
For details about the APIs used for audio playback, see [js-apis-media.md](../reference/apis/js-apis-media.md). For details about the APIs used for audio playback, see [AudioPlayer in the Media API](../reference/apis/js-apis-media.md).
### Full-Process Scenario ### Full-Process Scenario
......
...@@ -16,7 +16,7 @@ During audio recording, audio signals are captured, encoded, and saved to files. ...@@ -16,7 +16,7 @@ During audio recording, audio signals are captured, encoded, and saved to files.
## How to Develop ## How to Develop
For details about the APIs used for audio recording, see [js-apis-media.md](../reference/apis/js-apis-media.md). For details about the APIs, see [AudioRecorder in the Media API](../reference/apis/js-apis-media.md).
### Full-Process Scenario ### Full-Process Scenario
...@@ -127,7 +127,7 @@ import mediaLibrary from '@ohos.multimedia.mediaLibrary' ...@@ -127,7 +127,7 @@ import mediaLibrary from '@ohos.multimedia.mediaLibrary'
let testFdNumber; let testFdNumber;
function SetCallBack(audioPlayer) { function SetCallBack(audioRecorder) {
audioRecorder.on('prepare', () => { // Set the 'prepare' event callback. audioRecorder.on('prepare', () => { // Set the 'prepare' event callback.
console.log('prepare success'); console.log('prepare success');
// The recording page is ready. You can click the Record button to start recording. // The recording page is ready. You can click the Record button to start recording.
......
# Audio Playback Development Using AudioRenderer # Audio Rendering Development
--- ---
## ***Note***: ## ***Note***:
...@@ -17,7 +17,7 @@ When a higher priority stream wants to play, the AudioRenderer framework interru ...@@ -17,7 +17,7 @@ When a higher priority stream wants to play, the AudioRenderer framework interru
For example, if a call is arrived when you listen to music, the music playback, which is the lower priority stream, is paused.\ For example, if a call is arrived when you listen to music, the music playback, which is the lower priority stream, is paused.\
With the sample code below, we'll look at how AudioInterrupt works in detail.\ With the sample code below, we'll look at how AudioInterrupt works in detail.\
<br/> <br/>
Please see [**js-apis-audio.md**](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-audio.md) for a list of supported audio stream types and formats, such as AudioSampleFormat, AudioChannel, AudioSampleFormat, and AudioEncodingType. Please see [AudioRenderer in the Audio API](../reference/apis/js-apis-audio.md#audiorenderer8) for a list of supported audio stream types and formats, such as AudioSampleFormat, AudioChannel, AudioSampleFormat, and AudioEncodingType.
## **Usage** ## **Usage**
...@@ -267,8 +267,8 @@ The system may throw an error/exception or generate other undefined behaviour if ...@@ -267,8 +267,8 @@ The system may throw an error/exception or generate other undefined behaviour if
## **Asynchronous Operations:** ## **Asynchronous Operations:**
Most of the AudioRenderer calls are asynchronous. As a result, the UI thread will not be blocked.\ Most of the AudioRenderer calls are asynchronous. As a result, the UI thread will not be blocked.\
For each API, the framework provides both callback and promises functions.\ For each API, the framework provides both callback and promises functions.\
In the example, promise functions are used for simplicity. [**js-apis-audio.md**](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-audio.md) In the example, promise functions are used for simplicity. [AudioRender in the Audio API](../reference/apis/js-apis-audio.md#audiorenderer8)
provides reference for both callback and promise. provides reference for both callback and promise.
## **Other APIs:** ## **Other APIs:**
See [**js-apis-audio.md**](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-audio.md) for more useful APIs like getAudioTime, drain, and getBufferSize. See [Audio](../reference/apis/js-apis-audio.md) for more useful APIs like getAudioTime, drain, and getBufferSize.
...@@ -6,7 +6,7 @@ You can use image development APIs to decode images into pixel maps and encode t ...@@ -6,7 +6,7 @@ You can use image development APIs to decode images into pixel maps and encode t
## Available APIs ## Available APIs
For details about the APIs, see [js-apis-image.md](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-image.md). For details about the APIs, see [Image Processing](../reference/apis/js-apis-image.md).
## How to Develop ## How to Develop
......
...@@ -20,9 +20,22 @@ Note: Video playback requires hardware capabilities such as display, audio, and ...@@ -20,9 +20,22 @@ Note: Video playback requires hardware capabilities such as display, audio, and
2. The third-party application transfers the surface ID to the VideoPlayer JS. 2. The third-party application transfers the surface ID to the VideoPlayer JS.
3. The media service flushes the frame data to the surface buffer. 3. The media service flushes the frame data to the surface buffer.
## Compatibility
You are advised to use the mainstream playback formats and resolutions, rather than custom or abnormal streams to avoid playback failure, frame freezing, and artifacts. The system is not affected by incompatibility issues. If such an error occurs, you can exit stream playback mode.
The table below lists the mainstream playback formats and resolutions.
| Video Container Specification| Specification Description | Resolution |
| :----------: | :-----------------------------------------------: | :--------------------------------: |
| mp4 | Video format: H.264/MPEG-2/MPEG-4/H.263; audio format: AAC/MP3| Mainstream resolutions, such as 1080p, 720p, 480p, and 270p|
| mkv | Video format: H.264/MPEG-2/MPEG-4/H.263; audio format: AAC/MP3| Mainstream resolutions, such as 1080p, 720p, 480p, and 270p|
| ts | Video format: H.264/MPEG-2/MPEG-4; audio format: AAC/MP3 | Mainstream resolutions, such as 1080p, 720p, 480p, and 270p|
| webm | Video format: VP8; audio format: VORBIS | Mainstream resolutions, such as 1080p, 720p, 480p, and 270p|
## How to Develop ## How to Develop
For details about the APIs used for video playback, see [js-apis-media.md](../reference/apis/js-apis-media.md). For details about the APIs, see [VideoPlayer in the Media API](../reference/apis/js-apis-media.md).
### Full-Process Scenario ### Full-Process Scenario
......
# Video Recording Development
## When to Use
During video recording, audio and video signals are captured, encoded, and saved to files. You can specify parameters such as the encoding format, encapsulation format, and file path for video recording.
**Figure 1** Video recording state transition
![en-us_image_video_recorder_state_machine](figures/en-us_image_video_recorder_state_machine.png)
**Figure 2** Layer 0 diagram of video recording
![en-us_image_video_recorder_zero](figures/en-us_image_video_recorder_zero.png)
## How to Develop
For details about the APIs used for video recording, see [js-apis-media.md](../reference/apis/js-apis-media.md).
### Full-Process Scenario
The full video recording process includes creating an instance, setting recording parameters, recording video, pausing, resuming, and stopping recording, and releasing resources.
```js
import media from '@ohos.multimedia.media'
import mediaLibrary from '@ohos.multimedia.mediaLibrary'
let testFdNumber;
// pathName indicates the passed recording file name, for example, 01.mp4. The generated file address is /storage/media/100/local/files/Movies/01.mp4.
// To use the media library, declare the following permissions: ohos.permission.MEDIA_LOCATION, ohos.permission.WRITE_MEDIA, and ohos.permission.READ_MEDIA.
async function getFd(pathName) {
let displayName = pathName;
const mediaTest = mediaLibrary.getMediaLibrary();
let fileKeyObj = mediaLibrary.FileKey;
let mediaType = mediaLibrary.MediaType.VIDEO;
let publicPath = await mediaTest.getPublicDirectory(mediaLibrary.DirectoryType.DIR_VIDEO);
let dataUri = await mediaTest.createAsset(mediaType, displayName, publicPath);
if (dataUri != undefined) {
let args = dataUri.id.toString();
let fetchOp = {
selections : fileKeyObj.ID + "=?",
selectionArgs : [args],
}
let fetchFileResult = await mediaTest.getFileAssets(fetchOp);
let fileAsset = await fetchFileResult.getAllObject();
let fdNumber = await fileAsset[0].open('Rw');
fdNumber = "fd://" + fdNumber.toString();
testFdNumber = fdNumber;
}
}
await getFd('01.mp4');
let videoProfile = {
audioBitrate : 48000,
audioChannels : 2,
audioCodec : 'audio/mp4a-latm',
audioSampleRate : 48000,
fileFormat : 'mp4',
videoBitrate : 48000,
videoCodec : 'video/mp4v-es',
videoFrameWidth : 640,
videoFrameHeight : 480,
videoFrameRate : 30
}
let videoConfig = {
audioSourceType : 1,
videoSourceType : 0,
profile : videoProfile,
url: testFdNumber, // testFdNumber is generated by getFd.
orientationHint : 0,
location : { latitude : 30, longitude : 130 },
}
// Error callback triggered in the case of an error
function failureCallback(error) {
console.info('error happened, error name is ' + error.name);
console.info('error happened, error code is ' + error.code);
console.info('error happened, error message is ' + error.message);
}
// Error callback triggered in the case of an exception
function catchCallback(error) {
console.info('catch error happened, error name is ' + error.name);
console.info('catch error happened, error code is ' + error.code);
console.info('catch error happened, error message is ' + error.message);
}
let videoRecorder = null; // videoRecorder is an empty object and assigned with a value after createVideoRecorder is successfully called.
let surfaceID = null; // Used to save the surface ID returned by getInputSurface.
// Create a VideoRecorder object.
await media.createVideoRecorder().then((recorder) => {
console.info('case createVideoRecorder called');
if (typeof (recorder) != 'undefined') {
videoRecorder = recorder;
console.info('createVideoRecorder success');
} else {
console.info('createVideoRecorder failed');
}
}, failureCallback).catch(catchCallback);
// Obtain the surface ID, save it, and pass it to camera-related interfaces.
await videoRecorder.getInputSurface().then((surface) => {
console.info('getInputSurface success');
surfaceID = surface;
}, failureCallback).catch(catchCallback);
// Video recording depends on camera-related interfaces. The following operations can be performed only after the video output start interface is invoked.
// Start video recording.
await videoRecorder.start().then(() => {
console.info('start success');
}, failureCallback).catch(catchCallback);
// Pause video playback before the video output stop interface is invoked.
await videoRecorder.pause().then(() => {
console.info('pause success');
}, failureCallback).catch(catchCallback);
// Resume video playback after the video output start interface is invoked.
await videoRecorder.resume().then(() => {
console.info('resume success');
}, failureCallback).catch(catchCallback);
// Stop video recording after the video output stop interface is invoked.
await videoRecorder.stop().then(() => {
console.info('stop success');
}, failureCallback).catch(catchCallback);
// Reset the recording configuration.
await videoRecorder.reset().then(() => {
console.info('reset success');
}, failureCallback).catch(catchCallback);
// Release the video recording resources and camera object resources.
await videoRecorder.release().then(() => {
console.info('release success');
}, failureCallback).catch(catchCallback);
// Set the related object to null.
videoRecorder = null;
surfaceID = null;
```
# 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)
```
...@@ -2,11 +2,12 @@ ...@@ -2,11 +2,12 @@
- Getting Started - Getting Started
- [Preparations](start-overview.md) - [Preparations](start-overview.md)
- [Getting Started with eTS](start-with-ets.md) - [Getting Started with eTS in the Traditional Coding Approach](start-with-ets.md)
- [Getting Started with eTS in the Low-Code Approach](start-with-ets-low-code.md)
- [Getting Started with JavaScript in the Traditional Coding Approach](start-with-js.md) - [Getting Started with JavaScript in the Traditional Coding Approach](start-with-js.md)
- [Getting Started with JavaScript in the Low-Code Approach](start-with-js-low-code.md) - [Getting Started with JavaScript in the Low-Code Approach](start-with-js-low-code.md)
- Development Fundamentals - Development Fundamentals
- [Directory Structure](package-structure.md) - [Application Development Package Structure ](package-structure.md)
- [Resource File](basic-resource-file-categories.md) - [Resource File Categories](basic-resource-file-categories.md)
- [SysCap](syscap.md)
# DevEco Studio \(OpenHarmony\) User Guide # DevEco Studio (OpenHarmony) User Guide
DevEco Studio is a one-stop, distributed platform developed based on the IntelliJ IDEA Community (Open Source) Edition. It helps you develop versatile all-device, all-scenario applications, offering distributed multi-device development, debugging, and simulation, as well as comprehensive quality and security safeguards.
[DevEco Studio 3.0 Beta3](https://developer.harmonyos.com/cn/develop/deveco-studio#download_beta_openharmony) stands out in the following aspects:
- One-stop information acquisition platform
- A wide range of device project templates
- Efficient code editing
- Visualized UI development
- Bidirectional and instsant UI preview
- High-performing compilation tool Hvigor
- Support for application development based on the device Syscap capability set
- Automatic application signature mechanism
- A diverse array of code debugging and profiling features
For more information, see [DevEco Studio (OpenHarmony) User Guide](https://developer.harmonyos.com/en/docs/documentation/doc-guides/ohos-deveco-studio-overview-0000001263280421).
...@@ -23,7 +23,11 @@ ArkUI comes with two development paradigms: JavaScript-based web-like developmen ...@@ -23,7 +23,11 @@ ArkUI comes with two development paradigms: JavaScript-based web-like developmen
| Web-like&nbsp;development&nbsp;paradigm | JavaScript | Data-driven | Applications&nbsp;and&nbsp;service&nbsp;widgets&nbsp;with&nbsp;simple&nbsp;UIs | Frontend&nbsp;web&nbsp;developers | | Web-like&nbsp;development&nbsp;paradigm | JavaScript | Data-driven | Applications&nbsp;and&nbsp;service&nbsp;widgets&nbsp;with&nbsp;simple&nbsp;UIs | Frontend&nbsp;web&nbsp;developers |
| Declarative&nbsp;development&nbsp;paradigm | Extended&nbsp;TypeScript&nbsp;(eTS) | Data-driven | Applications&nbsp;involving&nbsp;technological&nbsp;sophistication&nbsp;and&nbsp;teamwork | Mobile&nbsp;application&nbsp;and&nbsp;system&nbsp;application&nbsp;developers | | Declarative&nbsp;development&nbsp;paradigm | Extended&nbsp;TypeScript&nbsp;(eTS) | Data-driven | Applications&nbsp;involving&nbsp;technological&nbsp;sophistication&nbsp;and&nbsp;teamwork | Mobile&nbsp;application&nbsp;and&nbsp;system&nbsp;application&nbsp;developers |
For DevEco Studio V2.2 Beta1 and later versions, both the traditional coding mode and the low-code mode are supported when the JS language is used for development. On the OpenHarmony low-code development pages, you can design your app UI in an efficient, intuitive manner, with a wide array of UI editing features complying with JS Development Specifications. For DevEco Studio V2.2 Beta1 and later versions, both the traditional coding mode and the low-code mode are supported when the JS language is used for development.
For eTS language development, DevEco Studio V3.0 Beta3 and later versions support low-code development in addition to the traditional code development mode.
On the OpenHarmony low-code development pages, you can design your application UI in an efficient, intuitive manner, with a wide array of UI editing features.
### Ability ### Ability
...@@ -43,4 +47,4 @@ This document provides a Page ability instance with two pages. For more informat ...@@ -43,4 +47,4 @@ This document provides a Page ability instance with two pages. For more informat
2. Install DevEco Studio and configure the development environment. For details, see [Configuring the OpenHarmony SDK](https://developer.harmonyos.com/en/docs/documentation/doc-guides/ohos-setting-up-environment-0000001263160443). 2. Install DevEco Studio and configure the development environment. For details, see [Configuring the OpenHarmony SDK](https://developer.harmonyos.com/en/docs/documentation/doc-guides/ohos-setting-up-environment-0000001263160443).
When you are done, follow the instructions in [Getting Started with eTS](start-with-ets.md),[Getting Started with JavaScript in the Traditional Coding Approach](start-with-js.md), and [Getting Started with JavaScript in the Low-Code Approach](start-with-js-low-code.md). When you are done, follow the instructions in [Getting Started with eTS in the Traditional Coding Approach](start-with-ets.md),[Getting Started with eTS in the Low-Code Approach](start-with-ets-low-code.md), [Getting Started with JavaScript in the Traditional Coding Approach](start-with-js.md), and [Getting Started with JavaScript in the Low-Code Approach](start-with-js-low-code.md).
# Getting Started with eTS in the Low-Code Approach
> ![icon-note.gif](public_sys-resources/icon-note.gif) **Note:**
> This feature is supported in DevEco Studio V3.0 Beta3 and later versions.
>
> The component lineup that supports low-code development in eTS is now at its preliminary stage and will be expanding in coming versions.
>
> For best possible results, use [DevEco Studio V3.0.0.900 Beta3](https://developer.harmonyos.com/cn/develop/deveco-studio#download_beta_openharmony) for your development.
On the OpenHarmony low-code development pages, you can design your application UI in an efficient, intuitive manner, with a wide array of UI editing features.
You can develop applications or services in the low-code approach using either of the following methods:
- Create a project that supports low-code development. This method is used as an example in this topic.
- In an existing project, create a .visual file for development.
## Creating a Project That Supports Low-Code Development
1. Open DevEco Studio, choose **File** &gt; **New** &gt; **Create Project**, select **Empty Ability**, and click **Next**.
![en-us_image_0000001233528152](figures/en-us_image_0000001233528152.png)
2. Go to the project configuration page, select **Enable Super Visual**, set **UI Syntax** to **eTS**, and retain the default values for other parameters.
![en-us_image_0000001277728569](figures/en-us_image_0000001277728569.png)
3. Click **Finish**. DevEco Studio will automatically generate the sample code and resources that match your project type. Wait until the project is created.
## Low-code Project Files
After the project synchronization is complete, a low-code directory structure is automatically generated in the project, as shown below.
![en-us_image_0000001277809333](figures/en-us_image_0000001277809333.png)
- **entry &gt; src &gt; main &gt; ets &gt; MainAbility &gt; pages &gt; index.ets**: defines logical relationships, such as data and events, used on low-code pages. For details, see [About Syntactic Sugar](../ui/ts-syntactic-sugar.md). If multiple low-code development pages are created, a page folder and the corresponding **.ets** file will be created for each of these pages.
- **entry &gt; src &gt; main &gt; supervisual &gt; MainAbility &gt; pages &gt; index.visual**: stores the data model of the low-code development page. You can double-click the file to open the low-code development page. If multiple low-code development pages are created, a page folder and the corresponding **.visual** file will be created for each of these pages.
## Building the First Page
After the project synchronization is complete, the default first page contains the **Column** and **Text** (**Hello World**) components. To better understand low-code development, we'll delete these template components from the canvas and set the page from scratch.
Add **Column**, **Text**, and **Button** components to the first page. A column is a container component whose child components are vertically arranged. For details, see [Column](../reference/arkui-ts/ts-container-column.md).
1. Delete the existing template components from the canvas.<a name="delete_origin_content"></a>
Open the index.visual file, right-click the existing template components on the canvas, and choose **Delete** from the shortcut menu to delete them. Below is an illustration of the operations.
![en-us_image_0000001233208980](figures/en-us_image_0000001233208980.gif)
2. Add a **Column** component and set its styles and attributes.<a name="add_container"></a>
Drag the **Column** component from the **UI Control** area to the canvas. In the **Attributes &amp; Styles** area on the right, click ![en-us_image_0000001233048996](figures/en-us_image_0000001233048996.png)**General** and set **Height** to **100%** so that the component fills the entire screen. Click ![en-us_image_0000001233368860](figures/en-us_image_0000001233368860.png)**Feature** and set **AlignItems** to **center** so that the child components of the **Column** component are centered along the horizontal axis. Below is an illustration of the operations.
![en-us_image_0000001277488977](figures/en-us_image_0000001277488977.gif)
3. Add a **Text** component.
Drag the **Text** component from the **UI Control** area to the canvas and then to the center area of the **Column** component. In the **Attributes &amp; Styles** area, click ![en-us_image_0000001277608813](figures/en-us_image_0000001277608813.png)**Feature**, set **Content** of the **Text** component to **this.message** (that is, **Hello World**), set **FontSize** to **30fp**, and set **TextAlign** to **center**. Then, select the **Text** component on the canvas and drag its corners to fully display the text. Below is an illustration of the operations.
![en-us_image_0000001235731706](figures/en-us_image_0000001235731706.gif)
4. Add a **Button** component.
Drag the **Button** component from the **UI Control** area to the canvas and then to a position under the **Text** component. In the **Attributes &amp; Styles** area on the right, click ![en-us_image_0000001277728577](figures/en-us_image_0000001277728577.png)**General** and set **Height** of the **Button** component to **40vp**. Click ![en-us_image_0000001277809337](figures/en-us_image_0000001277809337.png)**Feature** and set **Label** to **Next** and **FontSize** to **25fp**. Below is an illustration of the operations.
![en-us_image_0000001235732402](figures/en-us_image_0000001235732402.gif)
5. On the toolbar in the upper right corner of the editing window, click **Previewer** to open the Previewer. Below is how the first page looks in the Previewer.
![en-us_image_0000001235892798](figures/en-us_image_0000001235892798.png)
## Building the Second Page
1. Create the second page.
In the **Project** window, choose **entry** &gt; **src** &gt; **main** &gt; **ets** &gt; **MainAbility**, right-click the **pages** folder, choose **New** &gt; **Visual**, name the page **second**, and click **Finish**. Below is the structure of the **pages** folder.
![en-us_image_0000001233368868](figures/en-us_image_0000001233368868.png)
2. [Delete the existing template components from the canvas.](#delete_origin_content)
3. [Add a **Column** component and set its styles and attributes.](#add_container)
4. Add a **Text** component.
- In the **second.ets** file, set the message text content to **Hi there**. The sample code is as follows:
```
@Entry
@Component
struct Second {
@State message: string = 'Hi there'
/**
* In low-code mode, do not add anything to the build function, as it will be
* overwritten by the content generated by the .visual file in the build phase.
*/
build() {
}
}
```
- Drag the **Text** component to the canvas and then to the center area of the **Column** component. In the **Attributes &amp; Styles** area, click ![en-us_image_0000001277488985](figures/en-us_image_0000001277488985.png)**Feature**, set **Content** of the **Text** component to **this.message** (that is, **Hi there**), set **FontSize** to **30fp**, and set **TextAlign** to **center**. Then, select the **Text** component on the canvas and drag its corners to fully display the text. Below is an illustration of the operations.
![en-us_image_0000001280255513](figures/en-us_image_0000001280255513.gif)
5. Add a **Button** component.
Drag the **Button** component from the **UI Control** area to the canvas and then to a position under the **Text** component. In the **Attributes &amp; Styles** area on the right, click ![en-us_image_0000001233528160](figures/en-us_image_0000001233528160.png)**General** and set **Height** of the **Button** component to **40vp**. Click ![en-us_image_0000001277728597](figures/en-us_image_0000001277728597.png)**Feature** and set **Value** to **Back** and **FontSize** to **25fp**. Below is an illustration of the operations.
![en-us_image_0000001280383937](figures/en-us_image_0000001280383937.gif)
## Implementing Page Redirection
You can implement page redirection through the page router, which finds the target page based on the page URI. Import the **router** module and then perform the steps below:
1. Implement redirection from the first page to the second page.
In the files of the first page, bind the **onclick** method to the button so that clicking the button redirects the user to the second page. This operation needs to be completed in both .ets and .visual files.
- In the **index.ets** file:
```
import router from '@system.router';
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
/**
* In low-code mode, do not add anything to the build function, as it will be
* overwritten by the content generated by the .visual file in the build phase.
*/
onclick() {
router.push({
uri: 'pages/second', // Specify the page to be redirected to.
})
}
build() {
}
}
```
- In the index.visual file, select the **Button** component on the canvas. In the **Attributes &amp; Styles** area, click ![en-us_image_0000001233209020](figures/en-us_image_0000001233209020.png)**Events** and set **OnClick** to **this.onclick**.
![en-us_image_0000001235745716](figures/en-us_image_0000001235745716.png)
2. Implement redirection from the second page to the first page.
In the files of the second page, bind the **back** method to the **Back** button so that clicking the button redirects the user back to the first page. This operation needs to be completed in both .ets and .visual files.
- In the **second.ets** file:
```
import router from '@system.router';
@Entry
@Component
struct Second {
@State message: string = 'Hi there'
/**
* In low-code mode, do not add anything to the build function, as it will be
* overwritten by the content generated by the .visual file in the build phase.
*/
back() {
router.back()
}
build() {
}
}
```
- In the second.visual file, select the **Button** component on the canvas. In the **Attributes &amp; Styles** area, click ![en-us_image_0000001233368900](figures/en-us_image_0000001233368900.png)**Events** and set **OnClick** to **this.back**.
![en-us_image_0000001280385809](figures/en-us_image_0000001280385809.png)
3. Open the **index.visual** or **index.ets** file and click ![en-us_image_0000001277608849](figures/en-us_image_0000001277608849.png) in the Previewer to refresh the file. The figure below shows the effect.
![en-us_image_0000001233528192](figures/en-us_image_0000001233528192.png)
## Running the Application on a Real Device
1. Connect the development board running the OpenHarmony standard system to the computer.
2. Choose **File** &gt; **Project Structure** &gt; **Project** &gt; **Signing Configs**, select **Automatically generate signing**, wait until the automatic signing is complete, and click **OK**, as shown below.
![en-us_image_0000001277728613](figures/en-us_image_0000001277728613.png)
3. On the toolbar in the upper right corner of the editing window, click ![en-us_image_0000001277809373](figures/en-us_image_0000001277809373.png). The display effect is shown in the figure below.
![en-us_image_0000001233209024](figures/en-us_image_0000001233209024.png)
Congratulations! You have finished developing your OpenHarmony application in eTS in the low-code approach. To learn more about OpenHarmony, see [OpenHarmony Overview](../application-dev-guide.md).
# Getting Started with eTS # Getting Started with eTS in the Traditional Coding Approach
> ![icon-note.gif](public_sys-resources/icon-note.gif) **Note:** > ![icon-note.gif](public_sys-resources/icon-note.gif) **Note:**
> To use eTS, your DevEco Studio must be V3.0.0.601 Beta1 or later. > To use eTS, your DevEco Studio must be V3.0.0.601 Beta1 or later.
...@@ -247,4 +247,4 @@ You can implement page redirection through the page router, which finds the targ ...@@ -247,4 +247,4 @@ You can implement page redirection through the page router, which finds the targ
3. On the toolbar in the upper right corner of the editing window, click ![en-us_image_0000001262206247](figures/en-us_image_0000001262206247.png). The display effect is shown in the figure below. 3. On the toolbar in the upper right corner of the editing window, click ![en-us_image_0000001262206247](figures/en-us_image_0000001262206247.png). The display effect is shown in the figure below.
![en-us_image_0000001217526428](figures/en-us_image_0000001217526428.png) ![en-us_image_0000001217526428](figures/en-us_image_0000001217526428.png)
Congratulations! You have finished developing your OpenHarmony application in eTS. To learn more about OpenHarmony, see [OpenHarmony Overview](../application-dev-guide.md) Congratulations! You have finished developing your OpenHarmony application in eTS in the traditional coding approach. To learn more about OpenHarmony, see [OpenHarmony Overview](../application-dev-guide.md)
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
> For best possible results, use [DevEco Studio V3.0.0.900 Beta3](https://developer.harmonyos.com/cn/develop/deveco-studio#download_beta_openharmony) for your development. > For best possible results, use [DevEco Studio V3.0.0.900 Beta3](https://developer.harmonyos.com/cn/develop/deveco-studio#download_beta_openharmony) for your development.
On the OpenHarmony low-code development pages, you can design your app UI in an efficient, intuitive manner, with a wide array of UI editing features complying with JS Development Specifications. On the OpenHarmony low-code development pages, you can design your app UI in an efficient, intuitive manner, with a wide array of UI editing features.
You can develop applications or services in the low-code approach using either of the following methods: You can develop applications or services in the low-code approach using either of the following methods:
......
# SysCap Usage Guidelines
## Overview
### System Capabilities and APIs
SysCap is short for System Capability. It refers to each independent feature in the operating system, such as Bluetooth, Wi-Fi, NFC, and camera. Each system capability corresponds to multiple APIs. These APIs are bound together and their availability depends on the support on the target device. They can also be provided together with the IDE for association.
![image-20220326064841782](figures/image-20220326064841782.png)
### Supported Capability Set, Association Capability Set, and Required Capability Set
The supported capability set, association capability set, and required capability set are collections of system capabilities.
The supported capability set covers the device capabilities, and the required capability set covers the application capabilities. If the capability set required by application A is a subset of the capability set supported by device N, application A can be distributed to device N for installation and running. Otherwise, application A cannot be distributed.
The association capability set covers the system capabilities of APIs that can be associated by the IDE during application development.
![image-20220326064913834](figures/image-20220326064913834.png)
### Devices and Supported Capability Sets
Each device provides a capability set according to its hardware capability.
The SDK classifies devices into general devices and custom devices. The general devices' supported capability set is defined by OpenHarmony, and the custom devices' is defined by device vendors.
![image-20220326064955505](figures/image-20220326064955505.png)
### Mapping Between Devices and SDK Capabilities
The SDK provides full APIs for the IDE. The IDE identifies the supported capability set based on the devices supported by the project, filters the APIs contained in the capability set, and provides the supported APIs for association (to autocomplete input).
![image-20220326065043006](figures/image-20220326065043006.png)
## How to Develop
### Importing the PCID
DevEco Studio allows PCID imports for projects. After the imported PCID file is decoded, the output SysCap is written into the **syscap.json** file.
Right-click the project directory and choose **Import Product Compatibility ID** from the shortcut menu to upload the PCID file and import it to the **syscap.json** file.
![20220329-103626](figures/20220329-103626.gif)
### Configuring the Association Capability Set and Required Capability Set
The IDE automatically configures the association capability set and required capability set based on the settings supported by the created project. You can modify the capability sets when necessary.
For the association capability set, you can use more APIs in the IDE by adding more system capabilities. Note that these APIs may not be supported on the device. Therefore, you need to check whether these APIs are supported before using them.
Exercise caution when modifying the required capability set. Incorrect modifications may cause the application to unable to be distributed to the target device.
```
/* syscap.json */
{
devices: {
general: [ /* Each general device corresponds to a SysCap capability set. Multiple general devices can be configured.*/
"car,
...
],
custom: [ /* Vendor-defined device*/
{
"Custom device": [
"SystemCapability.Communication.SoftBus.Core",
...
]
},
...
]
},
development: { /* The SysCap set in addedSysCaps and the SysCap set supported by each device configured in devices form the association capability set.*/
addedSysCaps: [
"SystemCapability.Location.Location.Lite",
...
]
},
production: { /* Used to generate the RPCID. Exercise caution when adding this parameter. Under incorrect settings, applications may fail to be distributed to target devices.*/
addedSysCaps: [], // Intersection of SysCap sets supported by devices configured in devices. It is the required capability set with addedSysCaps set and removedSysCaps set.
removedSysCaps: [] // When the required capability set is a capability subset of a device, the application can be distributed to the device.
}
}
```
### Single-Device Application Development
By default, the association capability set and required system capability set of the application are the same as the supported system capability set of the device. Exercise caution when modifying the required capability set.
![image-20220326065124911](figures/image-20220326065124911.png)
### Cross-Device Application Development
By default, the association capability set of the application is the union of multiple devices' supported capability sets. The capability sets must be the intersection.
![image-20220326065201867](figures/image-20220326065201867.png)
### Checking Whether an API Is Available
To check whether a project supports a specific SysCap, you can use **canIUse**.
```
if (canIUse("SystemCapability.ArkUI.ArkUI.Full")) {
console.log("The application supports SystemCapability.ArkUI.ArkUI.Full.");
} else {
Console.log("The application does not support SystemCapability.ArkUI.ArkUI.Full".);
}
```
You can import a module. If the current device does not support the module, the import result is **undefined**. When using an API, you need to check whether the API is available.
```
import geolocation from '@ohos.geolocation';
if (geolocation) {
geolocation.getCurrentLocation((location) => {
console.log(location.latitude, location.longitude);
});
} else {
Console.log('The device does not support location information.');
}
```
### Checking the Differences Between Devices with the Same Capability
The performance of a system capability may vary by device type. For example, a tablet is superior to a smart wearable device in terms of the camera capability.
```
import userAuth from '@ohos.userIAM.userAuth';
const authenticator = userAuth.getAuthenticator();
const result = authenticator.checkAbility('FACE_ONLY', 'S1');
if (result == authenticator.CheckAvailabilityResult.AUTH_NOT_SUPPORT) {
Console.log('The device does not support facial recognition.');
}
// If an unsupported API is forcibly called, an error message is returned, but no syntax error occurs.
authenticator.execute('FACE_ONLY', 'S1', (err, result) => {
if (err) {
console.log(err.message);
return;
}
})
```
### How Are the SysCap Differences Between Devices Generated
The SysCap of devices varies according to the component combination assembled by the product solution vendor. The following figure shows the overall process.
![image-20220326072448840](figures/image-20220326072448840.png)
1. A set of OpenHarmony source code consists of optional and mandatory components. Different components have different system capabilities. In other words, different components represent different SysCaps.
2. In a normalized released SDK, the mapping exists between APIs and SysCap.
3. Product solution vendors can assemble components based on hardware capabilities and product requirements.
4. The components configured for a product can be OpenHarmony components or private components developed by a third party. Because there is mapping between components and SysCap, the SysCap set of the product can be obtained after all components are assembled.
5. The SysCap set is encoded to generate the PCID. You can import the PCID to the IDE and decode it into SysCap. During development, compatibility processing is performed on the SysCap differences of devices.
6. System parameters deployed on devices contain the SysCap set. The system provides native interfaces and application interfaces for components and applications in the system to check whether a SysCap set is available.
7. During application development, the SysCap required by the application is encoded into the Required Product Compatibility ID (RPCID) and written into the application installation package. During application installation, the package manager decodes the RPCID to obtain the SysCap required by the application and compares it with the SysCap of the device. If the SysCap required by the application is met, the application is successfully installed.
8. When an application is running, the **canIUse** API can be used to query the SysCap of a device to ensure compatibility on different devices.
# APIs # APIs
- Ability Framework - Ability Framework
- [FeatureAbility Module](js-apis-featureAbility.md)
- [ParticleAbility Module](js-apis-particleAbility.md) - [@ohos.ability.dataUriUtils](js-apis-DataUriUtils.md)
- [DataAbilityHelper Module](js-apis-dataAbilityHelper.md) - [@ohos.ability.errorCode](js-apis-ability-errorCode.md)
- [DataUriUtils Module](js-apis-DataUriUtils.md) - [@ohos.ability.wantConstant](js-apis-ability-wantConstant.md)
- [Bundle Module](js-apis-Bundle.md) - [@ohos.application.abilityDelegatorRegistry](js-apis-abilityDelegatorRegistry.md)
- [Context Module](js-apis-Context.md) - [@ohos.application.appManager](js-apis-appmanager.md)
- Event Notification - [@ohos.application.Configuration](js-apis-configuration.md)
- [CommonEvent Module](js-apis-commonEvent.md) - [@ohos.application.ConfigurationConstant](js-apis-configurationconstant.md)
- [Notification Module](js-apis-notification.md) - [@ohos.ability.featureAbility](js-apis-featureAbility.md)
- [Reminder Agent](js-apis-reminderAgent.md) - [@ohos.application.formBindingData](js-apis-formbindingdata.md)
- Resource Management - [@ohos.application.formError](js-apis-formerror.md)
- [Resource Manager](js-apis-resource-manager.md) - [@ohos.application.formHost](js-apis-formhost.md)
- [Internationalization \(intl\) ](js-apis-intl.md) - [@ohos.application.formInfo](js-apis-formInfo.md)
- [Internationalization \(i18n\) ](js-apis-i18n.md) - [@ohos.application.missionManager](js-apis-missionManager.md)
- [@ohos.application.formProvider](js-apis-formprovider.md)
- [@ohos.ability.particleAbility](js-apis-particleAbility.md)
- [@ohos.application.Want](js-apis-application-Want.md)
- [@ohos.wantAgent](js-apis-wantAgent.md)
- ability/[dataAbilityHelper](js-apis-dataAbilityHelper.md)
- app/[context](js-apis-Context.md)
- application/[abilityDelegator](js-apis-application-abilityDelegator.md)
- application/[abilityDelegatorArgs](js-apis-application-abilityDelegatorArgs.md)
- application/[AbilityRunningInfo](js-apis-abilityrunninginfo.md)
- application/[ExtensionContext](js-apis-extension-context.md)
- application/[ExtensionRunningInfo](js-apis-extensionrunninginfo.md)
- application/[FormExtensionContext](js-apis-formextensioncontext.md)
- application/[MissionSnapshot](js-apis-application-MissionSnapshot.md)
- application/[ProcessRunningInfo](js-apis-processrunninginfo.md)
- application/[ServiceExtensionContext](js-apis-service-extension-context.md)
- application/[shellCmdResult](js-apis-application-shellCmdResult.md)
- Common Event and Notification
- [@ohos.commonEvent](js-apis-commonEvent.md)
- [@ohos.events.emitter](js-apis-emitter.md)
- [@ohos.notification](js-apis-notification.md)
- [@ohos.reminderAgent](js-apis-reminderAgent.md)
- Bundle Management
- [@ohos.bundle](js-apis-Bundle.md)
- [@ohos.bundleState ](js-apis-deviceUsageStatistics.md)
- [@ohos.zlib](js-apis-zlib.md)
- UI Page
- [@ohos.animator](js-apis-animator.md)
- [@ohos.mediaquery](js-apis-mediaquery.md)
- [@ohos.prompt](js-apis-prompt.md)
- [@ohos.router](js-apis-router.md)
- Graphics
- [@ohos.display ](js-apis-display.md)
- [@ohos.screenshot](js-apis-screenshot.md)
- [@ohos.window](js-apis-window.md)
- [webgl](js-apis-webgl.md)
- [webgl2](js-apis-webgl2.md)
- Media - Media
- [Audio Management](js-apis-audio.md)
- [Media](js-apis-media.md) - [@ohos.multimedia.audio](js-apis-audio.md)
- [Image Processing](js-apis-image.md) - [@ohos.multimedia.image](js-apis-image.md)
- [Camera](js-apis-camera.md) - [@ohos.multimedia.media](js-apis-media.md)
- [@ohos.multimedia.medialibrary](js-apis-medialibrary.md)
- Resource Management
- [@ohos.i18n](js-apis-i18n.md)
- [@ohos.intl](js-apis-intl.md)
- [@ohos.resourceManager](js-apis-resource-manager.md)
- Resource Scheduling
- [@ohos.backgroundTaskManager](js-apis-backgroundTaskManager.md)
- Custom Management
- [@ohos.configPolicy](js-apis-config-policy.md)
- Security - Security
- [User Authentication](js-apis-useriam-userauth.md)
- [Access Control](js-apis-abilityAccessCtrl.md) - [@ohos.abilityAccessCtrl](js-apis-abilityAccessCtrl.md)
- [@ohos.security.huks ](js-apis-huks.md)
- [@ohos.userIAM.userAuth ](js-apis-useriam-userauth.md)
- [@system.cipher](js-apis-system-cipher.md)
- Data Management - Data Management
- [Lightweight Storage](js-apis-data-storage.md)
- [Distributed Data Management](js-apis-distributed-data.md) - [@ohos.data.dataAbility ](js-apis-data-ability.md)
- [Relational Database](js-apis-data-rdb.md) - [@ohos.data.distributedData](js-apis-distributed-data.md)
- [Result Set](js-apis-data-resultset.md) - [@ohos.data.distributedDataObject](js-apis-data-distributedobject.md)
- [DataAbilityPredicates](js-apis-data-ability.md) - [@ohos.data.rdb](js-apis-data-rdb.md)
- [Settings](js-apis-settings.md) - [@ohos.settings](js-apis-settings.md)
- data/rdb/[resultSet](js-apis-data-resultset.md)
- File Management - File Management
- [File Management](js-apis-fileio.md)
- [Statfs](js-apis-statfs.md) - [@ohos.environment](js-apis-environment.md)
- [Environment](js-apis-environment.md) - [@ohos.fileio](js-apis-fileio.md)
- [Public File Access and Management](js-apis-filemanager.md) - [@ohos.fileManager](js-apis-filemanager.md)
- [App Storage Statistics](js-apis-storage-statistics.md) - [@ohos.statfs](js-apis-statfs.md)
- Account Management - [@ohos.storageStatistics](js-apis-storage-statistics.md)
- [OS Account Management](js-apis-osAccount.md)
- [Distributed Account Management](js-apis-distributed-account.md)
- [App Account Management](js-apis-appAccount.md)
- Telephony Service - Telephony Service
- [Call](js-apis-call.md)
- [SMS](js-apis-sms.md) - [@ohos.contact](js-apis-contact.md)
- [SIM Management](js-apis-sim.md) - [@ohos.telephony.call](js-apis-call.md)
- [Radio](js-apis-radio.md) - [@ohos.telephony.observer](js-apis-observer.md)
- [Observer](js-apis-observer.md) - [@ohos.telephony.radio](js-apis-radio.md)
- [Cellular Data](js-apis-telephony-data.md) - [@ohos.telephony.sim](js-apis-sim.md)
- [@ohos.telephony.sms](js-apis-sms.md)
- [@ohos.telephony.data](js-apis-telephony-data.md)
- Network Management - Network Management
- [Network Connection Management](js-apis-net-connection.md) - [@ohos.net.connection](js-apis-net-connection.md)
- [Socket Connection](js-apis-socket.md) - [@ohos.net.http](js-apis-http.md)
- [WebSocket Connection](js-apis-webSocket.md) - [@ohos.request](js-apis-request.md)
- [Data Request](js-apis-http.md) - [@ohos.net.socket](js-apis-socket.md)
- Network and Connectivity - [@ohos.net.webSocket](js-apis-webSocket.md)
- [WLAN](js-apis-wifi.md)
- [Bluetooth](js-apis-bluetooth.md) - Connectivity
- [RPC](js-apis-rpc.md)
- [Upload and Download](js-apis-request.md) - [@ohos.bluetooth](js-apis-bluetooth.md)
- Device Management - [@ohos.connectedTag](js-apis-connectedTag.md)
- [Sensor](js-apis-sensor.md) - [@ohos.rpc](js-apis-rpc.md)
- [Vibrator](js-apis-vibrator.md) - [@ohos.wifi](js-apis-wifi.md)
- [Brightness](js-apis-brightness.md) - [@ohos.wifiext](js-apis-wifiext.md)
- [Battery Info](js-apis-battery-info.md)
- [Power Management](js-apis-power.md)
- [Thermal Management](js-apis-thermal.md)
- [Running Lock](js-apis-runninglock.md)
- [Device Info](js-apis-device-info.md)
- [systemParameter](js-apis-system-parameter.md)
- [Device Management](js-apis-device-manager.md)
- [Window](js-apis-window.md)
- [Display](js-apis-display.md)
- [Update](js-apis-update.md)
- [USB](js-apis-usb.md)
- [Location](js-apis-geolocation.md)
- Basic Features - Basic Features
- [Application Context](js-apis-basic-features-app-context.md)
- [Console Logs](js-apis-basic-features-logs.md) - [@ohos.accessibility](js-apis-accessibility.md)
- [Page Routing](js-apis-basic-features-routes.md) - [@ohos.faultLogger](js-apis-faultLogger.md)
- [Timer](js-apis-basic-features-timer.md) - [@ohos.hiAppEvent](js-apis-hiappevent.md)
- [Screen Lock Management](js-apis-screen-lock.md) - [@ohos.hichecker](js-apis-hichecker.md)
- [Setting the System Time](js-apis-system-time.md) - [@ohos.hidebug](js-apis-hidebug.md)
- [Wallpaper](js-apis-wallpaper.md) - [@ohos.hilog](js-apis-hilog.md)
- [Pasteboard](js-apis-pasteboard.md) - [@ohos.hiTraceChain](js-apis-hitracechain.md)
- [Animation](js-apis-basic-features-animator.md) - [@ohos.hiTraceMeter](js-apis-hitracemeter.md)
- [WebGL](js-apis-webgl.md) - [@ohos.inputMethod](js-apis-inputmethod.md)
- [WebGL2](js-apis-webgl2.md) - [@ohos.inputMethodEngine](js-apis-inputmethodengine.md)
- [Screenshot](js-apis-screenshot.md) - [@ohos.pasteboard](js-apis-pasteboard.md)
- [Accessibility](js-apis-accessibility.md) - [@ohos.screenLock](js-apis-screen-lock.md)
- DFX - [@ohos.systemTime](js-apis-system-time.md)
- [HiAppEvent](js-apis-hiappevent.md) - [@ohos.wallpaper](js-apis-wallpaper.md)
- [Performance Tracing](js-apis-hitracemeter.md) - [Timer](js-apis-timer.md)
- [Fault Logger](js-apis-faultLogger.md)
- [Distributed Call Chain Tracing](js-apis-hitracechain.md) - Device Management
- [HiLog](js-apis-hilog.md)
- [HiChecker](js-apis-hichecker.md) - [@ohos.batteryInfo ](js-apis-battery-info.md)
- [HiDebug](js-apis-hidebug.md) - [@ohos.brightness](js-apis-brightness.md)
- [@ohos.deviceInfo](js-apis-device-info.md)
- [@ohos.distributedHardware.deviceManager](js-apis-device-manager.md)
- [@ohos.geolocation](js-apis-geolocation.md)
- [@ohos.multimodalInput.inputConsumer](js-apis-inputconsumer.md)
- [@ohos.multimodalInput.inputDevice](js-apis-inputdevice.md)
- [@ohos.multimodalInput.inputEventClient](js-apis-inputeventclient.md)
- [@ohos.multimodalInput.inputMonitor](js-apis-inputmonitor.md)
- [@ohos.power](js-apis-power.md)
- [@ohos.runningLock](js-apis-runninglock.md)
- [@ohos.sensor](js-apis-sensor.md)
- [@ohos.systemParameter](js-apis-system-parameter.md)
- [@ohos.thermal](js-apis-thermal.md)
- [@ohos.update](js-apis-update.md)
- [@ohos.usb](js-apis-usb.md)
- [@ohos.vibrator](js-apis-vibrator.md)
- Account Management
- [@ohos.account.appAccount](js-apis-appAccount.md)
- [@ohos.account.distributedAccount](js-apis-distributed-account.md)
- [@ohos.account.osAccount](js-apis-osAccount.md)
- Language Base Class Library - Language Base Class Library
- [Obtaining Process Information](js-apis-process.md)
- [URL String Parsing](js-apis-url.md)
- [URI String Parsing](js-apis-uri.md)
- [Util](js-apis-util.md)
- [XML Parsing and Generation](js-apis-xml.md)
- [XML-to-JavaScript Conversion](js-apis-convertxml.md)
- [Worker Startup](js-apis-worker.md)
- [Linear Container ArrayList](js-apis-arraylist.md)
- [Linear Container Deque](js-apis-deque.md)
- [Linear Container List](js-apis-list.md)
- [Linear Container LinkedList](js-apis-linkedlist.md)
- [Linear Container Queue](js-apis-queue.md)
- [Linear Container Stack](js-apis-stack.md)
- [Linear Container Vector](js-apis-vector.md)
- [Nonlinear Container HashSet](js-apis-hashset.md)
- [Nonlinear Container HashMap](js-apis-hashmap.md)
- [Nonlinear Container PlainArray](js-apis-plainarray.md)
- [Nonlinear Container TreeMap](js-apis-treemap.md)
- [Nonlinear Container TreeSet](js-apis-treeset.md)
- [Nonlinear Container LightWeightMap](js-apis-lightweightmap.md)
- [Nonlinear Container LightWeightSet](js-apis-lightweightset.md)
- Custom Management
- [Configuration Policy](js-apis-config-policy.md)
- [@ohos.convertxml](js-apis-convertxml.md)
- [@ohos.process](js-apis-process.md)
- [@ohos.uri](js-apis-uri.md)
- [@ohos.url](js-apis-url.md)
- [@ohos.util](js-apis-util.md)
- [@ohos.util.ArrayList](js-apis-arraylist.md)
- [@ohos.util.Deque](js-apis-deque.md)
- [@ohos.util.HashMap](js-apis-hashmap.md)
- [@ohos.util.HashSet](js-apis-hashset.md)
- [@ohos.util.LightWeightMap](js-apis-lightweightmap.md)
- [@ohos.util.LightWeightSet](js-apis-lightweightset.md)
- [@ohos.util.LinkedList](js-apis-linkedlist.md)
- [@ohos.util.List](js-apis-list.md)
- [@ohos.util.PlainArray](js-apis-plainarray.md)
- [@ohos.util.Queue](js-apis-queue.md)
- [@ohos.util.Stack](js-apis-stack.md)
- [@ohos.util.TreeMap](js-apis-treemap.md)
- [@ohos.util.TreeSet](js-apis-treeset.md)
- [@ohos.util.Vector](js-apis-vector.md)
- [@ohos.worker](js-apis-worker.md)
- [@ohos.xml](js-apis-xml.md)
- Test
- [@ohos.application.testRunner](js-apis-testRunner.md)
- [@ohos.uitest](js-apis-uitest.md)
- APIs No Longer Maintained
- [@ohos.bytrace](js-apis-bytrace.md)
- [@system.app](js-apis-system-app.md)
- [@system.battery](js-apis-system-battery.md)
- [@system.brightness](js-apis-system-brightness.md)
- [@system.configuration](js-apis-system-configuration.md)
- [@system.device](js-apis-system-device.md)
- [@system.fetch](js-apis-system-fetch.md)
- [@system.file](js-apis-system-file.md)
- [@system.geolocation](js-apis-system-location.md)
- [@system.mediaquery](js-apis-system-mediaquery.md)
- [@system.network](js-apis-system-network.md)
- [@system.package](js-apis-system-package.md)
- [@system.prompt](js-apis-system-prompt.md)
- [@system.request](js-apis-system-request.md)
- [@system.router](js-apis-system-router.md)
- [@system.sensor](js-apis-system-sensor.md)
- [@system.storage](js-apis-system-storage.md)
- [@system.vibrator](js-apis-system-vibrate.md)
- [console](js-apis-logs.md)
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册