提交 765f6f52 编写于 作者: 田雨 提交者: Gitee

Merge branch 'master' of gitee.com:openharmony/docs into master

此差异已折叠。
......@@ -38,6 +38,7 @@
<!--filteritem type="filename" name="*.uvwxyz" desc="Describe the reason for filtering scan results"/-->
<!--filteritem type="filepath" name="abcdefg/.*.uvwxyz" desc="Describe the reason for filtering scan results"/-->
<!--filteritem type="filepath" name="projectroot/[a-zA-Z0-9]{20,}.sh" desc="Temp files"/-->
<filteritem type="filename" name="en/contribute/license-and-copyright-specifications.md" desc="already checked"/>
</filefilter>
<filefilter name="copyrightPolicyFilter" desc="Filters for copyright header policies">
<!--filteritem type="filename" name="*.uvwxyz" desc="Describe the reason for filtering scan results"/-->
......@@ -48,6 +49,7 @@
<!--filteritem type="filename" name="*.uvwxyz" desc="Describe the reason for filtering scan results"/-->
<!--filteritem type="filepath" name="abcdefg/.*.uvwxyz" desc="Describe the reason for filtering scan results"/-->
<!--filteritem type="filepath" name="projectroot/[a-zA-Z0-9]{20,}.sh" desc="Temp files"/-->
<filteritem type="filename" name="license-and-copyright-specifications.md" desc="already checked"/>
</filefilter>
<filefilter name="readmeFileNamePolicyFilter" desc="Filters for README file policies">
<!--filteritem type="filename" name="*.uvwxyz" desc="Describe the reason for filtering scan results"/-->
......
......@@ -90,11 +90,11 @@ OpenHarmony supports the following types:
- Small system
A small system runs on the devices whose memory is greater than or equal to 1 MiB and that are equipped with application processors such as Arm Cortex-A. This system provides higher security capabilities, standard graphics frameworks, and video encoding and decoding capabilities. Typical products include smart home IP cameras, electronic cat eyes, and routers, and event data recorders \(EDRs\) for smart travel.
A small system runs on the devices whose memory is greater than or equal to 1 MiB and that are equipped with application processors such as Arm Cortex-A. This system provides higher security capabilities, standard graphics frameworks, and video encoding and decoding capabilities. Typical products include smart home IP cameras, electronic cat eyes, routers, and event data recorders \(EDRs\) for smart travel.
- Standard system
A standard system runs on the devices whose memory is greater than or equal to 128 MiB and that are equipped with application processors such as ARM Cortex-A. This system provides a complete application framework supporting the enhanced interaction, 3D GPU, hardware composer, diverse components, and rich animations. This system applies to high-end refrigerator displays.
A standard system runs on the devices whose memory is greater than or equal to 128 MiB and that are equipped with application processors such as Arm Cortex-A. This system provides a complete application framework supporting the enhanced interaction, 3D GPU, hardware composer, diverse components, and rich animations. This system applies to high-end refrigerator displays.
## Subsystems<a name="section25831825174419"></a>
......@@ -125,7 +125,7 @@ The following table describes the subsystems of OpenHarmony. For details about t
| Account | Provides interconnection with vendors' cloud account apps on the device side, and query and update of the cloud account login status. | Standard system |
| Compilation and Building | Provides a compilation and building framework based on Generate Ninja (GN) and Ninja. | All systems |
| Test | The test-driven development mode is used during the development process. You can develop new cases or modify existing cases to test new or enhanced system features. The test helps you develop high-quality code in the development phase. | All systems |
| Data Management | Provides local data management and distributed data management:<\br> - Local app data management for lightweight preference databases and relational databases<\br> - Distributed data service to provide apps with the capability to store data in the databases of different devices | Standard system |
| Data Management | Provides local data management and distributed data management:<br/> - Local app data management for lightweight preference databases and relational databases<br> - Distributed data service to provide apps with the capability to store data in the databases of different devices | Standard system |
| Programming Language Runtime | Provides the compilation and execution environment for programs developed with JavaScript or C/C++, basic libraries that support the runtime, and the runtime-associated APIs, compilers, and auxiliary tools. | All systems |
| Distributed Scheduler | Starts, registers, queries, and manages system services. | All systems |
| JS UI framework | OpenHarmony UI development framework that supports web-development-like paradigm. | All systems |
......@@ -153,7 +153,7 @@ Currently, OpenHarmony supports the development boards listed in the following t
| Standard system| Runhe HH-SCDAYU200| RK3568 | Bolstered by the Rockchip RK3568, the HH-SCDAYU200 development board integrates a dual-core GPU and high-efficiency NPU. Its quad-core 64-bit Cortex-A55 processor uses the advanced 22 nm fabrication process and is clocked at up to 2.0 GHz. The board is packed with Bluetooth, WiFi, audio, video, and camera features, with a wide range of expansion ports as well as video input and output ports. It comes with dual GE auto-sensing RJ45 ports, so it can be used in multi-connectivity products, such as network video recorders (NVRs) and industrial gateways.| Video and audio entertainment, smart travel, and smart home, such as kitchen hoods, ovens, and treadmills.| Code repositories:<br>[device_soc_rockchip](https://gitee.com/openharmony/device_soc_rockchip)<br>[device_board_hihope](https://gitee.com/openharmony/device_board_hihope)<br>[vendor_hihope](https://gitee.com/openharmony/vendor_hihope) <br> Daily build:<br>http://ci.openharmony.cn/dailys/dailybuilds |
| Lightweight| Goodix GR5515-STARTER-KIT| GR5515 | The GR5515-STARTER-KIT development board is a Bluetooth 5.1-capable single-mode Bluetooth low energy (BLE) SoC and comes with multifunctional keys and LED indicators.| Smart hardware, such as watches, wristbands, and price tags.| Code repositories:<br>[device_soc_goodix](https://gitee.com/openharmony/device_soc_goodix)<br>[device_board_goodix](https://gitee.com/openharmony/device_board_goodix)<br> Daily build:<br>http://ci.openharmony.cn/dailys/dailybuilds |
| Lightweight| Langguo LANGO200| ASR582X | The LANGO200 IoT development board integrates the high-performance WiFi-BLE dual-mode chip ASR5822, external storage chip, voice playing chip, and analog-to-digital converter. It supports common peripheral interfaces like SPI, and can be connected to an external OLED display and infrared remote control.| Connection modules for smart home products.| Code repositories:<br>[device_soc_asrmicro](https://gitee.com/openharmony/device_soc_asrmicro)<br>[device_board_lango](https://gitee.com/openharmony/device_board_lango)<br>[vendor_asrmicro](https://gitee.com/openharmony/vendor_asrmicro) <br> Daily build:<br>http://ci.openharmony.cn/dailys/dailybuilds |
| Lightweight| Fn-Link multi-modal V200ZR| BES2600 | The multi-modal V200Z-R development board is a high-performance, multi-functional, and cost-effective AIoT SoC powered by the BES2600WM chip of Bestechnic. It integrates a quad-core ARM processor with a frequency of up to 1 GHz as well as dual-mode WiFi and dual-mode Bluetooth. The board supports the 802.11 a/b/g/n/ and BT/BLE 5.2 standards. It is able to accommodate RAM of up to 42 MB and flash memory of up to 32 MB, and supports the MIPI display serial interface (DSI) and camera serial interface (CSI). It is applicable to various AIoT multi-modal VUI and GUI interaction scenarios.| Smart hardware with screens, such as speakers and watches.| Code repositories:<br>[device_soc_bestechnic](https://gitee.com/openharmony/device_soc_bestechnic)<br>[device_board_fnlink](https://gitee.com/openharmony/device_board_fnlink)<br>[vendor_bestechnic](https://gitee.com/openharmony/vendor_bestechnic) <br> Daily build:<br>http://ci.openharmony.cn/dailys/dailybuilds |
| Lightweight| Fn-Link multi-modal V200ZR| BES2600 | The multi-modal V200Z-R development board is a high-performance, multi-functional, and cost-effective AIoT SoC powered by the BES2600WM chip of Bestechnic. It integrates a quad-core Arm processor with a frequency of up to 1 GHz as well as dual-mode WiFi and dual-mode Bluetooth. The board supports the 802.11 a/b/g/n/ and BT/BLE 5.2 standards. It is able to accommodate RAM of up to 42 MB and flash memory of up to 32 MB, and supports the MIPI display serial interface (DSI) and camera serial interface (CSI). It is applicable to various AIoT multi-modal VUI and GUI interaction scenarios.| Smart hardware with screens, such as speakers and watches.| Code repositories:<br>[device_soc_bestechnic](https://gitee.com/openharmony/device_soc_bestechnic)<br>[device_board_fnlink](https://gitee.com/openharmony/device_board_fnlink)<br>[vendor_bestechnic](https://gitee.com/openharmony/vendor_bestechnic) <br> Daily build:<br>http://ci.openharmony.cn/dailys/dailybuilds |
| Lightweight| BearPi-HM_Nano| Hi3861 | The BearPi-HM_Nano development board is specially designed for OpenHarmony. It is equipped with the highly integrated 2.4 GHz WiFi SoC chip Hi3861, near field communication (NFC) circuits, and standard E53 interfaces, which can be used to connect to smart humidifiers, smart desk lamps, smart security facilities, and intelligent smoke detectors.| Connection devices like smart street lamps, smart logistics sensors, and human body infrared sensors.| Code repositories:<br>[device_soc_hisilicon](https://gitee.com/openharmony/device_soc_hisilicon)<br>[device_board_bearpi](https://gitee.com/openharmony/device_board_bearpi)<br>[vendor_bearpi](https://gitee.com/openharmony/vendor_bearpi)<br> Daily build:<br>http://ci.openharmony.cn/dailys/dailybuilds |
## Getting Started<a name="section44681652104210"></a>
......
此差异已折叠。
......@@ -7,14 +7,14 @@
- [OpenHarmony Release Notes](../release-notes/Readme.md)
- Quick Start
- Getting Started
- [Preparations](start-overview.md)
- [Preparations](quick-start/start-overview.md)
- [Getting Started with eTS in the Traditional Coding Approach](quick-start/start-with-ets.md)
- [Getting Started with eTS in the Low-Code Approach](quick-start/start-with-ets-low-code.md)
- [Getting Started with JavaScript in the Traditional Coding Approach](quick-start/start-with-js.md)
- [Getting Started with JavaScript in the Low-Code Approach](quick-start/start-with-js-low-code.md)
- Development Fundamentals
- [Application Development Package Structure (FA Model)](quick-start/package-structure.md)
- [Application Development Package Structure (Stage Model)](quick-start/module-structure.md)
- [Application Package Structure Configuration File (FA Model)](quick-start/package-structure.md)
- [Application Package Structure Configuration File (Stage Model)](quick-start/stage-structure.md)
- [Resource File Categories](quick-start/basic-resource-file-categories.md)
- [SysCap](quick-start/syscap.md)
- Development
......@@ -36,8 +36,8 @@
- [Device Usage Statistics](device-usage-statistics/Readme-EN.md)
- [DFX](dfx/Readme-EN.md)
- [Internationalization](internationalization/Readme-EN.md)
-
- [Using Native APIs in Application Projects](napi/napi-guidelines.md)
- [OpenHarmony IDL Specifications and User Guide](IDL/idl-guidelines.md)
- [Using Native APIs in Application Projects](napi/Readme-EN.md)
- Tools
- [DevEco Studio (OpenHarmony) User Guide](quick-start/deveco-studio-user-guide-for-openharmony.md)
- Hands-On Tutorials
......
# 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.
The delegator test framework provides a self-test 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).
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.
## Starting the Test Framework
The test framework can be started using either of the following methods:
The test framework can be started in either of the following ways:
- Method 1: Run the **aa test** command.
- Method 1: Run the <idp:inline class="- topic/inline " val="code" displayname="code" id="code779717408187" tempcmdid="code779717408187">aa test</idp:inline> 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.
To start the test framework, specify the **TestRunner** 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
aa test -b BundleName -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
aa test -b BundleName -m com.example.myapplicationfaets -s unittest OpenHarmonyTestRunner -s class ActsAbilityTest -w 20
```
| Parameter | Mandatory| Description |
| --------------- | -------- | ------------------------------------------------------------ |
| -b | Yes | Bundle name of the HAP where the **TestRunner** is located. |
| -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.|
| -w | No | Timeout interval of a test case, in seconds. If this parameter is not specified or is set to a value less than or equal to **0**, the test framework exits only after **finishTest** is invoked.|
| -s \<key>\<value> | No | **-s** can be followed by any key-value pair obtained through **AbilityDelegatorArgs.parameters**. For example, in **-s classname myTest**, **-s classname** is the key and **myTest** is the value.|
| -D | No | Debug mode for starting the tested application. |
| -h | No | Help information. |
### 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).
For details about how to use the IDE to start the test framework, 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 AbilityDelegatorRegistry
**AbilityDelegatorRegistry** is the **AbilityDelegator** repository class provided by the test framework. You can use **AbilityDelegatorRegistry** to obtain an **AbilityDelegator** instance and the input and generated parameters **AbilityDelegatorArgs** during the test. You can use **AbilityDelegator** to invoke the function set provided by the test framework for testing and verification. For details, see [AbilityDelegatorRegistry](../reference/apis/js-apis-abilityDelegatorRegistry.md).
## Introduction to AbilityDelegatorArgs
**AbilityDelegatorArgs** is a test parameter class provided by the test framework. You can use **AbilityDelegatorArgs** to obtain the parameters passed and generated during the test. For details, see [AbilityDelegatorArgs](../reference/apis/js-apis-application-abilityDelegatorArgs.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).
**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. When **AbilityMonitor** is bound to an ability, 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() {
function onAbilityCreateCallback(data) {
console.info("onAbilityCreateCallback");
}
......@@ -64,7 +75,7 @@ var monitor = {
}
var abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
abilityDelegator.addAbilityMonitor(monitor).then((void) => {
abilityDelegator.addAbilityMonitor(monitor).then(() => {
console.info("addAbilityMonitor promise");
});
```
......@@ -94,7 +105,7 @@ var abilityDelegator;
var ability;
var timeout = 100;
function onAbilityCreateCallback() {
function onAbilityCreateCallback(data) {
console.info("onAbilityCreateCallback");
}
......@@ -113,8 +124,6 @@ var want = {
bundleName: "bundleName",
abilityName: "abilityName"
};
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
abilityDelegator.startAbility(want, (err, data) => {
console.info("startAbility callback");
});
......@@ -126,14 +135,44 @@ abilityDelegator.startAbility(want, (err, data) => {
### 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.
**AbilityDelegator** provides APIs to run shell commands in the test environment.
**Example**
```javascript
var abilityDelegator;
var cmd = "cmd";
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
abilityDelegator.executeShellCommand(cmd, (err,data) => {
var abilityDelegator;
var cmd = "cmd";
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
abilityDelegator.executeShellCommand(cmd, (err, data) => {
console.info("executeShellCommand callback");
});
});
```
### Printing Log Information
**AbilityDelegator** provides APIs for printing log information. You can call any API in the test code to print process logs to the unit test console.
**Example**
```javascript
var abilityDelegator;
var msg = "msg";
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
abilityDelegator.print(msg, (err) => {
console.info("print callback");
});
```
### Finishing the Test and Printing Log Information
**AbilityDelegator** provides the APIs for actively finishing the test. You can call any API in test code to finish the test and print logs to the unit test console.
**Example**
```javascript
var abilityDelegator;
var msg = "msg";
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
abilityDelegator.finishTest(msg, 0, (err) => {
console.info("finishTest callback");
});
```
......@@ -2,13 +2,13 @@
## Overview
### Concepts
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**.
The Page ability implements the ArkUI and provides the capability of interacting with developers. When you create an ability in DevEco Studio, DevEco Studio 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** or **app.ets**.
### Page Ability Lifecycle
**Ability lifecycle**
The Page ability lifecycle is a general term for all states of a Page ability, such as **INACTIVE**, **ACTIVE**, and **BACKGROUND**.
The Page ability lifecycle defines all states of a Page ability, such as **INACTIVE**, **ACTIVE**, and **BACKGROUND**.
The following figure shows the lifecycle state transition of the Page ability.
......@@ -17,25 +17,25 @@ The following figure shows the lifecycle state transition of the Page ability.
Description of ability lifecycle states:
- **UNINITIALIZED**: The Page ability is not initialized. This is a temporary state. A Page ability changes directly to the **INITIAL** state upon its creation.
- **UNINITIALIZED**: The Page ability is not initialized. This is a temporary state, from which a Page ability changes directly to the **INITIAL** state upon its creation.
- **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.
- **INITIAL**: The Page ability is initialized but 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 Page ability is visible but does not gain focus.
- **ACTIVE**: The ability runs in the foreground and gains focus.
- **ACTIVE**: The Page ability runs in the foreground and has focus.
- **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.
- **BACKGROUND**: The Page ability runs in 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 relationship between lifecycle callbacks and lifecycle states of the Page ability.**
![fa-pageAbility-lifecycle](figures/fa-pageAbility-lifecycle.png)
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.
You can override the lifecycle callbacks provided by the Page ability in the **app.js** or **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 two launch types: singleton and multi-instance.
The **launchType** item in the **config.json** file is used to specify the launch type.
You can specify the launch type by setting **launchType** in the **config.json** file.
| Launch Type | Description |Description |
| ----------- | ------- |---------------- |
......@@ -55,7 +55,7 @@ By default, **singleton** is used.
| void startAbility(parameter: StartAbilityParameter) | Starts an ability. |
| Context getContext(): | Obtains the application context.|
| void terminateSelf() | Terminates the ability. |
| bool hasWindowFocus() | Checks whether the ability gains focus. |
| bool hasWindowFocus() | Checks whether the ability has focus. |
### Starting a Local Page Ability
......@@ -76,37 +76,10 @@ By default, **singleton** is used.
action: "",
entities: [""],
type: "",
options: {
// Grant the permission to perform read operations on the URI.
authReadUriPermission: true,
// Grant the permission to perform write operations on the URI.
authWriteUriPermission: true,
// Support forwarding the Want result to the ability.
abilityForwardResult: true,
// Enable abiligy continuation.
abilityContinuation: true,
// Specify that a component does not belong to ohos.
notOhosComponent: true,
// Specify that an ability is started.
abilityFormEnabled: true,
// Grant the permission for possible persisting on the URI.
authPersistableUriPermission: true,
// Grant the permission for possible persisting on the prefix URI.
authPrefixUriPermission: true,
// Support distributed scheduling system startup on multiple devices.
abilitySliceMultiDevice: true,
// A service ability is started regardless of whether the host application has been started.
startForegroundAbility: true,
// Install the specified ability if it is not installed.
installOnDemand: true,
// Return the result to the ability slice.
abilitySliceForwardResult: true,
// Install the specified ability with background mode if it is not installed.
installWithBackgroundMode: true
},
deviceId: "",
bundleName: "com.example.startability",
abilityName: "com.example.startability.MainAbility",
bundleName: "com.example.myapplication",
/* In the FA model, abilityName consists of package and ability name. */
abilityName: "com.example.entry.secondAbility",
uri: ""
},
},
......@@ -122,10 +95,10 @@ You can also include **parameters** in the **want** parameter and set its value
featureAbility.startAbility({
want:
{
bundleName: "com.example.startability",
bundleName: "com.example.myapplication",
uri: "",
parameters: {
abilityName: "com.example.startability.MainAbility"
abilityName: "com.example.entry.secondAbility"
}
},
},
......@@ -227,15 +200,15 @@ In the cross-device scenario, the application must also apply for the data synch
| API | Description |
| ------------ | ------------------------------------------------------------ |
| onShow() | Called when the ability is switched from the background to the foreground. In this case, the ability is visible to users.|
| onHide() | Called when the ability is switched from the foreground to the background. In this case, the ability is invisible.|
| onDestroy() | Called when the ability is destroyed. In this callback, you can make preparations for app exit, such as recycling resources and clearing the cache.|
| onHide() | Called when the ability is switched from the foreground to the background. In this case, the ability is invisible to users.|
| onDestroy() | Called when the ability is destroyed. In this callback, you can make preparations for application exit, such as recycling resources and clearing the cache.|
| onCreate() | Called when the ability is created for the first time. You can initialize the application in this callback.|
| onInactive() | Called when the ability loses focus. An ability loses focus before entering the background state.|
| onInactive() | Called when the ability loses focus. An ability loses focus when it is about to enter the background state.|
| onActive() | Called when the ability is switched to the foreground and gains focus. |
**Example**
You need to override the lifecycle callbacks in **app.js/app.ets**. The IDE template generates **onCreate()** and **onDestroy()** by default. You need to override the other callbacks.
You need to override the lifecycle callbacks except **onCreate()** and **onDestroy()** in **app.js** or **app.ets**. The **onCreate()** and **onDestroy()** callbacks are automatically generated in the template code provided by DevEco Studio.
```javascript
export default {
......@@ -261,4 +234,5 @@ export default {
```
## Samples
The following sample is provided to help you better understand how to develop a Page ability:
- [`DMS`: Distributed Demo (eTS) (API7)](https://gitee.com/openharmony/app_samples/tree/master/ability/DMS)
- [`DMS`: Distributed Demo (eTS, API version 7)](https://gitee.com/openharmony/app_samples/tree/master/ability/DMS)
......@@ -8,13 +8,17 @@ The following figure shows the ability call process.
![stage-call](figures/stage-call.png)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br/>
> The startup mode of the callee must be **singleton**.
> Currently, only system applications and Service Extension abilities can use the **Call** APIs to access the callee.
## Available APIs
The table below describes the ability call APIs. For details, see [Ability](../reference/apis/js-apis-application-ability.md#caller).
**Table 1** Ability call APIs
|API|Description|
|:------|:------|
|Promise<Caller> startAbilityByCall(want: Want)|Obtains the caller interface of the specified ability, and if the specified ability is not started, starts the ability in the background.|
|Promise<Caller> startAbilityByCall(want: Want)|Obtains the caller interface of the specified ability and, if the specified ability is not running, starts the ability in the background.|
|void on(method: string, callback: CalleeCallBack)|Callee.on: callback invoked when the callee registers a method.|
|void off(method: string)|Callee.off: callback invoked when the callee deregisters a method.|
|Promise<void> call(method: string, data: rpc.Sequenceable)|Caller.call: sends agreed sequenceable data to the callee.|
......@@ -77,7 +81,7 @@ export default class MySequenceable {
```
4. Implement **Callee.on** and **Callee.off**.
The time to register a listener for the callee depends on your application. The data sent and received before the listener is registered and that after the listener is deregistered are not processed. In the following example, the **CalleeSortMethod** listener is registered in **onCreate** of the ability and deregistered in **onDestroy**. After receiving sequenceable data, the application processes the data and returns them. You need to implement processing based on service requirements. The sample code is as follows:
The time to register a listener for the callee depends on your application. The data sent and received before the listener is registered and that after the listener is deregistered are not processed. In the following example, the **CalleeSortMethod** listener is registered in **onCreate** of the ability and deregistered in **onDestroy**. After receiving sequenceable data, the application processes the data and returns the data result. You need to implement processing based on service requirements. The sample code is as follows:
```ts
const TAG: string = '[CalleeAbility]'
const MSG_SEND_METHOD: string = 'CallSendMsg'
......@@ -196,7 +200,7 @@ context.requestPermissionsFromUser(permissions).then((data) => {
```
3. Send agreed sequenceable data.
The sequenceable data can be sent to the callee in either of the following ways: without a return value or obtaining data returned by the callee. The method and sequenceable data must be consistent with those of the callee. The following example describes how to invoke the **Call** API to send data to the callee. The sample code is as follows:
The sequenceable data can be sent to the callee with or without a return value. The method and sequenceable data must be consistent with those of the callee. The following example describes how to invoke the **Call** API to send data to the callee. The sample code is as follows:
```ts
const MSG_SEND_METHOD: string = 'CallSendMsg'
async onButtonCall() {
......@@ -242,9 +246,6 @@ try {
}
```
## Development Example
## Samples
The following sample is provided to help you better understand how to develop an ability call in the stage model:
[StageCallAbility](https://gitee.com/openharmony/app_samples/tree/master/ability/StageCallAbility)
In this sample, the **AbilityStage** APIs are implemented in the **AbilityStage.ts** file in the **Application** directory, the **Ability** APIs are implemented in the **MainAbility** directory, and **pages/index** is the pages of the ability. Another ability and callee are implemented in the **CalleeAbility** directory, and its pages are the content configured in **pages/second**. The **MainAbility** functions as the caller, and the **CalleeAbility** functions as the callee. After starting the **CalleeAbility**, the **MainAbility** obtains the caller interface, processes the string entered by the user, and transfers the processed string to the **CalleeAbility**. The **CalleeAbility** refreshes the page based on the received data and returns the result to the **MainAbility**.
- [`StageCallAbility`: Stage Ability Creation and Usage (eTS, API version 9)](https://gitee.com/openharmony/app_samples/tree/master/ability/StageCallAbility)
......@@ -44,7 +44,7 @@ DevEco Studio is a high-performance integrated development environment (IDE) rec
### Hands-On Tutorials
To make you better understand how functions work together and jumpstart your application development projects, we provide stripped-down, real-world [samples](https://gitee.com/openharmony/app_samples/blob/master/README.md).
To make you better understand how functions work together and jumpstart your application development projects, we provide stripped-down, real-world [samples](https://gitee.com/openharmony/app_samples/blob/master/README.md) and [codelabs](https://gitee.com/openharmony/codelabs).
### API References
......
......@@ -44,7 +44,7 @@ DevEco Studio is a high-performance integrated development environment (IDE) rec
### Hands-On Tutorials
To make you better understand how functions work together and jumpstart your application development projects, we provide stripped-down, real-world [samples](https://gitee.com/openharmony/app_samples/blob/master/README.md).
To make you better understand how functions work together and jumpstart your application development projects, we provide stripped-down, real-world [samples](https://gitee.com/openharmony/app_samples/blob/master/README.md) and [codelabs](https://gitee.com/openharmony/codelabs).
### API References
......
# Background Task Overview
# Background Task Management Overview
Frequent activities of background applications cause user devices to consume power quickly and respond slowly. To meet performance and power consumption requirements, the system allows applications to execute only activities within the specifications in the background. Activities beyond the specifications are suspended by default, and resources allocated to them will be reclaimed when the available resources are insufficient.
......
# Network and Connectivity
# Connectivity
- Network Management
- [Network Management Overview](net-mgmt-overview.md)
......@@ -7,5 +7,5 @@
- [Socket Connection](socket-connection.md)
- IPC & RPC
- [IPC & RPC Overview](ipc-rpc-overview.md)
- [IPC & RPC Development Guidelines](ipc-rpc-development-guideline.md)
- [IPC & RPC Development](ipc-rpc-development-guideline.md)
- [Subscribing to State Changes of a Remote Object](subscribe-remote-state.md)
......@@ -12,20 +12,20 @@ To use related APIs, you must declare the **ohos.permission.INTERNET** permissio
The following table describes the related APIs.
| API | Description |
| ----------------------------------------- | ----------------------------------- |
| createHttp() | Creates an HTTP request. |
| request() | Initiates an HTTP request to a given URL. |
| destroy() | Destroys an HTTP request. |
| API | Description |
| ----------------------------------------- | --------------------------------------------------------- |
| createHttp() | Creates an HTTP request. |
| request() | Initiates an HTTP request to a given URL. |
| destroy() | Destroys an HTTP request. |
| on(type: 'headersReceive') | Registers an observer for HTTP Response Header events. |
| off(type: 'headersReceive') | Unregisters the observer for HTTP Response Header events.|
| off(type: 'headersReceive') | Unregisters the observer for HTTP Response Header events. |
## How to Develop
1. Import the required HTTP module.
2. Create an **HttpRequest** object.
3. (Optional) Listen for HTTP Response Header events.
4. Initiates an HTTP request to a given URL.
4. Initiate an HTTP request to a given URL.
5. (Optional) Process the HTTP Response Header event and the return result of the HTTP request.
```js
......@@ -71,3 +71,7 @@ httpRequest.request(
}
);
```
## Samples
The following sample is provided to help you better understand how to develop the HTTP data request feature:
- [`Http`: HTTP Data Request (eTS) (API 8)](https://gitee.com/openharmony/app_samples/tree/master/Network/Http)
......@@ -6,7 +6,7 @@ IPC/RPC enables a proxy and a stub that run on different processes to communicat
## Available APIs<a name="section1633115419401"></a>
**Table 1** Native IPC APIs
**Table 1** Native IPC APIs
<a name="table178849240013"></a>
<table><thead align="left"><tr id="row6884924608"><th class="cellrowborder" valign="top" width="14.12141214121412%" id="mcps1.2.4.1.1"><p id="p98846241706"><a name="p98846241706"></a><a name="p98846241706"></a>Class/Interface</p>
......@@ -44,9 +44,9 @@ IPC/RPC enables a proxy and a stub that run on different processes to communicat
**Using Native APIs**
1. Define the IPC interface **ITestAbility**.
1. Define the IPC interface **ITestAbility**.
**ITestAbility** inherits the IPC base class **IRemoteBroker** and defines descriptors, functions, and message code. The functions need to be implemented on both the proxy and stub.
**ITestAbility** inherits the IPC base class **IRemoteBroker** and defines descriptors, functions, and message code. The functions need to be implemented on both the proxy and stub.
```
class ITestAbility : public IRemoteBroker {
......@@ -58,9 +58,9 @@ IPC/RPC enables a proxy and a stub that run on different processes to communicat
};
```
2. Define and implement service provider **TestAbilityStub**.
2. Define and implement service provider **TestAbilityStub**.
This class is related to the IPC framework and needs to inherit **IRemoteStub<ITestAbility\>**. You need to override **OnRemoteRequest** on the stub to receive requests from the proxy.
This class is related to the IPC framework and needs to inherit **IRemoteStub<ITestAbility\>**. You need to override **OnRemoteRequest** on the stub to receive requests from the proxy.
```
class TestAbilityStub : public IRemoteStub<ITestAbility> {
......@@ -85,7 +85,7 @@ IPC/RPC enables a proxy and a stub that run on different processes to communicat
}
```
3. Define the **TestAbility** class that implements functions for the stub.
3. Define the **TestAbility** class that implements functions for the stub.
```
class TestAbility : public TestAbilityStub {
......@@ -98,9 +98,9 @@ IPC/RPC enables a proxy and a stub that run on different processes to communicat
}
```
4. Define and implement **TestAbilityProxy**.
4. Define and implement **TestAbilityProxy**.
This class is implemented on the proxy and inherits **IRemoteProxy<ITestAbility\>**. You can call **SendRequest** to send a request to the stub and expose the capabilities provided by the stub.
This class is implemented on the proxy and inherits **IRemoteProxy<ITestAbility\>**. You can call **SendRequest** to send a request to the stub and expose the capabilities provided by the stub.
```
class TestAbilityProxy : public IRemoteProxy<ITestAbility> {
......@@ -128,7 +128,7 @@ IPC/RPC enables a proxy and a stub that run on different processes to communicat
5. Register and start an SA.
Call **AddSystemAbility** to register the **TestAbilityStub** instance of the SA with **SystemAbilityManager**. The registration parameters vary depending on whether the **SystemAbilityManager** resides on the same device as the SA.
Call **AddSystemAbility** to register the **TestAbilityStub** instance of the SA with **SystemAbilityManager**. The registration parameters vary depending on whether the **SystemAbilityManager** resides on the same device as the SA.
```
// Register the TestAbilityStub instance with the SystemAbilityManager on the same device as the SA.
......@@ -144,7 +144,7 @@ IPC/RPC enables a proxy and a stub that run on different processes to communicat
6. Obtain the SA.
Call the **GetSystemAbility** function of the **SystemAbilityManager** class to obtain the **IRemoteObject** for the SA, and create a **TestAbilityProxy** instance.
Call the **GetSystemAbility** function of the **SystemAbilityManager** class to obtain the **IRemoteObject** for the SA, and create a **TestAbilityProxy** instance.
```
// Obtain the proxy of the SA registered on the local device.
......
......@@ -19,4 +19,4 @@ In OpenHarmony documents, proxy represents the service requester, and stub repre
## Related Modules
Distributed Scheduler
[Distributed Scheduler](https://gitee.com/openharmony/distributedschedule_dms_fwk)
......@@ -10,26 +10,26 @@ Your application can transmit data through Socket connections. Currently, the TC
The Socket connection function is mainly implemented by the Socket module. The following table describes the related APIs.
| API| Description|
| API| Description |
| -------- | -------- |
| constructUDPSocketInstance() | Creates a **UDPSocket** object.|
| constructTCPSocketInstance() | Creates a **TCPSocket** object.|
| bind() | Binds the IP address and port number.|
| constructUDPSocketInstance() | Creates a **UDPSocket** object. |
| constructTCPSocketInstance() | Creates a **TCPSocket** object. |
| bind() | Binds the IP address and port number. |
| send() | Sends data.|
| close() | Closes a Socket connection.|
| getState() | Obtains the Socket connection status.|
| connect() | Connects to the specified IP address and port. This function is supported only for TCP.|
| getRemoteAddress() | Obtains the peer address of the Socket connection. This function is supported only for TCP. The **connect** API must have been called before you use this API.|
| on(type:&nbsp;'message') | Enables listening for **message** events of the Socket connection.|
| off(type:&nbsp;'message') | Disables listening for **message** events of the Socket connection.|
| on(type:&nbsp;'close') | Enables listening for **close** events of the Socket connection.|
| off(type:&nbsp;'close') | Disables listening for **close** events of the Socket connection.|
| on(type:&nbsp;'error') | Enables listening for **error** events of the Socket connection.|
| off(type:&nbsp;'error') | Disables listening for **error** events of the Socket connection.|
| close() | Closes a Socket connection. |
| getState() | Obtains the Socket connection status. |
| connect() | Connects to the specified IP address and port. This function is supported only for TCP. |
| getRemoteAddress() | Obtains the peer address of the Socket connection. This function is supported only for TCP. The **connect** API must have been called before you use this API. |
| on(type:&nbsp;'message') | Enables listening for **message** events of the Socket connection. |
| off(type:&nbsp;'message') | Disables listening for **message** events of the Socket connection. |
| on(type:&nbsp;'close') | Enables listening for **close** events of the Socket connection. |
| off(type:&nbsp;'close') | Disables listening for **close** events of the Socket connection. |
| on(type:&nbsp;'error') | Enables listening for **error** events of the Socket connection. |
| off(type:&nbsp;'error') | Disables listening for **error** events of the Socket connection. |
| on(type:&nbsp;'listening') | Enables listening for **listening** events of the UDPSocket connection. |
| off(type:&nbsp;'listening') | Disables listening for **listening** events of the UDPSocket connection. |
| on(type:&nbsp;'connect') | Enables listening for **connect** events of the TCPSocket connection. |
| off(type:&nbsp;'connect') | Disables listening for **connect** events of the TCPSocket connection.|
| off(type:&nbsp;'connect') | Disables listening for **connect** events of the TCPSocket connection. |
## How to Develop
......@@ -122,3 +122,7 @@ The implementation is similar for UDPSocket and TCPSocket. The following uses th
tcp.off('close');
}, 30 * 1000);
```
## Samples
The following sample is provided to help you better understand how to develop the socket connection feature:
- [`Socket`: Socket Connection (eTS) (API 8)](https://gitee.com/openharmony/app_samples/tree/master/Network/Socket)
......@@ -12,20 +12,20 @@ If an error occurs in any of the preceding processes, the client will receive a
The WebSocket connection function is mainly implemented by the WebSocket module. To use related APIs, you must declare the **ohos.permission.INTERNET** permission. The following table describes the related APIs.
| API| Description|
| API | Description |
| -------- | -------- |
| createWebSocket() | Creates a WebSocket connection.|
| connect() | Establishes a WebSocket connection to a given URL.|
| send() | Sends data through the WebSocket connection.|
| close() | Closes a WebSocket connection.|
| on(type:&nbsp;'open') | Enables listening for **open** events of a WebSocket connection.|
| off(type:&nbsp;'open') | Disables listening for **open** events of a WebSocket connection.|
| on(type:&nbsp;'message') | Enables listening for **message** events of a WebSocket connection.|
| off(type:&nbsp;'message') | Disables listening for **message** events of a WebSocket connection.|
| on(type:&nbsp;'close') | Enables listening for **close** events of a WebSocket connection.|
| off(type:&nbsp;'close') | Disables listening for **close** events of a WebSocket connection.|
| on(type:&nbsp;'error') | Enables listening for **error** events of a WebSocket connection.|
| off(type:&nbsp;'error') | Disables listening for **error** events of a WebSocket connection.|
| createWebSocket() | Creates a WebSocket connection. |
| connect() | Establishes a WebSocket connection to a given URL. |
| send() | Sends data through the WebSocket connection. |
| close() | Closes a WebSocket connection. |
| on(type:&nbsp;'open') | Enables listening for **open** events of a WebSocket connection. |
| off(type:&nbsp;'open') | Disables listening for **open** events of a WebSocket connection. |
| on(type:&nbsp;'message') | Enables listening for **message** events of a WebSocket connection. |
| off(type:&nbsp;'message') | Disables listening for **message** events of a WebSocket connection. |
| on(type:&nbsp;'close') | Enables listening for **close** events of a WebSocket connection. |
| off(type:&nbsp;'close') | Disables listening for **close** events of a WebSocket connection. |
| on(type:&nbsp;'error') | Enables listening for **error** events of a WebSocket connection. |
| off(type:&nbsp;'error') | Disables listening for **error** events of a WebSocket connection. |
## How to Develop
......
......@@ -6,9 +6,9 @@
- Relational Database
- [RDB Overview](database-relational-overview.md)
- [RDB Development](database-relational-guidelines.md)
- Lightweight Data Store
- [Lightweight Data Store Overview](database-preference-overview.md)
- [Lightweight Data Store Development](database-preference-guidelines.md)
- Preferences
- [Preferences Overview](database-preference-overview.md)
- [Preferences Development](database-preference-guidelines.md)
- Distributed Data Object
- [Distributed Data Object Overview](database-distributedobject-overview.md)
- [Distributed Data Object Development](database-distributedobject-guidelines.md)
......@@ -2,7 +2,7 @@
## When to Use
The distributed data objects allow data across devices to be processed like local variables by shielding complex data interaction between devices. For the devices that form a Super Device, when data in the distributed data object of an application is added, deleted, or modified on a device, the data for the same application is also updated on the other devices. The devices can listen for the data changes and online and offline states of other devices. The distributed data objects support basic data types, such as number, string, and Boolean, as well as complex data types, such as array and nested basic types.
The distributed data objects allow data across devices to be processed like local variables by shielding complex data interaction between devices. For the devices that form a Super Device, when data in the distributed data object of an application is added, deleted, or modified on a device, the data for the same application is also updated on the other devices. The devices can listen for the data changes and online and offline status of other devices. The distributed data objects support basic data types, such as number, string, and Boolean, as well as complex data types, such as array and nested basic types.
## Available APIs
......@@ -13,47 +13,47 @@ Call **createDistributedObject()** to create a distributed data object instance.
**Table 1** API for creating a distributed data object instance
| Package| API| Description|
| -------- | -------- | -------- |
| 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.|
| Package | API | Description |
| -------- | -------- | -------- |
| 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
Call **genSessionId()** to generate a session ID randomly. The generated session ID can be used to set the session ID of a distributed data object.
**Table 2** API for generating a session ID randomly
| Package| API| Description|
| -------- | -------- | -------- |
| ohos.data.distributedDataObject| genSessionId(): string | Generates a session ID, which can be used as the session ID of a distributed data object.|
| Package | API | Description |
| -------- | -------- | -------- |
| ohos.data.distributedDataObject | genSessionId(): string | Generates a session ID, which can be used as the session ID of a distributed data object. |
### Setting a SessionID for Distributed Data Objects
Call setSessionId() to set the session ID for a distributed data object. The session ID is a unique identifier for one collaboration across devices. The distributed data objects to be synchronized must be associated with the same session ID.
Call **setSessionId()** to set a session ID for a distributed data object. The session ID is a unique identifier for one collaboration across devices. The distributed data objects to be synchronized must be associated with the same session ID.
**Table 3** API for setting a session ID
| Class| API| Description|
| -------- | -------- | -------- |
| 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.|
| Class | API | Description |
| -------- | -------- | -------- |
| DistributedDataObject | setSessionId(sessionId?: string): boolean | Sets a session ID for distributed data objects.<br>**sessionId**: session 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
Call **on()** to subscribe to data changes of a distributed data object. When the data changes, a callback will be invoked to return the data changes. You can use **off()** to unsubscribe from the data changes.
**Table 4** APIs for observing data changes of a distributed data object
| Class| API| Description|
| -------- | -------- | -------- |
| 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. Callback used to return changes of the distributed object. If this parameter is not specified, all callbacks related to data changes will be unregistered.|
| Class | API | Description |
| -------- | -------- | -------- |
| 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. <br>**Callback**: specifies callback used to return changes of the distributed data object. If this parameter is not specified, all callbacks related to data changes will be unregistered. |
### Observing Online or Offline Status
Call **on()** to subscribe to status changes of a distributed data object. The status can be online or offline. When the status changes, a callback will be invoked to return the status. You can use **off()** to unsubscribe from the status changes.
**Table 5** APIs for observing status changes of a distributed data object
| Class| API| Description|
| -------- | -------- | -------- |
| DistributedDataObject| on(type: 'status', callback: Callback<{ sessionId: string, networkId: string, status: 'online' \| 'offline' }>): void | Subscribes to the status changes of a distributed data object.|
| DistributedDataObject| off(type: 'status', callback?: Callback<{ sessionId: string, deviceId: string, status: 'online' \| 'offline' }>): void | Unsubscribes from status changes of a distributed data object.|
| Class | API | Description |
| -------- | -------- | -------- |
| DistributedDataObject | on(type: 'status', callback: Callback<{ sessionId: string, networkId: string, status: 'online' \ | 'offline' }>): void | Subscribes to the status changes of a distributed data object. |
| DistributedDataObject | off(type: 'status', callback?: Callback<{ sessionId: string, deviceId: string, status: 'online' \ | 'offline' }>): void | Unsubscribes from status changes of a distributed data object. |
......@@ -62,13 +62,13 @@ Call **on()** to subscribe to status changes of a distributed data object. The s
The following example shows how to implement a distributed data object synchronization.
1. Import the @ohos.data.distributedDataObject module to the development environment.
```js
import distributedObject from '@ohos.data.distributedDataObject'
```
2. Obtain a distributed data object instance.
The sample code is as follows:
```js
var local_object = distributedObject.createDistributedObject({name:undefined, age:undefined, isVis:true,
parent:undefined, list:undefined});
......@@ -77,8 +77,6 @@ The following example shows how to implement a distributed data object synchroni
3. Add the synchronization network. The data objects in the synchronization network include the local and remote objects.
The sample code is as follows:
```js
// Local object
......@@ -90,13 +88,11 @@ The following example shows how to implement a distributed data object synchroni
var remote_object = distributedObject.createDistributedObject({name:undefined, age:undefined, isVis:true,
parent:undefined, list:undefined});
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 learning that the device goes online, the remote object synchronizes data. That is, name changes to jack and age to 18.
```
4. Observe the data changes of the distributed data object. Subscribe to data changes of the remote end. When the data is the peer end changes, a callback will be called to return the data changes.
The sample code is as follows:
4. Observe the data changes of the distributed data object. You can subscribe to data changes of the remote object. When the data in the remote object changes, a callback will be called to return the data changes.
```js
function changeCallback(sessionId, changeData) {
console.info("change" + sessionId);
......@@ -107,14 +103,13 @@ The following example shows how to implement a distributed data object synchroni
});
}
}
// To refresh the page in changeCallback, correctly set this.changeCallback.bind(this) in
changeCallback.
// To refresh the page in changeCallback, correctly bind (this) to the changeCallback.
local_object.on("change", this.changeCallback.bind(this));
```
5. Modify object attributes. The object attributes support basic data types (such as number, Boolean, and string) and complex data types (array and nested basic types).
The sample code is as follows:
```js
local_object.name = "jack";
local_object.age = 19;
......@@ -123,7 +118,7 @@ The following example shows how to implement a distributed data object synchroni
local_object.list = [{mother:"jack mom"}, {father:"jack Dad"}];
```
> ![icon-note.gif](../public_sys-resources/icon-note.gif) **NOTE**<br/>
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
> For the distributed data object of the complex type, only the root attribute can be modified. The subordinate attributes cannot be modified. Example:
```js
// Supported modification.
......@@ -133,22 +128,22 @@ The following example shows how to implement a distributed data object synchroni
```
6. Access the distributed data object. Obtain the distributed data object attribute, which is the latest data on the network.
The sample code is as follows:
```js
console.info("name " + local_object["name"]);
```
7. Unsubscribe from data changes. You can specify the callback to unsubscribe from. If you do not specify the callback, all data change callbacks of the distributed data object will be unsubscribed from.
The sample code is as follows:
```js
// Unsubscribe from changeCallback.
// Unsubscribe from the specified data change callback.
local_object.off("change", changeCallback);
// Unsubscribe from all data change callbacks.
local_object.off("change");
```
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:
```js
function statusCallback(sessionId, networkId, status) {
this.response += "status changed " + sessionId + " " + status + " " + networkId;
......@@ -156,27 +151,28 @@ The following example shows how to implement a distributed data object synchroni
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.
The sample code is as follows:
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, this API unsubscribes from all callbacks of this distributed data object.
```js
// Unsubscribe from the online status change callback.
// Unsubscribe from the specified status change callback.
local_object.off("status", statusCallback);
// Unsubscribe from all online status change callbacks.
// Unsubscribe from all status change callbacks.
local_object.off("status");
```
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:
```js
local_object.setSessionId("");
```
## Development Example
10. Remove a distributed data object from the synchronization network. Data changes on the local object will not be synchronized to the removed distributed data object.
```js
local_object.setSessionId("");
```
## Samples
The following example is provided for you to better understand the development of distributed data object:
The following example is provided for you to better understand the development of distributed data objects:
- [Distributed Notepad](https://gitee.com/openharmony/distributeddatamgr_objectstore/tree/master/samples/distributedNotepad)
When an event occurs on a device, such as a note is added, the tile or content of a note is changed, and the event list is cleared, the change will be synchronized to other devices in the trusted network by the Notepad app.
When an event of the Notepad app occurs on a device, such as a note is added, the tile or content of a note is changed, or the event list is cleared, the change will be synchronized to other devices in the trusted network.
......@@ -11,15 +11,15 @@ The table below describes the APIs provided by the OpenHarmony DDS module.
**Table 1** APIs provided by the DDS
| Category | API | Description |
| -------------------------- | ------------------------------------------------------------ | ----------------------------------------------- |
| Creating a distributed database | createKVManager(config:&nbsp;KVManagerConfig,&nbsp;callback:&nbsp;AsyncCallback&lt;KVManager&gt;):&nbsp;void<br>createKVManager(config:&nbsp;KVManagerConfig):&nbsp;Promise&lt;KVManager> | Creates a **KVManager** object for database management.|
| Obtaining a distributed KV store | getKVStore&lt;T&nbsp;extends&nbsp;KVStore&gt;(storeId:&nbsp;string,&nbsp;options:&nbsp;Options,&nbsp;callback:&nbsp;AsyncCallback&lt;T&gt;):&nbsp;void<br>getKVStore&lt;T&nbsp;extends&nbsp;KVStore&gt;(storeId:&nbsp;string,&nbsp;options:&nbsp;Options):&nbsp;Promise&lt;T&gt; | Obtains the KV store with the specified **Options** and **storeId**.|
| Managing data in a distributed KV store| put(key:&nbsp;string,&nbsp;value:&nbsp;Uint8Array&nbsp;\|&nbsp;string&nbsp;\|&nbsp;number&nbsp;\|&nbsp;boolean,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void<br>put(key:&nbsp;string,&nbsp;value:&nbsp;Uint8Array&nbsp;\|&nbsp;string&nbsp;\|&nbsp;number&nbsp;\|&nbsp;boolean):&nbsp;Promise&lt;void> | Inserts and updates data. |
| Managing data in a distributed KV store| delete(key:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;void&gt;):&nbsp;void<br>delete(key:&nbsp;string):&nbsp;Promise&lt;void> | Deletes data. |
| Managing data in a distributed KV store| get(key:&nbsp;string,&nbsp;callback:&nbsp;AsyncCallback&lt;Uint8Array&nbsp;\|&nbsp;string&nbsp;\|&nbsp;boolean&nbsp;\|&nbsp;number&gt;):&nbsp;void<br>get(key:&nbsp;string):&nbsp;Promise&lt;Uint8Array&nbsp;\|&nbsp;string&nbsp;\|&nbsp;boolean&nbsp;\|&nbsp;number> | Queries data. |
| Subscribing to changes in the distributed data | on(event:&nbsp;'dataChange',&nbsp;type:&nbsp;SubscribeType,&nbsp;observer:&nbsp;Callback&lt;ChangeNotification&gt;):&nbsp;void<br>on(event:&nbsp;'syncComplete',&nbsp;syncCallback:&nbsp;Callback&lt;Array&lt;[string,&nbsp;number]&gt;&gt;):&nbsp;void | Subscribes to data changes in the KV store. |
| Synchronizing data across devices | sync(deviceIdList:&nbsp;string[],&nbsp;mode:&nbsp;SyncMode,&nbsp;allowedDelayMs?:&nbsp;number):&nbsp;void | Triggers database synchronization in manual mode. |
| Category | API | Description |
| -------- | --- | ----------- |
| Creating a distributed database | createKVManager(config: KVManagerConfig, callback: AsyncCallback&lt;KVManager&gt;): void<br>createKVManager(config: KVManagerConfig): Promise&lt;KVManager> | Creates a **KVManager** object for database management.|
| Obtaining a distributed KV store | getKVStore&lt;T extends KVStore&gt;(storeId: string, options: Options, callback: AsyncCallback&lt;T&gt;): void<br>getKVStore&lt;T extends KVStore&gt;(storeId: string, options: Options): Promise&lt;T&gt; | Obtains the KV store with the specified **Options** and **storeId**. |
| Managing data in a distributed KV store | put(key: string, value: Uint8Array \| string \| number \| boolean, callback: AsyncCallback&lt;void&gt;): void<br>put(key: string, value: Uint8Array \| string \| number \| boolean): Promise&lt;void> | Inserts and updates data. |
| Managing data in a distributed KV store| delete(key: string, callback: AsyncCallback&lt;void&gt;): void<br>delete(key: string): Promise&lt;void> | Deletes data. |
| Managing data in a distributed KV store | get(key: string, callback: AsyncCallback&lt;Uint8Array \| string \| boolean \| number&gt;): void<br>get(key: string): Promise&lt;Uint8Array \| string \| boolean \| number> | Queries data. |
| Subscribing to changes in the distributed data | on(event: 'dataChange', type: SubscribeType, observer: Callback&lt;ChangeNotification&gt;): void<br>on(event: 'syncComplete', syncCallback: Callback&lt;Array&lt;[string, number]&gt;&gt;): void | Subscribes to data changes in the KV store. |
| Synchronizing data across devices | sync(deviceIdList: string[], mode: SyncMode, allowedDelayMs?: number): void | Triggers database synchronization in manual mode. |
......@@ -29,6 +29,7 @@ The table below describes the APIs provided by the OpenHarmony DDS module.
The following uses a single KV store as an example to describe the development procedure.
1. Import the distributed data module.
```js
import distributedData from '@ohos.data.distributedData';
```
......@@ -95,6 +96,7 @@ The following uses a single KV store as an example to describe the development p
4. Subscribe to changes in the distributed data.<br/>
The following is the sample code for subscribing to the data changes of a single KV store:
```js
kvStore.on('dataChange', distributedData.SubscribeType.SUBSCRIBE_TYPE_ALL, function (data) {
console.log("dataChange callback call data: " + JSON.stringify(data));
......@@ -128,6 +130,7 @@ The following uses a single KV store as an example to describe the development p
2. Query data from the single KV store.
The following is the sample code for querying data of the string type from the single KV store:
```js
const KEY_TEST_STRING_ELEMENT = 'key_test_string';
const VALUE_TEST_STRING_ELEMENT = 'value-test-string';
......@@ -177,5 +180,5 @@ The following uses a single KV store as an example to describe the development p
```
## Samples
The following samples are provided to help you better understand the distributed data development:
- [`KvStore`: distributed database (eTS) (API8)](https://gitee.com/openharmony/app_samples/tree/master/data/Kvstore)
- [Distributed Database](https://gitee.com/openharmony/codelabs/tree/master/Data/JsDistributedData)
- [`KvStore`: Distributed Data Management (eTS) (API8)](https://gitee.com/openharmony/app_samples/tree/master/data/Kvstore)
- [Distributed Data Service](https://gitee.com/openharmony/codelabs/tree/master/Data/JsDistributedData)
# Lightweight Data Store Development
# Preferences Development
## When to Use
The lightweight data store is ideal for storing lightweight and frequently used data, but not for storing a large amount of data or data with frequent changes. The application data is persistently stored on a device in the form of files. Note that the instance accessed by an application contains all data of the file. The data is always loaded to the memory of the device until the application removes it from the memory. The application can perform data operations using the **Storage** APIs.
Preferences are ideal for storing data frequently used by applications, but not for storing a large amount of data or data with frequent changes. The application data is persistently stored on a device in the form of files. Note that the instance accessed by an application contains all data of the file. The data is always loaded to the memory of the device until the application removes it from the memory. The application can perform data operations using the **Preferences** APIs.
## Available APIs
The lightweight data store provides applications with data processing capability and allows applications to perform lightweight data storage and query. Data is stored in key-value (KV) pairs. Keys are of the string type, and values can be of the number, string, or Boolean type.
Preferences provide capabilities for processing data in the form of key-value (KV) pairs and support data persistence, modification, and query. In KV pairs, keys are of the string type, and values can be of the number, string, or Boolean type.
**Creating a Storage Instance**
### Creating a Preferences Instance
Create a **Storage** instance for data operations. A **Storage** instance is created after data is read from a specified file and loaded to the instance.
Create a **Preferences** instance for data operations. A **Preferences** instance is created after data is read from a specified file and loaded to the instance.
**Table 1** API for creating a **Storage** instance
**Table 1** API for creating a **Preferences** instance
| Package | API | Description |
| ----------------- | ------------------------------------------- | ------------------------------------------- |
| ohos.data.storage | getStorage(path: string): Promise\<Storage> | Obtains the **Storage** singleton corresponding to a file for data operations.|
| ohos.data.preferences | getPreferences(context: Context, name: string): Promise\<Preferences> | Obtains a **Preferences** instance for data operations.|
**Writing Data**
### Writing Data
Call the **put()** method to add or modify data in a **Storage** instance.
Call the **put()** method to add or modify data in a **Preferences** instance.
**Table 2** API for writing data
| Class | API | Description |
| ------- | -------------------------------------------------- | ----------------------------------------------- |
| Storage | put(key: string, value: ValueType): Promise\<void> | Writes data of the number, string, and Boolean types.|
| Preferences | put(key: string, value: ValueType): Promise\<void> | Writes data of the number, string, and Boolean types.|
**Reading Data**
### Reading Data
Call the **get()** method to read data from a **Storage** instance.
Call the **get()** method to read data from a **Preferences** instance.
**Table 3** API for reading data
| Class | API | Description |
| ------- | ---------------------------------------------------------- | ----------------------------------------------- |
| Storage | get(key: string, defValue: ValueType): Promise\<ValueType> | Reads data of the number, string, and Boolean types.|
| Preferences | get(key: string, defValue: ValueType): Promise\<ValueType> | Reads data of the number, string, and Boolean types.|
**Storing Data Persistently**
### Storing Data Persistently
Call the **flush()** method to write the cached data back to its text file for persistent storage.
......@@ -46,119 +46,120 @@ Call the **flush()** method to write the cached data back to its text file for p
| Class | API | Description |
| ------- | ----------------------- | --------------------------------------- |
| Storage | flush(): Promise\<void> | Writes data in the **Storage** instance back to its file through an asynchronous thread.|
| Preferences | flush(): Promise\<void> | Writes data from the **Preferences** instance back to its file through an asynchronous thread.|
**Observing Data Changes**
### Observing Data Changes
Specify **StorageObserver** as the callback to subscribe to data changes. When the value of the subscribed key is changed and the **flush()** method is executed, **StorageObserver** will be invoked.
You can subscribe to data changes. When the value of the subscribed key is changed by **flush()**, a callback will be invoked to return the new data.
**Table 5** APIs for observing data changes
**Table 5** APIs for observing **Preferences** changes
| Class | API | Description |
| ------- | ------------------------------------------------------------ | -------------- |
| Storage | on(type: 'change', callback: Callback\<StorageObserver>): void | Subscribe to data changes.|
| Storage | off(type: 'change', callback: Callback\<StorageObserver>): void | Unsubscribes from data changes. |
| Preferences | on(type: 'change', callback: Callback<{ key : string }>): void | Subscribes to data changes.|
| Preferences | off(type: 'change', callback: Callback<{ key : string }>): void | Unsubscribes from data changes. |
**Deleting Data**
### Deleting Data
Use the following APIs to delete a **Storage** instance or data file.
Use the following APIs to delete a **Preferences** instance or data file.
**Table 6** APIs for deleting data
**Table 6** APIs for deleting **Preferences**
| Package | API | Description |
| ----------------- | ---------------------------------------------------- | ------------------------------------------------------------ |
| ohos.data.storage | deleteStorage(path: string): Promise\<void> | Deletes a **Storage** instance from the cache and deletes its file from the device.|
| ohos.data.storage | removeStorageFromCache(path: string): Promise\<void> | Deletes a **Storage** instance from the cache to release memory. |
| ohos.data.preferences | deletePreferences(context: Context, name: string): Promise<void>; | Deletes a **Preferences** instance from the cache and deletes its file from the device.|
| ohos.data.preferences | removePreferencesFromCache(context: Context, name: string): Promise\<void>; | Removes a **Preferences** instance from the memory to release memory.
## How to Develop
1. Import @ohos.data.storage and related modules to the development environment.
1. Import @ohos.data.preferences and related modules to the development environment.
```js
import dataStorage from '@ohos.data.storage'
import featureAbility from '@ohos.ability.featureAbility' // Used to obtain the file storage path.
import data_preferences from '@ohos.data.preferences'
```
2. Create a **Storage** instance.
2. Create a **Preferences** instance.
Read the specified file and load its data to the **Storage** instance for data operations.
Read the specified file and load its data to the **Preferences** instance for data operations.
```js
var context = featureAbility.getContext()
context.getFilesDir().then(() => {
console.info("======================>getFilesDirPromsie====================>");
});
let promise = dataStorage.getStorage(path + '/mystore')
let promise = data_preferences.getPreferences(this.context, 'mystore')
```
3. Write data.
Use the **put()** method of the **Storage** class to write data to the cached **Storage** instance.
Use the **put()** method of the **Preferences** class to write data to the cached **Preferences** instance.
```js
promise.then((storage) => {
let getPromise = storage.put('startup', 'auto') // Save data to the Storage instance.
promise.then((preferences) => {
let getPromise = preferences.put('startup', 'auto')
getPromise.then(() => {
console.info("Put the value of startup successfully.")
}).catch((err) => {
console.info("Put the value of startup failed with err: " + err)
console.info("Failed to put the value of startup with err: " + err)
})
}).catch((err) => {
console.info("Get the storage failed")
console.info("Failed to get the preferences")
})
```
4. Read data.
Use the **get()** method of the **Storage** class to read data.
Use the **get()** method of the **Preferences** class to read data.
```js
promise.then((storage) => {
let getPromise = storage.get('startup', 'default')
promise.then((preferences) => {
let getPromise = preferences.get('startup', 'default')
getPromise.then((value) => {
console.info("The value of startup is " + value)
}).catch((err) => {
console.info("Get the value of startup failed with err: " + err)
console.info("Failed to get the value of startup with err: " + err)
})
}).catch((err) => {
console.info("Get the storage failed")})
console.info("Failed to get the preferences")})
```
5. Store data persistently.
Use the **flush()** or **flushSync()** method to flush data in the **Storage** instance to its file.
Use the **flush()** method to flush data from the **Preferences** instance to its file.
```js
storage.flush();
preferences.flush();
```
6. Observe data changes.
6. Observe data changes.
Specify **StorageObserver** as the callback to subscribe to data changes for an application. When the value of the subscribed key is changed and the **flush()** method is executed, **StorageObserver** will be invoked. Unregister the **StorageObserver** when it is no longer required.
Specify an observer as the callback to subscribe to data changes for an application. When the value of the subscribed key is changed and the **flush()** method is executed, the observe callback will be invoked to return the change.
```js
promise.then((storage) => {
var observer = function (key) {
console.info("The key of " + key + " changed.")
}
storage.on('change', observer)
storage.putSync('startup', 'auto') // Modify data in the Storage instance.
storage.flushSync() // Trigger the StorageObserver callback.
storage.off(...change..., observer) // Unsubscribe from the data changes.
}).catch((err) => {
console.info("Get the storage failed")
})
var observer = function (key) {
console.info("The key of " + key + " changed.")
}
preferences.on('change', observer)
preferences.put('startup', 'auto', function (err) {
if (err) {
console.info("Failed to put the value of startup with err: " + err)
return
}
console.info("Put the value of startup successfully.")
preferences.flush(function (err) {
if (err) {
console.info("Failed to flush data to file with err: " + err)
return
}
console.info("Flushed to file successfully.") // Observer will be called.
})
})
```
7. Delete the specified file.
Use the **deleteStorage** method to delete the **Storage** singleton of the specified file from the memory, and delete the specified file, its backup file, and damaged files. After the specified files are deleted, the application cannot use that instance to perform any data operation. Otherwise, data inconsistency will occur. The deleted data and files cannot be restored.
Use the **deletePreferences** method to delete the **Preferences** singleton of the specified file from the memory, and delete the specified file, its backup file, and corrupted files. After the specified files are deleted, the application cannot use that instance to perform any data operation. Otherwise, data inconsistency will occur. The deleted data and files cannot be restored.
```js
let promise = dataStorage.deleteStorage(path + '/mystore')
promise.then(() => {
console.info("Deleted successfully.")
}).catch((err) => {
console.info("Deleted failed with err: " + err)})
let proDelete = data_preferences.deletePreferences(context, 'mystore')
proDelete.then(() => {
console.info("Data deleted successfully.")
}).catch((err) => {
console.info("Failed to delete data with err: " + err)
})
```
# Lightweight Data Store Overview<a name="EN-US_TOPIC_0000001230752103"></a>
# Preferences Overview
Lightweight data store is applicable to access and persistence operations on the data in key-value pairs. When an application accesses a lightweight **Storage** instance, data in the **Storage** instance will be cached in the memory for faster access. The cached data can also be written back to the text file for persistent storage. Since file read and write consume system resources, you are advised to minimize the frequency of reading and writing persistent files.
Preferences are used for access and persistence operations on the data in the key-value structure. When an application accesses a **Preferences** instance, the data in the instance will be cached in the memory for faster access. The cached data can also be written back to the text file for persistent storage. Since file read and write consume system resources, you are advised to minimize the frequency of reading and writing persistent files.
## Basic Concepts<a name="section1055404171115"></a>
## Basic Concepts
- **Key-Value data structure**
- **Key-value data structure**
A type of data structure. The key is the unique identifier for a piece of data, and the value is the specific data being identified.
A type of data structure. The key is the unique identifier for a piece of data, and the value is the specific data being identified.
- **Non-relational database**
- **Non-relational database**
A database not in compliance with the atomicity, consistency, isolation, and durability \(ACID\) database management properties of relational data transactions. The data in a non-relational database is independent.
A database not in compliance with the atomicity, consistency, isolation, and durability (ACID) database management properties of relational data transactions. The data in a non-relational database is independent.
## Working Principles
## Working Principles<a name="section682631371115"></a>
When an application loads data from a **Preferences** file to a **Preferences** instance, the system stores the instance in the memory through a static container. Each file of an application or process has only one **Preferences** instance in the memory, till the application removes the instance from the memory or deletes the **Preferences** file.
1. When an application loads data from a specified **Storage** file to a **Storage** instance, the system stores the instance in the memory through a static container. Each file of an application or process has only one **Storage** instance in the memory, till the application removes the instance from the memory or deletes the **Storage** file.
2. When obtaining a **Storage** instance, the application can read data from or write data to the instance. The data in the **Storage** instance can be flushed to its **Storage** file by calling the **flush** or **flushSync** method.
When obtaining a **Preferences** instance, the application can read data from or write data to the instance. The data in the instance can be flushed to its **Preferences** file by calling the **flush()** method.
**Figure 1** How lightweight data store works<a name="fig1657785713509"></a>
**Figure 1** How **Preferences** work
![](figures/preferences.png)
![](figures/en-us_image_0000001199139454.png)
## Constraints<a name="section17243172883219"></a>
- **Storage** instances are loaded to the memory. To minimize non-memory overhead, the number of data records stored in a **Storage** instance cannot exceed 10,000. Delete the instances that are no longer used in a timely manner.
- The key in the key-value pairs is of the string type. It cannot be empty or exceed 80 characters.
- If the value in the key-value pairs is of the string type, it can be empty or contain a maximum of 8192 characters.
## Constraints
- **Preferences** instances are loaded to the memory. To minimize non-memory overhead, the number of data records stored in a **Preferences** instance cannot exceed 10,000. Delete the instances that are no longer used in a timely manner.
- The key in key-value pairs is of the string type. It cannot be empty or exceed 80 bytes.
- The value of the string type in key-value pairs can be empty, but cannot exceed 8192 bytes if not empty.
......@@ -116,8 +116,8 @@ The RDB provides **RdbPredicates** for you to set database operation conditions.
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/>
> After a result set is used, you must call the **close()** method to close it explicitly.**
> ![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.
**Table 7** APIs for using the result set
......@@ -306,3 +306,8 @@ You can obtain the distributed table name for a remote device based on the local
let tableName = rdbStore.obtainDistributedTableName(deviceId, "test");
let resultSet = rdbStore.querySql("SELECT * FROM " + tableName)
```
## Samples
The following samples are provided for you to better understand the RDB development:
- [`Rdb`: eTS RDB (API8)](https://gitee.com/openharmony/app_samples/tree/master/data/Rdb)
- [`DistributedRdb`: eTS Distributed Relational Database (API8)](https://gitee.com/openharmony/app_samples/tree/master/data/DistributedRdb)
- [Relational Database](https://gitee.com/openharmony/codelabs/tree/master/Data/JSRelationshipData)
......@@ -13,3 +13,6 @@
- Vibrator
- [Vibrator Overview](vibrator-overview.md)
- [Vibrator Development](vibrator-guidelines.md)
- Update Servcie
- [Sample Server Overview](sample-server-overview.md)
- [Sample Server Development](sample-server-guidelines.md)
# Sample Server Development
## When to Use
The sample server provides a package search server for checking update packages and obtaining the update package download URLs, which was previously unavailable in the real-world update service. The sample server supports update service testing and secondary development function verification, building an end-to-end environment to cater for diverse update service use cases.
## How to Develop
1. Generate an SSL certificate.
Generate the **serverKey.pem** and **serverCert.cer** files for SSL communication of the sample server.
```
openssl req -newkey rsa:2048 -nodes -keyout serverKey.pem -x509 -days 365 -out serverCert.cer -subj "/C=CN/ST=GD/L=GZ/O=abc/OU=defg/CN=hijk/emailAddress=test.com"
```
2. Modify the **bundle.json** file.
Add **sub_component** to the **build** field.
```
"sub_component": [
"//base/update/updateservice/server_sample:testserver",
...
],
```
3. Create a code directory.
Go to the **update_updateservice** directory and run the following commands to create a code directory:
```
mkdir server_sample // Create the server_sample folder.
touch server_sample/BUILD.gn // Create the BUILD.gn file.
mkdir server_sample/include // Create the include folder to store the header file of the sample server.
touch server_process.h // Create the server_process.h header file.
mkdir server_sample/src // Create the src folder to store the C/C++ files of the sample server.
touch server_sample/src/server_process.c // Create the server_process.c file.
touch server_sample/src/main.cpp // Create the main.cpp file.
```
4. Write the **BUILD.gn** file.
The **BUILD.gn** file contains two **ohos** components: **ohos_shared_library** file named **libserver_process.z.so** and **ohos_executable** file named **testserver**.
```
import("//build/ohos.gni")
ohos_shared_library("server_process") {
sources = [
"//base/update/updateservice/server_sample/src/server_process.c",
]
include_dirs = [
"//base/update/updateservice/server_sample/include",
"//third_party/openssl/include",
]
deps = [
"//base/update/updater/services/log:libupdaterlog",
"//third_party/bounds_checking_function:libsec_static",
"//third_party/openssl:crypto_source",
"//third_party/openssl:ssl_source",
"//utils/native/base:utils",
]
part_name = "update_service"
}
ohos_executable("testserver") {
sources = [
"//base/update/updateservice/server_sample/src/main.cpp",
]
include_dirs = [
"//base/update/updateservice/server_sample/include",
]
deps = [
"//base/update/updateservice/server_sample:server_process",
]
part_name = "update_service"
}
```
5. Write the **server_process.h** file.
Declare the sample server APIs in the **server_process.h** file.
```c++
#ifndef __SERVER_PROCESS_H__
#define __SERVER_PROCESS_H__
/*
Init: creates a socket environment and presets certain attributes.
*/
int Init();
/*
SetParam: sets all plug-in parameters.
*/
int SetParam(const char *key, const char *value);
/*
GetParam: obtains all plug-in parameters.
*/
int GetParam(const char *key, char *value);
/*
ReverseSetParamCallback: callback.
*/
int ReverseSetParamCallback(int(*setParam)(const char *key, const char *value));
/*
Open: starts the service.
*/
int Open();
/*
MainLoop: invoked every 100 ms.
*/
int MainLoop();
/*
Close: stops the service and releases related resources.
*/
int Close();
#endif //__SERVER_PROCESS_H__
```
6. Write the **server_process.c** and **main.cpp** files.
In the **server_process.c** file, mainly declare **respondContent**, the format of the response message returned by the server. Write the **main.cpp** file based on instructions for the common SSL protocol server. Be sure to include related header files and load the **serverKey.pem** and **serverCert.cer** files.
```c
#include "server_process.h"
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "openssl/err.h"
#include "openssl/ssl.h"
#define SERVER_PEM "/data/sdcard/serverKey.pem" // Use an absolute path.
#define SERVER_CER "/data/sdcard/serverCert.cer" // Use an absolute path.
#define LOG_PRINT(fmt, ...) printf("[ServerProcess][%s:%d] " fmt "\n", __func__, __LINE__, ##__VA_ARGS__)
#define DO_CHECK(cond, log, ...) \
if (!(cond)) {\
LOG_PRINT(log);\
__VA_ARGS__;\
return -1;\
}
// Implement the function by referring to the APIs in the server_process.h file. Pay attention to the format of the response message from the server.
respondContent = "{"
"\"searchStatus\": 0,"
"\"errMsg\": \"success\","
"\"checkResults\": [{"
"\"versionName\": \"sampleVersionName\","
"\"versionCode\": \"sampleVersionCode\","
"\"verifyInfo\": \"sampleVerifyInfoSha256Value\","
"\"size\": 1234567,"
"\"packageType\": 1,"
"\"descriptPackageId\": \"abcdefg1234567ABCDEFG\","
"}],"
"\"descriptInfo\": [{"
"\"descriptPackageId\": \"abcdefg1234567ABCDEFG\","
"\"content\": \"This package message is used for sampleContent\""
"}]"
"}";
```
7. Start building.
The **testserver** and **libserver_process.z.so** files are added to the build output directory.
8. Develop an update package.
For details, see the [update_packaging_tools repository](https://gitee.com/openharmony/update_packaging_tools).
9. Start the package search server.
Create a directory that contains only English characters on the development board. Place the **testserver**, **libserver_process.z.so**, **serverCert.cer**, and **serverKey.pem** files in the directory, go to the directory, and run the following command to start the package search server:
```
./testserver ./libserver_process.z.so &
```
# Sample Server Overview
The sample server provides a simple server instance for deploying update packages. It can be used as an auxiliary test environment for the UpdateService subsystem.
## Basic Concepts
- Package search service: one of the service capabilities provided by the UpdateService. It depends on the server that supports the TCP and SSL protocols.
- Package search server: a server that provisions the package search service through the TCP connection and the SSL protocol. The sample server mentioned in this document is such a package search server.
- Download server: an HTTP server.
- update.serverip.search: a system parameter that indicates the IP address of the package search server configured on the UpdateService. The default value is **127.0.0.1**.
## Constraints
The following is an example of the JSON response returned by the server. Note that the **verifyInfo** field indicates the SHA-256 value of the update package, and the **size** field indicates the size of the update package, in bytes.
```json
{
"searchStatus": 0,
"errMsg": "success",
"checkResults": [{
"versionName": "versionNameSample",
"versionCode": "versionCodeSample",
"verifyInfo": "verifyInfoSHA256Value1234567",
"size": 1234567,
"packageType": 1,
"url": "http://serverAddressSample/packageNameSample.fileTypeSample",
"descriptPackageId": "abcdefg1234567ABCDEFG"
}],
"descriptInfo": [{
"descriptPackageId": "abcdefg1234567ABCDEFG",
"content": "This package is used for update."
}]
}
```
......@@ -20,38 +20,38 @@ You can set different vibration effects as needed, for example, customizing the
## 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": [
{
"name":"ohos.permission.ACCELEROMETER",
"reason"":"",
"usedScene":{
"ability""[
".MainAbility"
"name": "ohos.permission.ACCELEROMETER",
"reason": "",
"usedScene": {
"ability": [
".MainAbility"
],
"when":"inuse"
"when": "inuse"
}
},
{
"name":"ohos.permission.VIBRATE",
"reason"":"",
"usedScene":{
"ability""[
".MainAbility"
"name": "ohos.permission.VIBRATE",
"reason": "",
"usedScene": {
"ability": [
".MainAbility"
],
"when":"inuse"
"when": "inuse"
}
},
{
"name":"ohos.permission.ACTIVITY_MOTION",
"reason"":"",
"usedScene":{
"ability""[
".MainAbility"
"name": "ohos.permission.ACTIVITY_MOTION",
"reason": "",
"usedScene": {
"ability": [
".MainAbility"
],
"when":"inuse"
"when": "inuse"
}
},
]
......@@ -77,7 +77,7 @@ You can set different vibration effects as needed, for example, customizing the
vibrator.stop(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_PRESET).then((error)=>{
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);
}else{ // The call is successful, and the device stops vibration.
}else{ // The call is successful, and the device stops vibrating.
Console.log("Promise returned to indicate a successful stop.");
};
})
......
......@@ -75,4 +75,4 @@ In this example, an application event is logged after the application startup ex
The following sample is provided to help you better understand how to develop the application event logging feature:
- [`JsDotTest`: Event Logging Test (JavaScript) (API 7)](https://gitee.com/openharmony/app_samples/tree/master/DFX/JsDotTest)
- [`JsDotTest`: Event Logging Test (JavaScript) (API 8)](https://gitee.com/openharmony/app_samples/tree/master/DFX/JsDotTest)
......@@ -9,7 +9,7 @@ APIs are provided to access the system language and region information.
### Available APIs
| Module | API | Description |
| Module | API | Description |
| -------- | -------- | -------- |
| ohos.i18n | getSystemLanguage(): string | Obtains the system language. |
| ohos.i18n | getSystemRegion(): string | Obtains the system region. |
......@@ -22,7 +22,7 @@ APIs are provided to access the system language and region information.
### How to Develop
1. Obtain the system language.
1. Obtain the system language.<br>
Call the **getSystemLanguage** method to obtain the system language (**i18n** is the name of the imported module).
......@@ -30,21 +30,21 @@ APIs are provided to access the system language and region information.
var language = i18n.getSystemLanguage();
```
2. Obtains the system region.
2. Obtain the system region.<br>
Call the **getSystemRegion** method to obtain the system region.
```
var region = i18n.getSystemRegion();
```
3. Obtain the system locale.
3. Obtain the system locale.<br>
Call the **getSystemLocale** method to obtain the system locale.
```
var locale = i18n.getSystemLocale();
```
4. Check whether the locale's language is RTL.
4. Check whether the locale's language is RTL.<br>
Call the **isRTL** method to check whether the locale's language is RTL.
......@@ -52,15 +52,15 @@ APIs are provided to access the system language and region information.
var rtl = i18n.isRTL("zh-CN");
```
5. Check whether the system uses a 24-hour clock.
Call the **is24HourClock** method to check whether the system uses a 24-hour clock.
5. Check whether the system uses a 24-hour clock.<br>
Call the **is24HourClock** method to check whether the system uses a 24-hour clock.
```
var hourClock = i18n.is24HourClock();
```
6. Obtain the localized display of a language.
Call the **getDisplayLanguage** method to obtain the localized display of a language. **language** indicates the language to be localized, **locale** indicates the locale, and **sentenceCase** indicates whether the first letter of the result must be capitalized.
6. Obtain the localized display of a language.<br>
Call the **getDisplayLanguage** method to obtain the localized display of a language. **language** indicates the language to be localized, **locale** indicates the locale, and **sentenceCase** indicates whether the first letter of the result must be capitalized.
```
var language = "en";
......@@ -69,8 +69,8 @@ APIs are provided to access the system language and region information.
var localizedLanguage = i18n.getDisplayLanguage(language, locale, sentenceCase);
```
7. Obtain the localized display of a country.
Call the **getDisplayCountry** method to obtain the localized display of a country. **country** indicates the country to be localized, **locale** indicates the locale, and **sentenceCase** indicates whether the first letter of the result must be capitalized.
7. Obtain the localized display of a country.<br>
Call the **getDisplayCountry** method to obtain the localized display of a country. **country** indicates the country to be localized, **locale** indicates the locale, and **sentenceCase** indicates whether the first letter of the result must be capitalized.
```
var country = "US";
......@@ -105,7 +105,7 @@ APIs are provided to access the system language and region information.
### How to Develop
1. Instantiate a **Calendar** object.
1. Instantiate a **Calendar** object.<br>
Call the **getCalendar** method to obtain the time zone object of a specific locale and type (**i18n** is the name of the imported module). **type** indicates the valid calendar type, for example, **buddhist**, **chinese**, **coptic**, **ethiopic**, **hebrew**, **gregory**, **indian**, **islamic_civil**, **islamic_tbla**, **islamic_umalqura**, **japanese**, and **persian**. If **type** is left unspecified, the default calendar type of the locale is used.
......@@ -113,8 +113,8 @@ APIs are provided to access the system language and region information.
var calendar = i18n.getCalendar("zh-CN", "gregory);
```
2. Set the time for the **Calendar** object.
Call the **setTime** method to set the time of the **Calendar** object. This method receives two types of parameters. One is a **Date** object, and the other is a value indicating the number of milliseconds elapsed since January 1, 1970, 00:00:00 GMT.
2. Set the time for the **Calendar** object.<br>
Call the **setTime** method to set the time of the **Calendar** object. This method receives two types of parameters. One is a **Date** object, and the other is a value indicating the number of milliseconds elapsed since January 1, 1970, 00:00:00 GMT.
```
var date1 = new Date();
......@@ -123,14 +123,14 @@ APIs are provided to access the system language and region information.
calendar.setTime(date2);
```
3. Set the year, month, day, hour, minute, and second for the **Calendar** object.
Call the **set** method to set the year, month, day, hour, minute, and second for the **Calendar** object.
3. Set the year, month, day, hour, minute, and second for the **Calendar** object.<br>
Call the **set** method to set the year, month, day, hour, minute, and second for the **Calendar** object.
```
calendar.set(2021, 12, 21, 6, 0, 0)
```
4. Set and obtain the time zone for the **Calendar** object.
4. Set and obtain the time zone for the **Calendar** object.<br>
Call the **setTimeZone** and **getTimeZone** methods to set and obtain the time zone for the **Calendar** object. The **setTimeZone** method requires an input string to indicate the time zone to be set.
......@@ -139,7 +139,7 @@ APIs are provided to access the system language and region information.
var timezone = calendar.getTimeZone();
```
5. Set and obtain the first day of a week for the **Calendar** object.
5. Set and obtain the first day of a week for the **Calendar** object.<br>
Call the **setFirstDayOfWeek** and **getFirstDayOfWeek** methods to set and obtain the first day of a week for the **Calendar** object. **setFirstDayOfWeek** must be set to a value indicating the first day of a week. The value **1** indicates Sunday, and the value **7** indicates Saturday.
......@@ -148,15 +148,15 @@ APIs are provided to access the system language and region information.
var firstDayOfWeek = calendar.getFirstDayOfWeek();
```
6. Set and obtain the minimum count of days in the first week for the **Calendar** object.
Call the **setMinimalDaysInFirstWeek** and **getMinimalDaysInFirstWeek** methods to set and obtain the minimum count of days in the first week for the **Calendar** object.
6. Set and obtain the minimum count of days in the first week for the **Calendar** object.<br>
Call the **setMinimalDaysInFirstWeek** and **getMinimalDaysInFirstWeek** methods to set and obtain the minimum count of days in the first week for the **Calendar** object.
```
calendar.setMinimalDaysInFirstWeek(3);
var minimalDaysInFirstWeek = calendar.getMinimalDaysInFirstWeek();
```
7. Obtain the localized display of the **Calendar** object.
7. Obtain the localized display of the **Calendar** object.<br>
Call the **getDisplayName** method to obtain the localized display of the **Calendar** object.
......@@ -164,7 +164,7 @@ APIs are provided to access the system language and region information.
var localizedName = calendar.getDisplayName("zh-CN");
```
8. Check whether a date is a weekend.
8. Check whether a date is a weekend.<br>
Call the **isWeekend** method to determine whether the input date is a weekend.
......@@ -181,7 +181,7 @@ APIs are provided to access the system language and region information.
### Available APIs
| Module | API | Description |
| Module | API | Description |
| -------- | -------- | -------- |
| ohos.i18n | constructor(country: string, options?: PhoneNumberFormatOptions)<sup>8+</sup> | Instantiates a **PhoneNumberFormat** object. |
| ohos.i18n | isValidNumber(number: string): boolean<sup>8+</sup> | Checks whether the value of **number** is a phone number in the correct format. |
......@@ -190,7 +190,7 @@ APIs are provided to access the system language and region information.
### How to Develop
1. Instantiate a **PhoneNumberFormat** object.
1. Instantiate a **PhoneNumberFormat** object.<br>
Call the **PhoneNumberFormat** constructor to instantiate a **PhoneNumberFormat** object. The country code and formatting options of the phone number need to be passed into this constructor. The formatting options are optional, including a style option. Values of this option include: **E164**, **INTERNATIONAL**, **NATIONAL**, and **RFC3966**.
......@@ -199,14 +199,14 @@ APIs are provided to access the system language and region information.
```
2. Check whether the phone number format is correct.
Call the **isValidNumber** method to check whether the format of the input phone number is correct.
Call the **isValidNumber** method to check whether the format of the input phone number is correct.
```
var validNumber = phoneNumberFormat.isValidNumber("15812341234");
```
3. Format a phone number.
Call the **format** method of **PhoneNumberFormat** to format the input phone number.
Call the **format** method of **PhoneNumberFormat** to format the input phone number.
```
var formattedNumber = phoneNumberFormat.format("15812341234");
......@@ -258,7 +258,7 @@ An API can be called to implement measurement conversion.
### How to Develop
1. Instantiate an **IndexUtil** object.
1. Instantiate an **IndexUtil** object.<br>
Call the **getInstance** method to instantiate an **IndexUtil** object for a specific locale. When the **locale** parameter is empty, instantiate an **IndexUtil** object of the default locale.
......@@ -266,22 +266,22 @@ An API can be called to implement measurement conversion.
var indexUtil = getInstance("zh-CN");
```
2. Obtain the index list.
Call the **getIndexList** method to obtain the alphabet index list of the current locale.
2. Obtain the index list.<br>
Call the **getIndexList** method to obtain the alphabet index list of the current locale.
```
var indexList = indexUtil.getIndexList();
```
3. Add an index.
Call the **addLocale** method to add the alphabet index of a new locale to the current index list.
3. Add an index.<br>
Call the **addLocale** method to add the alphabet index of a new locale to the current index list.
```
indexUtil.addLocale("ar")
```
4. Obtain the index of a string.
Call the **getIndex** method to obtain the alphabet index of a string.
4. Obtain the index of a string.<br>
Call the **getIndex** method to obtain the alphabet index of a string.
```
var text = "access index";
......@@ -312,7 +312,7 @@ When a text is displayed in more than one line, [BreakIterator](../reference/api
### How to Develop
1. Instantiate a **BreakIterator** object.
1. Instantiate a **BreakIterator** object.<br>
Call the **getLineInstance** method to instantiate a **BreakIterator** object.
......@@ -321,7 +321,7 @@ When a text is displayed in more than one line, [BreakIterator](../reference/api
var breakIterator = i18n.getLineInstance(locale);
```
2. Set and access the text that requires line breaking.
2. Set and access the text that requires line breaking.<br>
Call the **setLineBreakText** and **getLineBreakText** methods to set and access the text that requires line breaking.
......@@ -331,7 +331,7 @@ When a text is displayed in more than one line, [BreakIterator](../reference/api
var breakText = breakIterator.getLineBreakText();
```
3. Obtain the current position of the **BreakIterator** object.
3. Obtain the current position of the **BreakIterator** object.<br>
Call the **current** method to obtain the current position of the **BreakIterator** object in the text being processed.
......@@ -339,7 +339,7 @@ When a text is displayed in more than one line, [BreakIterator](../reference/api
var pos = breakIterator.current();
```
4. Set the position of a **BreakIterator** object.
4. Set the position of a **BreakIterator** object.<br>
The following APIs are provided to adjust the **first**, **last**, **next**, **previous**, or **following** position of the **BreakIterator** object in the text to be processed.
......@@ -355,7 +355,7 @@ When a text is displayed in more than one line, [BreakIterator](../reference/api
var followingPos = breakIterator.following(10);
```
5. Determine whether a position is a break point.
5. Determine whether a position is a break point.<br>
Call the **isBoundary** method to determine whether a position is a break point. If yes, **true** is returned and the **BreakIterator** object is moved to this position. If no, **false** is returned and the **BreakIterator** object is moved to a break point after this position.
......
......@@ -4,11 +4,10 @@
- [Audio Overview](audio-overview.md)
- [Audio Playback Development](audio-playback.md)
- [Audio Recording Development](audio-recorder.md)
- [Audio Rendering Development](audio-renderer.md)
- [Audio Capture Development](audio-capturer)
- [Audio Capture Development](audio-capturer.md)
- [OpenSL ES Audio Playback Development](opensles-playback.md)
- Video
- [Video Playback Development](video-playback.md)
......
......@@ -39,36 +39,36 @@ function printfDescription(obj) {
// Set the player callbacks.
function setCallBack(audioPlayer) {
audioPlayer.on('dataLoad', () => { // Set the 'dataLoad' event callback, which is triggered when the src attribute is set successfully.
audioPlayer.on('dataLoad', () => { // Set the dataLoad event callback, which is triggered when the src attribute is set successfully.
console.info('audio set source success');
audioPlayer.play(); // The play() API can be invoked only after the 'dataLoad' event callback is complete. The 'play' event callback is then triggered.
audioPlayer.play(); // The play() API can be invoked only after the dataLoad event callback is complete. The play event callback is then triggered.
});
audioPlayer.on('play', () => { // Set the 'play' event callback.
audioPlayer.on('play', () => { // Set the play event callback.
console.info('audio play success');
audioPlayer.pause(); // Trigger the 'pause' event callback and pause the playback.
audioPlayer.pause(); // Trigger the pause event callback and pause the playback.
});
audioPlayer.on('pause', () => { // Set the 'pause' event callback.
audioPlayer.on('pause', () => { // Set the pause event callback.
console.info('audio pause success');
audioPlayer.seek(5000); // Trigger the 'timeUpdate' event callback, and seek to 5000 ms for playback.
audioPlayer.seek(5000); // Trigger the timeUpdate event callback, and seek to 5000 ms for playback.
});
audioPlayer.on('stop', () => { // Set the 'stop' event callback.
audioPlayer.on('stop', () => { // Set the stop event callback.
console.info('audio stop success');
audioPlayer.reset(); // Trigger the 'reset' event callback, and reconfigure the src attribute to switch to the next song.
audioPlayer.reset(); // Trigger the reset event callback, and reconfigure the src attribute to switch to the next song.
});
audioPlayer.on('reset', () => { // Set the 'reset' event callback.
audioPlayer.on('reset', () => { // Set the reset event callback.
console.info('audio reset success');
audioPlayer.release(); // Release the AudioPlayer resources.
audioPlayer = undefined;
});
audioPlayer.on('timeUpdate', (seekDoneTime) => {// Set the 'timeUpdate' event callback.
audioPlayer.on('timeUpdate', (seekDoneTime) => {// Set the timeUpdate event callback.
if (typeof(seekDoneTime) == 'undefined') {
console.info('audio seek fail');
return;
}
console.info('audio seek success, and seek time is ' + seekDoneTime);
audioPlayer.setVolume(0.5); // Trigger the 'volumeChange' event callback.
audioPlayer.setVolume(0.5); // Trigger the volumeChange event callback.
});
audioPlayer.on('volumeChange', () => { // Set the 'volumeChange' event callback.
audioPlayer.on('volumeChange', () => { // Set the volumeChange event callback.
console.info('audio volumeChange success');
audioPlayer.getTrackDescription((error, arrlist) => { // Obtain the audio track information in callback mode.
if (typeof (arrlist) != 'undefined') {
......@@ -78,13 +78,13 @@ function setCallBack(audioPlayer) {
} else {
console.log(`audio getTrackDescription fail, error:${error.message}`);
}
audioPlayer.stop(); // Trigger the 'stop' event callback to stop the playback.
audioPlayer.stop(); // Trigger the stop event callback to stop the playback.
});
});
audioPlayer.on('finish', () => { // Set the 'finish' event callback, which is triggered when the playback is complete.
audioPlayer.on('finish', () => { // Set the finish event callback, which is triggered when the playback is complete.
console.info('audio play finish');
});
audioPlayer.on('error', (error) => { // Set the 'error' event callback.
audioPlayer.on('error', (error) => { // Set the error event callback.
console.info(`audio error called, errName is ${error.name}`);
console.info(`audio error called, errCode is ${error.code}`);
console.info(`audio error called, errMessage is ${error.message}`);
......@@ -92,22 +92,22 @@ function setCallBack(audioPlayer) {
}
async function audioPlayerDemo() {
// 1. Create an audioPlayer instance.
// 1. Create an AudioPlayer instance.
let audioPlayer = media.createAudioPlayer();
setCallBack(audioPlayer); // Set the event callbacks.
// 2. Set the URI of the audio file selected by the user.
// 2. Set the URI of the audio file.
let fdPath = 'fd://'
// The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\01.mp3 /data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile" command.
let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile/01.mp3';
await fileIO.open(path).then((fdNumber) => {
fdPath = fdPath + '' + fdNumber;
console.info('open fd sucess fd is' + fdPath);
console.info('open fd success fd is' + fdPath);
}, (err) => {
console.info('open fd failed err is' + err);
}).catch((err) => {
console.info('open fd failed err is' + err);
});
audioPlayer.src = fdPath; // Set the src attribute and trigger the 'dataLoad' event callback.
audioPlayer.src = fdPath; // Set the src attribute and trigger the dataLoad event callback.
}
```
......@@ -119,14 +119,14 @@ import fileIO from '@ohos.fileio'
export class AudioDemo {
// Set the player callbacks.
setCallBack(audioPlayer) {
audioPlayer.on('dataLoad', () => { // Set the 'dataLoad' event callback, which is triggered when the src attribute is set successfully.
audioPlayer.on('dataLoad', () => { // Set the dataLoad event callback, which is triggered when the src attribute is set successfully.
console.info('audio set source success');
audioPlayer.play(); // Call the play() API to start the playback and trigger the 'play' event callback.
audioPlayer.play(); // Call the play() API to start the playback and trigger the play event callback.
});
audioPlayer.on('play', () => { // Set the 'play' event callback.
audioPlayer.on('play', () => { // Set the play event callback.
console.info('audio play success');
});
audioPlayer.on('finish', () => { // Set the 'finish' event callback, which is triggered when the playback is complete.
audioPlayer.on('finish', () => { // Set the finish event callback, which is triggered when the playback is complete.
console.info('audio play finish');
audioPlayer.release(); // Release the AudioPlayer resources.
audioPlayer = undefined;
......@@ -141,13 +141,13 @@ export class AudioDemo {
let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile/01.mp3';
await fileIO.open(path).then((fdNumber) => {
fdPath = fdPath + '' + fdNumber;
console.info('open fd sucess fd is' + fdPath);
console.info('open fd success fd is' + fdPath);
}, (err) => {
console.info('open fd failed err is' + err);
}).catch((err) => {
console.info('open fd failed err is' + err);
});
audioPlayer.src = fdPath; // Set the src attribute and trigger the 'dataLoad' event callback.
audioPlayer.src = fdPath; // Set the src attribute and trigger the dataLoad event callback.
}
}
```
......@@ -161,15 +161,15 @@ export class AudioDemo {
// Set the player callbacks.
private isNextMusic = false;
setCallBack(audioPlayer) {
audioPlayer.on('dataLoad', () => { // Set the 'dataLoad' event callback, which is triggered when the src attribute is set successfully.
audioPlayer.on('dataLoad', () => { // Set the dataLoad event callback, which is triggered when the src attribute is set successfully.
console.info('audio set source success');
audioPlayer.play(); // Call the play() API to start the playback and trigger the 'play' event callback.
audioPlayer.play(); // Call the play() API to start the playback and trigger the play event callback.
});
audioPlayer.on('play', () => { // Set the 'play' event callback.
audioPlayer.on('play', () => { // Set the play event callback.
console.info('audio play success');
audioPlayer.reset(); // Call the reset() API and trigger the 'reset' event callback.
audioPlayer.reset(); // Call the reset() API and trigger the reset event callback.
});
audioPlayer.on('reset', () => { // Set the 'reset' event callback.
audioPlayer.on('reset', () => { // Set the reset event callback.
console.info('audio play success');
if (!this.isNextMusic) { // When isNextMusic is false, changing songs is implemented.
this.nextMusic(audioPlayer); // Changing songs is implemented.
......@@ -187,13 +187,13 @@ export class AudioDemo {
let nextpath = '/data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile/02.mp3';
await fileIO.open(nextpath).then((fdNumber) => {
nextFdPath = nextFdPath + '' + fdNumber;
console.info('open fd sucess fd is' + nextFdPath);
console.info('open fd success fd is' + nextFdPath);
}, (err) => {
console.info('open fd failed err is' + err);
}).catch((err) => {
console.info('open fd failed err is' + err);
});
audioPlayer.src = nextFdPath; // Set the src attribute and trigger the 'dataLoad' event callback.
audioPlayer.src = nextFdPath; // Set the src attribute and trigger the dataLoad event callback.
}
async audioPlayerDemo() {
......@@ -204,13 +204,13 @@ export class AudioDemo {
let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile/01.mp3';
await fileIO.open(path).then((fdNumber) => {
fdPath = fdPath + '' + fdNumber;
console.info('open fd sucess fd is' + fdPath);
console.info('open fd success fd is' + fdPath);
}, (err) => {
console.info('open fd failed err is' + err);
}).catch((err) => {
console.info('open fd failed err is' + err);
});
audioPlayer.src = fdPath; // Set the src attribute and trigger the 'dataLoad' event callback.
audioPlayer.src = fdPath; // Set the src attribute and trigger the dataLoad event callback.
}
}
```
......@@ -223,12 +223,12 @@ import fileIO from '@ohos.fileio'
export class AudioDemo {
// Set the player callbacks.
setCallBack(audioPlayer) {
audioPlayer.on('dataLoad', () => { // Set the 'dataLoad' event callback, which is triggered when the src attribute is set successfully.
audioPlayer.on('dataLoad', () => { // Set the dataLoad event callback, which is triggered when the src attribute is set successfully.
console.info('audio set source success');
audioPlayer.loop = true; // Set the loop playback attribute.
audioPlayer.play(); // Call the play() API to start the playback and trigger the 'play' event callback.
audioPlayer.play(); // Call the play() API to start the playback and trigger the play event callback.
});
audioPlayer.on('play', () => { // Sets the 'play' event callback to start loop playback.
audioPlayer.on('play', () => { // Sets the play event callback to start loop playback.
console.info('audio play success');
});
}
......@@ -241,13 +241,13 @@ export class AudioDemo {
let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile/01.mp3';
await fileIO.open(path).then((fdNumber) => {
fdPath = fdPath + '' + fdNumber;
console.info('open fd sucess fd is' + fdPath);
console.info('open fd success fd is' + fdPath);
}, (err) => {
console.info('open fd failed err is' + err);
}).catch((err) => {
console.info('open fd failed err is' + err);
});
audioPlayer.src = fdPath; // Set the src attribute and trigger the 'dataLoad' event callback.
audioPlayer.src = fdPath; // Set the src attribute and trigger the dataLoad event callback.
}
}
```
......@@ -256,7 +256,7 @@ export class AudioDemo {
The following samples are provided to help you better understand how to develop audio playback:
- [`JsDistributedMusicPlayer`: Distributed Music Player (JS) (API7)](https://gitee.com/openharmony/app_samples/tree/master/ability/JsDistributedMusicPlayer)
- [`JsAudioPlayer`: Audio Playback and Management (JS, API 7)](https://gitee.com/openharmony/app_samples/tree/master/media/JsAudioPlayer)
- [`eTsAudioPlayer`: Audio Player (eTS)](https://gitee.com/openharmony/app_samples/blob/master/media/Recorder/entry/src/main/ets/MainAbility/pages/Play.ets)
- [<idp:inline class="- topic/inline " val="code" displayname="code" id="code04927441464" tempcmdid="code04927441464">JsDistributedMusicPlayer</idp:inline>: Distributed Music Player (JS, API version 7)](https://gitee.com/openharmony/app_samples/tree/master/ability/JsDistributedMusicPlayer)
- [<idp:inline class="- topic/inline " val="code" displayname="code" id="code4276559568" tempcmdid="code4276559568">JsAudioPlayer</idp:inline>: Audio Playback and Management (JS, API version 7)](https://gitee.com/openharmony/app_samples/tree/master/media/JsAudioPlayer)
- [<idp:inline class="- topic/inline " val="code" displayname="code" id="code246413101579" tempcmdid="code246413101579">eTsAudioPlayer</idp:inline>: Audio Player (eTS)](https://gitee.com/openharmony/app_samples/blob/master/media/Recorder/entry/src/main/ets/MainAbility/pages/Play.ets)
- [Audio Player](https://gitee.com/openharmony/codelabs/tree/master/Media/Audio_OH_ETS)
......@@ -30,35 +30,35 @@ export class AudioRecorderDemo {
// Set the callbacks related to audio recording.
setCallBack(audioRecorder) {
audioRecorder.on('prepare', () => { // Set the 'prepare' event callback.
audioRecorder.on('prepare', () => { // Set the prepare event callback.
console.log('prepare success');
audioRecorder.start(); // Call the start API to start recording and trigger the 'start' event callback.
audioRecorder.start(); // Call the start API to start recording and trigger the start event callback.
});
audioRecorder.on('start', () => { // Set the 'start' event callback.
audioRecorder.on('start', () => { // Set the start event callback.
console.log('audio recorder start success');
audioRecorder.pause(); // Call the pause API to pause recording and trigger the 'pause' event callback.
audioRecorder.pause(); // Call the pause API to pause recording and trigger the pause event callback.
});
audioRecorder.on('pause', () => { // Set the 'pause' event callback.
audioRecorder.on('pause', () => { // Set the pause event callback.
console.log('audio recorder pause success');
audioRecorder.resume(); // Call the resume API to resume recording and trigger the 'resume' event callback.
audioRecorder.resume(); // Call the resume API to resume recording and trigger the resume event callback.
});
audioRecorder.on('resume', () => { // Set the 'resume' event callback.
audioRecorder.on('resume', () => { // Set the resume event callback.
console.log('audio recorder resume success');
audioRecorder.stop(); // Call the stop API to stop recording and trigger the 'stop' event callback.
audioRecorder.stop(); // Call the stop API to stop recording and trigger the stop event callback.
});
audioRecorder.on('stop', () => { // Set the 'stop' event callback.
audioRecorder.on('stop', () => { // Set the stop event callback.
console.log('audio recorder stop success');
audioRecorder.reset(); // Call the reset API to reset the recorder and trigger the 'reset' event callback.
audioRecorder.reset(); // Call the reset API to reset the recorder and trigger the reset event callback.
});
audioRecorder.on('reset', () => { // Set the 'reset' event callback.
audioRecorder.on('reset', () => { // Set the reset event callback.
console.log('audio recorder reset success');
audioRecorder.release(); // Call the release API to release resources and trigger the 'release' event callback.
audioRecorder.release(); // Call the release API to release resources and trigger the release event callback.
});
audioRecorder.on('release', () => { // Set the 'release' event callback.
audioRecorder.on('release', () => { // Set the release event callback.
console.log('audio recorder release success');
audioRecorder = undefined;
});
audioRecorder.on('error', (error) => { // Set the 'error' event callback.
audioRecorder.on('error', (error) => { // Set the error event callback.
console.info(`audio error called, errName is ${error.name}`);
console.info(`audio error called, errCode is ${error.code}`);
console.info(`audio error called, errMessage is ${error.message}`);
......@@ -103,7 +103,7 @@ export class AudioRecorderDemo {
audioEncoderMime : media.CodecMimeType.AUDIO_AAC,
fileFormat : media.ContainerFormatType.CFT_MPEG_4A,
}
audioRecorder.prepare(audioRecorderConfig); // Call the prepare method to trigger the 'prepare' event callback.
audioRecorder.prepare(audioRecorderConfig); // Call the prepare method to trigger the prepare event callback.
}
}
```
......@@ -120,23 +120,23 @@ export class AudioRecorderDemo {
// Set the callbacks related to audio recording.
setCallBack(audioRecorder) {
audioRecorder.on('prepare', () => { // Set the 'prepare' event callback.
audioRecorder.on('prepare', () => { // Set the prepare event callback.
console.log('prepare success');
audioRecorder.start(); // Call the start API to start recording and trigger the 'start' event callback.
audioRecorder.start(); // Call the start API to start recording and trigger the start event callback.
});
audioRecorder.on('start', () => { // Set the 'start' event callback.
audioRecorder.on('start', () => { // Set the start event callback.
console.log('audio recorder start success');
audioRecorder.stop(); // Call the stop API to stop recording and trigger the 'stop' event callback.
audioRecorder.stop(); // Call the stop API to stop recording and trigger the stop event callback.
});
audioRecorder.on('stop', () => { // Set the 'stop' event callback.
audioRecorder.on('stop', () => { // Set the stop event callback.
console.log('audio recorder stop success');
audioRecorder.release(); // Call the release API to release resources and trigger the 'release' event callback.
audioRecorder.release(); // Call the release API to release resources and trigger the release event callback.
});
audioRecorder.on('release', () => { // Set the 'release' event callback.
audioRecorder.on('release', () => { // Set the release event callback.
console.log('audio recorder release success');
audioRecorder = undefined;
});
audioRecorder.on('error', (error) => { // Set the 'error' event callback.
audioRecorder.on('error', (error) => { // Set the error event callback.
console.info(`audio error called, errName is ${error.name}`);
console.info(`audio error called, errCode is ${error.code}`);
console.info(`audio error called, errMessage is ${error.message}`);
......@@ -181,7 +181,7 @@ export class AudioRecorderDemo {
audioEncoderMime : media.CodecMimeType.AUDIO_AAC,
fileFormat : media.ContainerFormatType.CFT_MPEG_4A,
}
audioRecorder.prepare(audioRecorderConfig); // Call the prepare method to trigger the 'prepare' event callback.
audioRecorder.prepare(audioRecorderConfig); // Call the prepare method to trigger the prepare event callback.
}
}
```
......@@ -190,6 +190,7 @@ export class AudioRecorderDemo {
The following samples are provided to help you better understand how to develop audio recording:
- [`Recorder`: Recorder (eTS, API 8)](https://gitee.com/openharmony/app_samples/tree/master/media/Recorder)
- [`eTsAudioPlayer`: Audio Player (eTS)](https://gitee.com/openharmony/app_samples/blob/master/media/Recorder/entry/src/main/ets/MainAbility/pages/Play.ets)
- [<idp:inline class="- topic/inline " val="code" displayname="code" id="code15884933169" tempcmdid="code15884933169">Recorder</idp:inline>: Recorder (eTS, API version 8)](https://gitee.com/openharmony/app_samples/tree/master/media/Recorder)
- [<idp:inline class="- topic/inline " val="code" displayname="code" id="code563211231612" tempcmdid="code563211231612">JsRecorder</idp:inline>: Recorder (JS, API version 8)](https://gitee.com/openharmony/app_samples/tree/master/media/JSRecorder)
- [<idp:inline class="- topic/inline " val="code" displayname="code" id="code7932192919168" tempcmdid="code7932192919168">eTsAudioPlayer</idp:inline>: Audio Player (eTS)](https://gitee.com/openharmony/app_samples/blob/master/media/Recorder/entry/src/main/ets/MainAbility/pages/Play.ets)
- [Audio Player](https://gitee.com/openharmony/codelabs/tree/master/Media/Audio_OH_ETS)
# OpenSL ES Audio Playback Development
## When to Use
You can use OpenSL ES to develop the audio playback function in OpenHarmony. Currently, only some [OpenSL ES APIs](https://gitee.com/openharmony/third_party_opensles/blob/master/api/1.0.1/OpenSLES.h) are implemented. If an API that has not been implemented is called, **SL_RESULT_FEATURE_UNSUPPORTED** will be returned.
## How to Develop
To use OpenSL ES to develop the audio playback function in OpenHarmony, perform the following steps:
1. Add the header files.
```c++
#include <OpenSLES.h>
#include <OpenSLES_OpenHarmony.h>
#include <OpenSLES_Platform.h>
```
2. Use the **slCreateEngine** API to obtain an **engine** instance.
```c++
SLObjectItf engineObject = nullptr;
slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
(*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
```
3. Obtain the **engineEngine** instance of the **SL_IID_ENGINE** interface.
```c++
SLEngineItf engineEngine = nullptr;
(*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
```
4. Configure the player and create an **AudioPlayer** instance.
```c++
SLDataLocator_BufferQueue slBufferQueue = {
SL_DATALOCATOR_BUFFERQUEUE,
0
};
// Configure the parameters based on the audio file format.
SLDataFormat_PCM pcmFormat = {
SL_DATAFORMAT_PCM,
2,
48000,
16,
0,
0,
0
};
SLDataSource slSource = {&slBufferQueue, &pcmFormat};
SLObjectItf pcmPlayerObject = nullptr;
(*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject, &slSource, null, 0, nullptr, nullptr);
(*pcmPlayerObject)->Realize(pcmPlayerObject, SL_BOOLEAN_FALSE);
```
5. Obtain the **bufferQueueItf** instance of the **SL_IID_OH_BUFFERQUEUE** interface.
```
SLOHBufferQueueItf bufferQueueItf;
(*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
```
6. Open an audio file and register the **BufferQueueCallback** function.
```c++
FILE *wavFile_ = nullptr;
static void BuqqerQueueCallback (SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size)
{
FILE *wavFile = (FILE *)pContext;
if (!feof(wavFile)) {
SLuint8 *buffer = nullptr;
SLuint32 pSize = 0;
(*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, pSize);
// Read data from the file.
fread(buffer, 1, size, wavFile);
(*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, size);
}
return;
}
// Set wavFile_ to the descriptor of the file to be played.
wavFile_ = fopen(path, "rb");
(*bufferQueueItf)->RegisterCallback(bufferQueueItf, BuqqerQueueCallback, wavFile_);
```
7. Obtain the **playItf** instance of the **SL_PLAYSTATE_PLAYING** interface and start playback.
```c++
SLPlayItf playItf = nullptr;
(*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_PLAY, &playItf);
(*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
```
8. Stop audio playback.
```c++
(*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
(*pcmPlayerObject)->Destroy(pcmPlayerObject);
(*engineObject)->Destroy(engineObject);
```
......@@ -76,13 +76,13 @@ export class VideoPlayerDemo {
async videoPlayerDemo() {
let videoPlayer = undefined;
let surfaceID = 'test' // The surfaceID parameter is used for screen display. Its value is obtained through the XComponent interface. For details about the document link, see the method of creating the XComponent.
let surfaceID = 'test' // The surfaceID parameter is used for screen display. Its value is obtained through the XComponent API. For details about the document link, see the method of creating the XComponent.
let fdPath = 'fd://'
// The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\H264_AAC.mp4 /data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile" command.
let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile/H264_AAC.mp4';
await fileIO.open(path).then((fdNumber) => {
fdPath = fdPath + '' + fdNumber;
console.info('open fd sucess fd is' + fdPath);
console.info('open fd success fd is' + fdPath);
}, (err) => {
console.info('open fd failed err is' + err);
}).catch((err) => {
......@@ -97,7 +97,7 @@ export class VideoPlayerDemo {
console.info('createVideoPlayer fail!');
}
}, this.failureCallback).catch(this.catchCallback);
// Set the playback source URL for the player.
// Set the playback source for the player.
videoPlayer.url = fdPath;
// Set the surface ID to display the video image.
......@@ -134,19 +134,19 @@ export class VideoPlayerDemo {
this.printfDescription(arrayDescription[i]);
}
// Seek to the 50s position. For details about the input parameters, see the interface document.
// Seek to the 50s position. For details about the input parameters, see the API document.
let seekTime = 50000;
await videoPlayer.seek(seekTime, media.SeekMode.SEEK_NEXT_SYNC).then((seekDoneTime) => {
console.info('seek success');
}, this.failureCallback).catch(this.catchCallback);
// Set the volume. For details about the input parameters, see the interface document.
// Set the volume. For details about the input parameters, see the API document.
let volume = 0.5;
await videoPlayer.setVolume(volume).then(() => {
console.info('setVolume success');
}, this.failureCallback).catch(this.catchCallback);
// Set the playback speed. For details about the input parameters, see the interface document.
// Set the playback speed. For details about the input parameters, see the API document.
let speed = media.PlaybackSpeed.SPEED_FORWARD_2_00_X;
await videoPlayer.setSpeed(speed).then(() => {
console.info('setSpeed success');
......@@ -205,13 +205,13 @@ export class VideoPlayerDemo {
async videoPlayerDemo() {
let videoPlayer = undefined;
let surfaceID = 'test' // The surfaceID parameter is used for screen display. Its value is obtained through the XComponent interface. For details about the document link, see the method of creating the XComponent.
let surfaceID = 'test' // The surfaceID parameter is used for screen display. Its value is obtained through the XComponent API. For details about the document link, see the method of creating the XComponent.
let fdPath = 'fd://'
// The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\H264_AAC.mp4 /data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile" command.
let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile/H264_AAC.mp4';
await fileIO.open(path).then((fdNumber) => {
fdPath = fdPath + '' + fdNumber;
console.info('open fd sucess fd is' + fdPath);
console.info('open fd success fd is' + fdPath);
}, (err) => {
console.info('open fd failed err is' + err);
}).catch((err) => {
......@@ -292,14 +292,14 @@ export class VideoPlayerDemo {
async videoPlayerDemo() {
let videoPlayer = undefined;
let surfaceID = 'test' // The surfaceID parameter is used for screen display. Its value is obtained through the XComponent interface. For details about the document link, see the method of creating the XComponent.
let surfaceID = 'test' // The surfaceID parameter is used for screen display. Its value is obtained through the XComponent API. For details about the document link, see the method of creating the XComponent.
let fdPath = 'fd://'
// The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\H264_AAC.mp4 /data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile" command.
let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile/H264_AAC.mp4';
let nextPath = '/data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile/MP4_AAC.mp4';
await fileIO.open(path).then((fdNumber) => {
fdPath = fdPath + '' + fdNumber;
console.info('open fd sucess fd is' + fdPath);
console.info('open fd success fd is' + fdPath);
}, (err) => {
console.info('open fd failed err is' + err);
}).catch((err) => {
......@@ -341,7 +341,7 @@ export class VideoPlayerDemo {
fdPath = 'fd://'
await fileIO.open(nextPath).then((fdNumber) => {
fdPath = fdPath + '' + fdNumber;
console.info('open fd sucess fd is' + fdPath);
console.info('open fd success fd is' + fdPath);
}, (err) => {
console.info('open fd failed err is' + err);
}).catch((err) => {
......@@ -350,7 +350,7 @@ export class VideoPlayerDemo {
// Set the second video playback source.
videoPlayer.url = fdPath;
// Call the prepare interface to prepare for playback.
// Call the prepare API to prepare for playback.
await videoPlayer.prepare().then(() => {
console.info('prepare success');
}, this.failureCallback).catch(this.catchCallback);
......@@ -401,19 +401,15 @@ export class VideoPlayerDemo {
}
}
sleep(time) {
for(let t = Date.now(); Date.now() - t <= time;);
}
async videoPlayerDemo() {
let videoPlayer = undefined;
let surfaceID = 'test' // The surfaceID parameter is used for screen display. Its value is obtained through the XComponent interface. For details about the document link, see the method of creating the XComponent.
let surfaceID = 'test' // The surfaceID parameter is used for screen display. Its value is obtained through the XComponent API. For details about the document link, see the method of creating the XComponent.
let fdPath = 'fd://'
// The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\H264_AAC.mp4 /data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile" command.
let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile/H264_AAC.mp4';
await fileIO.open(path).then((fdNumber) => {
fdPath = fdPath + '' + fdNumber;
console.info('open fd sucess fd is' + fdPath);
console.info('open fd success fd is' + fdPath);
}, (err) => {
console.info('open fd failed err is' + err);
}).catch((err) => {
......@@ -442,23 +438,15 @@ export class VideoPlayerDemo {
}, this.failureCallback).catch(this.catchCallback);
// Set the loop playback attribute.
videoPlayer.loop = true;
// Call the play API to start playback.
// Call the play API to start loop playback.
await videoPlayer.play().then(() => {
console.info('play success');
}, this.failureCallback).catch(this.catchCallback);
// After the progress bar reaches the end, the playback continues for 3 seconds and then starts from the beginning, since loop playback is configured.
await videoPlayer.seek(videoPlayer.duration, media.SeekMode.SEEK_NEXT_SYNC).then((seekDoneTime) => {
console.info('seek duration success');
console.info('play success, loop value is ' + videoPlayer.loop);
}, this.failureCallback).catch(this.catchCallback);
this.sleep(3000);
// Release playback resources.
await videoPlayer.release().then(() => {
console.info('release success');
}, this.failureCallback).catch(this.catchCallback);
// Set the related instances to undefined.
videoPlayer = undefined;
surfaceID = undefined;
}
}
```
## Samples
The following samples are provided to help you better understand how to develop video playback:
- [`VideoPlayer`: Video Playback (eTS, API version 9)](https://gitee.com/openharmony/app_samples/tree/master/media/VideoPlayer)
# Native APIs
- [Using Native APIs in Application Projects](napi-guidelines.md)
......@@ -174,4 +174,4 @@ if (this.subscriber != null) {
The following sample is provided to help you better understand how to use the common event functionality:
- [`CommonEvent`: eTS Common Event (API 7)](https://gitee.com/openharmony/app_samples/tree/master/Notification/CommonEvent)
- [`CommonEvent`: eTS Common Event (API 8)](https://gitee.com/openharmony/app_samples/tree/master/Notification/CommonEvent)
......@@ -133,7 +133,7 @@ var subscriber = {
##### Enabling Notification
Before publishing a notification, check whether the notification feature is enabled for your application. By default, the feature is disabled. The application can use **Notification.requestEnableNotification** to prompt the user to enable the feature.
Before publishing a notification, check whether the notification feature is enabled for your application. By default, the feature is disabled. The application calls **Notification.requestEnableNotification** to prompt the user to enable the feature.
```js
Notification.requestEnableNotification() .then((data) => {
......@@ -262,4 +262,4 @@ Notification.cancel(1, "label", cancelCallback)
The following sample is provided to help you better understand how to develop notification functions:
[`Notification`: EtsNotification (API 7)](https://gitee.com/openharmony/app_samples/tree/master/common/Notification)
\ No newline at end of file
[`Notification`: EtsNotification (API 8)](https://gitee.com/openharmony/app_samples/tree/master/common/Notification)
\ No newline at end of file
......@@ -6,9 +6,9 @@
- [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 Low-Code Approach](start-with-js-low-code.md)
- Development Fundamentals
- [Application Development Package Structure (FA Model)](package-structure.md)
- [Application Development Package Structure (Stage Model)](module-structure.md)
- [Application Package Structure Configuration File (FA Model)](package-structure.md)
- [Application Package Structure Configuration File (Stage Model)](stage-structure.md)
- [Resource File Categories](basic-resource-file-categories.md)
- [SysCap](syscap.md)
......@@ -271,11 +271,12 @@ Example of the **module** tag structure:
Table 12 Internal structure of the distro attribute
| Attribute | Description | Data Type| Initial Value Allowed|
| ---------------- | ------------------------------------------------------------ | -------- | ---------- |
| moduleName | Name of the current HAP file. The maximum length is 31 characters. | String | No |
| moduleType | Type of the current HAP file. The value can be **entry** or **feature**. For the HAR type, set this attribute to **har**.| String | No |
| installationFree | Whether the HAP file supports the installation-free feature.<br> **true**: The HAP file supports the installation-free feature and meets installation-free constraints.<br> **false**: The HAP file does not support the installation-free feature.<br> Pay attention to the following:<br> When **entry.hap** is set to **true**, all **feature.hap** fields related to **entry.hap **must be **true**.<br> When **entry.hap** is set to **false**, **feature.hap** related to **entry.hap** can be set to **true** or **false** based on service requirements.| Boolean | No |
| Attribute | Description | Data Type| Initial Value Allowed|
| ---------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -------- | ---------- |
| moduleName | Name of the current HAP file. The maximum length is 31 characters. | String | No |
| moduleType | Type of the current HAP file. The value can be **entry** or **feature**. For the HAR type, set this attribute to **har**. | String | No |
| installationFree | Whether the HAP file supports the installation-free feature.<br> **true**: The HAP file supports the installation-free feature and meets installation-free constraints.<br> **false**: The HAP file does not support the installation-free feature.<br> Pay attention to the following:<br> When **entry.hap** is set to **true**, all **feature.hap** fields related to **entry.hap **must be **true**.<br> When **entry.hap** is set to **false**, **feature.hap** related to **entry.hap** can be set to **true** or **false** based on service requirements. | Boolean | No |
| deliveryWithInstall | Whether the HAP file supports the installation with application。<br /> true: Support。<br /> false:No Support。 | Boolean | No |
Example of the **distro** attribute structure:
......@@ -283,7 +284,8 @@ Example of the **distro** attribute structure:
"distro": {
"moduleName": "ohos_entry",
"moduleType": "entry",
"installationFree": true
"installationFree": true,
"deliveryWithInstall": true
}
```
......
......@@ -175,12 +175,12 @@ Table 2 Internal structure of the app tag
| vendor | Application vendor. The value is a string with a maximum of 255 bytes.| String | Yes (initial value: left empty) |
| versionCode | Version number of the application. The value is a 32-bit non-negative integer and less than 2 to the power of 31. It is used only to determine whether a version is later than another version. A larger value indicates a later version. Ensure that a new version of the application uses a value greater than any of its predecessors. | Number | No |
| versionName | Text description of the version number, which is displayed to users.<br>The value consists of only digits and dots. The four-segment format *A.B.C.D* is recommended, wherein:<br>Segment 1: major version number, which ranges from 0 to 99. A major version consists of major new features or large changes.<br>Segment 2: minor version number, which ranges from 0 to 99. A minor version consists of some new features and large bug fixes.<br>Segment 3: feature version number, which ranges from 0 to 99. A feature version consists of scheduled new features.<br>Segment 4: maintenance release number or patch number, which ranges from 0 to 999. A maintenance release or patch consists of resolution to security flaws or minor bugs.| String | No |
| minCompatibleVersionCode | Minimum API version required for running the application. | Number | Yes (initial value: value of **versionCode**)|
| minAPIVersion | Target API version required for running the application. | Number | No |
| minCompatibleVersionCode | Minimum API version compatible with the application. | Number | Yes (initial value: value of **versionCode**)|
| minAPIVersion | Minimum API version required for running the application. | Number | No |
| targetAPIVersion | Target API version required for running the application. | Integer | No |
| apiReleaseType | Type of the target API version required for running the application. The value can be **CanaryN**, **BetaN**, or **Release**, where **N** represents a positive integer.<br>**Canary**: indicates a restricted release.<br>**Beta**: indicates a publicly released beta version.<br>**Release**: indicates a publicly released official version.| String | Yes (initial value: **"Release"**) |
| distributedNotificationEnabled | Whether the distributed notification feature is enabled for the application. | Boolean | Yes (initial value: **true**) |
| entityType | Category of the application, which can be **game**, **media**, **communication**, **news**, **travel**, **utility**, **shopping**, **education**, **kids**, **business**, and **photography**.| String | Yes (initial value: unspecified) |
| entityType | Type of the application, which can be **game**, **media**, **communication**, **news**, **travel**, **utility**, **shopping**, **education**, **kids**, **business**, and **photography**.| String | Yes (initial value: unspecified) |
### Internal Structure of the module Tag
......@@ -212,9 +212,9 @@ Table 4 System-defined deviceTypes values
| Device Type | Value | Description |
| ------------ | ------------ | -------------------------------------------------------- |
| tablet | tablet | Tablet, speaker with a screen |
| smart TV | tv | |
| smart TV | tv | N/A |
| smart watch | wearable | Smart watch, kids' watch, especially a watch that provides call features|
| head unit | car | |
| head unit | car | N/A |
| router | router | Router |
Example of the **deviceTypes** attribute structure:
......@@ -309,7 +309,7 @@ Table 6 Internal structure of the abilities attribute
| icon | Icon of the ability. The value is the index to the resource file. This attribute can be left empty, and the default value is an empty array.<br>If **ability** is set to **MainElement**, this attribute is mandatory.| String | Yes (initial value: left empty)<br>If **ability** is set to **MainElement**, this attribute is mandatory.|
| permissions | A set of permissions that need to be applied for when the capability of another application is invoked. The value is a string array. Each array element is a permission name, which is usually represented by a reverse domain name (a maximum of 255 bytes). The permission can be predefined by the system or customized by the application. For the latter, the value must be the same as the **name** value of a permission defined in the **defPermissions** attribute. | String array| Yes (initial value: left empty) |
| metadata | Metadata about the ability. For details about metadata, see [Internal Structure of the metadata Attribute](#internal-structure-of-the-metadata-attribute).| Array | Yes (initial value: left empty) |
| visible | Indicates whether the ability can be invoked by other applications. The value **true** means that the ability can be invoked by other applications, and **false** means the opposite.| Boolean | Yes (initial value: **false**) |
| visible | Whether the ability can be invoked by other applications. The value **true** means that the ability can be invoked by other applications, and **false** means the opposite.| Boolean | Yes (initial value: **false**) |
| continuable | Whether the ability can be migrated. The value **true** means that the ability can be migrated, and **false** means the opposite.| Boolean | Yes (initial value: **false**) |
| skills | Feature set of wants that can be received by the ability.<br>Configuration rule: In an entry package, you can configure multiple abilities with the **skills** attribute (where **action.system.home** and **entity.system.home** are configured) that has the entry capability. The **label** and **icon** in the first ability that has **skills** configured are used as the **label** and **icon** of the entire service/application.<br>The **skills** attribute with the entry capability can be configured for the feature package of an OpenHarmony application,<br>but not for an OpenHarmony service.<br>For details about the internal structure of **skills**, see [Internal Structure of the skills Attribute](#internal-structure-of-the-skills-attribute).| Array | Yes (initial value: left empty) |
| backgroundModes | Continuous task modes of the ability.<br>Continuous tasks are classified into the following types:<br>**dataTransfer**: service for downloading, backing up, sharing, or transferring data from the network or peer devices<br>**audioPlayback**: audio playback service<br>**audioRecording**: audio recording service<br>**location**: location and navigation services<br>**bluetoothInteraction**: Bluetooth scanning, connection, and transmission services (wearables)<br>**multiDeviceConnection**: multi-device interconnection service<br>**wifiInteraction**: Wi-Fi scanning, connection, and transmission services (multi-screen cloning)<br>**voip**: voice/video call and VoIP services<br>**taskKeeping**: computing service<br>| String | Yes (initial value: left empty) |
......@@ -361,7 +361,7 @@ Table 7 Internal structure of the skills attribute
| -------- | ------------------------------------------------------------ | ---------- | -------------------- |
| actions | A set of want action values that can be received. The value can be a value predefined by the system or a custom value.| String array| Yes (initial value: left empty)|
| entities | Categories of abilities that can receive the want. The value can be a value predefined by the system or a custom value.| String array| Yes (initial value: left empty)|
| uris | Data specifications to be added to the want filter. The specification can be of data type only (**mimeType** attribute), URI only, or both. For details about the internal structure of **uris**, see Table 8.| Object array | Yes (initial value: left empty)|
| uris | Data specification to be added to the want filter. The specification can be of data type only (**mimeType** attribute), URI only, or both. For details about the internal structure of **uris**, see Table 8.| Object array | Yes (initial value: left empty)|
Table 8 Internal structure of the uris attribute
......@@ -612,7 +612,7 @@ Table 13 Internal structure of the shortcuts attribute
| Attribute | Description | Data Type| Initial Value Allowed |
| ---------- | ------------------------------------------------------------ | -------- | -------------------------- |
| shortcutId | Shortcut ID. The value is a string with a maximum of 63 bytes. | String | No |
| shortcutId | ID of the shortcut. The value is a string with a maximum of 63 bytes. | String | No |
| label | Label of the shortcut, that is, the text description displayed by the shortcut. The value can be a string or a resource index to the description. The value is a string with a maximum of 63 bytes.| String | Yes (initial value: left empty) |
| icon | Icon of the shortcut. The value is the index to the resource file. | String | Yes (initial value: left empty)|
| wants | Wants to which the shortcut points. The attribute consists of the **bundleName** and **abilityName** sub-attributes.<br>**bundleName**: target bundle name of the shortcut; string type.<br>**abilityName**: target component name of the shortcut; string type.| Object | Yes (initial value: left empty) |
......
......@@ -47,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).
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).
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).
......@@ -20,17 +20,18 @@
## eTS Project Files
- **entry** : OpenHarmony project module, which can be built into an ability package ([HAP](../../glossary.md#hap)).
- **src &gt; main &gt; ets** : a collection of eTS source code.
- **src &gt; main &gt; ets &gt; MainAbility** : entry to your application/service.
- **src &gt; main &gt; ets &gt; MainAbility &gt; pages** : pages contained in **MainAbility**.
- **src &gt; main &gt; ets &gt; MainAbility &gt; app.ets** : ability lifecycle file.
- **src &gt; main &gt; resources** : a collection of resource files used by your application/service, such as graphics, multimedia, character strings, and layout files.
- **src &gt; main &gt; config.json** : module configuration file. This file describes the global configuration information of the application/service, the device-specific configuration information, and the configuration information of the HAP file.
- **build-profile.json5** : current module information and build configuration options, including **buildOption target**.
- **hvigorfile.js** : module-level compilation and build task script. You can customize related tasks and code implementation.
- **build-profile.json5** : application-level configuration information, including the signature and product configuration.
- **hvigorfile.js** : application-level compilation and build task script.
- **entry**: OpenHarmony project module, which can be built into an ability package ([HAP](../../glossary.md#hap)).
- **src &gt; main &gt; ets**: a collection of eTS source code.
- **src &gt; main &gt; ets &gt; MainAbility**: entry to your application/service.
- **src &gt; main &gt; ets &gt; MainAbility &gt; pages**: pages contained in **MainAbility**.
- **src &gt; main &gt; ets &gt; MainAbility &gt; pages &gt; index.ets**: the first page in the pages list, that is, the home page of your application.
- **src &gt; main &gt; ets &gt; MainAbility &gt; app.ets**: ability lifecycle file.
- **src &gt; main &gt; resources**: a collection of resource files used by your application/service, such as graphics, multimedia, character strings, and layout files.
- **src &gt; main &gt; config.json**: module configuration file. This file describes the global configuration information of the application/service, the device-specific configuration information, and the configuration information of the HAP file.
- **build-profile.json5**: current module information and build configuration options, including **buildOption target**.
- **hvigorfile.js**: module-level compilation and build task script. You can customize related tasks and code implementation.
- **build-profile.json5**: application-level configuration information, including the signature and product configuration.
- **hvigorfile.js**: application-level compilation and build task script.
## Building the First Page
......@@ -62,7 +63,7 @@
2. Add a **&lt;Button&gt;** component.
On the default page, add a **&lt;Button&gt;** component to accept user clicks and implement redirection to another page. The sample code in the **index.ets** file is shown below:
On the default page, add a **&lt;Button&gt;** component to respond to user clicks and implement redirection to another page. The sample code in the **index.ets** file is shown below:
```
......@@ -77,7 +78,7 @@
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
// Add a button to accept user clicks.
// Add a button to respond to user clicks.
Button() {
Text('Next')
.fontSize(30)
......@@ -174,7 +175,7 @@ You can implement page redirection through the page router, which finds the targ
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
// Add a button to accept user clicks.
// Add a button to respond to user clicks.
Button() {
Text('Next')
.fontSize(30)
......
......@@ -37,10 +37,11 @@ After the project synchronization is complete, a low-code directory structure is
![en-us_image_0000001223558810](figures/en-us_image_0000001223558810.png)
- **entry &gt; src &gt; main &gt; js &gt; MainAbility &gt; pages &gt; index &gt; index.js** : defines logical relationships, such as data and events, used on low-code pages. For details, see [JavaScript](../ui/js-framework-syntax-js.md). If multiple low-code development pages are created, a page folder and the corresponding **.js** file will be created for each of these pages.
- **entry &gt; src &gt; main &gt; js &gt; MainAbility &gt; pages &gt; index &gt; index.js**: defines logical relationships, such as data and events, used on low-code pages. For details, see [JavaScript](../ui/js-framework-syntax-js.md). If multiple low-code development pages are created, a page folder and the corresponding **.js** file will be created for each of these pages.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br/>To avoid build errors when using the low-code development page, make sure the directory where the corresponding **.js** file is located does not contain **.hml** or **.css** files. For example, in the preceding example, no **.hml** or **.css** file is allowed in **js** &gt; **MainAbility** &gt; **pages** &gt; **index**.
>
- **entry &gt; src &gt; main &gt; supervisual &gt; MainAbility &gt; pages &gt; index &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.
- **entry &gt; src &gt; main &gt; supervisual &gt; MainAbility &gt; pages &gt; index &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
......
......@@ -19,7 +19,7 @@
## JavaScript Project Files
- **entry** : OpenHarmony project module, which can be built into an ability package ([HAP](../../glossary.md#hap)).
- **entry**: OpenHarmony project module, which can be built into an ability package ([HAP](../../glossary.md#hap)).
- **src &gt; main &gt; js**: a collection of JS source code.
- **src &gt; main &gt; js &gt; MainAbility**: entry to your application/service.
- **src &gt; main &gt; js &gt; MainAbility &gt; i18n**: resources in different languages, for example, UI strings and image paths.
......@@ -50,7 +50,7 @@
2. Add a button and bind the **onclick** method to this button.
On the default page, add an **&lt;input&gt;** component of the button type to accept user clicks and implement redirection to another page. The sample code in the **index.hml** file is shown below:
On the default page, add an **&lt;input&gt;** component of the button type to respond to user clicks and implement redirection to another page. The sample code in the **index.hml** file is shown below:
```
......
# SysCap Usage Guidelines
# SysCap
## Overview
......
......@@ -4,7 +4,8 @@
- [TypeScript-based Declarative Development Paradigm](arkui-ts/Readme-EN.md)
- [APIs](apis/Readme-EN.md)
- [JS (eTS Included) APIs](reference/apis/Readme-EN.md)
- [JS (eTS Included) APIs](apis/Readme-EN.md)
- Native APIs
- [Standard Library](reference/native-lib/third_party_libc/musl.md)
- [Node_API](reference/native-lib/third_party_napi/napi.md)
\ No newline at end of file
- [Standard Library](native-lib/third_party_libc/musl.md)
- [Node_API](native-lib/third_party_napi/napi.md)
# AbilityStageContext
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> **NOTE**<br>
> The initial APIs of this module are supported since API version 9. Newly added APIs will be marked with a superscript to indicate their earliest API version.
......@@ -28,7 +28,7 @@ class MyAbilityStage extends AbilityStage {
**System capability**: SystemCapability.Ability.AbilityRuntime.Core
| Name| Type| Readable| Writable| Description|
| Name| Type | Readable | Writable | Description |
| -------- | -------- | -------- | -------- | -------- |
| currentHapModuleInfo | HapModuleInfo | Yes| No| **ModuleInfo** object corresponding to the **AbilityStage**.|
| config | [Configuration](js-apis-configuration.md) | Yes| No| Configuration for the environment where the application is running.|
| currentHapModuleInfo | HapModuleInfo | Yes | No | **ModuleInfo** object corresponding to the **AbilityStage**. |
| config | [Configuration](js-apis-configuration.md) | Yes| No| Configuration for the environment where the application is running. |
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册