提交 fb61a60b 编写于 作者: D dy 提交者: Gitee

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

Signed-off-by: Ndy <dingyao5@huawei.com>

要显示的变更太多。

To preserve performance only 1000 of 1000+ files are displayed.
此差异已折叠。
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
<!--filteritem type="filename" name="*.uvwxyz" desc="Describe the reason for filtering scan results"/--> <!--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="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="filepath" name="projectroot/[a-zA-Z0-9]{20,}.sh" desc="Temp files"/-->
<filteritem type="filename" name="*.jpg|*.png|*.gif|*.pdf|*.xlsm" desc="already checked"/> <filteritem type="filename" name="*.jpg|*.png|*.gif|*.pdf|*.xlsm|*.zip" desc="already checked"/>
</filefilter> </filefilter>
</filefilterlist> </filefilterlist>
......
...@@ -18,15 +18,15 @@ ...@@ -18,15 +18,15 @@
- master:最新开发版本。 - master:最新开发版本。
- OpenHarmony 3.2 Beta2版本:点击[此处](zh-cn/release-notes/OpenHarmony-v3.2-beta2.md)了解版本详情。 - OpenHarmony 3.2 Beta3版本:点击[此处](zh-cn/release-notes/OpenHarmony-v3.2-beta3.md)了解版本详情。
- OpenHarmony 3.1 Release版本:点击[此处](zh-cn/release-notes/OpenHarmony-v3.1-release.md)了解版本详情。 - OpenHarmony 3.1 Release版本:点击[此处](zh-cn/release-notes/OpenHarmony-v3.1-release.md)了解版本详情。
已更新至OpenHarmony 3.1.1 Release,点击[此处](zh-cn/release-notes/OpenHarmony-v3.1.1-release.md)了解版本详情。 版本已更新至OpenHarmony 3.1.3 Release,点击[此处](zh-cn/release-notes/OpenHarmony-v3.1.3-release.md)了解版本详情。
- OpenHarmony 3.0 LTS版本:点击[此处](zh-cn/release-notes/OpenHarmony-v3.0-LTS.md)了解版本详情。 - OpenHarmony 3.0 LTS版本:点击[此处](zh-cn/release-notes/OpenHarmony-v3.0-LTS.md)了解版本详情。
该版本已更新至OpenHarmony 3.0.5 LTS,点击[此处](zh-cn/release-notes/OpenHarmony-v3.0.5-LTS.md)了解版本详情。 该版本已更新至OpenHarmony 3.0.6 LTS,点击[此处](zh-cn/release-notes/OpenHarmony-v3.0.6-LTS.md)了解版本详情。
- OpenHarmony 2.2 Beta2版本:点击[此处](zh-cn/release-notes/OpenHarmony-v2.2-beta2.md)了解版本详情。 - OpenHarmony 2.2 Beta2版本:点击[此处](zh-cn/release-notes/OpenHarmony-v2.2-beta2.md)了解版本详情。
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
### 历史稳定版本 ### 历史稳定版本
OpenHarmony_v1.x_release:OpenHarmony 1.1.4 LTS稳定版本,点击[此处](zh-cn/release-notes/OpenHarmony-v1-1-4-LTS.md)了解版本详情。 OpenHarmony_v1.x_release:OpenHarmony 1.1.5 LTS稳定版本,点击[此处](zh-cn/release-notes/OpenHarmony-v1.1.5-LTS.md)了解版本详情。
如需了解更多版本详情,点击[此处](zh-cn/release-notes/) 如需了解更多版本详情,点击[此处](zh-cn/release-notes/)
......
# Legal Notices
**Copyright (c) 2020-2022 OpenAtom OpenHarmony. All rights reserved.**
## Copyright
All copyrights of the OpenHarmony documents are reserved by OpenAtom OpenHarmony.
The OpenHarmony documents are licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). For easier understanding, you can visit [Creative Commons](https://creativecommons.org/licenses/by/4.0/) to get a human-readable summary of the license. For the complete content, see [Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/legalcode).
## Trademarks and Permissions
No content provided in the OpenHarmony documentation shall be deemed as a grant of the approval or right to use any trademark, name, or logo of the OpenAtom Foundation and OpenAtom OpenHarmony. No third parties shall use any of the aforementioned trademarks, names, or logos in any way without explicit prior written permission of the OpenAtom Foundation.
## Disclaimer
The information in the OpenHarmony documents is subject to change without notice.
The OpenHarmony documents are provided without any express or implied warranty. In any case, the OpenAtom Foundation or the copyright owner is not liable for any direct or indirect loss arising from the use of the OpenHarmony documents, regardless of the cause or legal theory, even if the OpenHarmony documents have stated that there is a possibility of such loss.
<!--no_check-->
\ No newline at end of file
...@@ -150,7 +150,7 @@ Currently, the OpenHarmony community supports 17 types of development boards, wh ...@@ -150,7 +150,7 @@ Currently, the OpenHarmony community supports 17 types of development boards, wh
| System Type| Board Model| Chip Model| <div style="width:200pt">Function Description and Use Case</div> | Application Scenario| Code Repository | | System Type| Board Model| Chip Model| <div style="width:200pt">Function Description and Use Case</div> | Application Scenario| Code Repository |
| -------- | -------- | -------- | -------- | -------- | -------- | | -------- | -------- | -------- | -------- | -------- | -------- |
| Standard system| Runhe HH-SCDAYU200| RK3568 | <div style="width:200pt">Function description:<br>Bolstered by the Rockchip RK3568, the HH-SCDAYU200 development board integrates the dual-core GPU and efficient 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, Wi-Fi, audio, video, and camera features, with a wide range of expansion ports to accommodate various video input and outputs. 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.<br>Use case:<br>[DAYU200 Use Case](device-dev/porting/porting-dayu200-on_standard-demo.md)</div> | Entertainment, easy travel, and smart home, such as kitchen hoods, ovens, and treadmills.| [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> | | Standard system| Runhe HH-SCDAYU200| RK3568 | <div style="width:200pt">Function description:<br>Bolstered by the Rockchip RK3568, the HH-SCDAYU200 development board integrates the dual-core GPU and efficient 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, Wi-Fi, audio, video, and camera features, with a wide range of expansion ports to accommodate various video input and outputs. 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.</div> | Entertainment, easy travel, and smart home, such as kitchen hoods, ovens, and treadmills.| [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> |
| Small system| Hispark_Taurus | Hi3516DV300 | <div style="width:200pt">Function Description:<br>Hi3516D V300 is the next-generation system on chip (SoC) for smart HD IP cameras. It integrates the next-generation image signal processor (ISP), H.265 video compression encoder, and high-performance NNIE engine, and delivers high performance in terms of low bit rate, high image quality, intelligent processing and analysis, and low power consumption.</div> | Smart device with screens, such as refrigerators with screens and head units.| [device_soc_hisilicon](https://gitee.com/openharmony/device_soc_hisilicon)<br>[device_board_hisilicon](https://gitee.com/openharmony/device_board_hisilicon)<br>[vendor_hisilicon](https://gitee.com/openharmony/vendor_hisilicon) <br> | | Small system| Hispark_Taurus | Hi3516DV300 | <div style="width:200pt">Function Description:<br>Hi3516D V300 is the next-generation system on chip (SoC) for smart HD IP cameras. It integrates the next-generation image signal processor (ISP), H.265 video compression encoder, and high-performance NNIE engine, and delivers high performance in terms of low bit rate, high image quality, intelligent processing and analysis, and low power consumption.</div> | Smart device with screens, such as refrigerators with screens and head units.| [device_soc_hisilicon](https://gitee.com/openharmony/device_soc_hisilicon)<br>[device_board_hisilicon](https://gitee.com/openharmony/device_board_hisilicon)<br>[vendor_hisilicon](https://gitee.com/openharmony/vendor_hisilicon) <br> |
| Mini system| Multi-modal V200Z-R | BES2600 | <div style="width:200pt">Function description:<br>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 Wi-Fi 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.<br>Use case:<br>[Multi-modal V200Z-R Use Case](device-dev/porting/porting-bes2600w-on-minisystem-display-demo.md)</div> | Smart hardware, and smart devices with screens, such as speakers and watches.| [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> | | Mini system| Multi-modal V200Z-R | BES2600 | <div style="width:200pt">Function description:<br>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 Wi-Fi 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.<br>Use case:<br>[Multi-modal V200Z-R Use Case](device-dev/porting/porting-bes2600w-on-minisystem-display-demo.md)</div> | Smart hardware, and smart devices with screens, such as speakers and watches.| [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> |
......
...@@ -7,7 +7,7 @@ To ensure successful communications between the client and server, interfaces re ...@@ -7,7 +7,7 @@ To ensure successful communications between the client and server, interfaces re
![IDL-interface-description](./figures/IDL-interface-description.png) ![IDL-interface-description](./figures/IDL-interface-description.png)
IDL provides the following functions: **IDL provides the following functions:**
- Declares interfaces provided by system services for external systems, and based on the interface declaration, generates C, C++, JS, or TS code for inter-process communication (IPC) or remote procedure call (RPC) proxies and stubs during compilation. - Declares interfaces provided by system services for external systems, and based on the interface declaration, generates C, C++, JS, or TS code for inter-process communication (IPC) or remote procedure call (RPC) proxies and stubs during compilation.
...@@ -17,7 +17,7 @@ IDL provides the following functions: ...@@ -17,7 +17,7 @@ IDL provides the following functions:
![IPC-RPC-communication-model](./figures/IPC-RPC-communication-model.png) ![IPC-RPC-communication-model](./figures/IPC-RPC-communication-model.png)
IDL has the following advantages: **IDL has the following advantages:**
- Services are defined in the form of interfaces in IDL. Therefore, you do not need to focus on implementation details. - Services are defined in the form of interfaces in IDL. Therefore, you do not need to focus on implementation details.
...@@ -433,7 +433,7 @@ export default { ...@@ -433,7 +433,7 @@ export default {
console.log('ServiceAbility want:' + JSON.stringify(want)); console.log('ServiceAbility want:' + JSON.stringify(want));
console.log('ServiceAbility want name:' + want.bundleName) console.log('ServiceAbility want name:' + want.bundleName)
} catch(err) { } catch(err) {
console.log("ServiceAbility error:" + err) console.log('ServiceAbility error:' + err)
} }
console.info('ServiceAbility onConnect end'); console.info('ServiceAbility onConnect end');
return new IdlTestImp('connect'); return new IdlTestImp('connect');
...@@ -455,13 +455,13 @@ import featureAbility from '@ohos.ability.featureAbility'; ...@@ -455,13 +455,13 @@ import featureAbility from '@ohos.ability.featureAbility';
function callbackTestIntTransaction(result: number, ret: number): void { function callbackTestIntTransaction(result: number, ret: number): void {
if (result == 0 && ret == 124) { if (result == 0 && ret == 124) {
console.log("case 1 success "); console.log('case 1 success');
} }
} }
function callbackTestStringTransaction(result: number): void { function callbackTestStringTransaction(result: number): void {
if (result == 0) { if (result == 0) {
console.log("case 2 success "); console.log('case 2 success');
} }
} }
...@@ -472,17 +472,17 @@ var onAbilityConnectDone = { ...@@ -472,17 +472,17 @@ var onAbilityConnectDone = {
testProxy.testStringTransaction('hello', callbackTestStringTransaction); testProxy.testStringTransaction('hello', callbackTestStringTransaction);
}, },
onDisconnect:function (elementName) { onDisconnect:function (elementName) {
console.log("onDisconnectService onDisconnect"); console.log('onDisconnectService onDisconnect');
}, },
onFailed:function (code) { onFailed:function (code) {
console.log("onDisconnectService onFailed"); console.log('onDisconnectService onFailed');
} }
}; };
function connectAbility: void { function connectAbility: void {
let want = { let want = {
"bundleName":"com.example.myapplicationidl", bundleName: 'com.example.myapplicationidl',
"abilityName": "com.example.myapplicationidl.ServiceAbility" abilityName: 'com.example.myapplicationidl.ServiceAbility'
}; };
let connectionId = -1; let connectionId = -1;
connectionId = featureAbility.connectAbility(want, onAbilityConnectDone); connectionId = featureAbility.connectAbility(want, onAbilityConnectDone);
...@@ -495,7 +495,7 @@ function connectAbility: void { ...@@ -495,7 +495,7 @@ function connectAbility: void {
You can send a class from one process to another through IPC interfaces. However, you must ensure that the peer can use the code of this class and this class supports the **marshalling** and **unmarshalling** methods. OpenHarmony uses **marshalling** and **unmarshalling** to serialize and deserialize objects into objects that can be identified by each process. You can send a class from one process to another through IPC interfaces. However, you must ensure that the peer can use the code of this class and this class supports the **marshalling** and **unmarshalling** methods. OpenHarmony uses **marshalling** and **unmarshalling** to serialize and deserialize objects into objects that can be identified by each process.
To create a class that supports the sequenceable type, perform the following operations: **To create a class that supports the sequenceable type, perform the following operations:**
1. Implement the **marshalling** method, which obtains the current state of the object and serializes the object into a **Parcel** object. 1. Implement the **marshalling** method, which obtains the current state of the object and serializes the object into a **Parcel** object.
2. Implement the **unmarshalling** method, which deserializes the object from a **Parcel** object. 2. Implement the **unmarshalling** method, which deserializes the object from a **Parcel** object.
...@@ -595,7 +595,7 @@ export default class IdlTestServiceProxy implements IIdlTestService { ...@@ -595,7 +595,7 @@ export default class IdlTestServiceProxy implements IIdlTestService {
let _reply = new rpc.MessageParcel(); let _reply = new rpc.MessageParcel();
_data.writeInt(data); _data.writeInt(data);
this.proxy.sendRequest(IdlTestServiceProxy.COMMAND_TEST_INT_TRANSACTION, _data, _reply, _option).then(function(result) { this.proxy.sendRequest(IdlTestServiceProxy.COMMAND_TEST_INT_TRANSACTION, _data, _reply, _option).then(function(result) {
if (result.errCode === 0) { if (result.errCode == 0) {
let _errCode = result.reply.readInt(); let _errCode = result.reply.readInt();
if (_errCode != 0) { if (_errCode != 0) {
let _returnValue = undefined; let _returnValue = undefined;
...@@ -605,7 +605,7 @@ export default class IdlTestServiceProxy implements IIdlTestService { ...@@ -605,7 +605,7 @@ export default class IdlTestServiceProxy implements IIdlTestService {
let _returnValue = result.reply.readInt(); let _returnValue = result.reply.readInt();
callback(_errCode, _returnValue); callback(_errCode, _returnValue);
} else { } else {
console.log("sendRequest failed, errCode: " + result.errCode); console.log('sendRequest failed, errCode: ' + result.errCode);
} }
}) })
} }
...@@ -617,11 +617,11 @@ export default class IdlTestServiceProxy implements IIdlTestService { ...@@ -617,11 +617,11 @@ export default class IdlTestServiceProxy implements IIdlTestService {
let _reply = new rpc.MessageParcel(); let _reply = new rpc.MessageParcel();
_data.writeString(data); _data.writeString(data);
this.proxy.sendRequest(IdlTestServiceProxy.COMMAND_TEST_STRING_TRANSACTION, _data, _reply, _option).then(function(result) { this.proxy.sendRequest(IdlTestServiceProxy.COMMAND_TEST_STRING_TRANSACTION, _data, _reply, _option).then(function(result) {
if (result.errCode === 0) { if (result.errCode == 0) {
let _errCode = result.reply.readInt(); let _errCode = result.reply.readInt();
callback(_errCode); callback(_errCode);
} else { } else {
console.log("sendRequest failed, errCode: " + result.errCode); console.log('sendRequest failed, errCode: ' + result.errCode);
} }
}) })
} }
...@@ -644,12 +644,12 @@ import nativeMgr from 'nativeManager'; ...@@ -644,12 +644,12 @@ import nativeMgr from 'nativeManager';
function testIntTransactionCallback(errCode: number, returnValue: number) function testIntTransactionCallback(errCode: number, returnValue: number)
{ {
console.log("errCode: " + errCode + " returnValue: " + returnValue); console.log('errCode: ' + errCode + ' returnValue: ' + returnValue);
} }
function testStringTransactionCallback(errCode: number) function testStringTransactionCallback(errCode: number)
{ {
console.log("errCode: " + errCode); console.log('errCode: ' + errCode);
} }
function jsProxyTriggerCppStub() function jsProxyTriggerCppStub()
...@@ -660,6 +660,6 @@ function jsProxyTriggerCppStub() ...@@ -660,6 +660,6 @@ function jsProxyTriggerCppStub()
tsProxy.testIntTransaction(10, testIntTransactionCallback); tsProxy.testIntTransaction(10, testIntTransactionCallback);
// Call testStringTransaction. // Call testStringTransaction.
tsProxy.testStringTransaction("test", testIntTransactionCallback); tsProxy.testStringTransaction('test', testIntTransactionCallback);
} }
``` ```
...@@ -8,14 +8,14 @@ ...@@ -8,14 +8,14 @@
- Quick Start - Quick Start
- Getting Started - Getting Started
- [Preparations](quick-start/start-overview.md) - [Preparations](quick-start/start-overview.md)
- [Getting Started with eTS in Stage Model](quick-start/start-with-ets-stage.md) - [Getting Started with ArkTS in Stage Model](quick-start/start-with-ets-stage.md)
- [Getting Started with eTS in FA Model](quick-start/start-with-ets-fa.md) - [Getting Started with ArkTS in FA Model](quick-start/start-with-ets-fa.md)
- [Getting Started with JavaScript in FA Model](quick-start/start-with-js-fa.md) - [Getting Started with JavaScript in FA Model](quick-start/start-with-js-fa.md)
- Development Fundamentals - Development Fundamentals
- [Application Package Structure Configuration File (FA Model)](quick-start/package-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) - [Application Package Structure Configuration File (Stage Model)](quick-start/stage-structure.md)
- [SysCap](quick-start/syscap.md) - [SysCap](quick-start/syscap.md)
- [HarmonyAppProvision Configuration File](quick-start/app-provision-structure.md)
- Development - Development
- [Ability Development](ability/Readme-EN.md) - [Ability Development](ability/Readme-EN.md)
- [UI Development](ui/Readme-EN.md) - [UI Development](ui/Readme-EN.md)
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
- [Security](security/Readme-EN.md) - [Security](security/Readme-EN.md)
- [Connectivity](connectivity/Readme-EN.md) - [Connectivity](connectivity/Readme-EN.md)
- [Data Management](database/Readme-EN.md) - [Data Management](database/Readme-EN.md)
- [File Management](file-management/Readme-EN.md)
- [Telephony](telephony/Readme-EN.md) - [Telephony](telephony/Readme-EN.md)
- [Task Management](task-management/Readme-EN.md) - [Task Management](task-management/Readme-EN.md)
- [Device Management](device/Readme-EN.md) - [Device Management](device/Readme-EN.md)
......
# Ability Development # Ability Development
- [Ability Framework Overview](ability-brief.md) - [Ability Framework Overview](ability-brief.md)
- [Context Usage](context-userguide.md) - [Context Usage](context-userguide.md)
- FA Model - FA Model
...@@ -19,5 +20,3 @@ ...@@ -19,5 +20,3 @@
- [Ability Assistant Usage](ability-assistant-guidelines.md) - [Ability Assistant Usage](ability-assistant-guidelines.md)
- [ContinuationManager Development](continuationmanager.md) - [ContinuationManager Development](continuationmanager.md)
- [Test Framework Usage](ability-delegator.md) - [Test Framework Usage](ability-delegator.md)
...@@ -5,7 +5,7 @@ An ability is the abstraction of a functionality that an application can provide ...@@ -5,7 +5,7 @@ An ability is the abstraction of a functionality that an application can provide
The ability framework model has two forms: The ability framework model has two forms:
- FA model, which applies to application development using API version 8 and earlier versions. In the FA model, there is Feature Ability (FA) and Particle Ability (PA). The FA supports Page abilities, and the PA supports Service, Data, and Form abilities. - FA model, which applies to application development using API version 8 and earlier versions. In the FA model, there is Feature Ability (FA) and Particle Ability (PA). The FA supports Page abilities, and the PA supports Service, Data, and Form abilities.
- Stage model, which is introduced since API version 9. In the stage model, there is `Ability` and `ExtensionAbility`. `ExtensionAbility` is further extended to `ServiceExtensionAbility`, `FormExtensionAbility`, `DataShareExtensionAbility`, and more. - Stage model, which is introduced since API version 9. In the stage model, there is `PageAbility` and `ExtensionAbility`. `ExtensionAbility` is further extended to `ServiceExtensionAbility`, `FormExtensionAbility`, `DataShareExtensionAbility`, and more.
The stage model is designed to make it easier to develop complex applications in the distributed environment. The table below lists the design differences between the two models. The stage model is designed to make it easier to develop complex applications in the distributed environment. The table below lists the design differences between the two models.
......
...@@ -56,7 +56,7 @@ The methods are used to set the display orientation of the current ability. ...@@ -56,7 +56,7 @@ The methods are used to set the display orientation of the current ability.
**Example** **Example**
```javascript ```javascript
import featureAbility from '@ohos.ability.featureAbility' import featureAbility from '@ohos.ability.featureAbility'
import bundle from '../@ohos.bundle'; import bundle from '@ohos.bundle';
export default { export default {
onCreate() { onCreate() {
...@@ -79,7 +79,7 @@ The following describes the contexts provided by the stage model in detail. ...@@ -79,7 +79,7 @@ The following describes the contexts provided by the stage model in detail.
### application/Context ### application/Context
**application/Context** is the base class context that provides basic application information such as **resourceManager**, **applicationInfo**, **cacheDir**, and **area**. It also provides basic application methods such as **createBundleContext**. **application/Context** is the base class context. It provides basic application information, such as **resourceManager**, **applicationInfo**, **cacheDir**, and **area**. It also provides basic application methods such as **createModuleContext**.
**d.ts statement** **d.ts statement**
...@@ -235,13 +235,13 @@ export default class MainAbility extends Ability { ...@@ -235,13 +235,13 @@ export default class MainAbility extends Ability {
For details, see [FormExtensionContext](../reference/apis/js-apis-formextensioncontext.md). For details, see [FormExtensionContext](../reference/apis/js-apis-formextensioncontext.md).
### Obtaining the Context on an eTS Page ### Obtaining the Context on an ArkTS Page
In the stage model, in the `onWindowStageCreate` lifecycle of an ability, you can call `SetUIContent` of `WindowStage` to load an eTS page. In some scenarios, you need to obtain the context on the page to call related APIs. In the stage model, in the `onWindowStageCreate` lifecycle of an ability, you can call `SetUIContent` of `WindowStage` to load an ArkTS page. In some scenarios, you need to obtain the context on the page to call related APIs.
**How to Obtain** **How to Obtain**
Use the API described in the table below to obtain the context associated with an eTS page. Use the API described in the table below to obtain the context associated with an ArkTS page.
| API | Description | | API | Description |
| :------------------------------------ | :--------------------------- | | :------------------------------------ | :--------------------------- |
......
...@@ -14,20 +14,20 @@ As the entry of the ability continuation capability, **continuationManager** is ...@@ -14,20 +14,20 @@ As the entry of the ability continuation capability, **continuationManager** is
## Available APIs ## Available APIs
| API | Description| | API | Description|
| ---------------------------------------------------------------------------------------------- | ----------- | | ---------------------------------------------------------------------------------------------- | ----------- |
| register(callback: AsyncCallback\<number>): void | Registers the continuation management service and obtains a token. This API does not involve any filter parameters and uses an asynchronous callback to return the result.| | registerContinuation(callback: AsyncCallback\<number>): void | Registers the continuation management service and obtains a token. This API does not involve any filter parameters and uses an asynchronous callback to return the result.|
| register(options: ContinuationExtraParams, callback: AsyncCallback\<number>): void | Registers the continuation management service and obtains a token. This API uses an asynchronous callback to return the result.| | registerContinuation(options: ContinuationExtraParams, callback: AsyncCallback\<number>): void | Registers the continuation management service and obtains a token. This API uses an asynchronous callback to return the result.|
| register(options?: ContinuationExtraParams): Promise\<number> | Registers the continuation management service and obtains a token. This API uses a promise to return the result.| | registerContinuation(options?: ContinuationExtraParams): Promise\<number> | Registers the continuation management service and obtains a token. This API uses a promise to return the result.|
| on(type: "deviceConnect", token: number, callback: Callback\<Array\<ContinuationResult>>): void | Subscribes to device connection events. This API uses an asynchronous callback to return the result.| | on(type: "deviceSelected", token: number, callback: Callback\<Array\<ContinuationResult>>): void | Subscribes to device connection events. This API uses an asynchronous callback to return the result.|
| on(type: "deviceDisconnect", token: number, callback: Callback\<Array\<string>>): void | Subscribes to device disconnection events. This API uses an asynchronous callback to return the result.| | on(type: "deviceUnselected", token: number, callback: Callback\<Array\<ContinuationResult>>): void | Subscribes to device disconnection events. This API uses an asynchronous callback to return the result.|
| off(type: "deviceConnect", token: number): void | Unsubscribes from device connection events.| | off(type: "deviceSelected", token: number): void | Unsubscribes from device connection events.|
| off(type: "deviceDisconnect", token: number): void | Unsubscribes from device disconnection events.| | off(type: "deviceUnselected", token: number): void | Unsubscribes from device disconnection events.|
| startDeviceManager(token: number, callback: AsyncCallback\<void>): void | Starts the device selection module to show the list of available devices. This API does not involve any filter parameters and uses an asynchronous callback to return the result.| | startContinuationDeviceManager(token: number, callback: AsyncCallback\<void>): void | Starts the device selection module to show the list of available devices. This API does not involve any filter parameters and uses an asynchronous callback to return the result.|
| startDeviceManager(token: number, options: ContinuationExtraParams, callback: AsyncCallback\<void>): void | Starts the device selection module to show the list of available devices. This API uses an asynchronous callback to return the result.| | startContinuationDeviceManager(token: number, options: ContinuationExtraParams, callback: AsyncCallback\<void>): void | Starts the device selection module to show the list of available devices. This API uses an asynchronous callback to return the result.|
| startDeviceManager(token: number, options?: ContinuationExtraParams): Promise\<void> | Starts the device selection module to show the list of available devices. This API uses a promise to return the result.| | startContinuationDeviceManager(token: number, options?: ContinuationExtraParams): Promise\<void> | Starts the device selection module to show the list of available devices. This API uses a promise to return the result.|
| updateConnectStatus(token: number, deviceId: string, status: DeviceConnectState, callback: AsyncCallback\<void>): void | Instructs the device selection module to update the device connection state. This API uses an asynchronous callback to return the result.| | updateContinuationState(token: number, deviceId: string, status: DeviceConnectState, callback: AsyncCallback\<void>): void | Instructs the device selection module to update the device connection state. This API uses an asynchronous callback to return the result.|
| updateConnectStatus(token: number, deviceId: string, status: DeviceConnectState): Promise\<void> | Instructs the device selection module to update the device connection state. This API uses a promise to return the result.| | updateContinuationState(token: number, deviceId: string, status: DeviceConnectState): Promise\<void> | Instructs the device selection module to update the device connection state. This API uses a promise to return the result.|
| unregister(token: number, callback: AsyncCallback\<void>): void | Deregisters the continuation management service. This API uses an asynchronous callback to return the result.| | unregisterContinuation(token: number, callback: AsyncCallback\<void>): void | Deregisters the continuation management service. This API uses an asynchronous callback to return the result.|
| unregister(token: number): Promise\<void> | Deregisters the continuation management service. This API uses a promise to return the result.| | unregisterContinuation(token: number): Promise\<void> | Deregisters the continuation management service. This API uses a promise to return the result.|
## How to Develop ## How to Develop
1. Import the **continuationManager** module. 1. Import the **continuationManager** module.
...@@ -36,7 +36,7 @@ As the entry of the ability continuation capability, **continuationManager** is ...@@ -36,7 +36,7 @@ As the entry of the ability continuation capability, **continuationManager** is
import continuationManager from '@ohos.continuation.continuationManager'; import continuationManager from '@ohos.continuation.continuationManager';
``` ```
2. Apply for permissions required for cross-device continuation or collaboration operations. 2. Apply for the **DISTRIBUTED_DATASYNC** permission.
The permission application operation varies according to the ability model in use. In the FA mode, add the required permission in the `config.json` file, as follows: The permission application operation varies according to the ability model in use. In the FA mode, add the required permission in the `config.json` file, as follows:
...@@ -57,6 +57,7 @@ As the entry of the ability continuation capability, **continuationManager** is ...@@ -57,6 +57,7 @@ As the entry of the ability continuation capability, **continuationManager** is
```ts ```ts
import abilityAccessCtrl from "@ohos.abilityAccessCtrl"; import abilityAccessCtrl from "@ohos.abilityAccessCtrl";
import bundle from '@ohos.bundle'; import bundle from '@ohos.bundle';
import featureAbility from '@ohos.ability.featureAbility';
async function requestPermission() { async function requestPermission() {
let permissions: Array<string> = [ let permissions: Array<string> = [
...@@ -124,7 +125,8 @@ As the entry of the ability continuation capability, **continuationManager** is ...@@ -124,7 +125,8 @@ As the entry of the ability continuation capability, **continuationManager** is
// If the permission is not granted, call requestPermissionsFromUser to apply for the permission. // If the permission is not granted, call requestPermissionsFromUser to apply for the permission.
if (needGrantPermission) { if (needGrantPermission) {
try { try {
await globalThis.abilityContext.requestPermissionsFromUser(permissions); // globalThis.context is Ability.context, which must be assigned a value in the MainAbility.ts file in advance.
await globalThis.context.requestPermissionsFromUser(permissions);
} catch (err) { } catch (err) {
console.error('app permission request permissions error' + JSON.stringify(err)); console.error('app permission request permissions error' + JSON.stringify(err));
} }
...@@ -140,13 +142,16 @@ As the entry of the ability continuation capability, **continuationManager** is ...@@ -140,13 +142,16 @@ As the entry of the ability continuation capability, **continuationManager** is
```ts ```ts
let token: number = -1; // Used to save the token returned after the registration. The token will be used when listening for device connection/disconnection events, starting the device selection module, and updating the device connection state. let token: number = -1; // Used to save the token returned after the registration. The token will be used when listening for device connection/disconnection events, starting the device selection module, and updating the device connection state.
try {
continuationManager.register().then((data) => { continuationManager.registerContinuation().then((data) => {
console.info('register finished, ' + JSON.stringify(data)); console.info('registerContinuation finished, ' + JSON.stringify(data));
token = data; // Obtain a token and assign a value to the token variable. token = data; // Obtain a token and assign a value to the token variable.
}).catch((err) => { }).catch((err) => {
console.error('register failed, cause: ' + JSON.stringify(err)); console.error('registerContinuation failed, cause: ' + JSON.stringify(err));
}); });
} catch (err) {
console.error('registerContinuation failed, cause: ' + JSON.stringify(err));
}
``` ```
4. Listen for the device connection/disconnection state. 4. Listen for the device connection/disconnection state.
...@@ -156,28 +161,31 @@ As the entry of the ability continuation capability, **continuationManager** is ...@@ -156,28 +161,31 @@ As the entry of the ability continuation capability, **continuationManager** is
```ts ```ts
let remoteDeviceId: string = ""; // Used to save the information about the remote device selected by the user, which will be used for cross-device continuation or collaboration. let remoteDeviceId: string = ""; // Used to save the information about the remote device selected by the user, which will be used for cross-device continuation or collaboration.
// The token parameter is the token obtained during the registration. try {
continuationManager.on("deviceConnect", token, (continuationResults) => { // The token parameter is the token obtained during the registration.
console.info('registerDeviceConnectCallback len: ' + continuationResults.length); continuationManager.on("deviceSelected", token, (continuationResults) => {
if (continuationResults.length <= 0) { console.info('registerDeviceSelectedCallback len: ' + continuationResults.length);
console.info('no selected device'); if (continuationResults.length <= 0) {
return; console.info('no selected device');
} return;
remoteDeviceId = continuationResults[0].id; // Assign the deviceId of the first selected remote device to the remoteDeviceId variable. }
remoteDeviceId = continuationResults[0].id; // Assign the deviceId of the first selected remote device to the remoteDeviceId variable.
// Pass the remoteDeviceId parameter to want.
let want = { // Pass the remoteDeviceId parameter to want.
deviceId: remoteDeviceId, let want = {
bundleName: 'ohos.samples.continuationmanager', deviceId: remoteDeviceId,
abilityName: 'MainAbility' bundleName: 'ohos.samples.continuationmanager',
}; abilityName: 'MainAbility'
// To initiate multi-device collaboration, you must obtain the ohos.permission.DISTRIBUTED_DATASYNC permission. };
globalThis.abilityContext.startAbility(want).then((data) => { globalThis.abilityContext.startAbility(want).then((data) => {
console.info('StartRemoteAbility finished, ' + JSON.stringify(data)); console.info('StartRemoteAbility finished, ' + JSON.stringify(data));
}).catch((err) => { }).catch((err) => {
console.error('StartRemoteAbility failed, cause: ' + JSON.stringify(err)); console.error('StartRemoteAbility failed, cause: ' + JSON.stringify(err));
});
}); });
}); } catch (err) {
console.error('on failed, cause: ' + JSON.stringify(err));
}
``` ```
The preceding multi-device collaboration operation is performed across devices in the stage model. For details about this operation in the FA model, see [Page Ability Development](https://gitee.com/openharmony/docs/blob/master/en/application-dev/ability/fa-pageability.md). The preceding multi-device collaboration operation is performed across devices in the stage model. For details about this operation in the FA model, see [Page Ability Development](https://gitee.com/openharmony/docs/blob/master/en/application-dev/ability/fa-pageability.md).
...@@ -189,35 +197,43 @@ As the entry of the ability continuation capability, **continuationManager** is ...@@ -189,35 +197,43 @@ As the entry of the ability continuation capability, **continuationManager** is
let deviceConnectStatus: continuationManager.DeviceConnectState = continuationManager.DeviceConnectState.CONNECTED; let deviceConnectStatus: continuationManager.DeviceConnectState = continuationManager.DeviceConnectState.CONNECTED;
// The token parameter is the token obtained during the registration, and the remoteDeviceId parameter is the remoteDeviceId obtained. // The token parameter is the token obtained during the registration, and the remoteDeviceId parameter is the remoteDeviceId obtained.
continuationManager.updateConnectStatus(token, remoteDeviceId, deviceConnectStatus).then((data) => { try {
console.info('updateConnectStatus finished, ' + JSON.stringify(data)); continuationManager.updateContinuationState(token, remoteDeviceId, deviceConnectStatus).then((data) => {
}).catch((err) => { console.info('updateContinuationState finished, ' + JSON.stringify(data));
console.error('updateConnectStatus failed, cause: ' + JSON.stringify(err)); }).catch((err) => {
}); console.error('updateContinuationState failed, cause: ' + JSON.stringify(err));
});
} catch (err) {
console.error('updateContinuationState failed, cause: ' + JSON.stringify(err));
}
``` ```
Listen for the device disconnection state so that the user can stop cross-device continuation or collaboration in time. The sample code is as follows: Listen for the device disconnection state so that the user can stop cross-device continuation or collaboration in time. The sample code is as follows:
```ts ```ts
// The token parameter is the token obtained during the registration. try {
continuationManager.on("deviceDisconnect", token, (deviceIds) => { // The token parameter is the token obtained during the registration.
console.info('onDeviceDisconnect len: ' + deviceIds.length); continuationManager.on("deviceUnselected", token, (continuationResults) => {
if (deviceIds.length <= 0) { console.info('onDeviceUnselected len: ' + continuationResults.length);
console.info('no unselected device'); if (continuationResults.length <= 0) {
return; console.info('no unselected device');
} return;
}
// Update the device connection state. // Update the device connection state.
let unselectedDeviceId: string = deviceIds[0]; // Assign the deviceId of the first deselected remote device to the unselectedDeviceId variable. let unselectedDeviceId: string = continuationResults[0].id; // Assign the deviceId of the first deselected remote device to the unselectedDeviceId variable.
let deviceConnectStatus: continuationManager.DeviceConnectState = continuationManager.DeviceConnectState.DISCONNECTING; // Device disconnected. let deviceConnectStatus: continuationManager.DeviceConnectState = continuationManager.DeviceConnectState.DISCONNECTING; // Device disconnected.
// The token parameter is the token obtained during the registration, and the unselectedDeviceId parameter is the unselectedDeviceId obtained. // The token parameter is the token obtained during the registration, and the unselectedDeviceId parameter is the unselectedDeviceId obtained.
continuationManager.updateConnectStatus(token, unselectedDeviceId, deviceConnectStatus).then((data) => { continuationManager.updateContinuationState(token, unselectedDeviceId, deviceConnectStatus).then((data) => {
console.info('updateConnectStatus finished, ' + JSON.stringify(data)); console.info('updateContinuationState finished, ' + JSON.stringify(data));
}).catch((err) => { }).catch((err) => {
console.error('updateConnectStatus failed, cause: ' + JSON.stringify(err)); console.error('updateContinuationState failed, cause: ' + JSON.stringify(err));
});
}); });
}); } catch (err) {
console.error('updateContinuationState failed, cause: ' + JSON.stringify(err));
}
``` ```
5. Start the device selection module to show the list of available devices on the network. 5. Start the device selection module to show the list of available devices on the network.
...@@ -231,12 +247,16 @@ As the entry of the ability continuation capability, **continuationManager** is ...@@ -231,12 +247,16 @@ As the entry of the ability continuation capability, **continuationManager** is
continuationMode: continuationManager.ContinuationMode.COLLABORATION_SINGLE // Single-choice mode of the device selection module. continuationMode: continuationManager.ContinuationMode.COLLABORATION_SINGLE // Single-choice mode of the device selection module.
}; };
// The token parameter is the token obtained during the registration. try {
continuationManager.startDeviceManager(token, continuationExtraParams).then((data) => { // The token parameter is the token obtained during the registration.
console.info('startDeviceManager finished, ' + JSON.stringify(data)); continuationManager.startContinuationDeviceManager(token, continuationExtraParams).then((data) => {
}).catch((err) => { console.info('startContinuationDeviceManager finished, ' + JSON.stringify(data));
console.error('startDeviceManager failed, cause: ' + JSON.stringify(err)); }).catch((err) => {
}); console.error('startContinuationDeviceManager failed, cause: ' + JSON.stringify(err));
});
} catch (err) {
console.error('startContinuationDeviceManager failed, cause: ' + JSON.stringify(err));
}
``` ```
6. If you do not need to perform cross-device migration or collaboration operations, you can deregister the continuation management service, by passing the token obtained during the registration. 6. If you do not need to perform cross-device migration or collaboration operations, you can deregister the continuation management service, by passing the token obtained during the registration.
...@@ -244,10 +264,14 @@ As the entry of the ability continuation capability, **continuationManager** is ...@@ -244,10 +264,14 @@ As the entry of the ability continuation capability, **continuationManager** is
The sample code is as follows: The sample code is as follows:
```ts ```ts
// The token parameter is the token obtained during the registration. try {
continuationManager.unregister(token).then((data) => { // The token parameter is the token obtained during the registration.
console.info('unregister finished, ' + JSON.stringify(data)); continuationManager.unregisterContinuation(token).then((data) => {
}).catch((err) => { console.info('unregisterContinuation finished, ' + JSON.stringify(data));
console.error('unregister failed, cause: ' + JSON.stringify(err)); }).catch((err) => {
}); console.error('unregisterContinuation failed, cause: ' + JSON.stringify(err));
});
} catch (err) {
console.error('unregisterContinuation failed, cause: ' + JSON.stringify(err));
}
``` ```
...@@ -12,6 +12,7 @@ The Feature Ability (FA) model applies to application development using API vers ...@@ -12,6 +12,7 @@ The Feature Ability (FA) model applies to application development using API vers
## Lifecycle ## Lifecycle
Among all abilities, the Page ability has the most complex lifecycle, because it has a UI and acts as a touchpoint for interacting with users. Among all abilities, the Page ability has the most complex lifecycle, because it has a UI and acts as a touchpoint for interacting with users.
**The following figure shows the lifecycle of the Page ability.** **The following figure shows the lifecycle of the Page ability.**
![fa-pageAbility-lifecycle](figures/fa-pageAbility-lifecycle.png) ![fa-pageAbility-lifecycle](figures/fa-pageAbility-lifecycle.png)
...@@ -26,3 +27,9 @@ Currently, the **app.js** file provides only the **onCreate** and **onDestroy** ...@@ -26,3 +27,9 @@ Currently, the **app.js** file provides only the **onCreate** and **onDestroy**
An application exclusively uses an independent process, and an ability exclusively uses an independent thread. When an ability is started for the first time, an application process as well as a thread for this ability is created. After the application is started, other abilities in the application are started, and a thread is created for every of these started abilities. Each ability is bound to an independent JSRuntime instance. In this way, abilities are isolated from each other. An application exclusively uses an independent process, and an ability exclusively uses an independent thread. When an ability is started for the first time, an application process as well as a thread for this ability is created. After the application is started, other abilities in the application are started, and a thread is created for every of these started abilities. Each ability is bound to an independent JSRuntime instance. In this way, abilities are isolated from each other.
![fa-threading-model](figures/fa-threading-model.png) ![fa-threading-model](figures/fa-threading-model.png)
## Application Package Structure
For details about the project directory structure of the FA model, see [OpenHarmony Project Overview](https://developer.harmonyos.com/en/docs/documentation/doc-guides/ohos-project-overview-0000001218440650#section4154183910141).
For details about how to configure the application package structure of the FA model, see [Application Package Structure Configuration File](../quick-start/package-structure.md).
# Page Ability Development # Page Ability Development
## Overview ## Overview
### Concepts ### Concepts
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**.
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 ### Page Ability Lifecycle
**Ability lifecycle** Introduction to the Page ability lifecycle:
The Page ability lifecycle defines 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**.
...@@ -27,27 +31,30 @@ Description of ability lifecycle states: ...@@ -27,27 +31,30 @@ Description of ability lifecycle states:
- **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. - **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.** The following figure shows the relationship between lifecycle callbacks and lifecycle states of the Page ability.
![fa-pageAbility-lifecycle](figures/fa-pageAbility-lifecycle.png) ![fa-pageAbility-lifecycle](figures/fa-pageAbility-lifecycle.png)
You can override the lifecycle 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. 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 ### Launch Type
The ability supports two launch types: singleton and multi-instance. The ability supports two launch types: singleton and multi-instance.
You can specify the launch type by setting **launchType** in the **config.json** file. You can specify the launch type by setting **launchType** in the **config.json** file.
**Table 1** Introduction to startup mode **Table 1** Startup modes
| Launch Type | Description |Description | | Launch Type | Description |Description |
| ----------- | ------- |---------------- | | ----------- | ------- |---------------- |
| standard | Multi-instance | A new instance is started each time an ability starts.| | standard | Multi-instance | A new instance is started each time an ability starts.|
| singleton | Singleton | Only one instance exists in the system. If an instance already exists when an ability is started, that instance is reused.| | singleton | Singleton | The ability has only one instance in the system. If an instance already exists when an ability is started, that instance is reused.|
By default, **singleton** is used. By default, **singleton** is used.
## Development Guidelines ## Development Guidelines
### Available APIs ### Available APIs
**Table 2** APIs provided by featureAbility **Table 2** APIs provided by featureAbility
...@@ -73,23 +80,21 @@ By default, **singleton** is used. ...@@ -73,23 +80,21 @@ By default, **singleton** is used.
```javascript ```javascript
import featureAbility from '@ohos.ability.featureAbility' import featureAbility from '@ohos.ability.featureAbility'
featureAbility.startAbility({ featureAbility.startAbility({
want: want: {
{ action: "",
action: "", entities: [""],
entities: [""], type: "",
type: "", deviceId: "",
deviceId: "", bundleName: "com.example.myapplication",
bundleName: "com.example.myapplication", /* In the FA model, abilityName consists of package and ability name. */
/* In the FA model, abilityName consists of package and ability name. */ abilityName: "com.example.entry.secondAbility",
abilityName: "com.example.entry.secondAbility", uri: ""
uri: "" }
}, });
},
);
``` ```
### Starting a Remote Page Ability ### Starting a Remote Page Ability
>Note >NOTE
> >
>This feature applies only to system applications, since the **getTrustedDeviceListSync** API of the **DeviceManager** class is open only to system applications. >This feature applies only to system applications, since the **getTrustedDeviceListSync** API of the **DeviceManager** class is open only to system applications.
......
...@@ -92,7 +92,7 @@ After the preceding code is executed, the **startAbility()** API is called to st ...@@ -92,7 +92,7 @@ After the preceding code is executed, the **startAbility()** API is called to st
- If the Service ability is not running, the system calls **onStart()** to initialize the Service ability, and then calls **onCommand()** on the Service ability. - If the Service ability is not running, the system calls **onStart()** to initialize the Service ability, and then calls **onCommand()** on the Service ability.
- If the Service ability is running, the system directly calls **onCommand()** on the Service ability. - If the Service ability is running, the system directly calls **onCommand()** on the Service ability.
The following code snippet shows how to start a Service ability running on the remote device. For details about **getRemoteDeviceId()**, see [Connecting to a Remote Service Ability](#connecting-to-a-remote-service-ability-applying-only-to-system-applications). The following code snippet shows how to start a Service ability running on the remote device. For details about **getRemoteDeviceId()**, see [Connecting to a Remote Service Ability](#connecting-to-a-remote-service-ability).
```javascript ```javascript
import featureAbility from '@ohos.ability.featureAbility'; import featureAbility from '@ohos.ability.featureAbility';
......
...@@ -12,8 +12,8 @@ An ability can be launched in the **standard**, **singleton**, or **specified** ...@@ -12,8 +12,8 @@ An ability can be launched in the **standard**, **singleton**, or **specified**
| Launch Type | Description |Action | | Launch Type | Description |Action |
| ----------- | ------- |---------------- | | ----------- | ------- |---------------- |
| standard | Multi-instance | A new instance is started each time an ability starts.| | standard | Standard mode. | A new instance is started each time an ability starts.|
| singleton | Singleton | The ability has only one instance in the system. If an instance already exists when an ability is started, that instance is reused.| | singleton | Singleton mode. | The ability has only one instance in the system. If an instance already exists when an ability is started, that instance is reused.|
| specified | Instance-specific| The internal service of an ability determines whether to create multiple instances during running.| | specified | Instance-specific| The internal service of an ability determines whether to create multiple instances during running.|
By default, the singleton mode is used. The following is an example of the `module.json5` file: By default, the singleton mode is used. The following is an example of the `module.json5` file:
......
...@@ -49,6 +49,8 @@ The ability and ability stage lifecycles are the rudiments of the basic process ...@@ -49,6 +49,8 @@ The ability and ability stage lifecycles are the rudiments of the basic process
To implement device-specific tailoring and multi-window scalability, OpenHarmony decouples the component manager from the window manager. The ability lifecycle defined in the stage model includes only the creation, destruction, foreground, and background states. The gain focus and lose focus states that are closely related to UI content are defined in the window stage. This implements weak coupling between the abilities and windows. On the service side, the window manager notifies the component manager of the foreground and background changes, so the component manager only senses the foreground and background changes but not the focus changes. To implement device-specific tailoring and multi-window scalability, OpenHarmony decouples the component manager from the window manager. The ability lifecycle defined in the stage model includes only the creation, destruction, foreground, and background states. The gain focus and lose focus states that are closely related to UI content are defined in the window stage. This implements weak coupling between the abilities and windows. On the service side, the window manager notifies the component manager of the foreground and background changes, so the component manager only senses the foreground and background changes but not the focus changes.
There are two lifecycle states related to **WindowStage** in **Ability**: **onWindowStageCreate** and **onWindowStageDestroy**. They are valid only for devices with the window display capability. **onWindowStageCreate** is invoked when a window stage is created, where you can call **loadContent** to set pages to be loaded for the ability. **onWindowStageDestroy** is invoked when the window stage is destroyed, where you can release resources.
## Ability Instances and Missions ## Ability Instances and Missions
...@@ -58,7 +60,7 @@ Abilities can be started in any of the following modes: ...@@ -58,7 +60,7 @@ Abilities can be started in any of the following modes:
+ **Standard**: Each time **startAbility** is called, an instance of the specified ability type is created in the application process. **Ability2** in the figure below is started in standard mode. + **Standard**: Each time **startAbility** is called, an instance of the specified ability type is created in the application process. **Ability2** in the figure below is started in standard mode.
+ **Specified**: Before creating an **AbilityRecord**, you can create a key for the instance. Each time **startAbility** is called, the system asks the application which ability instance (corresponding to a key) will be used. **Ability3** in the figure below is started in specified mode. + **Specified**: Before creating an **Ability** instance, you can create a key for the instance. Each time **startAbility** is called, the system asks the application which ability instance (corresponding to a key) will be used. **Ability3** in the figure below is started in specified mode.
Each ability instance corresponds to a mission in **Launcher Recent**. Each ability instance corresponds to a mission in **Launcher Recent**.
...@@ -92,6 +94,12 @@ All OpenHarmony applications are designed to meet the single-process model. In t ...@@ -92,6 +94,12 @@ All OpenHarmony applications are designed to meet the single-process model. In t
- Render process: created for the WebView and used to load the WebView rendering library. - Render process: created for the WebView and used to load the WebView rendering library.
The following figure shows the process model of an application. The following figure shows the process model of an application.
![stageprocessmodel](figures/stageprocessmodel.png)
## Application Package Structure
For details about the project directory structure of the stage model, see [OpenHarmony Project Overview](https://developer.harmonyos.com/en/docs/documentation/doc-guides/ohos-project-overview-0000001218440650#section56487581904).
![stageprocessmodel](figures/stageprocessmodel.png) For details about how to configure the application package structure of the stage model, see [Application Package Structure Configuration File (Stage Model)](../quick-start/stage-structure.md).
...@@ -81,7 +81,7 @@ import Ability from '@ohos.application.Ability' ...@@ -81,7 +81,7 @@ import Ability from '@ohos.application.Ability'
```ts ```ts
export default class MySequenceable { export default class MySequenceable {
num: number = 0 num: number = 0
str: String = "" str: string = ""
constructor(num, string) { constructor(num, string) {
this.num = num this.num = num
......
...@@ -12,7 +12,7 @@ To use related APIs, you must declare the **ohos.permission.INTERNET** permissio ...@@ -12,7 +12,7 @@ To use related APIs, you must declare the **ohos.permission.INTERNET** permissio
For details about how to apply for permissions, see [Access Control Development](../security/accesstoken-guidelines.md). For details about how to apply for permissions, see [Access Control Development](../security/accesstoken-guidelines.md).
The following table describes the related APIs. The following table provides only a simple description of the related APIs. For details, see [API Reference](../reference/apis/js-apis-http.md).
| API | Description | | API | Description |
| ----------------------------------------- | --------------------------------------------------------- | | ----------------------------------------- | --------------------------------------------------------- |
......
...@@ -10,7 +10,7 @@ IPC/RPC enables a proxy and a stub that run on different processes to communicat ...@@ -10,7 +10,7 @@ IPC/RPC enables a proxy and a stub that run on different processes to communicat
| Class/Interface | Function | Description | | Class/Interface | Function | Description |
| --------------- | -------- | ----------- | | --------------- | -------- | ----------- |
| IRemoteBroker | sptr<IRemoteObject> AsObject() | Obtains the holder of a remote proxy object. This method must be implemented by the derived classes of **IRemoteBroker**. If you call this method on the stub, the **RemoteObject** is returned; if you call this method on the proxy, the proxy object is returned. | | [IRemoteBroker](../reference/apis/js-apis-rpc.md#iremotebroker) | sptr<IRemoteObject> AsObject() | Obtains the holder of a remote proxy object. This method must be implemented by the derived classes of **IRemoteBroker**. If you call this method on the stub, the **RemoteObject** is returned; if you call this method on the proxy, the proxy object is returned. |
| IRemoteStub | virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) | Called to process a request from the proxy and return the result. Derived classes need to override this method. | | IRemoteStub | virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) | Called to process a request from the proxy and return the result. Derived classes need to override this method. |
| IRemoteProxy | | Service proxy classes are derived from the **IRemoteProxy** class. | | IRemoteProxy | | Service proxy classes are derived from the **IRemoteProxy** class. |
...@@ -25,10 +25,10 @@ IPC/RPC enables a proxy and a stub that run on different processes to communicat ...@@ -25,10 +25,10 @@ IPC/RPC enables a proxy and a stub that run on different processes to communicat
``` ```
class ITestAbility : public IRemoteBroker { class ITestAbility : public IRemoteBroker {
public: public:
// DECLARE_INTERFACE_DESCRIPTOR is mandatory, and the input parameter is std::u16string. // DECLARE_INTERFACE_DESCRIPTOR is mandatory, and the input parameter is std::u16string.
DECLARE_INTERFACE_DESCRIPTOR(u"test.ITestAbility"); DECLARE_INTERFACE_DESCRIPTOR(u"test.ITestAbility");
int TRANS_ID_PING_ABILITY = 1; // Define the message code. int TRANS_ID_PING_ABILITY = 1; // Define the message code.
virtual int TestPingAbility(const std::u16string &dummy) = 0; // Define functions. virtual int TestPingAbility(const std::u16string &dummy) = 0; // Define functions.
}; };
``` ```
......
...@@ -52,9 +52,9 @@ Examples are given below. ...@@ -52,9 +52,9 @@ Examples are given below.
3. Implement the data provider services. For example, implement data storage of the data provider by using a database, reading and writing files, or accessing the network. 3. Implement the data provider services. For example, implement data storage of the data provider by using a database, reading and writing files, or accessing the network.
```ts ```ts
let DB_NAME = "DB00.db"; const DB_NAME = "DB00.db";
let TBL_NAME = "TBL00"; const TBL_NAME = "TBL00";
let DDL_TBL_CREATE = "CREATE TABLE IF NOT EXISTS " const DDL_TBL_CREATE = "CREATE TABLE IF NOT EXISTS "
+ TBL_NAME + TBL_NAME
+ " (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, isStudent BOOLEAN, Binary BINARY)"; + " (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, isStudent BOOLEAN, Binary BINARY)";
...@@ -132,9 +132,9 @@ Examples are given below. ...@@ -132,9 +132,9 @@ Examples are given below.
1. Import the dependencies. 1. Import the dependencies.
```ts ```ts
import Ability from '@ohos.application.Ability' import Ability from '@ohos.application.Ability';
import dataShare from '@ohos.data.dataShare' import dataShare from '@ohos.data.dataShare';
import dataSharePredicates from '@ohos.data.dataSharePredicates' import dataSharePredicates from '@ohos.data.dataSharePredicates';
``` ```
2. Define the URI string for communicating with the data provider. 2. Define the URI string for communicating with the data provider.
...@@ -164,29 +164,25 @@ Examples are given below. ...@@ -164,29 +164,25 @@ Examples are given below.
```ts ```ts
// Construct a piece of data. // Construct a piece of data.
var valuesBucket = { "name": "ZhangSan", "age": 21, "isStudent": false, "Binary": new Uint8Array([1, 2, 3]) }; let valuesBucket = { "name": "ZhangSan", "age": 21, "isStudent": false, "Binary": new Uint8Array([1, 2, 3]) };
var updateBucket = { "name": "LiSi", "age": 18, "isStudent": true, "Binary": new Uint8Array([1, 2, 3]) }; let updateBucket = { "name": "LiSi", "age": 18, "isStudent": true, "Binary": new Uint8Array([1, 2, 3]) };
let da = new dataSharePredicates.DataSharePredicates(); let predicates = new dataSharePredicates.DataSharePredicates();
var valArray = new Array("*"); let valArray = new Array("*");
let people = new Array(
{ "name": "LiSi", "age": 41, "Binary": ar },
{ "name": "WangWu", "age": 21, "Binary": arr },
{ "name": "ZhaoLiu", "age": 61, "Binary": arr });
// Insert a piece of data. // Insert a piece of data.
dsHelper.insert(dseUri, valuesBucket, (err, data) => { dsHelper.insert(dseUri, valuesBucket, (err, data) => {
console.log("dsHelper insert result: " + data); console.log("dsHelper insert result: " + data);
}); });
// Delete data.
dsHelper.delete(dseUri, da, (err, data) => {
console.log("dsHelper delete result: " + data);
});
// Update data. // Update data.
dsHelper.update(dseUri, da, updateBucket, (err, data) => { dsHelper.update(dseUri, predicates, updateBucket, (err, data) => {
console.log("dsHelper update result: " + data); console.log("dsHelper update result: " + data);
}); });
// Query data. // Query data.
dsHelper.query(dseUri, da, valArray, (err, data) => { dsHelper.query(dseUri, predicates, valArray, (err, data) => {
console.log("dsHelper query result: " + data); console.log("dsHelper query result: " + data);
}); });
// Delete data.
dsHelper.delete(dseUri, predicates, (err, data) => {
console.log("dsHelper delete result: " + data);
});
``` ```
...@@ -22,7 +22,7 @@ Before you get started, familiarize yourself with the following concepts: ...@@ -22,7 +22,7 @@ Before you get started, familiarize yourself with the following concepts:
An application that accesses the data or services provided by a data provider. It is also called a client. An application that accesses the data or services provided by a data provider. It is also called a client.
- Value bucket (**ValuesBucket**) - **ValuesBucket**
One or more data records stored in the form of key-value (KV) pairs. The keys are of the string type. The values can be of the number, string, Boolean, or Unit8Array type. One or more data records stored in the form of key-value (KV) pairs. The keys are of the string type. The values can be of the number, string, Boolean, or Unit8Array type.
......
...@@ -12,7 +12,7 @@ The distributed data object management framework provides object-oriented in-mem ...@@ -12,7 +12,7 @@ The distributed data object management framework provides object-oriented in-mem
- **Distributed data object** - **Distributed data object**
A distributed data object is an encapsulation of the JS object type. Each distributed data object instance creates a data table in the in-memory database. The in-memory databases created for different applications are isolated from each other. Reading data from and writing data to a distributed data object are mapped to the **put** and **get** operations in the corresponding database, respectively. A distributed data object is an encapsulation of the JS object type. Each distributed data object instance creates a data table in the in-memory database. The in-memory databases created for different applications are isolated from each other. Reading data from and writing data to a distributed data object are mapped to the **get** and **put** operations in the corresponding database, respectively.
The distributed data object can be in the following states in its lifecycle: The distributed data object can be in the following states in its lifecycle:
......
...@@ -50,18 +50,41 @@ The following uses a single KV store as an example to describe the development p ...@@ -50,18 +50,41 @@ The following uses a single KV store as an example to describe the development p
This permission must also be granted by the user when the application is started for the first time. The sample code is as follows: This permission must also be granted by the user when the application is started for the first time. The sample code is as follows:
```js ```js
// FA model
import featureAbility from '@ohos.ability.featureAbility'; import featureAbility from '@ohos.ability.featureAbility';
function grantPermission() { function grantPermission() {
console.info('grantPermission'); console.info('grantPermission');
let context = featureAbility.getContext(); let context = featureAbility.getContext();
context.requestPermissionsFromUser(['ohos.permission.DISTRIBUTED_DATASYNC'], 666, function (result) { context.requestPermissionsFromUser(['ohos.permission.DISTRIBUTED_DATASYNC'], 666).then((data) => {
console.info(`result.requestCode=${result.requestCode}`) console.info('success: ${data}');
}).catch((error) => {
}) console.info('failed: ${error}');
console.info('end grantPermission'); })
} }
grantPermission();
// Stage model
import Ability from '@ohos.application.Ability';
let context = null;
function grantPermission() {
class MainAbility extends Ability {
onWindowStageCreate(windowStage) {
let context = this.context;
}
}
let permissions = ['ohos.permission.DISTRIBUTED_DATASYNC'];
context.requestPermissionsFromUser(permissions).then((data) => {
console.log('success: ${data}');
}).catch((error) => {
console.log('failed: ${error}');
});
}
grantPermission(); grantPermission();
``` ```
...@@ -73,25 +96,39 @@ The following uses a single KV store as an example to describe the development p ...@@ -73,25 +96,39 @@ The following uses a single KV store as an example to describe the development p
The sample code is as follows: The sample code is as follows:
```js ```js
// Obtain the context of the FA model.
import featureAbility from '@ohos.ability.featureAbility';
let context = featureAbility.getContext();
// Obtain the context of the stage model.
import AbilityStage from '@ohos.application.Ability';
let context = null;
class MainAbility extends AbilityStage{
onWindowStageCreate(windowStage){
context = this.context;
}
}
let kvManager; let kvManager;
try { try {
const kvManagerConfig = { const kvManagerConfig = {
bundleName: 'com.example.datamanagertest', bundleName: 'com.example.datamanagertest',
userInfo: { userInfo: {
context:context,
userId: '0', userId: '0',
userType: distributedData.UserType.SAME_USER_ID userType: distributedData.UserType.SAME_USER_ID
} }
} }
distributedData.createKVManager(kvManagerConfig, function (err, manager) { distributedData.createKVManager(kvManagerConfig, function (err, manager) {
if (err) { if (err) {
console.log("createKVManager err: " + JSON.stringify(err)); console.log('Failed to create KVManager: ${error}');
return; return;
} }
console.log("createKVManager success"); console.log('Created KVManager successfully');
kvManager = manager; kvManager = manager;
}); });
} catch (e) { } catch (e) {
console.log("An unexpected error occurred. Error: " + e); console.log('An unexpected error occurred. Error: ${e}');
} }
``` ```
...@@ -115,14 +152,14 @@ The following uses a single KV store as an example to describe the development p ...@@ -115,14 +152,14 @@ The following uses a single KV store as an example to describe the development p
}; };
kvManager.getKVStore('storeId', options, function (err, store) { kvManager.getKVStore('storeId', options, function (err, store) {
if (err) { if (err) {
console.log("getKVStore err: " + JSON.stringify(err)); console.log('Failed to get KVStore: ${err}');
return; return;
} }
console.log("getKVStore success"); console.log('Got KVStore successfully');
kvStore = store; kvStore = store;
}); });
} catch (e) { } catch (e) {
console.log("An unexpected error occurred. Error: " + e); console.log('An unexpected error occurred. Error: ${e}');
} }
``` ```
...@@ -136,7 +173,7 @@ The following uses a single KV store as an example to describe the development p ...@@ -136,7 +173,7 @@ The following uses a single KV store as an example to describe the development p
```js ```js
kvStore.on('dataChange', distributedData.SubscribeType.SUBSCRIBE_TYPE_ALL, function (data) { kvStore.on('dataChange', distributedData.SubscribeType.SUBSCRIBE_TYPE_ALL, function (data) {
console.log("dataChange callback call data: " + JSON.stringify(data)); console.log("dataChange callback call data: ${data}");
}); });
``` ```
...@@ -153,13 +190,13 @@ The following uses a single KV store as an example to describe the development p ...@@ -153,13 +190,13 @@ The following uses a single KV store as an example to describe the development p
try { try {
kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, function (err, data) { kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, function (err, data) {
if (err != undefined) { if (err != undefined) {
console.log("put err: " + JSON.stringify(err)); console.log('Failed to put data: ${error}');
return; return;
} }
console.log("put success"); console.log('Put data successfully');
}); });
} catch (e) { } catch (e) {
console.log("An unexpected error occurred. Error: " + e); console.log('An unexpected error occurred. Error: ${e}');
} }
``` ```
...@@ -176,16 +213,16 @@ The following uses a single KV store as an example to describe the development p ...@@ -176,16 +213,16 @@ The following uses a single KV store as an example to describe the development p
try { try {
kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, function (err, data) { kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, function (err, data) {
if (err != undefined) { if (err != undefined) {
console.log("put err: " + JSON.stringify(err)); console.log('Failed to put data: ${error}');
return; return;
} }
console.log("put success"); console.log('Put data successfully');
kvStore.get(KEY_TEST_STRING_ELEMENT, function (err, data) { kvStore.get(KEY_TEST_STRING_ELEMENT, function (err, data) {
console.log("get success data: " + data); console.log('Got data successfully: ${data}');
}); });
}); });
} catch (e) { } catch (e) {
console.log("An unexpected error occurred. Error: " + e); console.log('An unexpected error occurred. Error: ${e}');
} }
``` ```
...@@ -204,7 +241,7 @@ The following uses a single KV store as an example to describe the development p ...@@ -204,7 +241,7 @@ The following uses a single KV store as an example to describe the development p
let devManager; let devManager;
// Create deviceManager. // Create deviceManager.
deviceManager.createDeviceManager("bundleName", (err, value) => { deviceManager.createDeviceManager('bundleName', (err, value) => {
if (!err) { if (!err) {
devManager = value; devManager = value;
// deviceIds is obtained by deviceManager by calling getTrustedDeviceListSync(). // deviceIds is obtained by deviceManager by calling getTrustedDeviceListSync().
...@@ -219,7 +256,7 @@ The following uses a single KV store as an example to describe the development p ...@@ -219,7 +256,7 @@ The following uses a single KV store as an example to describe the development p
// 1000 indicates that the maximum delay is 1000 ms. // 1000 indicates that the maximum delay is 1000 ms.
kvStore.sync(deviceIds, distributedData.SyncMode.PUSH_ONLY, 1000); kvStore.sync(deviceIds, distributedData.SyncMode.PUSH_ONLY, 1000);
} catch (e) { } catch (e) {
console.log("An unexpected error occurred. Error: " + e); console.log('An unexpected error occurred. Error: ${e}');
} }
} }
}); });
......
# Distributed Data Service Overview # Distributed Data Service Overview
The distributed data service (DDS) implements distributed database collaboration across devices for applications. The distributed data service (DDS) implements distributed database collaboration across devices for applications.
Applications save data to distributed databases by calling the DDS APIs. The DDS isolates data of different applications based on a triplet of account, application, and database to ensure secure data access. The DDS synchronizes application data between trusted devices to provide users with consistent data access experience on different devices. Applications save data to distributed databases by calling the DDS APIs. The DDS isolates data of different applications based on a triplet of account, application, and database to ensure secure data access. The DDS synchronizes application data between trusted devices to provide users with consistent data access experience on different devices.
You do not need to care about the implementation of the database locking mechanism. You do not need to care about the implementation of the database locking mechanism.
## Basic Concepts ## Basic Concepts
- **KV data model** ### KV Data Model
The key-value \(KV\) data model allows data to be organized, indexed, and stored in key-value pairs. The key-value (KV) data model allows data to be organized, indexed, and stored in KV pairs.
The KV data model is suitable for storing service data that is not related. It provides better read and write performance than the SQL database. The KV data model is widely used in distributed scenarios because it handles database version compatibility issues and data synchronization conflicts easily. The distributed database is based on the KV data model and provides KV-based access interfaces. The KV data model is suitable for storing service data that is not related. It provides better read and write performance than the SQL database. The KV data model is widely used in distributed scenarios because it handles database version compatibility issues and data synchronization conflicts easily. The distributed database is based on the KV data model and provides KV-based access interfaces.
- **Distributed database transactions** ### Distributed Database Transaction
Distributed database transactions include local transactions \(same as the transactions of traditional databases\) and synchronization transactions. Synchronization transactions allow data to be synchronized between devices by local transaction. Synchronization of a local transaction modification either succeeds or fails on all the devices. Distributed database transactions include local transactions (same as the transactions of traditional databases) and synchronization transactions. Synchronization transactions allow data to be synchronized between devices by local transaction. Synchronization of a local transaction modification either succeeds or fails on all the devices.
- **Distributed database consistency** ### Distributed Database Consistency
In a distributed scenario, cross-device collaboration demands consistent data between the devices in the same network. The data consistency can be classified into the following types: In a distributed scenario, cross-device collaboration demands consistent data between the devices in the same network. The data consistency can be classified into the following types:
- **Strong consistency**: When data is inserted, deleted, or modified on a device, other devices in the same network will obtain the latest data immediately. - **Strong consistency**: When data is inserted, deleted, or modified on a device, other devices in the same network will obtain the latest data immediately.
- **Weak consistency**: When data is added, deleted, or modified on a device, other devices in the same network may or may not obtain the latest data. The data on these devices may be inconsistent after a certain period of time. - **Weak consistency**: When data is added, deleted, or modified on a device, other devices in the same network may or may not obtain the latest data. The data on these devices may be inconsistent after a certain period of time.
- **Eventual consistency**: When data is added, deleted, or modified on a device, other devices in the same network may not obtain the latest data immediately. However, data on these devices will become consistent after a certain period of time. - **Eventual consistency**: When data is added, deleted, or modified on a device, other devices in the same network may not obtain the latest data immediately. However, data on these devices will become consistent after a certain period of time.
Strong consistency has high requirements on distributed data management and may be used in distributed server deployment. The DDS supports only the eventual consistency because mobile devices are not always online and the network has no center. Strong consistency has high requirements on distributed data management and may be used in distributed server deployment. The DDS supports only the eventual consistency because mobile devices are not always online and the network has no center.
- **Distributed database synchronization** ### Distributed Database Synchronization
After discovering and authenticating a device, the underlying communication component notifies the upper-layer application \(including the DDS\) that the device goes online. The DDS then establishes an encrypted transmission channel to synchronize data between the two devices. After discovering and authenticating a device, the underlying communication component notifies the upper-layer application (including the DDS) that the device goes online. The DDS then establishes an encrypted transmission channel to synchronize data between the two devices.
The DDS provides the following synchronization modes: The DDS provides the following synchronization modes:
- **Manual synchronization**: Applications call **sync** to trigger a synchronization. The list of devices to be synchronized and the synchronization mode must be specified. The synchronization mode can be **PULL\_ONLY** \(pulling remote data to the local end\), **PUSH\_ONLY** \(pushing local data to the remote end\), or **PUSH\_PULL** \(pushing local data to the remote end and pulling remote data to the local end\). The internal interface supports condition-based synchronization. The data that meets the conditions can be synchronized to the remote end. - **Manual synchronization**: Applications call **sync()** to trigger a synchronization. The list of devices to be synchronized and the synchronization mode must be specified. The synchronization mode can be **PULL_ONLY** (pulling remote data to the local end), **PUSH_ONLY** (pushing local data to the remote end), or **PUSH_PULL** (pushing local data to the remote end and pulling remote data to the local end). The internal interface supports condition-based synchronization. The data that meets the conditions can be synchronized to the remote end.
- **Automatic synchronization**: includes full synchronization and condition-based subscription synchronization. In full synchronization, the distributed database automatically pushes local data to the remote end and pulls remote data to the local end when a device goes online or application data is updated. Applications do not need to call **sync**. The internal interface supports condition-based subscription synchronization. The data that meets the subscription conditions on the remote end is automatically synchronized to the local end. - **Automatic synchronization**: includes full synchronization and condition-based subscription synchronization. In full synchronization, the distributed database automatically pushes local data to the remote end and pulls remote data to the local end when a device goes online or application data is updated. Applications do not need to call **sync()**. The internal interface supports condition-based subscription synchronization. The data that meets the subscription conditions on the remote end is automatically synchronized to the local end.
- **Single KV store** ### Single KV Store
Data is saved locally in the unit of a single KV entry. Only one entry is saved for each key. Data can be modified only locally and synchronized to remote devices in sequence based on the update time. Data is saved locally in the unit of a single KV entry. Only one entry is saved for each key. Data can be modified only locally and synchronized to remote devices in sequence based on the update time.
- **Device KV store** ### Device KV Store
The device KV store is based on the single KV store. The local device ID is added to the key when KV data is stored in the device KV store. Data can be isolated, managed, and queried by device. However, the data synchronized from remote devices cannot be modified locally. The device KV store is based on the single KV store. The local device ID is added to the key when KV data is stored in the device KV store. Data can be isolated, managed, and queried by device. However, the data synchronized from remote devices cannot be modified locally.
- **Conflict resolution** ### Conflict Resolution
A data conflict occurs when multiple devices modify the same data and commit the modification to the database. The last write wins \(LWW\) is the default conflict resolution policy used for data conflicts. Based on the commit timestamps, the data with a later timestamp is used. Currently, customized conflict resolution policies are not supported. A data conflict occurs when multiple devices modify the same data and commit the modification to the database. The last write wins (LWW) is the default conflict resolution policy used for data conflicts. Based on the commit timestamps, the data with a later timestamp is used. Currently, customized conflict resolution policies are not supported.
- **Schema-based database management and data query based on predicates** ### Schema-based Database Management and Predicate-based Data Query
A schema is specified when you create or open a single KV store. Based on the schema, the database detects the value format of key-value pairs and checks the value structure. Based on the fields in the values, the database implements index creation and predicate-based query. A schema is specified when you create or open a single KV store. Based on the schema, the database detects the value format of KV pairs and checks the value structure. Based on the fields in the values, the database implements index creation and predicate-based query.
- **Distributed database backup** ### Distributed Database Backup
The DDS provides the database backup capability. You can set **backup** to **true** to enable daily backup. If a distributed database is damaged, the DDS deletes the database and restores the most recent data from the backup database. If no backup database is available, the DDS creates one. The DDS can also back up encrypted databases. The DDS provides the database backup capability. You can set **backup** to **true** to enable daily backup. If a distributed database is damaged, the DDS deletes the database and restores the most recent data from the backup database. If no backup database is available, the DDS creates one. The DDS can also back up encrypted databases.
## Working Principles ## Working Principles
The DDS supports distributed management of application database data in the OpenHarmony system. Data can be synchronized between multiple devices with the same account, delivering a consistent user experience across devices. The DDS consists of the following: The DDS supports distributed management of application database data in the OpenHarmony system. Data can be synchronized between multiple devices with the same account, delivering a consistent user experience across devices.
- **APIs** The DDS consists of the following:
The DDS provides APIs to create databases, access data, and subscribe to data. The APIs support the KV data model and common data types. They are highly compatible and easy to use, and can be released. - **APIs**<br>The DDS provides APIs to create databases, access data, and subscribe to data. The APIs support the KV data model and common data types. They are highly compatible and easy to use, and can be released.
- **Service component** - **Service component**<br>The service component implements management of metadata, permissions, encryption, backup and restore, and multiple users, and completes initialization of the storage component, synchronization component, and communication adaptation layer of the distributed database.
The service component implements management of metadata, permissions, encryption, backup and restore, and multiple users, and completes initialization of the storage component, synchronization component, and communication adaptation layer of the distributed database. - **Storage component**<br>The storage component implements data access, data reduction, transactions, snapshots, database encryption, data combination, and conflict resolution.
- **Storage component** - **Synchronization component**<br>The synchronization component interacts with the storage component and the communication adaptation layer to maintain data consistency between online devices. It synchronizes data generated on the local device to other devices and merges data from other devices into the local device.
The storage component implements data access, data reduction, transactions, snapshots, database encryption, data combination, and conflict resolution. - **Communication adaptation layer**<br>The communication adaptation layer calls APIs of the underlying public communication layer to create and connect to communication channels, receive device online and offline messages, update metadata of the connected and disconnected devices, send device online and offline messages to the synchronization component. The synchronization component updates the list of connected devices, and calls the APIs of the communication adaption layer to encapsulate data and send the data to the connected devices.
- **Synchronization component** Applications call the DDS APIs to create, access, and subscribe to distributed databases. The APIs store data to the storage component based on the capabilities provided by the service component. The storage component interacts with the synchronization component to synchronize data. The synchronization component uses the communication adaptation layer to synchronize data to remote devices, which update the data in the storage component and provide the data for applications through service APIs.
The synchronization component interacts with the storage component and the communication adaptation layer to maintain data consistency between online devices. It synchronizes data generated on the local device to other devices and merges data from other devices into the local device.
- **Communication adaptation layer** **Figure 1** How DDS works
The communication adaptation layer calls APIs of the underlying public communication layer to create and connect to communication channels, receive device online and offline messages, update metadata of the connected and disconnected devices, send device online and offline messages to the synchronization component. The synchronization component updates the list of connected devices, and calls the APIs of the communication adaption layer to encapsulate data and send the data to the connected devices.
![](figures/en-us_image_0000001183386164.png)
Applications call the DDS APIs to create, access, and subscribe to distributed databases. The APIs store data to the storage component based on the capabilities provided by the service component. The storage component interacts with the synchronization component to synchronize data. The synchronization component uses the communication adaptation layer to synchronize data to remote devices, which update the data in the storage component and provide the data for applications through service APIs.
**Figure 1** How DDS works<a name="fig9151258063"></a> ## Constraints
- The DDS supports the KV data model only. It does not support foreign keys or triggers of the relational database.
![](figures/en-us_image_0000001183386164.png) - The KV data model specifications supported by the DDS are as follows:
## Constraints - For each record in a device KV store, the key must be less than or equal to 896 bytes and the value be less than 4 MB.
- For each record in a single KV store, the key must be less than or equal to 1 KB and the value be less than 4 MB.
- An application can open a maximum of 16 KV stores simultaneously.
- The data that needs to be synchronized between devices should be stored in distributed databases rather than local databases.
- The DDS supports the KV data model only. It does not support foreign keys or triggers of the relational database. - The DDS does not support customized conflict resolution policies.
- The KV data model specifications supported by the DDS are as follows:
- For each record in a device KV store, the key must be less than or equal to 896 bytes and the value be less than 4 MB.
- For each record in a single KV store, the key must be less than or equal to 1 KB and the value be less than 4 MB.
- An application can open a maximum of 16 KV stores simultaneously.
- The data that needs to be synchronized between devices should be stored in distributed databases rather than local databases. - The maximum number of access requests to the KvStore API is 1000 per second and 10000 per minute. The maximum number of access requests to the KvManager API is 50 per second and 500 per minute.
- The DDS does not support customized conflict resolution policies.
- The maximum number of access requests to the KvStore API is 1000 per second and 10000 per minute. The maximum number of access requests to the KvManager API is 50 per second and 500 per minute.
- Blocking operations, such as modifying UI components, are not allowed in the distributed database event callback.
- Blocking operations, such as modifying UI components, are not allowed in the distributed database event callback.
...@@ -88,15 +88,22 @@ Use the following APIs to delete a **Preferences** instance or data file. ...@@ -88,15 +88,22 @@ Use the following APIs to delete a **Preferences** instance or data file.
2. Obtain a **Preferences** instance. 2. Obtain a **Preferences** instance.
Read the specified file and load its data to the **Preferences** instance for data operations. Read the specified file and load its data to the **Preferences** instance for data operations.
FA model: FA model:
```js ```js
// Obtain the context. // Obtain the context.
import featureAbility from '@ohos.ability.featureAbility' import featureAbility from '@ohos.ability.featureAbility'
var context = featureAbility.getContext() let context = featureAbility.getContext();
let preferences = null;
let promise = data_preferences.getPreferences(context, 'mystore'); let promise = data_preferences.getPreferences(context, 'mystore');
promise.then((pref) => {
preferences = pref;
}).catch((err) => {
console.info("Failed to get the preferences.");
})
``` ```
Stage model: Stage model:
...@@ -104,14 +111,21 @@ Use the following APIs to delete a **Preferences** instance or data file. ...@@ -104,14 +111,21 @@ Use the following APIs to delete a **Preferences** instance or data file.
```ts ```ts
// Obtain the context. // Obtain the context.
import Ability from '@ohos.application.Ability' import Ability from '@ohos.application.Ability'
var context let context = null;
class MainAbility extends Ability{ let preferences = null;
export default class MainAbility extends Ability {
onWindowStageCreate(windowStage){ onWindowStageCreate(windowStage){
context = this.context context = this.context;
} }
} }
let promise = data_preferences.getPreferences(context, 'mystore'); let promise = data_preferences.getPreferences(context, 'mystore');
promise.then((pref) => {
preferences = pref;
}).catch((err) => {
console.info("Failed to get the preferences.");
})
``` ```
3. Write data. 3. Write data.
...@@ -119,35 +133,27 @@ Use the following APIs to delete a **Preferences** instance or data file. ...@@ -119,35 +133,27 @@ Use the following APIs to delete a **Preferences** instance or data file.
Use the **preferences.put()** method to write data to the **Preferences** instance. Use the **preferences.put()** method to write data to the **Preferences** instance.
```js ```js
promise.then((preferences) => { let putPromise = preferences.put('startup', 'auto');
let putPromise = preferences.put('startup', 'auto'); putPromise.then(() => {
putPromise.then(() => { console.info("Put the value of 'startup' successfully.");
console.info("Put the value of 'startup' successfully.");
}).catch((err) => {
console.info("Failed to put the value of 'startup'. Cause: " + err);
})
}).catch((err) => { }).catch((err) => {
console.info("Failed to get the preferences."); console.info("Failed to put the value of 'startup'. Cause: " + err);
}) })
``` ```
4. Read data. 4. Read data.
Use the **preferences.get()** method to read data. Use the **preferences.get()** method to read data.
```js ```js
promise.then((preferences) => { let getPromise = preferences.get('startup', 'default');
let getPromise = preferences.get('startup', 'default'); getPromise.then((value) => {
getPromise.then((value) => {
console.info("The value of 'startup' is " + value); console.info("The value of 'startup' is " + value);
}).catch((err) => {
console.info("Failed to get the value of 'startup'. Cause: " + err);
})
}).catch((err) => { }).catch((err) => {
console.info("Failed to get the preferences.") console.info("Failed to get the value of 'startup'. Cause: " + err);
}); })
``` ```
5. Store data persistently. 5. Store data persistently.
Use the **flush()** method to flush data from the **Preferences** instance to its file. Use the **flush()** method to flush data from the **Preferences** instance to its file.
...@@ -161,11 +167,12 @@ Use the following APIs to delete a **Preferences** instance or data file. ...@@ -161,11 +167,12 @@ Use the following APIs to delete a **Preferences** instance or data file.
Specify an observer as the callback to subscribe to data changes for an application. When the value of the subscribed key is changed and saved by **flush()**, the observer callback will be invoked to return the new data. Specify an observer as the callback to subscribe to data changes for an application. When the value of the subscribed key is changed and saved by **flush()**, the observer callback will be invoked to return the new data.
```js ```js
var observer = function (key) { let observer = function (key) {
console.info("The key" + key + " changed."); console.info("The key" + key + " changed.");
} }
preferences.on('change', observer); preferences.on('change', observer);
preferences.put('startup', 'auto', function (err) { // The data is changed from 'auto' to 'manual'.
preferences.put('startup', 'manual', function (err) {
if (err) { if (err) {
console.info("Failed to put the value of 'startup'. Cause: " + err); console.info("Failed to put the value of 'startup'. Cause: " + err);
return; return;
......
...@@ -140,7 +140,7 @@ You can obtain the distributed table name for a remote device based on the local ...@@ -140,7 +140,7 @@ You can obtain the distributed table name for a remote device based on the local
| Class | API | Description | | Class | API | Description |
| -------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | -------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| RdbStore | sync(mode: SyncMode, predicates: RdbPredicates): Promise\<Array\<[string, number]>> | Synchronizes data between devices. This API uses a promise to return the result.<br>- **mode**: synchronization mode. **SYNC_MODE_PUSH** means to push data from the local device to a remote device. **SYNC_MODE_PULL** means to pull data from a remote device to the local device.<br>- **predicates**: specifies the data and devices to synchronize.<br>- **string**: device ID. <br>- **number**: synchronization status of that device. The value **0** indicates a successful synchronization. Other values indicate a synchronization failure.| | RdbStore | sync(mode: SyncMode, predicates: RdbPredicates): Promise\<Array\<[string, number]>> | Synchronizes data between devices. This API uses a promise to return the result.<br>- **mode**: synchronization mode. **SYNC_MODE_PUSH** means to push data from the local device to a remote device. **SYNC_MODE_PULL** means to pull data from a remote device to the local device.<br>- **predicates**: specifies the data and devices to synchronize.<br>- **string**: device ID. <br>- **number**: synchronization status of each device. The value **0** indicates a successful synchronization. Other values indicate a synchronization failure.|
**Registering an RDB Store Observer** **Registering an RDB Store Observer**
...@@ -196,17 +196,41 @@ Table 15 Transaction APIs ...@@ -196,17 +196,41 @@ Table 15 Transaction APIs
(3) Create an RDB store. (3) Create an RDB store.
The sample code is as follows: FA model:
```js ```js
import data_rdb from '@ohos.data.rdb' import data_rdb from '@ohos.data.rdb'
// Obtain the context.
import featureAbility from '@ohos.ability.featureAbility'
let context = featureAbility.getContext()
const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)";
const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; const STORE_CONFIG = { name: "RdbTest.db" }
const STORE_CONFIG = { name: "rdbstore.db" } data_rdb.getRdbStore(context, STORE_CONFIG, 1, function (err, rdbStore) {
data_rdb.getRdbStore(this.context, STORE_CONFIG, 1, function (err, rdbStore) {
rdbStore.executeSql(CREATE_TABLE_TEST) rdbStore.executeSql(CREATE_TABLE_TEST)
console.info('create table done.') console.info('create table done.')
}) })
```
Stage model:
```ts
import data_rdb from '@ohos.data.rdb'
// Obtain the context.
import Ability from '@ohos.application.Ability'
let context = null
class MainAbility extends Ability {
onWindowStageCreate(windowStage) {
context = this.context
}
}
const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)";
const STORE_CONFIG = { name: "rdbstore.db" }
data_rdb.getRdbStore(context, STORE_CONFIG, 1, function (err, rdbStore) {
rdbStore.executeSql(CREATE_TABLE_TEST)
console.info('create table done.')
})
``` ```
2. Insert data. 2. Insert data.
......
...@@ -22,15 +22,16 @@ import stats from '@ohos.bundleState'; ...@@ -22,15 +22,16 @@ import stats from '@ohos.bundleState';
| function queryAppUsagePriorityGroup(callback: AsyncCallback&lt;number&gt;): void | Queries the priority group of this application. This API uses an asynchronous callback to return the result.| | function queryAppUsagePriorityGroup(callback: AsyncCallback&lt;number&gt;): void | Queries the priority group of this application. This API uses an asynchronous callback to return the result.|
| function queryAppUsagePriorityGroup(): Promise&lt;number&gt;; | Queries the priority group of this application. This API uses a promise to return the result.| | function queryAppUsagePriorityGroup(): Promise&lt;number&gt;; | Queries the priority group of this application. This API uses a promise to return the result.|
| function isIdleState(bundleName: string, callback: AsyncCallback&lt;boolean&gt;): void | Checks whether the application specified by **bundleName** is in the idle state. | | function isIdleState(bundleName: string, callback: AsyncCallback&lt;boolean&gt;): void | Checks whether the application specified by **bundleName** is in the idle state. |
| function getRecentlyUsedModules(maxNum? : number, callback: AsyncCallback&lt;BundleActiveModuleInfo&gt;): void | Obtains the number of FA usage records specified by **maxNum**. If **maxNum** is not specified, the default value **1000** is used.| | function getRecentlyUsedModules(callback: AsyncCallback&lt;BundleActiveModuleInfo&gt;): void | Obtains a maximum of 1000 FA usage records. |
| function getRecentlyUsedModules(maxNum: number, callback: AsyncCallback&lt;BundleActiveModuleInfo&gt;): void | Obtains the number of FA usage records specified by **maxNum**, which cannot exceed 1000.|
| function queryAppNotificationNumber(begin: number, end: number, callback: AsyncCallback&lt;Array&lt;BundleActiveEventState&gt;&gt;): void | Queries the number of notifications from all applications based on the specified start time and end time.| | function queryAppNotificationNumber(begin: number, end: number, callback: AsyncCallback&lt;Array&lt;BundleActiveEventState&gt;&gt;): void | Queries the number of notifications from all applications based on the specified start time and end time.|
| function queryBundleActiveEventStates(begin: number, end: number, callback: AsyncCallback&lt;Array&lt;BundleActiveEventState&gt;&gt;): void | Queries statistics about system events (hibernation, wakeup, unlocking, and screen locking) that occur between the specified start time and end time.| | function queryBundleActiveEventStates(begin: number, end: number, callback: AsyncCallback&lt;Array&lt;BundleActiveEventState&gt;&gt;): void | Queries statistics about system events (hibernation, wakeup, unlocking, and screen locking) that occur between the specified start time and end time.|
| function queryAppUsagePriorityGroup(bundleName? : string, callback: AsyncCallback&lt;number&gt;): void | Queries the priority group of the application specified by **bundleName**. If **bundleName** is not specified, the priority group of the current application is queried. This API uses an asynchronous callback to return the result.| | function queryAppUsagePriorityGroup(bundleName : string, callback: AsyncCallback&lt;number&gt;): void | Queries the priority group of the application specified by **bundleName**. This API uses an asynchronous callback to return the result.|
| function queryAppUsagePriorityGroup(bundleName? : string): Promise&lt;number&gt;; | Queries the priority group of the application specified by **bundleName**. If **bundleName** is not specified, the priority group of the current application is queried. This API uses a promise to return the result.| | function queryAppUsagePriorityGroup(bundleName? : string): Promise&lt;number&gt;; | Queries the priority group of the application specified by **bundleName**. If **bundleName** is not specified, the priority group of the current application is queried. This API uses a promise to return the result.|
| function setBundleGroup(bundleName : string, newGroup: GroupType, callback: AsyncCallback&gt;boolean&gt;): void | Sets the group for the application specified by **bundleName**. This API uses an asynchronous callback to return the result.| | function setBundleGroup(bundleName : string, newGroup: GroupType, callback: AsyncCallback&gt;boolean&gt;): void | Sets the group for the application specified by **bundleName**. This API uses an asynchronous callback to return the result.|
| function setBundleGroup(bundleName : string, newGroup : GroupType): Promise&gt;boolean&gt;; | Sets the group for the application specified by **bundleName**. This API uses a promise to return the result.| | function setBundleGroup(bundleName : string, newGroup : GroupType): Promise&gt;boolean&gt;; | Sets the group for the application specified by **bundleName**. This API uses a promise to return the result.|
| function registerGroupCallBack(callback: Callback&gt;BundleActiveGroupCallbackInfo&gt;, callback: AsyncCallback&gt;boolean&gt;): void | Registers a callback for application group changes. When an application group of the user changes, the change is returned to all applications that have registered the callback. This API uses an asynchronous callback to return the result.| | function registerGroupCallBack(groupCallback: Callback&gt;BundleActiveGroupCallbackInfo&gt;, callback: AsyncCallback&gt;boolean&gt;): void | Registers a callback for application group changes. When an application group of the user changes, the change is returned to all applications that have registered the callback. This API uses an asynchronous callback to return the result.|
| function registerGroupCallBack(callback: Callback&gt;BundleActiveGroupCallbackInfo&gt;): Promise&gt;boolean&gt;; | Registers a callback for application group changes. When an application group of the user changes, the change is returned to all applications that have registered the callback. This API uses a promise to return the result.| | function registerGroupCallBack(groupCallback: Callback&gt;BundleActiveGroupCallbackInfo&gt;): Promise&gt;boolean&gt;; | Registers a callback for application group changes. When an application group of the user changes, the change is returned to all applications that have registered the callback. This API uses a promise to return the result.|
| function unRegisterGroupCallBack(callback: AsyncCallback&gt;boolean&gt;): void | Deregisters the callback for application group changes. This API uses an asynchronous callback to return the result.| | function unRegisterGroupCallBack(callback: AsyncCallback&gt;boolean&gt;): void | Deregisters the callback for application group changes. This API uses an asynchronous callback to return the result.|
| function unRegisterGroupCallBack(): Promise&gt;boolean&gt;; | Deregisters the callback for application group changes. This API uses a promise to return the result.| | function unRegisterGroupCallBack(): Promise&gt;boolean&gt;; | Deregisters the callback for application group changes. This API uses a promise to return the result.|
...@@ -325,14 +326,14 @@ import stats from '@ohos.bundleState'; ...@@ -325,14 +326,14 @@ import stats from '@ohos.bundleState';
```js ```js
import stats from '@ohos.bundleState' import stats from '@ohos.bundleState'
// Promise mode without parameters // Promise mode when bundleName is not specified
stats.queryAppUsagePriorityGroup().then(res => { stats.queryAppUsagePriorityGroup().then(res => {
console.log('BUNDLE_ACTIVE queryAppUsagePriorityGroup promise succeeded. result: ' + JSON.stringify(res)); console.log('BUNDLE_ACTIVE queryAppUsagePriorityGroup promise succeeded. result: ' + JSON.stringify(res));
}).catch(err => { }).catch(err => {
console.log('BUNDLE_ACTIVE queryAppUsagePriorityGroup promise failed. because: ' + err.code); console.log('BUNDLE_ACTIVE queryAppUsagePriorityGroup promise failed. because: ' + err.code);
}); });
// Asynchronous callback mode without parameters // Asynchronous callback mode when bundleName is not specified
stats.queryAppUsagePriorityGroup((err, res) => { stats.queryAppUsagePriorityGroup((err, res) => {
if (err) { if (err) {
console.log('BUNDLE_ACTIVE queryAppUsagePriorityGroup callback failed. because: ' + err.code); console.log('BUNDLE_ACTIVE queryAppUsagePriorityGroup callback failed. because: ' + err.code);
...@@ -340,16 +341,16 @@ import stats from '@ohos.bundleState'; ...@@ -340,16 +341,16 @@ import stats from '@ohos.bundleState';
console.log('BUNDLE_ACTIVE queryAppUsagePriorityGroup callback succeeded. result: ' + JSON.stringify(res)); console.log('BUNDLE_ACTIVE queryAppUsagePriorityGroup callback succeeded. result: ' + JSON.stringify(res));
} }
}); });
let bundleName = "com.ohos.camera";
// Promise mode with parameters // Promise mode when bundleName is specified
stats.queryAppUsagePriorityGroup(this.bundleName).then(res => { stats.queryAppUsagePriorityGroup(bundleName).then(res => {
console.log('BUNDLE_ACTIVE QueryPackageGroup promise succeeded. result: ' + JSON.stringify(res)); console.log('BUNDLE_ACTIVE QueryPackageGroup promise succeeded. result: ' + JSON.stringify(res));
}).catch(err => { }).catch(err => {
console.log('BUNDLE_ACTIVE QueryPackageGroup promise failed. because: ' + err.code); console.log('BUNDLE_ACTIVE QueryPackageGroup promise failed. because: ' + err.code);
}); });
// Asynchronous callback mode with parameters // Asynchronous callback mode when bundleName is specified
stats.queryAppUsagePriorityGroup(this.bundleName, (err, res) => { stats.queryAppUsagePriorityGroup(bundleName, (err, res) => {
if (err) { if (err) {
console.log('BUNDLE_ACTIVE QueryPackageGroup callback failed. because: ' + err.code); console.log('BUNDLE_ACTIVE QueryPackageGroup callback failed. because: ' + err.code);
} else { } else {
...@@ -436,3 +437,4 @@ import stats from '@ohos.bundleState'; ...@@ -436,3 +437,4 @@ import stats from '@ohos.bundleState';
} }
}); });
``` ```
...@@ -66,25 +66,7 @@ To learn more about the APIs for obtaining device location information, see [Geo ...@@ -66,25 +66,7 @@ To learn more about the APIs for obtaining device location information, see [Geo
If your application needs to access the device location information when running on the background, it must be configured to be able to run on the background and be granted the **ohos.permission.LOCATION_IN_BACKGROUND** permission. In this way, the system continues to report device location information after your application moves to the background. If your application needs to access the device location information when running on the background, it must be configured to be able to run on the background and be granted the **ohos.permission.LOCATION_IN_BACKGROUND** permission. In this way, the system continues to report device location information after your application moves to the background.
To allow your application to access device location information, declare the required permissions in the **module.json** file of your application. The sample code is as follows: You can declare the required permission in your application's configuration file. For details, see [Access Control (Permission) Development](../security/accesstoken-guidelines.md).
```
{
"module": {
"reqPermissions": [
"name": "ohos.permission.LOCATION",
"reason": "$string:reason_description",
"usedScene": {
"ability": ["com.myapplication.LocationAbility"],
"when": "inuse"
}
]
}
}
```
For details about these fields, see [Application Package Structure Configuration File](../quick-start/stage-structure.md).
2. Import the **geolocation** module by which you can implement all APIs related to the basic location capabilities. 2. Import the **geolocation** module by which you can implement all APIs related to the basic location capabilities.
......
...@@ -15,15 +15,18 @@ Your application can call location-specific APIs to obtain the location informat ...@@ -15,15 +15,18 @@ Your application can call location-specific APIs to obtain the location informat
Location awareness helps determine where a mobile device locates. The system identifies the location of a mobile device with its coordinates, and uses location technologies such as Global Navigation Satellite System (GNSS) and network positioning (for example, base station positioning or WLAN/Bluetooth positioning) to provide diverse location-based services. These advanced location technologies make it possible to obtain the accurate location of the mobile device, regardless of whether it is indoors or outdoors. Location awareness helps determine where a mobile device locates. The system identifies the location of a mobile device with its coordinates, and uses location technologies such as Global Navigation Satellite System (GNSS) and network positioning (for example, base station positioning or WLAN/Bluetooth positioning) to provide diverse location-based services. These advanced location technologies make it possible to obtain the accurate location of the mobile device, regardless of whether it is indoors or outdoors.
- **Coordinate** - **Coordinate**
A coordinate describes a location on the earth using the longitude and latitude in reference to the World Geodetic Coordinate System 1984. A coordinate describes a location on the earth using the longitude and latitude in reference to the World Geodetic Coordinate System 1984.
- **GNSS positioning** - **GNSS positioning**
GNSS positioning locates a mobile device by using the location algorithm offered by the device chip to compute the location information provided by the Global Navigation Satellite System, for example, GPS, GLONASS, BeiDou, and Galileo. Whichever positioning system will be used during the location process depends on a hardware capability of the device. GNSS positioning locates a mobile device by using the location algorithm offered by the device chip to compute the location information provided by the Global Navigation Satellite System, for example, GPS, GLONASS, BeiDou, and Galileo. Whichever positioning system will be used during the location process depends on a hardware capability of the device.
- **Base station positioning** - **Base station positioning**
Base station positioning estimates the current location of a mobile device based on the location of the resident base station in reference to the neighboring base stations. This technology provides only a low accuracy and requires access to the cellular network. Base station positioning estimates the current location of a mobile device based on the location of the resident base station in reference to the neighboring base stations. This technology provides only a low accuracy and requires access to the cellular network.
- **WLAN or Bluetooth positioning** - **WLAN or Bluetooth positioning**
WLAN or Bluetooth positioning estimates the current location of a mobile device based on the locations of WLANs and Bluetooth devices that can be discovered by the device. The location accuracy of this technology depends on the distribution of fixed WLAN access points (APs) and Bluetooth devices around the device. A high density of WLAN APs and Bluetooth devices can produce a more accurate location result than base station positioning. This technology also requires access to the network. WLAN or Bluetooth positioning estimates the current location of a mobile device based on the locations of WLANs and Bluetooth devices that can be discovered by the device. The location accuracy of this technology depends on the distribution of fixed WLAN access points (APs) and Bluetooth devices around the device. A high density of WLAN APs and Bluetooth devices can produce a more accurate location result than base station positioning. This technology also requires access to the network.
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
## When to Use ## 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. 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 functional verification for secondary development, building an end-to-end environment to cater for diverse update service use cases.
## How to Develop ## How to Develop
...@@ -14,8 +14,6 @@ The sample server provides a package search server for checking update packages ...@@ -14,8 +14,6 @@ The sample server provides a package search server for checking update packages
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" 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. 2. Modify the **bundle.json** file.
Add **sub_component** to the **build** field. Add **sub_component** to the **build** field.
...@@ -32,13 +30,13 @@ The sample server provides a package search server for checking update packages ...@@ -32,13 +30,13 @@ The sample server provides a package search server for checking update packages
Go to the **update_updateservice** directory and run the following commands to 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. mkdir server_sample // Create the server_sample folder.
touch server_sample/BUILD.gn // Create the BUILD.gn file. 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. 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. 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. 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/server_process.c // Create the server_process.c file.
touch server_sample/src/main.cpp // Create the main.cpp file. touch server_sample/src/main.cpp // Create the main.cpp file.
``` ```
4. Write the **BUILD.gn** file. 4. Write the **BUILD.gn** file.
......
...@@ -26,70 +26,30 @@ ...@@ -26,70 +26,30 @@
| -------- | -------- | -------- | | -------- | -------- | -------- |
| ohos.sensor | sensor.on(sensorType, callback:AsyncCallback&lt;Response&gt;): void | Subscribes to data changes of a type of sensor.| | ohos.sensor | sensor.on(sensorType, callback:AsyncCallback&lt;Response&gt;): void | Subscribes to data changes of a type of sensor.|
| ohos.sensor | sensor.once(sensorType, callback:AsyncCallback&lt;Response&gt;): void | Subscribes to only one data change of a type of sensor.| | ohos.sensor | sensor.once(sensorType, callback:AsyncCallback&lt;Response&gt;): void | Subscribes to only one data change of a type of sensor.|
| ohos.sensor | sensor.off(sensorType, callback:AsyncCallback&lt;void&gt;): void | Unsubscribes from sensor data changes.| | ohos.sensor | sensor.off(sensorType, callback?:AsyncCallback&lt;void&gt;): void | Unsubscribes from sensor data changes.|
## How to Develop ## How to Develop
1. To obtain data from a type of sensor, configure the requested permissions in the **config.json** file. 1. Before obtaining data from a type of sensor, check whether the required permission has been configured.<br>
The system provides the following sensor-related permissions:
``` - ohos.permission.ACCELEROMETER
"reqPermissions": [
{ - ohos.permission.GYROSCOPE
"name": "ohos.permission.ACCELEROMETER",
"reason": "", - ohos.permission.ACTIVITY_MOTION
"usedScene": {
"ability": [ - ohos.permission.READ_HEALTH_DATA
"sensor.index.MainAbility",
".MainAbility" For details about how to configure a permission, see [Declaring Permissions](../security/accesstoken-guidelines.md).
],
"when": "inuse"
}
},
{
"name": "ohos.permission.GYROSCOPE",
"reason": "",
"usedScene": {
"ability": [
"sensor.index.MainAbility",
".MainAbility"
],
"when": "inuse"
}
},
{
"name": "ohos.permission.ACTIVITY_MOTION",
"reason": "ACTIVITY_MOTION_TEST",
"usedScene": {
"ability": [
"sensor.index.MainAbility",
".MainAbility"
],
"when": "inuse"
}
},
{
"name": "ohos.permission.READ_HEALTH_DATA",
"reason": "HEALTH_DATA_TEST",
"usedScene": {
"ability": [
"sensor.index.MainAbility",
".MainAbility"
],
"when": "inuse"
}
}
]
```
2. Subscribe to data changes of a type of sensor. 2. Subscribe to data changes of a type of sensor.
``` ```
import sensor from "@ohos.sensor" import sensor from "@ohos.sensor";
sensor.on(sensor.sensorType.SENSOR_TYPE_ACCELEROMETER,function(data){ sensor.on(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function(data){
console.info("Subscription succeeded. data = " + data); // The call is successful, and the obtained sensor data is printed. console.info("Data obtained successfully. x: " + data.x + "y: " + data.y + "z: " + data.z); // Data is obtained.
} });
);
``` ```
The following figure shows the successful call result when **SensorType** is **SENSOR_TYPE_ID_ACCELEROMETER**. The following figure shows the successful call result when **SensorType** is **SENSOR_TYPE_ID_ACCELEROMETER**.
...@@ -99,11 +59,8 @@ ...@@ -99,11 +59,8 @@
3. Unsubscribe from sensor data changes. 3. Unsubscribe from sensor data changes.
``` ```
import sensor from "@ohos.sensor" import sensor from "@ohos.sensor";
sensor.off(sensor.sensorType.SENSOR_TYPE_ACCELEROMETER,function() { sensor.off(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER);
console.info("Succeeded in unsubscribing from acceleration sensor data."); // The unsubscription is successful, and the result is printed.
}
);
``` ```
The following figure shows the successful call result when **SensorType** is **SENSOR_TYPE_ID_ACCELEROMETER**. The following figure shows the successful call result when **SensorType** is **SENSOR_TYPE_ID_ACCELEROMETER**.
...@@ -113,11 +70,10 @@ ...@@ -113,11 +70,10 @@
4. Subscribe to only one data change of a type of sensor. 4. Subscribe to only one data change of a type of sensor.
``` ```
import sensor from "@ohos.sensor" import sensor from "@ohos.sensor";
sensor.once(sensor.sensorType.SENSOR_TYPE_ACCELEROMETER,function(data) { sensor.once(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function(data) {
console.info("Data obtained successfully. data=" + data); // The call is successful, and the obtained sensor data is printed. console.info("Data obtained successfully. x: " + data.x + "y: " + data.y + "z: " + data.z); // Data is obtained.
} });
);
``` ```
The following figure shows the successful call result when **SensorType** is **SENSOR_TYPE_ID_ACCELEROMETER**. The following figure shows the successful call result when **SensorType** is **SENSOR_TYPE_ID_ACCELEROMETER**.
...@@ -127,11 +83,12 @@ ...@@ -127,11 +83,12 @@
If the API fails to be called, you are advised to use the **try/catch** statement to capture error information that may occur in the code. Example: If the API fails to be called, you are advised to use the **try/catch** statement to capture error information that may occur in the code. Example:
``` ```
import sensor from "@ohos.sensor";
try { try {
sensor.once(sensor.sensorType.SENSOR_TYPE_ACCELEROMETER,function(data) { sensor.once(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function(data) {
console.info("Data obtained successfully. data=" + data); // The call is successful, and the obtained sensor data is printed. console.info("Data obtained successfully. x: " + data.x + "y: " + data.y + "z: " + data.z); // Data is obtained.
}); });
} catch (error) { } catch (error) {
console.error(error); console.error("Failed to get sensor data");
} }
``` ```
\ No newline at end of file
...@@ -52,15 +52,12 @@ The following modules work cooperatively to implement OpenHarmony sensors: Senso ...@@ -52,15 +52,12 @@ The following modules work cooperatively to implement OpenHarmony sensors: Senso
1. To obtain data of the following sensors, you must claim the required permissions. 1. To obtain data of the following sensors, you must claim the required permissions.
Table 7 Sensor data permissions | Sensor | Permission | Sensitivity | Permission Description |
| ------------------------- | -------------------------------- | ------------ | ----------------------- |
| Sensor | Permission | Sensitivity | Permission Description | | Acceleration sensor, uncalibrated acceleration sensor, and linear acceleration sensor| ohos.permission.ACCELEROMETER | system_grant | Allows an application to subscribe to data of these acceleration-related sensors in the motion category.|
| ------------------------- | -------------------------------- | ------------ | ----------------------- | | Gyroscope sensor and uncalibrated gyroscope sensor | ohos.permission.GYROSCOPE | system_grant | Allows an application to subscribe to data of the gyroscope-related sensors in the motion category.|
| Acceleration sensor, uncalibrated acceleration sensor, and linear acceleration sensor| ohos.permission.ACCELEROMETER | system_grant | Allows an application to subscribe to data of these acceleration-related sensors in the motion category.| | Pedometer sensor | ohos.permission.ACTIVITY_MOTION | user_grant | Allows an application to subscribe to the motion status. |
| Gyroscope sensor and uncalibrated gyroscope sensor | ohos.permission.GYROSCOPE | system_grant | Allows an application to subscribe to data of the gyroscope-related sensors in the motion category.| | Heart rate sensor | ohos.permission.READ_HEALTH_DATA | user_grant | Allows an application to read health data. |
| Pedometer sensor | ohos.permission.ACTIVITY_MOTION | user_grant | Allows an application to subscribe to the motion status. |
| Heart rate sensor | ohos.permission.READ_HEALTH_DATA | user_grant | Allows an application to read health data. |
2. The APIs for subscribing to and unsubscribing from sensor data work in pairs. If you do not need sensor data, call the unsubscription API to stop sensor data reporting. 2. The APIs for subscribing to and unsubscribing from sensor data work in pairs. If you do not need sensor data, call the unsubscription API to stop sensor data reporting.
...@@ -38,7 +38,7 @@ You can set a USB device as the USB host to connect to other USB devices for dat ...@@ -38,7 +38,7 @@ You can set a USB device as the USB host to connect to other USB devices for dat
// Import the USB API package. // Import the USB API package.
import usb from '@ohos.usb'; import usb from '@ohos.usb';
// Obtain the USB device list. // Obtain the USB device list.
var deviceList = usb.getDevices(); let deviceList = usb.getDevices();
/* /*
Example deviceList structure Example deviceList structure
[ [
...@@ -81,21 +81,21 @@ You can set a USB device as the USB host to connect to other USB devices for dat ...@@ -81,21 +81,21 @@ You can set a USB device as the USB host to connect to other USB devices for dat
number: 1, number: 1,
type: 3, type: 3,
interfaceId: 0, interfaceId: 0,
}, }
], ]
}, }
], ]
}, }
], ]
}, }
], ]
*/ */
``` ```
2. Obtain the device operation permissions. 2. Obtain the device operation permissions.
```js ```js
var deviceName = deviceList[0].name; let deviceName = deviceList[0].name;
// Request the permissions to operate a specified device. // Request the permissions to operate a specified device.
usb.requestRight(deviceName).then(hasRight => { usb.requestRight(deviceName).then(hasRight => {
console.info("usb device request right result: " + hasRight); console.info("usb device request right result: " + hasRight);
...@@ -108,7 +108,7 @@ You can set a USB device as the USB host to connect to other USB devices for dat ...@@ -108,7 +108,7 @@ You can set a USB device as the USB host to connect to other USB devices for dat
```js ```js
// Open the device, and obtain the USB device pipe for data transfer. // Open the device, and obtain the USB device pipe for data transfer.
var pipe = usb.connectDevice(deviceList[0]); let pipe = usb.connectDevice(deviceList[0]);
/* /*
Claim the corresponding interface from deviceList. Claim the corresponding interface from deviceList.
interface1 must be one present in the device configuration. interface1 must be one present in the device configuration.
...@@ -127,7 +127,7 @@ You can set a USB device as the USB host to connect to other USB devices for dat ...@@ -127,7 +127,7 @@ You can set a USB device as the USB host to connect to other USB devices for dat
usb.bulkTransfer(pipe, inEndpoint, dataUint8Array, 15000).then(dataLength => { usb.bulkTransfer(pipe, inEndpoint, dataUint8Array, 15000).then(dataLength => {
if (dataLength >= 0) { if (dataLength >= 0) {
console.info("usb readData result Length : " + dataLength); console.info("usb readData result Length : " + dataLength);
var resultStr = this.ab2str(dataUint8Array); // Convert uint8 data into a string. let resultStr = this.ab2str(dataUint8Array); // Convert uint8 data into a string.
console.info("usb readData buffer : " + resultStr); console.info("usb readData buffer : " + resultStr);
} else { } else {
console.info("usb readData failed : " + dataLength); console.info("usb readData failed : " + dataLength);
......
...@@ -22,42 +22,7 @@ For details about the APIs, see [Vibrator](../reference/apis/js-apis-vibrator.md ...@@ -22,42 +22,7 @@ For details about the APIs, see [Vibrator](../reference/apis/js-apis-vibrator.md
## How to Develop ## How to Develop
1. Declare the permissions required for controlling vibrators on the hardware device in the `config.json` file. 1. Before using the vibrator on a device, you must declare the **ohos.permission.VIBRATE** permission. For details about how to configure a permission, see [Declaring Permissions](../security/accesstoken-guidelines.md).
```
"reqPermissions": [
{
"name": "ohos.permission.ACCELEROMETER",
"reason": "",
"usedScene": {
"ability": [
".MainAbility"
],
"when": "inuse"
}
},
{
"name": "ohos.permission.VIBRATE",
"reason": "",
"usedScene": {
"ability": [
".MainAbility"
],
"when": "inuse"
}
},
{
"name": "ohos.permission.ACTIVITY_MOTION",
"reason": "",
"usedScene": {
"ability": [
".MainAbility"
],
"when": "inuse"
}
}
]
```
2. Trigger the device to vibrate. 2. Trigger the device to vibrate.
......
...@@ -23,4 +23,4 @@ The vibrator is a Misc device that consists of four modules: Vibrator API, Vibra ...@@ -23,4 +23,4 @@ The vibrator is a Misc device that consists of four modules: Vibrator API, Vibra
## Constraints ## Constraints
When using a vibrator, you must declare the **ohos.permission.VIBRATE** permission before you can control the vibration effect. The authorization mode of this permission is **system_grant**. When using a vibrator, you must declare the **ohos.permission.VIBRATE** permission before you can control the vibration effect.
...@@ -12,12 +12,10 @@ The following table provides only a brief description of related APIs. For detai ...@@ -12,12 +12,10 @@ The following table provides only a brief description of related APIs. For detai
**Table 1** APIs for application event logging **Table 1** APIs for application event logging
| API | Description | | API | Description |
| ------------------------------------------------------------ | ------------------------------------------------------------ | | ------------------------------------------------------------ | ---------------------------------------------------- |
| write(string eventName, EventType type, object keyValues, AsyncCallback\<void> callback): void | Logs application events in asynchronous mode. This API uses an asynchronous callback to return the result. | | write(AppEventInfo info, AsyncCallback\<void> callback): void | Logs application events in asynchronous mode. This API uses an asynchronous callback to return the result.|
| write(string eventName, EventType type, object keyValues): Promise\<void> | Logs application events in asynchronous mode. This API uses a promise to return the result. | | write(AppEventInfo info): Promise\<void> | Logs application events in asynchronous mode. This API uses a promise to return the result. |
| write(AppEventInfo info, AsyncCallback\<void> callback): void | Logs application events by domain in asynchronous mode. This API uses an asynchronous callback to return the result.|
| write(AppEventInfo info): Promise\<void> | Logs application events by domain in asynchronous mode. This API uses a promise to return the result.|
When an asynchronous callback is used, the return value can be processed directly in the callback. When an asynchronous callback is used, the return value can be processed directly in the callback.
...@@ -84,6 +82,7 @@ The following uses a one-time event watcher as an example to illustrate the deve ...@@ -84,6 +82,7 @@ The following uses a one-time event watcher as an example to illustrate the deve
.fontWeight(FontWeight.Bold) .fontWeight(FontWeight.Bold)
Button("1 writeTest").onClick(()=>{ Button("1 writeTest").onClick(()=>{
// Perform event logging based on the input event parameters.
hiAppEvent.write({ hiAppEvent.write({
domain: "test_domain", domain: "test_domain",
name: "test_event", name: "test_event",
...@@ -100,6 +99,7 @@ The following uses a one-time event watcher as an example to illustrate the deve ...@@ -100,6 +99,7 @@ The following uses a one-time event watcher as an example to illustrate the deve
}) })
Button("2 addWatcherTest").onClick(()=>{ Button("2 addWatcherTest").onClick(()=>{
// Add an event watcher based on the input subscription parameters.
hiAppEvent.addWatcher({ hiAppEvent.addWatcher({
name: "watcher1", name: "watcher1",
appEventFilters: [{ domain: "test_domain" }], appEventFilters: [{ domain: "test_domain" }],
...@@ -109,17 +109,23 @@ The following uses a one-time event watcher as an example to illustrate the deve ...@@ -109,17 +109,23 @@ The following uses a one-time event watcher as an example to illustrate the deve
timeOut: 2 timeOut: 2
}, },
onTrigger: function (curRow, curSize, holder) { onTrigger: function (curRow, curSize, holder) {
// If the holder object is null, return an error after recording it in the log.
if (holder == null) { if (holder == null) {
console.error("HiAppEvent holder is null"); console.error("HiAppEvent holder is null");
return; return;
} }
// Set the size threshold to 1,000 bytes for obtaining an event package.
holder.setSize(1000);
let eventPkg = null; let eventPkg = null;
// Obtain the event package based on the configured size threshold. If returned event package is null, all event data has been obtained.
while ((eventPkg = holder.takeNext()) != null) { while ((eventPkg = holder.takeNext()) != null) {
console.info("HiAppEvent eventPkg.packageId=" + eventPkg.packageId); // Parse the obtained event package and display the result on the Log page.
console.info("HiAppEvent eventPkg.row=" + eventPkg.row); console.info('HiAppEvent eventPkg.packageId=' + eventPkg.packageId);
console.info("HiAppEvent eventPkg.size=" + eventPkg.size); console.info('HiAppEvent eventPkg.row=' + eventPkg.row);
console.info('HiAppEvent eventPkg.size=' + eventPkg.size);
// Traverse and parse event string arrays in the obtained event package.
for (const eventInfo of eventPkg.data) { for (const eventInfo of eventPkg.data) {
console.info("HiAppEvent eventPkg.data=" + eventInfo); console.info('HiAppEvent eventPkg.data=' + eventInfo);
} }
} }
} }
...@@ -127,6 +133,7 @@ The following uses a one-time event watcher as an example to illustrate the deve ...@@ -127,6 +133,7 @@ The following uses a one-time event watcher as an example to illustrate the deve
}) })
Button("3 removeWatcherTest").onClick(()=>{ Button("3 removeWatcherTest").onClick(()=>{
// Remove the specified event watcher.
hiAppEvent.removeWatcher({ hiAppEvent.removeWatcher({
name: "watcher1" name: "watcher1"
}) })
......
...@@ -12,7 +12,7 @@ The performance tracing APIs are provided by the **hiTraceMeter** module. For de ...@@ -12,7 +12,7 @@ The performance tracing APIs are provided by the **hiTraceMeter** module. For de
| API| Return Value| Description| | API| Return Value| Description|
| ---------------------------------------------------------------------------- | --------- | ------------ | | ---------------------------------------------------------------------------- | --------- | ------------ |
| hiTraceMeter.startTrace(name: string, taskId: number, expectedTime?: number) | void | Starts a trace task. If multiple trace tasks with the same name need to be performed at the same time or a trace task needs to be performed multiple times concurrently, different task IDs must be specified in **startTrace**. If the trace tasks with the same name are not performed at the same time, the same task ID can be used.| | hiTraceMeter.startTrace(name: string, taskId: number) | void | Starts a trace task. If multiple trace tasks with the same name need to be performed at the same time or a trace task needs to be performed multiple times concurrently, different task IDs must be specified in **startTrace**. If the trace tasks with the same name are not performed at the same time, the same task ID can be used.|
| hiTraceMeter.finishTrace(name: string, taskId: number) | void | Stops a trace task. The values of **name** and **taskId** must be the same as those of **hiTraceMeter.startTrace**.| | hiTraceMeter.finishTrace(name: string, taskId: number) | void | Stops a trace task. The values of **name** and **taskId** must be the same as those of **hiTraceMeter.startTrace**.|
| hiTraceMeter.traceByValue(name: string, value: number) | void | Traces the value changes of a variable.| | hiTraceMeter.traceByValue(name: string, value: number) | void | Traces the value changes of a variable.|
...@@ -31,10 +31,6 @@ In this example, distributed call chain tracing begins when the application star ...@@ -31,10 +31,6 @@ In this example, distributed call chain tracing begins when the application star
}, },
onInit() { onInit() {
this.title = this.$t('strings.world'); this.title = this.$t('strings.world');
// The expected duration of the trace task is 5 ms.
hiTraceMeter.startTrace("business", 1);
hiTraceMeter.startTrace("business", 1, 5);
// Start track tasks with the same name concurrently. // Start track tasks with the same name concurrently.
hiTraceMeter.startTrace("business", 1); hiTraceMeter.startTrace("business", 1);
......
# FAQs # FAQs
- [Ability Framework Development](faqs-ability.md) - [Ability Framework Development](faqs-ability.md)
- [Data Management Development](faqs-data-management.md)
- [File Management Development](faqs-file-management.md)
- [Graphics and Image Development](faqs-graphics.md)
- [hdc_std Command Usage](faqs-ide.md)
- [IDE Usage](faqs-hdc-std.md)
- [ArkUI (JavaScript) Development](faqs-ui-js.md) - [ArkUI (JavaScript) Development](faqs-ui-js.md)
- [ArkUI (eTS) Development](faqs-ui-ets.md) - [ArkUI (eTS) Development](faqs-ui-ets.md)
- [Graphics and Image Development](faqs-graphics.md) - [Graphics and Image Development](faqs-graphics.md)
- [File Management Development](faqs-file-management.md) - [File Management Development](faqs-file-management.md)
- [Network and Connection Development](faqs-connectivity.md)
- [Data Management Development](faqs-data-management.md) - [Data Management Development](faqs-data-management.md)
- [Device Management Development](faqs-device-management.md) - [Device Management Development](faqs-device-management.md)
- [Native API Usage](faqs-native.md) - [Native API Usage](faqs-native.md)
- [Network and Connection Development](faqs-connectivity.md)
- [Usage of Third- and Fourth-Party Libraries](faqs-third-party-library.md) - [Usage of Third- and Fourth-Party Libraries](faqs-third-party-library.md)
- [hdc_std Command Usage](faqs-ide.md)
- [IDE Usage](faqs-hdc-std.md)
- [Development Board](faqs-development-board.md) - [Development Board](faqs-development-board.md)
...@@ -19,7 +19,7 @@ Applicable to: OpenHarmony SDK 3.2.2.5, stage model of API version 9 ...@@ -19,7 +19,7 @@ Applicable to: OpenHarmony SDK 3.2.2.5, stage model of API version 9
Applicable to: OpenHarmony SDK 3.2.2.5, stage model of API version 9 Applicable to: OpenHarmony SDK 3.2.2.5, stage model of API version 9
Error code 28 refers to **CURLE_OPERATION_TIMEDOUT**, which means a libcurl library operation timeout. For details, see any HTTP status code description available. Error code 28 refers to **CURLE_OPERATION_TIMEDOUT**, which means a cURL operation timeout. For details, see any HTTP status code description available.
Reference: [Development Guide](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-http.md#httpresponse) and [Curl Error Codes](https://curl.se/libcurl/c/libcurl-errors.html) Reference: [Development Guide](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-http.md#httpresponse) and [Curl Error Codes](https://curl.se/libcurl/c/libcurl-errors.html)
......
# Device Management Development # Data Management Development
......
...@@ -202,7 +202,7 @@ struct DialogTest { ...@@ -202,7 +202,7 @@ struct DialogTest {
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9 Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
The **\<List>** component is a scrollable container. By default, it taks up the entire screen height. When any component with a fixed height takes up part of the screen height, you need to explicitly specify **layoutWeight(1)** for the parent container of the **\<List>** component to take up the remaining height instead of the entire screen height. The **\<List>** component is a scrollable container. By default, it takes up the entire screen height. When any component with a fixed height takes up part of the screen height, you need to explicitly specify **layoutWeight(1)** for the parent container of the **\<List>** component to take up the remaining height instead of the entire screen height.
## How do I center child components in a grid container? ## How do I center child components in a grid container?
......
...@@ -30,7 +30,7 @@ let options = {trim : false, declarationKey:"_declaration", ...@@ -30,7 +30,7 @@ let options = {trim : false, declarationKey:"_declaration",
nameKey : "_name", elementsKey : "_elements"} nameKey : "_name", elementsKey : "_elements"}
let result:any = conv.convert(xml, options) // Convert fields in the XML file into JavaScript objects. let result:any = conv.convert(xml, options) // Convert fields in the XML file into JavaScript objects.
console.log('Test: ' + JSON.stringify(result)) console.log('Test: ' + JSON.stringify(result))
console.log('Test: ' + result._declaration._attributes.version) // vesion field in XML file console.log('Test: ' + result._declaration._attributes.version) // version field in XML file
console.log('Test: ' + result._elements[0]._elements[0]._elements[0]._text) // title field in XML file console.log('Test: ' + result._elements[0]._elements[0]._elements[0]._text) // title field in XML file
``` ```
......
# File Management
- MediaLibrary Management
- [MediaLibrary Overview](medialibrary-overview.md)
- [Media Asset Management](medialibrary-resource-guidelines.md)
- [File Path Management](medialibrary-filepath-guidelines.md)
- [Album Management](medialibrary-album-guidelines.md)
\ No newline at end of file
# Album Management
You can use the APIs provided by the **mediaLibrary** module to create and delete an album and obtain images in the album.
> **NOTE**
>
> Before developing features, read [MediaLibrary Overview](medialibrary-overview.md) to learn how to obtain a **MediaLibrary** instance and request the permissions to call the APIs of **MediaLibrary**.
To ensure the application running efficiency, most **MediaLibrary** API calls are asynchronous, and both callback and promise modes are provided for these APIs. The following code samples use the promise mode. For details about the APIs, see [MediaLibrary API Reference](../reference/apis/js-apis-medialibrary.md).
## Obtaining Images and Videos in an Album
You can obtain images and videos in an album in either of the following ways:
- Call [MediaLibrary.getFileAssets](../reference/apis/js-apis-medialibrary.md#getfileassets7-1) with an album specified to obtain the media assets. For details, see [Querying Media Assets with the Specified Album Name](medialibrary-resource-guidelines#querying-media-assets-with-the-specified-album-name).
- Call [Album.getFileAssets](../reference/apis/js-apis-medialibrary.md#getfileassets7-3) to obtain an **Album** instance, so as to obtain the media assets in it. For details, see [Obtaining Images and Videos in an Album](medialibrary-resource-guidelines#obtaining-images-and-videos-in-an-album).
## Creating an Album
You can use [MediaLibrary.createAsset](../reference/apis/js-apis-medialibrary.md#createasset8-1), with the relative path set, to create an album while adding a media asset to the album. The relative path is the album name.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.WRITE_MEDIA**.
The following describes how to create an album named **myAlbum**.
**How to Develop**
1. Call **getPublicDirectory** to obtain the public directory that stores files of a certain type.
For details about the operation, see [Obtaining a Public Directory](medialibrary-filepath-guidelines.md#obtaining-a-public-directory).
2. Call **createAsset** to create an image, with the relative path set to **path + 'myAlbum/'**.
This operation creates an album and adds an image to it.
```ts
async function example() {
let mediaType = mediaLibrary.MediaType.IMAGE;
let DIR_IMAGE = mediaLibrary.DirectoryType.DIR_IMAGE;
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
const path = await media.getPublicDirectory(DIR_IMAGE)
// myAlbum is the path for storing the new file and the name of the new album.
media.createAsset(mediaType, 'test.jpg', path + 'myAlbum/', (err, fileAsset) => {
if (fileAsset != undefined) {
console.info('createAlbum successfully, message = ' + fileAsset);
} else {
console.info('createAlbum failed, message = ' + err);
}
});
}
```
## Renaming an Album
Renaming modifies the **FileAsset.albumName** attribute of the album, that is, the album name. After the modification, call [Album.commitModify](../reference/apis/js-apis-medialibrary.md#commitmodify8-3) to commit the modification to the database.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.WRITE_MEDIA**.
The following describes how to rename the album **newAlbum**.
**How to Develop**
1. Create a retrieval condition for obtaining the target album.
2. Call **getAlbums** to obtain the album list.
3. Rename the album **newAlbum**.
4. Call **Album.commitModify** to commit the modification of the attributes to the database.
```ts
async function example() {
let AlbumNoArgsfetchOp = {
selections: '',
selectionArgs: [],
};
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
let albumList = await media.getAlbums(AlbumNoArgsfetchOp);
let album = albumList[0];
album.albumName = 'newAlbum';
// Void callback.
album.commitModify().then(function() {
console.info("albumRename successfully");
}).catch(function(err){
console.info("albumRename failed with error:"+ err);
});
}
```
# File Path Management
User data on OpenHarmony is managed by the **mediaLibrary** module in a unified manner. You can use the APIs provided by this module to access and operate the user data.
> **NOTE**
>
> Before developing features, read [MediaLibrary Overview](medialibrary-overview.md) to learn how to obtain a **MediaLibrary** instance and request the permissions to call the APIs of **MediaLibrary**.
To ensure the application running efficiency, most **MediaLibrary** API calls are asynchronous, and both callback and promise modes are provided for these APIs. The following code samples use the promise mode. For details about the APIs, see [MediaLibrary API Reference](../reference/apis/js-apis-medialibrary.md).
## File Formats Supported by Public Directories
Before using file paths for development, learn the file formats supported by each public directory.
> **CAUTION**
>
> The following table lists only the file types that can be identified by the system. In your application development, pay attention to the file formats supported by the corresponding interfaces. <br> For example, only .jpeg and .webp can be used for image encoding, and only .jpg, .png, .gif, .bmp, .webp, and .raw can be used for image decoding.
| Directory | Directory Type | Media Type | Description | Supported File Format |
| ---------- | ------------- | ------------- | -------------- | ------------------------------------------------------------ |
| Camera/ | DIR_CAMERA | VIDEO and IMAGE | Directory for storing images and videos taken by the camera. Videos and images can be stored in this directory and its subdirectories.| .bmp / .bm / .gif / .jpg /. jpeg / .jpe / .png / .webp / .raw / .svg / .heif / .mp4 / .3gp / .mpg / .mov / .webm / .mkv |
| Videos/ | DIR_VIDEO | VIDEO | Dedicated video directory. Only videos can be stored in this directory and its subdirectories.| .mp4 / .3gp / .mpg / .mov / .webm / .mkv |
| Pictures/ | DIR_IMAGE | IMAGE | Dedicated image directory. Only images can be stored in this directory and its subdirectories.| .bmp / .bm / .gif / .jpg /. jpeg / .jpe / .png / .webp / .raw / .svg / .heif |
| Audios/ | DIR_AUDIO | AUDIO |Dedicated audio directory. Only audio files can be stored in this directory and its subdirectories.| .aac/.mp3/.flac/.wav/.ogg |
| Documents/ | DIR_DOCUMENTS | FILE |Dedicated file directory. Only files except audios, images, and videos can be stored in this directory and its subdirectories.| - |
| Download/ | DIR_DOWNLOAD | ALLTYPE |Directory for storing downloaded files. The types of files in this directory and its subdirectories are not restricted.| - |
## Obtaining a Public Directory
Different types of files are stored in different public directories. You can call [getPublicDirectory](../reference/apis/js-apis-medialibrary.md#getpublicdirectory8-1) to obtain the public directory that stores files of a certain type.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.READ_MEDIA**.
The following describes how to obtain the public directory that stores camera files.
```ts
async function example(){
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
let DIR_CAMERA = mediaLibrary.DirectoryType.DIR_CAMERA;
const dicResult = await media.getPublicDirectory(DIR_CAMERA);
if (dicResult == 'Camera/') {
console.info('mediaLibraryTest : getPublicDirectory passed');
} else {
console.info('mediaLibraryTest : getPublicDirectory failed');
}
}
```
## Copying Files Between the Application Sandbox and the Public Directory
OpenHarmony provides the application sandbox to minimize the leakage of application data and user privacy information.
Users can access files stored in the public directories through the system applications **Files** and **Gallery**. However, files in the application sandbox can be accessed only by the application itself.
### Copying a File
You can call [mediaLibrary.FileAsset.open](../reference/apis/js-apis-medialibrary.md#open8-1) to open a file in a public directory.
You can call [fileio.open](../reference/apis/js-apis-fileio.md#fileioopen7) to open a file in the application sandbox. The sandbox directory can be accessed only through the application context.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.WRITE_MEDIA**.
- You have imported the module [@ohos.fileio](../reference/apis/js-apis-fileio.md) in addition to @ohos.multimedia.mediaLibrary.
**How to Develop**
1. Call [Context.getFilesDir](../reference/apis/js-apis-Context.md#contextgetfilesdir) to obtain the directory of the application sandbox.
2. Call **MediaLibrary.getFileAssets** and **FetchFileResult.getFirstObject** to obtain the first file in the result set of the public directory.
3. Call **fileio.open** to open the file in the sandbox.
4. Call **fileAsset.open** to open the file in the public directory.
5. Call **fileio.copyfile** to copy the file.
6. Call **fileAsset.close** and **fileio.close** to close the file.
**Example 1: Copying Files from the Public Directory to the Sandbox**
```ts
async function copyPublic2Sandbox() {
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
let sandboxDirPath = globalThis.context.filesDir;
let fileKeyObj = mediaLibrary.FileKey
let fileAssetFetchOp = {
selections: fileKeyObj.DISPLAY_NAME + '= ?' ,
selectionArgs: ['testFile.txt'],
};
let fetchResult = await media.getFileAssets(fileAssetFetchOp);
let fileAsset = await fetchResult.getFirstObject();
let fdPub = await fileAsset.open('rw');
let fdSand = await fileio.open(sandboxDirPath + '/testFile.txt', 0o2 | 0o100, 0o666);
await fileio.copyFile(fdPub, fdSand);
await fileAsset.close(fdPub);
await fileio.close(fdSand);
let content_sand = await fileio.readText(sandboxDirPath + '/testFile.txt');
console.log('content read from sandbox file: ', content_sand)
}
```
**Example 2: Copying a File from the Sandbox to the Public Directory**
```ts
async function copySandbox2Public() {
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
let sandboxDirPath = globalThis.context.filesDir;
let DIR_DOCUMENTS = mediaLibrary.DirectoryType.DIR_DOCUMENTS;
const publicDirPath = await media.getPublicDirectory(DIR_DOCUMENTS);
try {
let fileAsset = await media.createAsset(mediaLibrary.MediaType.FILE, 'testFile02.txt', publicDirPath);
console.info('createFile successfully, message = ' + fileAsset);
} catch (err) {
console.info('createFile failed, message = ' + err);
}
try {
let fileKeyObj = mediaLibrary.FileKey
let fileAssetFetchOp = {
selections: fileKeyObj.DISPLAY_NAME + '= ?' ,
selectionArgs: ['testFile02.txt'],
};
let fetchResult = await media.getFileAssets(fileAssetFetchOp);
var fileAsset = await fetchResult.getFirstObject();
} catch (err) {
console.info('file asset get failed, message = ', err)
}
var fdPub = await fileAsset.open('rw');
var fdSand = await fileio.open(sandboxDirPath + 'testFile.txt', 0o2);
await fileio.copyFile(fdSand, fdPub);
await fileio.close(fdPub);
await fileio.close(fdSand);
let fdPubRead = await fileAsset.open('rw');
try {
var arrayBuffer = new ArrayBuffer(4096);
await fileio.read(fdPubRead, arrayBuffer);
var content_pub = String.fromCharCode(new Uint8Array(arrayBuffer));
fileAsset.close(fdPubRead);
} catch (err) {
console.log('read text failed, message = ', err);
}
console.log('content read from public file: ', content_pub);
}
```
### Reading and Writing a File
You can use **FileAsset.open** and **FileAsset.close** of [mediaLibrary](../reference/apis/js-apis-medialibrary.md) to open and close a file, and use **fileio.read** and **fileio.write** of [fileio](../reference/apis/js-apis-fileio.md) to read and write a file.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.WRITE_MEDIA**.
- You have imported the module [@ohos.fileio](../reference/apis/js-apis-fileio.md) in addition to @ohos.multimedia.mediaLibrary.
**How to Develop**
1. Create a file.
```ts
async function example() {
let mediaType = mediaLibrary.MediaType.FILE;
let DIR_DOCUMENTS = mediaLibrary.DirectoryType.DIR_DOCUMENTS;
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
const path = await media.getPublicDirectory(DIR_DOCUMENTS);
media.createAsset(mediaType, "testFile.text", path).then (function (asset) {
console.info("createAsset successfully:"+ JSON.stringify(asset));
}).catch(function(err){
console.info("createAsset failed with error:"+ err);
});
}
```
2. Call **FileAsset.open** to open the file.
3. Call **fileio.write** to write a string to the file.
4. Call **fileio.read** to read the file and save the data read in an array buffer.
5. Convert the array buffer to a string.
6. Use **FileAsset.close** to close the file.
**Example 1: Opening an Existing File and Writing Data to It**
```ts
async function writeOnlyPromise() {
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
let fileKeyObj = mediaLibrary.FileKey
let fileAssetFetchOp = {
selections: fileKeyObj.DISPLAY_NAME + '= ?' ,
selectionArgs: ['testFile.txt'],
};
let fetchResult = await media.getFileAssets(fileAssetFetchOp);
let fileAsset = await fetchResult.getFirstObject();
console.info('fileAssetName: ', fileAsset.displayName);
try {
let fd = await fileAsset.open('w');
console.info('file descriptor: ', fd);
await fileio.write(fd, "Write file test content.");
await fileAsset.close(fd);
} catch (err) {
console.info('write file failed, message = ', err);
}
}
```
**Example 2: Opening an Existing File and Reading Data from It**
```ts
async function readOnlyPromise() {
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
let fileKeyObj = mediaLibrary.FileKey
let fileAssetFetchOp = {
selections: fileKeyObj.DISPLAY_NAME + '= ?' ,
selectionArgs: ['testFile.txt'],
};
let fetchResult = await media.getFileAssets(fileAssetFetchOp);
let fileAsset = await fetchResult.getFirstObject();
console.info('fileAssetName: ', fileAsset.displayName);
try {
let fd = await fileAsset.open('r');
let arrayBuffer = new ArrayBuffer(4096);
await fileio.read(fd, arrayBuffer);
let fileContent = String.fromCharCode(...new Uint8Array(arrayBuffer));
globalThis.fileContent = fileContent
globalThis.fileName = fileAsset.displayName;
console.info('file content: ', fileContent);
await fileAsset.close(fd);
} catch (err) {
console.info('read file failed, message = ', err);
}
}
```
# MediaLibrary Development Overview
The **mediaLibrary** module provides APIs for you to access and modify media files.
- You can manage [media assets (audios, videos, image, and files)](medialibrary-resource-guidelines.md) as follows:
- Query media assets.
- Obtain an image or a video.
- Obtain the thumbnail of an image or a video.
- Create a media asset.
- Rename a media asset.
- Move a media asset to the recycle bin.
- You can manage [file paths](medialibrary-filepath-guidelines.md) as follows:
- Obtain the public directory that stores files of a certain type.
- Copy files between the application sandbox and the public directory.
- Read and write a file.
- You can manage [albums](medialibrary-album-guidelines.md) as follows:
- Obtain images and videos in an album.
- Create an album.
- Rename an album.
> **NOTE**
>
> This development guide applies only to the stage model (available from API version 9).
To access and modify personal media data, an application must obtain a **MediaLibrary** instance and request the media asset read and write permissions from the user.
Before using the **MediaLibrary** APIs to develop features, you must learn how to:
- [Obtain a MediaLibrary Instance](#obtaining-a-medialibrary-instance)
- [Request Permissions](#requesting-permissions)
## Obtaining a MediaLibrary Instance
An application must call [getMediaLibrary](../reference/apis/js-apis-medialibrary.md#medialibrarygetmedialibrary8) to obtain a **MediaLibrary** instance based on the application context. Through this instance, the application can access and modify personal media data (such as audios, videos, images, and files).
**How to Develop**
1. Import the **mediaLibrary** module.
2. Call **getContext** to obtain the application context.
3. Obtain a **MediaLibrary** instance.
```ts
import mediaLibrary from '@ohos.multimedia.mediaLibrary';
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
```
## Requesting Permissions
To read and write a **MediaLibrary** instance, you must have the required permissions, as described in the table below. Before requesting the permissions, ensure that the [basic principles for permission management](../security/accesstoken-overview.md#basic-principles-for-permission-management) are met.
| Permission | Description | Authorization Mode |
| ------------------------------ | ------------------------------------------ | ---------- |
| ohos.permission.READ_MEDIA | Allows an application to read media files from the user's external storage.| user_grant |
| ohos.permission.WRITE_MEDIA | Allows an application to read media files from and write media files into the user's external storage.| user_grant |
| ohos.permission.MEDIA_LOCATION | Allows an application to access geographical locations in the user's media file.| user_grant |
After configuring the permissions in the **module.json5** file, the application must call [Context.requestPermissionsFromUser](../reference/apis/js-apis-ability-context.md#abilitycontextrequestpermissionsfromuser) to check for the required permissions and if they are not granted, request the permissions from the user by displaying a dialog box.
> **NOTE**<br>Even if the user has granted a permission, the application must check for the permission before calling an API protected by the permission. It should not persist the permission granted status, because the user can revoke the permission through the system application **Settings**.
**How to Develop**
1. Declare the permissions in the **module.json5** file. Add the **requestPermissions** tag under **module** in the file, and set the tag based on the project requirements. For details about the tag, see [Guide for Requesting Permissions from User](../security/accesstoken-guidelines.md).
```json
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.MEDIA_LOCATION",
"reason": "$string:reason",
"usedScene": {
"abilities": [
"MainAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.READ_MEDIA",
"reason": "$string:reason",
"usedScene": {
"abilities": [
"MainAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.WRITE_MEDIA",
"reason": "$string:reason",
"usedScene": {
"abilities": [
"MainAbility"
],
"when": "always"
}
}
]
}
}
```
2. Call **requestPermissionsFromUser** to check for the required permissions and if they are not granted, request the permissions from the user by displaying a dialog box.
```ts
import Ability from '@ohos.application.Ability'
export default class MainAbility extends Ability {
onWindowStageCreate(windowStage) {
var permissions=['ohos.permission.READ_MEDIA','ohos.permission.WRITE_MEDIA']
var permissionRequestResult;
this.context.requestPermissionsFromUser(permissions,(err,result) => {
if(err){
console.log('requestPermissionsFromUserError: ' + JSON.stringify(err));
}else{
permissionRequestResult=result;
console.log('permissionRequestResult: ' + JSON.stringify(permissionRequestResult));
}
});
}
}
```
# Media Asset Management
Your applications can use the APIs provided by the **mediaLibrary** module to perform operations on media assets such as audios, videos, images, and files.
> **NOTE**
>
> Before developing features, read [MediaLibrary Overview](medialibrary-overview.md) to learn how to obtain a **MediaLibrary** instance and request the permissions to call the APIs of **MediaLibrary**.
To ensure the application running efficiency, most **MediaLibrary** API calls are asynchronous, and both callback and promise modes are provided for these APIs. The following code samples use the promise mode. For details about the APIs, see [MediaLibrary API Reference](../reference/apis/js-apis-medialibrary.md).
## Querying Media Assets
You can query media assets by condition such as the media type, date, or album name.
To do so, call [MediaLibrary.getFileAssets](../reference/apis/js-apis-medialibrary.md#getfileassets7-1), with a **MediaFetchOptions** object passed in to specify the conditions. In this object, **MediaFetchOptions.selections** are the retrieval conditions, and the enumerated values of **FileKey** are used as the column names of the conditions; **MediaFetchOptions.selectionArgs** are the values of the conditions. You can also specify **order** (sorting mode of the search result), **uri** (file URI), and **networkId** (network ID of the registered device) as the conditions.
To obtain the object at the specified position (for example, the first, the last, or with the specified index) in the result set, call [FetchFileResult](../reference/apis/js-apis-medialibrary.md#fetchfileresult7). In this section, **getNextObject** is used cyclically to obtain all media assets in the result set.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.READ_MEDIA**.
### Querying Media Assets with the Specified Media Type
The following describes how to obtain images.
**How to Develop**
To specify the media type as the retrieval condition, set **selections** to **FileKey.MEDIA_TYPE**.
To specify the image as the media type, set **selectionArgs** to **MediaType.IMAGE**.
```ts
async function example() {
let fileKeyObj = mediaLibrary.FileKey
let fileType = mediaLibrary.MediaType.IMAGE
let option = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [fileType.toString()],
};
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
const fetchFileResult = await media.getFileAssets(option);
for (let i = 0; i < fetchFileResult.getCount(); i++) {
fetchFileResult.getNextObject((err, fileAsset) => {
if (err) {
console.error('Failed ');
return;
}
console.log('fileAsset.displayName ' + i + ': ' + fileAsset.displayName);
})
}
}
```
### Querying Media Assets with the Specified Date
The following describes how to obtain media assets that are added on the specified date. You can also use the modification date and shooting date as the retrieval conditions.
To specify the date when the files are added as the retrieval condition, set **selections** to **FileKey.DATE_ADDED**.
To specify the date 2022-8-5, set **selectionArgs** to **2022-8-5**.
```ts
async function example() {
let fileKeyObj = mediaLibrary.FileKey
let option = {
selections: fileKeyObj.DATE_ADDED + '= ?',
selectionArgs: ['2022-8-5'],
};
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
const fetchFileResult = await media.getFileAssets(option);
for (let i = 0; i < fetchFileResult.getCount(); i++) {
fetchFileResult.getNextObject((err, fileAsset) => {
if (err) {
console.error('Failed ');
return;
}
console.log('fileAsset.displayName ' + i + ': ' + fileAsset.displayName);
})
}
}
```
### Querying Media Assets and Sorting Them
The following describes how to query images and sort them in descending order by the date when they are added. You can also sort them in ascending order.
To sort files in descending order by the date when they are added, set **order** to **FileKey.DATE_ADDED + " DESC"**.
```ts
async function example() {
let fileKeyObj = mediaLibrary.FileKey
let fileType = mediaLibrary.MediaType.IMAGE
let option = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [fileType.toString()],
order: fileKeyObj.DATE_ADDED + " DESC",
};
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
const fetchFileResult = await media.getFileAssets(option);
for (let i = 0; i < fetchFileResult.getCount(); i++) {
fetchFileResult.getNextObject((err, fileAsset) => {
if (err) {
console.error('Failed ');
return;
}
console.log('fileAsset.displayName ' + i + ': ' + fileAsset.displayName);
})
}
}
```
### Querying Media Assets with the Specified Album Name
The following describes how to query media assets in **myAlbum**.
To specify the album name as the retrieval condition, set **selections** to **FileKey.ALBUM_NAME**.
To specify the album name **'myAlbum'**, set **selectionArgs** to **'myAlbum'**.
```ts
async function example() {
let fileKeyObj = mediaLibrary.FileKey
let fileType = mediaLibrary.MediaType.IMAGE
let option = {
selections: fileKeyObj.ALBUM_NAME + '= ?',
selectionArgs: ['myAlbum'],
};
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
const fetchFileResult = await media.getFileAssets(option);
for (let i = 0; i < fetchFileResult.getCount(); i++) {
fetchFileResult.getNextObject((err, fileAsset) => {
if (err) {
console.error('Failed ');
return;
}
console.log('fileAsset.displayName ' + i + ': ' + fileAsset.displayName);
})
}
}
```
## Obtaining Images and Videos in an Album
You can obtain media assets in an album in either of the following ways:
- Call [MediaLibrary.getFileAssets](../reference/apis/js-apis-medialibrary.md#getfileassets7-1) with an album specified, as described in [Querying Media Assets with the Specfied Album Name](#querying-media-assets-with-the-specified-album-name).
- Call [Album.getFileAssets](../reference/apis/js-apis-medialibrary.md#getfileassets7-3) to obtain an **Album** instance, so as to obtain the media assets in it.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.READ_MEDIA**.
**How to Develop**
The following describes how to obtain videos in an album named **New Album 1**.
1. Create a retrieval condition for obtaining the target **Album** instance.
```ts
let fileKeyObj = mediaLibrary.FileKey;
let AlbumNoArgsFetchOp = {
selections: fileKeyObj.ALBUM_NAME + '= ?',
selectionArgs:['New Album 1']
}
```
2. Create a retrieval condition for obtaining videos in the target album.
```ts
let fileKeyObj = mediaLibrary.FileKey;
let imageType = mediaLibrary.MediaType.VIDEO;
let imagesFetchOp = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [imageType.toString()],
}
```
3. Call **Album.getFileAssets** to obtain the videos in the target album.
Complete sample code:
```ts
async function getCameraImagePromise() {
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
let fileKeyObj = mediaLibrary.FileKey;
let imageType = mediaLibrary.MediaType.IMAGE;
let imagesFetchOp = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [imageType.toString()],
}
let AlbumNoArgsFetchOp = {
selections: fileKeyObj.ALBUM_NAME + '= ?',
selectionArgs:['New Album 1']
}
let albumList = await media.getAlbums(AlbumNoArgsFetchOp);
if (albumList.length > 0) {
const album = albumList[0];
let fetchFileResult = await album.getFileAssets(imagesFetchOp);
let count = fetchFileResult.getCount();
console.info("get mediaLibrary IMAGE number", count);
} else {
console.info('getAlbum list is: 0');
}
}
```
## Obtaining the Thumbnail of an Image or a Video
You can call [FileAsset.getThumbnail](../reference/apis/js-apis-medialibrary.md#getthumbnail8-2) with the thumbnail size passed in to obtain the thumbnail of an image or a video. Thumbnails are usually displayed on the UI.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.READ_MEDIA**.
### Obtaining the Thumbnail of an Image
Your application may need to obtain the thumbnail of an image for preview purposes.
The following describes how to obtain the thumbnail (size: 720 x 720) of the first image in the album.
**How to Develop**
1. Create a retrieval condition for obtaining images in the target album.
2. Call **getFileAssets** to obtain the images in the target album.
3. Call **getFirstObject** to obtain the first image among all the images obtained.
4. Call **getThumbnail** to obtain the thumbnail of the first image.
```ts
async function getFirstThumbnailPromise() {
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
let fileKeyObj = mediaLibrary.FileKey;
let imageType = mediaLibrary.MediaType.IMAGE;
let imagesFetchOp = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [imageType.toString()],
}
let size = { width: 720, height: 720 };
const fetchFileResult = await media.getFileAssets(imagesFetchOp);
if (fetchFileResult != undefined) {
const asset = await fetchFileResult.getFirstObject();
asset.getThumbnail(size).then((pixelMap) => {
pixelMap.getImageInfo().then((info) => {
console.info('get Thumbnail info: ' + "width: " + info.size.width + " height: " + info.size.height);
}).catch((err) => {
console.info("getImageInfo failed with error:" + err);
});
}).catch((err) => {
console.info("getImageInfo failed with error:" + err);
});
} else {
console.info("get image failed with error");
}
}
```
## Creating a Media Asset
You can call [MediaLibrary.createAsset](../reference/apis/js-apis-medialibrary.md#createasset8-1) to create a media asset.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.WRITE_MEDIA**.
- [Obtain the public directory](medialibrary-filepath-guidelines.md).
The following describes how to create a file of the **MediaType.FILE** type.
```ts
async function example() {
let mediaType = mediaLibrary.MediaType.FILE;
let DIR_DOCUMENTS = mediaLibrary.DirectoryType.DIR_DOCUMENTS;
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
const path = await media.getPublicDirectory(DIR_DOCUMENTS);
media.createAsset(mediaType, "testFile.text", path).then ((asset) => {
console.info("createAsset successfully:"+ JSON.stringify(asset));
}).catch((err) => {
console.info("createAsset failed with error:"+ err);
});
}
```
## Moving a Media Asset to the Recycle Bin
You can use [FileAsset.trash](../reference/apis/js-apis-medialibrary.md#trash8) to move a media asset to the recycle bin.
By default, files in the recycle bin will be stored for 30 days. During this period, you can set **isTrash** in **trash** to **false** to recover the files from the recycle bin. Application users can also recover the files through the system applications **Files** or **Gallery**.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.WRITE_MEDIA**.
The following describes how to move the first file in the result set to the recycle bin.
**How to Develop**
1. Create a retrieval condition for obtaining images in the target album.
2. Call **getFileAssets** to obtain the images in the target album.
3. Call **getFirstObject** to obtain the first image among all the images obtained.
4. Call **trash** to move the first image to the recycle bin.
```ts
async function example() {
let fileKeyObj = mediaLibrary.FileKey
let fileType = mediaLibrary.MediaType.FILE
let option = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [fileType.toString()],
};
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
const fetchFileResult = await media.getFileAssets(option);
let asset = await fetchFileResult.getFirstObject();
if (asset == undefined) {
console.error('asset not exist')
return
}
// Void callback.
asset.trash(true).then(() => {
console.info("trash successfully");
}).catch((err) => {
console.info("trash failed with error:"+ err);
});
}
```
## Renaming a Media Asset
Renaming modifies the **FileAsset.displayName** attribute of a file, that is, the displayed file name, including the file name extension.
After the modification, call [FileAsset.commitModify](../reference/apis/js-apis-medialibrary.md#commitmodify8-1) to commit the modification to the database.
Before renaming a file, you must call [FetchFileResult](../reference/apis/js-apis-medialibrary.md#fetchfileresult7) to obtain the file.
**Prerequisites**
- You have obtained a **MediaLibrary** instance.
- You have granted the permission **ohos.permission.WRITE_MEDIA**.
The following describes how to rename the first file in the result set as **newtitle.text**.
**How to Develop**
1. Create a retrieval condition for obtaining images in the target album.
2. Call **getFileAssets** to obtain the images in the target album.
3. Call **getFirstObject** to obtain the first image among all the images obtained.
4. Rename the image as **newImage.jpg**.
5. Call **FileAsset.commitModify** to commit the modification of the attributes to the database.
```ts
async function example() {
let fileKeyObj = mediaLibrary.FileKey
let fileType = mediaLibrary.MediaType.FILE
let option = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [fileType.toString()],
};
const context = getContext(this);
var media = mediaLibrary.getMediaLibrary(context);
const fetchFileResult = await media.getFileAssets(option);
let asset = await fetchFileResult.getFirstObject();
if (asset == undefined) {
console.error('asset not exist')
return
}
asset.displayName = 'newImage.jpg';
// Void callback.
asset.commitModify((err) => {
if (err) {
console.error('fileRename Failed ');
return;
}
console.log('fileRename successful.');
})
}
```
...@@ -9,15 +9,15 @@ You can use APIs provided in the following table to obtain the system language a ...@@ -9,15 +9,15 @@ You can use APIs provided in the following table to obtain the system language a
### Available APIs ### Available APIs
| Module | API | Description | | Module | API | Description |
| -------- | -------- | -------- | | -------- | -------- | -------- |
| ohos.i18n | getSystemLanguage(): string | Obtains the system language. | | ohos.i18n | getSystemLanguage(): string | Obtains the system language. |
| ohos.i18n | getSystemRegion(): string | Obtains the system region. | | ohos.i18n | getSystemRegion(): string | Obtains the system region. |
| ohos.i18n | getSystemLocale(): string | Obtains the system locale. | | ohos.i18n | getSystemLocale(): string | Obtains the system locale. |
| ohos.i18n | isRTL(locale: string): boolean<sup>7+</sup> | Checks whether the locale uses a right-to-left (RTL) language. | | ohos.i18n | isRTL(locale: string): boolean<sup>7+</sup> | Checks whether the locale uses a right-to-left (RTL) language. |
| ohos.i18n | is24HourClock(): boolean<sup>7+</sup> | Checks whether the system uses a 24-hour clock. | | ohos.i18n | is24HourClock(): boolean<sup>7+</sup> | Checks whether the system uses a 24-hour clock. |
| ohos.i18n | getDisplayLanguage(language: string, locale: string, sentenceCase?: boolean): string | Obtains the localized display of a language. | | ohos.i18n | getDisplayLanguage(language: string, locale: string, sentenceCase?: boolean): string | Obtains the localized display of a language. |
| ohos.i18n | getDisplayCountry(country: string, locale: string, sentenceCase?: boolean): string | Obtains the localized display of a country name. | | ohos.i18n | getDisplayCountry(country: string, locale: string, sentenceCase?: boolean): string | Obtains the localized display of a country name. |
### How to Develop ### How to Develop
...@@ -26,7 +26,7 @@ You can use APIs provided in the following table to obtain the system language a ...@@ -26,7 +26,7 @@ You can use APIs provided in the following table to obtain the system language a
Call the **getSystemLanguage** method to obtain the system language (**i18n** is the name of the imported module). Call the **getSystemLanguage** method to obtain the system language (**i18n** is the name of the imported module).
```js ```js
var language = i18n.getSystemLanguage(); var language = i18n.getSystemLanguage();
``` ```
...@@ -42,7 +42,7 @@ You can use APIs provided in the following table to obtain the system language a ...@@ -42,7 +42,7 @@ You can use APIs provided in the following table to obtain the system language a
3. Obtain the system locale. 3. Obtain the system locale.
Call the **getSystemLocale** method to obtain the system locale. Call the **getSystemLocale** method to obtain the system locale.
```js ```js
var locale = i18n.getSystemLocale(); var locale = i18n.getSystemLocale();
``` ```
...@@ -51,7 +51,7 @@ You can use APIs provided in the following table to obtain the system language a ...@@ -51,7 +51,7 @@ You can use APIs provided in the following table to obtain the system language a
Call the **isRTL** method to check whether the locale's language is RTL. Call the **isRTL** method to check whether the locale's language is RTL.
```js ```js
var rtl = i18n.isRTL("zh-CN"); var rtl = i18n.isRTL("zh-CN");
``` ```
...@@ -67,7 +67,7 @@ You can use APIs provided in the following table to obtain the system language a ...@@ -67,7 +67,7 @@ You can use APIs provided in the following table to obtain the system language a
6. Obtain the localized display of a language. 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. 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.
```js ```js
var language = "en"; var language = "en";
var locale = "zh-CN"; var locale = "zh-CN";
...@@ -78,7 +78,7 @@ You can use APIs provided in the following table to obtain the system language a ...@@ -78,7 +78,7 @@ You can use APIs provided in the following table to obtain the system language a
7. Obtain the localized display of a country. 7. Obtain the localized display of a country.
Call the **getDisplayCountry** method to obtain the localized display of a country name. **country** indicates the country code (a two-letter code in compliance with ISO-3166, for example, CN), **locale** indicates the locale, and **sentenceCase** indicates whether the first letter of the result must be capitalized. Call the **getDisplayCountry** method to obtain the localized display of a country name. **country** indicates the country code (a two-letter code in compliance with ISO-3166, for example, CN), **locale** indicates the locale, and **sentenceCase** indicates whether the first letter of the result must be capitalized.
```js ```js
var country = "US"; var country = "US";
var locale = "zh-CN"; var locale = "zh-CN";
...@@ -116,7 +116,7 @@ You can use APIs provided in the following table to obtain the system language a ...@@ -116,7 +116,7 @@ You can use APIs provided in the following table to obtain the system language a
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. 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.
```js ```js
var calendar = i18n.getCalendar("zh-CN", "gregory"); var calendar = i18n.getCalendar("zh-CN", "gregory");
``` ```
...@@ -135,7 +135,7 @@ You can use APIs provided in the following table to obtain the system language a ...@@ -135,7 +135,7 @@ You can use APIs provided in the following table to obtain the system language a
3. 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.
Call the **set** method to 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.
```js ```js
calendar.set(2021, 12, 21, 6, 0, 0) calendar.set(2021, 12, 21, 6, 0, 0)
``` ```
...@@ -144,7 +144,7 @@ You can use APIs provided in the following table to obtain the system language a ...@@ -144,7 +144,7 @@ You can use APIs provided in the following table to obtain the system language a
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. 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.
```js ```js
calendar.setTimeZone("Asia/Shanghai"); calendar.setTimeZone("Asia/Shanghai");
var timezone = calendar.getTimeZone(); var timezone = calendar.getTimeZone();
...@@ -163,7 +163,7 @@ You can use APIs provided in the following table to obtain the system language a ...@@ -163,7 +163,7 @@ You can use APIs provided in the following table to obtain the system language a
6. 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.
Call the **setMinimalDaysInFirstWeek** and **getMinimalDaysInFirstWeek** methods to 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.
```js ```js
calendar.setMinimalDaysInFirstWeek(3); calendar.setMinimalDaysInFirstWeek(3);
var minimalDaysInFirstWeek = calendar.getMinimalDaysInFirstWeek(); var minimalDaysInFirstWeek = calendar.getMinimalDaysInFirstWeek();
...@@ -173,7 +173,7 @@ You can use APIs provided in the following table to obtain the system language a ...@@ -173,7 +173,7 @@ You can use APIs provided in the following table to obtain the system language a
Call the **getDisplayName** method to obtain the localized display of the **Calendar** object. Call the **getDisplayName** method to obtain the localized display of the **Calendar** object.
```js ```js
var localizedName = calendar.getDisplayName("zh-CN"); var localizedName = calendar.getDisplayName("zh-CN");
``` ```
...@@ -196,11 +196,11 @@ You can use APIs provided in the following table to obtain the system language a ...@@ -196,11 +196,11 @@ You can use APIs provided in the following table to obtain the system language a
### Available APIs ### Available APIs
| Module | API | Description | | Module | API | Description |
| -------- | -------- | -------- | | -------- | -------- | -------- |
| ohos.i18n | constructor(country: string, options?: PhoneNumberFormatOptions)<sup>8+</sup> | Instantiates a **PhoneNumberFormat** object. | | 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. | | ohos.i18n | isValidNumber(number: string): boolean<sup>8+</sup> | Checks whether the value of **number** is a phone number in the correct format. |
| ohos.i18n | format(number: string): string<sup>8+</sup> | Formats the value of **number** based on the specified country and style. | | ohos.i18n | format(number: string): string<sup>8+</sup> | Formats the value of **number** based on the specified country and style. |
### How to Develop ### How to Develop
...@@ -209,7 +209,7 @@ You can use APIs provided in the following table to obtain the system language a ...@@ -209,7 +209,7 @@ You can use APIs provided in the following table to obtain the system language a
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**. 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**.
```js ```js
var phoneNumberFormat = new i18n.PhoneNumberFormat("CN", {type: "E164"}); var phoneNumberFormat = new i18n.PhoneNumberFormat("CN", {type: "E164"});
``` ```
...@@ -223,7 +223,7 @@ You can use APIs provided in the following table to obtain the system language a ...@@ -223,7 +223,7 @@ You can use APIs provided in the following table to obtain the system language a
3. Format a phone number. 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.
```js ```js
var formattedNumber = phoneNumberFormat.format("15812341234"); var formattedNumber = phoneNumberFormat.format("15812341234");
``` ```
...@@ -236,15 +236,15 @@ The **unitConvert** API is provided to help you implement measurement conversion ...@@ -236,15 +236,15 @@ The **unitConvert** API is provided to help you implement measurement conversion
### Available APIs ### Available APIs
| Module | API | Description | | Module | API | Description |
| -------- | -------- | -------- | | -------- | -------- | -------- |
| ohos.i18n | unitConvert(fromUnit: UnitInfo, toUnit: UnitInfo, value: number, locale: string, style?: string): string<sup>8+</sup> | Converts one measurement unit (**fromUnit**) into another (**toUnit**) and formats the unit based on the specified locale and style. | | ohos.i18n | unitConvert(fromUnit: UnitInfo, toUnit: UnitInfo, value: number, locale: string, style?: string): string<sup>8+</sup> | Converts one measurement unit (**fromUnit**) into another (**toUnit**) and formats the unit based on the specified locale and style. |
### How to Develop ### How to Develop
1. Convert a measurement unit. 1. Convert a measurement unit.
Call the [unitConvert](../reference/apis/js-apis-i18n.md#unitconvert8) method to convert a measurement unit and format the display result. Call the [unitConvert](../reference/apis/js-apis-i18n.md#unitconvert9) method to convert a measurement unit and format the display result.
```js ```js
...@@ -254,7 +254,7 @@ The **unitConvert** API is provided to help you implement measurement conversion ...@@ -254,7 +254,7 @@ The **unitConvert** API is provided to help you implement measurement conversion
var locale = "en-US"; var locale = "en-US";
var style = "long"; var style = "long";
i18n.Util.unitConvert(fromUtil, toUtil, number, locale, style); i18n.Util.unitConvert(fromUtil, toUtil, number, locale, style);
``` ```
## Alphabet Index ## Alphabet Index
...@@ -278,7 +278,7 @@ The **unitConvert** API is provided to help you implement measurement conversion ...@@ -278,7 +278,7 @@ The **unitConvert** API is provided to help you implement measurement conversion
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. 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.
```js ```js
var indexUtil = i18n.getInstance("zh-CN"); var indexUtil = i18n.getInstance("zh-CN");
``` ```
...@@ -294,7 +294,7 @@ The **unitConvert** API is provided to help you implement measurement conversion ...@@ -294,7 +294,7 @@ The **unitConvert** API is provided to help you implement measurement conversion
3. Add an index. 3. Add an index.
Call the **addLocale** method to add the alphabet index of a new locale to the current index list. Call the **addLocale** method to add the alphabet index of a new locale to the current index list.
```js ```js
indexUtil.addLocale("ar") indexUtil.addLocale("ar")
``` ```
...@@ -302,7 +302,7 @@ The **unitConvert** API is provided to help you implement measurement conversion ...@@ -302,7 +302,7 @@ The **unitConvert** API is provided to help you implement measurement conversion
4. Obtain the index of a string. 4. Obtain the index of a string.
Call the **getIndex** method to obtain the alphabet index of a string. Call the **getIndex** method to obtain the alphabet index of a string.
```js ```js
var text = "access index"; var text = "access index";
indexUtil.getIndex(text); indexUtil.getIndex(text);
...@@ -336,7 +336,7 @@ When a text is displayed in more than one line, [BreakIterator8](../reference/ap ...@@ -336,7 +336,7 @@ When a text is displayed in more than one line, [BreakIterator8](../reference/ap
Call the **getLineInstance** method to instantiate a **BreakIterator** object. Call the **getLineInstance** method to instantiate a **BreakIterator** object.
```js ```js
var locale = "en-US" var locale = "en-US"
var breakIterator = i18n.getLineInstance(locale); var breakIterator = i18n.getLineInstance(locale);
...@@ -357,7 +357,7 @@ When a text is displayed in more than one line, [BreakIterator8](../reference/ap ...@@ -357,7 +357,7 @@ When a text is displayed in more than one line, [BreakIterator8](../reference/ap
Call the **current** method to obtain the current position of the **BreakIterator** object in the text being processed. Call the **current** method to obtain the current position of the **BreakIterator** object in the text being processed.
```js ```js
var pos = breakIterator.current(); var pos = breakIterator.current();
``` ```
...@@ -383,7 +383,9 @@ When a text is displayed in more than one line, [BreakIterator8](../reference/ap ...@@ -383,7 +383,9 @@ When a text is displayed in more than one line, [BreakIterator8](../reference/ap
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. 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.
```js ```js
var isboundary = breakIterator.isBoundary(5); var isboundary = breakIterator.isBoundary(5);
``` ```
```
\ No newline at end of file
...@@ -13,13 +13,13 @@ Use [Locale](../reference/apis/js-apis-intl.md#locale) APIs to maximize or minim ...@@ -13,13 +13,13 @@ Use [Locale](../reference/apis/js-apis-intl.md#locale) APIs to maximize or minim
### Available APIs ### Available APIs
| Module | API | Description | | Module | API | Description |
| -------- | -------- | -------- | | -------- | -------- | -------- |
| ohos.intl | constructor()<sup>8+</sup> | Instantiates a **Locale** object. | | ohos.intl | constructor()<sup>8+</sup> | Instantiates a **Locale** object. |
| ohos.intl | constructor(locale?: string, options?: options) | Instantiates a **Locale** object based on the locale parameter and options. | | ohos.intl | constructor(locale?: string, options?: options) | Instantiates a **Locale** object based on the locale parameter and options. |
| ohos.intl | toString(): string | Converts locale information into a string. | | ohos.intl | toString(): string | Converts locale information into a string. |
| ohos.intl | maximize(): Locale | Maximizes locale information. | | ohos.intl | maximize(): Locale | Maximizes locale information. |
| ohos.intl | minimize(): Locale | Minimizes locale information. | | ohos.intl | minimize(): Locale | Minimizes locale information. |
### How to Develop ### How to Develop
...@@ -81,13 +81,13 @@ Use [DateTimeFormat](../reference/apis/js-apis-intl.md#datetimeformat) APIs to f ...@@ -81,13 +81,13 @@ Use [DateTimeFormat](../reference/apis/js-apis-intl.md#datetimeformat) APIs to f
### Available APIs ### Available APIs
| Module | API | Description | | Module | API | Description |
| -------- | -------- | -------- | | -------- | -------- | -------- |
| ohos.intl | constructor()<sup>8+</sup> | Creates a **DateTimeFormat** object. | | ohos.intl | constructor()<sup>8+</sup> | Creates a **DateTimeFormat** object. |
| ohos.intl | constructor(locale: string \| Array&lt;string&gt;, options?: DateTimeOptions) | Creates a **DateTimeFormat** object and sets the locale and other formatting-related attributes. | | ohos.intl | constructor(locale: string \| Array&lt;string&gt;, options?: DateTimeOptions) | Creates a **DateTimeFormat** object and sets the locale and other formatting-related attributes. |
| ohos.intl | format(date: Date): string | Calculates the date and time based on the locale and other formatting-related attributes of the **DateTimeFormat** object. | | ohos.intl | format(date: Date): string | Calculates the date and time based on the locale and other formatting-related attributes of the **DateTimeFormat** object. |
| ohos.intl | formatRange(startDate: Date, endDate: Date): string | Calculates the period based on the locale and other formatting-related attributes of the **DateTimeFormat** object. | | ohos.intl | formatRange(startDate: Date, endDate: Date): string | Calculates the period based on the locale and other formatting-related attributes of the **DateTimeFormat** object. |
| ohos.intl | resolvedOptions(): DateTimeOptions | Obtains the related attributes of the **DateTimeFormat** object. | | ohos.intl | resolvedOptions(): DateTimeOptions | Obtains the related attributes of the **DateTimeFormat** object. |
### How to Develop ### How to Develop
...@@ -144,12 +144,12 @@ Use [NumberFormat](../reference/apis/js-apis-intl.md#numberformat) APIs to forma ...@@ -144,12 +144,12 @@ Use [NumberFormat](../reference/apis/js-apis-intl.md#numberformat) APIs to forma
### Available APIs ### Available APIs
| Module | API | Description | | Module | API | Description |
| -------- | -------- | -------- | | -------- | -------- | -------- |
| ohos.intl | constructor()<sup>8+</sup> | Creates a **NumberFormat** object. | | ohos.intl | constructor()<sup>8+</sup> | Creates a **NumberFormat** object. |
| ohos.intl | constructor(locale: string \| Array&lt;string&gt;, options?: NumberOptions) | Creates a **NumberFormat** object and sets the locale and other formatting-related attributes. | | ohos.intl | constructor(locale: string \| Array&lt;string&gt;, options?: NumberOptions) | Creates a **NumberFormat** object and sets the locale and other formatting-related attributes. |
| ohos.intl | format(number: number): string | Calculates the number based on the locale and other formatting-related attributes of the **NumberFormat** object. | | ohos.intl | format(number: number): string | Calculates the number based on the locale and other formatting-related attributes of the **NumberFormat** object. |
| ohos.intl | resolvedOptions(): NumberOptions | Obtains attributes of the **NumberFormat** object. | | ohos.intl | resolvedOptions(): NumberOptions | Obtains attributes of the **NumberFormat** object. |
### How to Develop ### How to Develop
...@@ -195,12 +195,12 @@ Use [Collator](../reference/apis/js-apis-intl.md#collator8) APIs to sort strings ...@@ -195,12 +195,12 @@ Use [Collator](../reference/apis/js-apis-intl.md#collator8) APIs to sort strings
### Available APIs ### Available APIs
| Module | API | Description | | Module | API | Description |
| -------- | -------- | -------- | | -------- | -------- | -------- |
| ohos.intl | constructor()<sup>8+</sup> | Creates a **Collator** object. | | ohos.intl | constructor()<sup>8+</sup> | Creates a **Collator** object. |
| ohos.intl | constructor(locale: string \| Array&lt;string&gt;, options?: CollatorOptions)<sup>8+</sup> | Creates a **Collator** object and sets the locale and other related attributes. | | ohos.intl | constructor(locale: string \| Array&lt;string&gt;, options?: CollatorOptions)<sup>8+</sup> | Creates a **Collator** object and sets the locale and other related attributes. |
| ohos.intl | compare(first: string, second: string): number<sup>8+</sup> | Calculates the comparison result of two strings based on the locale and other attributes of the **Collator** object. | | ohos.intl | compare(first: string, second: string): number<sup>8+</sup> | Calculates the comparison result of two strings based on the locale and other attributes of the **Collator** object. |
| ohos.intl | resolvedOptions(): CollatorOptions<sup>8+</sup> | Obtains attributes of the **Collator** object. | | ohos.intl | resolvedOptions(): CollatorOptions<sup>8+</sup> | Obtains attributes of the **Collator** object. |
### How to Develop ### How to Develop
...@@ -214,7 +214,7 @@ Use [Collator](../reference/apis/js-apis-intl.md#collator8) APIs to sort strings ...@@ -214,7 +214,7 @@ Use [Collator](../reference/apis/js-apis-intl.md#collator8) APIs to sort strings
var collator = new intl.Collator(); var collator = new intl.Collator();
``` ```
Alternatively, use your own locale and formatting parameters to create a **Collator** object. For a full list of parameters, see [CollatorOptions](../reference/apis/js-apis-intl.md#collatoroptions8). Alternatively, use your own locale and formatting parameters to create a **Collator** object. For a full list of parameters, see [CollatorOptions](../reference/apis/js-apis-intl.md#collatoroptions9).
```js ```js
var collator= new intl.Collator("zh-CN", {localeMatcher: "best fit", usage: "sort"}); var collator= new intl.Collator("zh-CN", {localeMatcher: "best fit", usage: "sort"});
...@@ -246,11 +246,11 @@ Use [PluralRules](../reference/apis/js-apis-intl.md#pluralrules8) APIs to determ ...@@ -246,11 +246,11 @@ Use [PluralRules](../reference/apis/js-apis-intl.md#pluralrules8) APIs to determ
### Available APIs ### Available APIs
| Module | API | Description | | Module | API | Description |
| -------- | -------- | -------- | | -------- | -------- | -------- |
| ohos.intl | constructor()<sup>8+</sup> | Creates a **PluralRules** object. | | ohos.intl | constructor()<sup>8+</sup> | Creates a **PluralRules** object. |
| ohos.intl | constructor(locale: string \| Array&lt;string&gt;, options?: PluralRulesOptions)<sup>8+</sup> | Creates a **PluralRules** object and sets the locale and other related attributes. | | ohos.intl | constructor(locale: string \| Array&lt;string&gt;, options?: PluralRulesOptions)<sup>8+</sup> | Creates a **PluralRules** object and sets the locale and other related attributes. |
| ohos.intl | select(n: number): string<sup>8+</sup> | Determines the singular-plural type based on the locale and other formatting-related attributes of the **PluralRules** object. | | ohos.intl | select(n: number): string<sup>8+</sup> | Determines the singular-plural type based on the locale and other formatting-related attributes of the **PluralRules** object. |
### How to Develop ### How to Develop
...@@ -264,7 +264,7 @@ Use [PluralRules](../reference/apis/js-apis-intl.md#pluralrules8) APIs to determ ...@@ -264,7 +264,7 @@ Use [PluralRules](../reference/apis/js-apis-intl.md#pluralrules8) APIs to determ
var pluralRules = new intl.PluralRules(); var pluralRules = new intl.PluralRules();
``` ```
Alternatively, use your own locale and formatting parameters to create a **PluralRules** object. For a full list of parameters, see [PluralRulesOptions](../reference/apis/js-apis-intl.md#pluralrulesoptions8). Alternatively, use your own locale and formatting parameters to create a **PluralRules** object. For a full list of parameters, see [PluralRulesOptions](../reference/apis/js-apis-intl.md#pluralrulesoptions9).
```js ```js
var pluralRules = new intl.PluralRules("zh-CN", {localeMatcher: "best fit", type: "cardinal"}); var pluralRules = new intl.PluralRules("zh-CN", {localeMatcher: "best fit", type: "cardinal"});
...@@ -287,13 +287,13 @@ Use [RelativeTimeFormat](../reference/apis/js-apis-intl.md#relativetimeformat8) ...@@ -287,13 +287,13 @@ Use [RelativeTimeFormat](../reference/apis/js-apis-intl.md#relativetimeformat8)
### Available APIs ### Available APIs
| Module | API | Description | | Module | API | Description |
| -------- | -------- | -------- | | -------- | -------- | -------- |
| ohos.intl | constructor()<sup>8+</sup> | Creates a **RelativeTimeFormat** object. | | ohos.intl | constructor()<sup>8+</sup> | Creates a **RelativeTimeFormat** object. |
| ohos.intl | constructor(locale: string \| Array&lt;string&gt;, options?: RelativeTimeFormatInputOptions)<sup>8+</sup> | Creates a **RelativeTimeFormat** object and sets the locale and other formatting-related attributes. | | ohos.intl | constructor(locale: string \| Array&lt;string&gt;, options?: RelativeTimeFormatInputOptions)<sup>8+</sup> | Creates a **RelativeTimeFormat** object and sets the locale and other formatting-related attributes. |
| ohos.intl | format(value: number, unit: string): string<sup>8+</sup> | Calculates the relative time format based on the locale and other formatting-related attributes of the **RelativeTimeFormat** object. | | ohos.intl | format(value: number, unit: string): string<sup>8+</sup> | Calculates the relative time format based on the locale and other formatting-related attributes of the **RelativeTimeFormat** object. |
| ohos.intl | formatToParts(value: number, unit: string): Array&lt;object&gt;<sup>8+</sup> | Returns each part of the relative time format based on the locale and other formatting-related attributes of the **RelativeTimeFormat** object. | | ohos.intl | formatToParts(value: number, unit: string): Array&lt;object&gt;<sup>8+</sup> | Returns each part of the relative time format based on the locale and other formatting-related attributes of the **RelativeTimeFormat** object. |
| ohos.intl | resolvedOptions(): RelativeTimeFormatResolvedOptions<sup>8+</sup> | Obtains attributes of the **RelativeTimeFormat** object. | | ohos.intl | resolvedOptions(): RelativeTimeFormatResolvedOptions<sup>8+</sup> | Obtains attributes of the **RelativeTimeFormat** object. |
### How to Develop ### How to Develop
...@@ -307,7 +307,7 @@ Use [RelativeTimeFormat](../reference/apis/js-apis-intl.md#relativetimeformat8) ...@@ -307,7 +307,7 @@ Use [RelativeTimeFormat](../reference/apis/js-apis-intl.md#relativetimeformat8)
var relativeTimeFormat = new intl.RelativeTimeFormat(); var relativeTimeFormat = new intl.RelativeTimeFormat();
``` ```
Alternatively, use your own locale and formatting parameters to create a **RelativeTimeFormat** object. Formatting parameters are optional. For a full list of formatting parameters, see [RelativeTimeFormatInputOptions](../reference/apis/js-apis-intl.md#relativetimeformatinputoptions8). Alternatively, use your own locale and formatting parameters to create a **RelativeTimeFormat** object. Formatting parameters are optional. For a full list of formatting parameters, see [RelativeTimeFormatInputOptions](../reference/apis/js-apis-intl.md#relativetimeformatinputoptions9).
```js ```js
var relativeTimeFormat = new intl.RelativeTimeFormat("zh-CN", {numeric: "always", style: "long"}); var relativeTimeFormat = new intl.RelativeTimeFormat("zh-CN", {numeric: "always", style: "long"});
......
# Media # Media
- Audio - Audio
- [Audio Overview](audio-overview.md) - [Audio Overview](audio-overview.md)
- [Audio Playback Development](audio-playback.md) - [Audio Playback Development](audio-playback.md)
- [Audio Recording Development](audio-recorder.md) - [Audio Recording Development](audio-recorder.md)
- [Audio Rendering Development](audio-renderer.md) - [Audio Rendering Development](audio-renderer.md)
- [Audio Stream Management Development](audio-stream-manager.md) - [Audio Stream Management Development](audio-stream-manager.md)
- [Audio Capture Development](audio-capturer.md) - [Audio Capture Development](audio-capturer.md)
- [OpenSL ES Audio Playback Development](opensles-playback.md) - [OpenSL ES Audio Playback Development](opensles-playback.md)
- [OpenSL ES Audio Recording Development](opensles-capture.md) - [OpenSL ES Audio Recording Development](opensles-capture.md)
- [Audio Interruption Mode Development](audio-interruptmode.md) - [Audio Interruption Mode Development](audio-interruptmode.md)
- Video - Video
- [Video Playback Development](video-playback.md) - [Video Playback Development](video-playback.md)
- [Video Recording Development](video-recorder.md) - [Video Recording Development](video-recorder.md)
- Image
- Image
- [Image Development](image.md) - [Image Development](image.md)
- Camera - Camera
- [Camera Development](camera.md) - [Camera Development](camera.md)
- [Distributed Camera Development](remote-camera.md) - [Distributed Camera Development](remote-camera.md)
# Audio Capture Development # Audio Capture Development
## When to Use ## Introduction
You can use the APIs provided by **AudioCapturer** to record raw audio files. You can use the APIs provided by **AudioCapturer** to record raw audio files, thereby implementing audio data collection.
### State Check **Status check**: During application development, you are advised to use **on('stateChange')** to subscribe to state changes of the **AudioCapturer** instance. This is because some operations can be performed only when the audio capturer is in a given state. If the application performs an operation when the audio capturer is not in the given state, the system may throw an exception or generate other undefined behavior.
During application development, you are advised to use **on('stateChange')** to subscribe to state changes of the **AudioCapturer** instance. This is because some operations can be performed only when the audio capturer is in a given state. If the application performs an operation when the audio capturer is not in the given state, the system may throw an exception or generate other undefined behavior. ## Working Principles
For details about the APIs, see [AudioCapturer in Audio Management](../reference/apis/js-apis-audio.md#audiocapturer8). This following figure shows the audio capturer state transitions.
**Figure 1** Audio capturer state transitions
![audio-capturer-state](figures/audio-capturer-state.png)
- **PREPARED**: The audio capturer enters this state by calling **create()**.
- **RUNNING**: The audio capturer enters this state by calling **start()** when it is in the **PREPARED** state or by calling **start()** when it is in the **STOPPED** state.
- **STOPPED**: The audio capturer in the **RUNNING** state can call **stop()** to stop playing audio data.
- **RELEASED**: The audio capturer in the **PREPARED** or **STOPPED** state can use **release()** to release all occupied hardware and software resources. It will not transit to any other state after it enters the **RELEASED** state.
**Figure 1** Audio capturer state ## Constraints
![](figures/audio-capturer-state.png) Before developing the audio data collection feature, configure the **ohos.permission.MICROPHONE** permission for your application. For details about permission configuration, see [Permission Application Guide](../security/accesstoken-guidelines.md).
## How to Develop ## How to Develop
For details about the APIs, see [AudioCapturer in Audio Management](../reference/apis/js-apis-audio.md#audiocapturer8).
1. Use **createAudioCapturer()** to create an **AudioCapturer** instance. 1. Use **createAudioCapturer()** to create an **AudioCapturer** instance.
Set parameters of the **AudioCapturer** instance in **audioCapturerOptions**. This instance is used to capture audio, control and obtain the recording status, and register a callback for notification. Set parameters of the **AudioCapturer** instance in **audioCapturerOptions**. This instance is used to capture audio, control and obtain the recording state, and register a callback for notification.
```js ```js
var audioStreamInfo = { import audio from '@ohos.multimedia.audio';
samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
channels: audio.AudioChannel.CHANNEL_1,
sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
}
var audioCapturerInfo = {
source: audio.SourceType.SOURCE_TYPE_MIC,
capturerFlags: 1
}
var audioCapturerOptions = {
streamInfo: audioStreamInfo,
capturerInfo: audioCapturerInfo
}
let audioCapturer = await audio.createAudioCapturer(audioCapturerOptions);
var state = audioRenderer.state;
```
2. (Optional) Use **on('stateChange')** to subscribe to audio renderer state changes.
If an application needs to perform some operations when the audio renderer state is updated, the application can subscribe to the state changes. For more events that can be subscribed to, see [Audio Management](../reference/apis/js-apis-audio.md).
```js let audioStreamInfo = {
audioCapturer.on('stateChange',(state) => { samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
console.info('AudioCapturerLog: Changed State to : ' + state) channels: audio.AudioChannel.CHANNEL_1,
switch (state) { sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
case audio.AudioState.STATE_PREPARED: encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
console.info('--------CHANGE IN AUDIO STATE----------PREPARED--------------'); }
console.info('Audio State is : Prepared');
break; let audioCapturerInfo = {
case audio.AudioState.STATE_RUNNING: source: audio.SourceType.SOURCE_TYPE_MIC,
console.info('--------CHANGE IN AUDIO STATE----------RUNNING--------------'); capturerFlags: 0 // 0 is the extended flag bit of the audio capturer. The default value is 0.
console.info('Audio State is : Running'); }
break;
case audio.AudioState.STATE_STOPPED: let audioCapturerOptions = {
console.info('--------CHANGE IN AUDIO STATE----------STOPPED--------------'); streamInfo: audioStreamInfo,
console.info('Audio State is : stopped'); capturerInfo: audioCapturerInfo
break; }
case audio.AudioState.STATE_RELEASED:
console.info('--------CHANGE IN AUDIO STATE----------RELEASED--------------'); let audioCapturer = await audio.createAudioCapturer(audioCapturerOptions);
console.info('Audio State is : released'); console.log('AudioRecLog: Create audio capturer success.');
break;
default:
console.info('--------CHANGE IN AUDIO STATE----------INVALID--------------');
console.info('Audio State is : invalid');
break;
}
});
``` ```
3. Use **start()** to start audio recording. 2. Use **start()** to start audio recording.
The capturer state will be **STATE_RUNNING** once the audio capturer is started. The application can then begin reading buffers. The capturer state will be **STATE_RUNNING** once the audio capturer is started. The application can then begin reading buffers.
```js ```js
await audioCapturer.start(); import audio from '@ohos.multimedia.audio';
if (audioCapturer.state == audio.AudioState.STATE_RUNNING) {
console.info('AudioRecLog: Capturer started'); async function startCapturer() {
} else { let state = audioCapturer.state;
console.info('AudioRecLog: Capturer start failed'); // The audio capturer should be in the STATE_PREPARED, STATE_PAUSED, or STATE_STOPPED state after being started.
} if (state != audio.AudioState.STATE_PREPARED || state != audio.AudioState.STATE_PAUSED ||
``` state != audio.AudioState.STATE_STOPPED) {
console.info('Capturer is not in a correct state to start');
4. Use **getBufferSize()** to obtain the minimum buffer size to read. return;
}
await audioCapturer.start();
```js let state = audioCapturer.state;
var bufferSize = await audioCapturer.getBufferSize(); if (state == audio.AudioState.STATE_RUNNING) {
console.info('AudioRecLog: buffer size: ' + bufferSize); console.info('AudioRecLog: Capturer started');
} else {
console.error('AudioRecLog: Capturer start failed');
}
}
``` ```
5. Read the captured audio data and convert it to a byte stream. Call **read()** repeatedly to read the data until the application wants to stop the recording. 3. Read the captured audio data and convert it to a byte stream. Call **read()** repeatedly to read the data until the application stops the recording.
The following example shows how to write recorded data into a file. The following example shows how to write recorded data into a file.
```js ```js
import fileio from '@ohos.fileio'; import fileio from '@ohos.fileio';
let state = audioCapturer.state;
// The read operation can be performed only when the state is STATE_RUNNING.
if (state != audio.AudioState.STATE_RUNNING) {
console.info('Capturer is not in a correct state to read');
return;
}
const path = '/data/data/.pulse_dir/capture_js.wav'; const path = '/data/data/.pulse_dir/capture_js.wav'; // Path for storing the collected audio file.
let fd = fileio.openSync(path, 0o102, 0o777); let fd = fileio.openSync(path, 0o102, 0o777);
if (fd !== null) { if (fd !== null) {
console.info('AudioRecLog: file fd created'); console.info('AudioRecLog: file fd created');
...@@ -115,38 +110,140 @@ If an application needs to perform some operations when the audio renderer state ...@@ -115,38 +110,140 @@ If an application needs to perform some operations when the audio renderer state
console.info('AudioRecLog: file fd opened in append mode'); console.info('AudioRecLog: file fd opened in append mode');
} }
var numBuffersToCapture = 150; let numBuffersToCapture = 150; // Write data for 150 times.
while (numBuffersToCapture) { while (numBuffersToCapture) {
var buffer = await audioCapturer.read(bufferSize, true); let buffer = await audioCapturer.read(bufferSize, true);
if (typeof(buffer) == undefined) { if (typeof(buffer) == undefined) {
console.info('read buffer failed'); console.info('AudioRecLog: read buffer failed');
} else { } else {
var number = fileio.writeSync(fd, buffer); let number = fileio.writeSync(fd, buffer);
console.info('AudioRecLog: data written: ' + number); console.info(`AudioRecLog: data written: ${number}`);
} }
numBuffersToCapture--; numBuffersToCapture--;
} }
``` ```
6. Once the recording is complete, call **stop()** to stop the recording. 4. Once the recording is complete, call **stop()** to stop the recording.
```js
async function StopCapturer() {
let state = audioCapturer.state;
// The audio capturer can be stopped only when it is in STATE_RUNNING or STATE_PAUSED state.
if (state != audio.AudioState.STATE_RUNNING && state != audio.AudioState.STATE_PAUSED) {
console.info('AudioRecLog: Capturer is not running or paused');
return;
}
await audioCapturer.stop();
state = audioCapturer.state;
if (state == audio.AudioState.STATE_STOPPED) {
console.info('AudioRecLog: Capturer stopped');
} else {
console.error('AudioRecLog: Capturer stop failed');
}
}
``` ```
await audioCapturer.stop();
if (audioCapturer.state == audio.AudioState.STATE_STOPPED) { 5. After the task is complete, call **release()** to release related resources.
console.info('AudioRecLog: Capturer stopped');
} else { ```js
console.info('AudioRecLog: Capturer stop failed'); async function releaseCapturer() {
} let state = audioCapturer.state;
// The audio capturer can be released only when it is not in the STATE_RELEASED or STATE_NEW state.
if (state == audio.AudioState.STATE_RELEASED || state == audio.AudioState.STATE_NEW) {
console.info('AudioRecLog: Capturer already released');
return;
}
await audioCapturer.release();
state = audioCapturer.state;
if (state == audio.AudioState.STATE_RELEASED) {
console.info('AudioRecLog: Capturer released');
} else {
console.info('AudioRecLog: Capturer release failed');
}
}
``` ```
7. After the task is complete, call **release()** to release related resources. 6. (Optional) Obtain the audio capturer information.
You can use the following code to obtain the audio capturer information:
```js ```js
await audioCapturer.release(); // Obtain the audio capturer state.
if (audioCapturer.state == audio.AudioState.STATE_RELEASED) { let state = audioCapturer.state;
console.info('AudioRecLog: Capturer released');
} else { // Obtain the audio capturer information.
console.info('AudioRecLog: Capturer release failed'); let audioCapturerInfo : audio.AuduioCapturerInfo = await audioCapturer.getCapturerInfo();
}
// Obtain the audio stream information.
let audioStreamInfo : audio.AudioStreamInfo = await audioCapturer.getStreamInfo();
// Obtain the audio stream ID.
let audioStreamId : number = await audioCapturer.getAudioStreamId();
// Obtain the Unix timestamp, in nanoseconds.
let audioTime : number = await audioCapturer.getAudioTime();
// Obtain a proper minimum buffer size.
let bufferSize : number = await audioCapturer.getBuffersize();
``` ```
7. (Optional) Use **on('markReach')** to subscribe to the mark reached event, and use **off('markReach')** to unsubscribe from the event.
After the mark reached event is subscribed to, when the number of frames collected by the audio capturer reaches the specified value, a callback is triggered and the specified value is returned.
```js
audioCapturer.on('markReach', (reachNumber) => {
console.info('Mark reach event Received');
console.info(`The Capturer reached frame: ${reachNumber}`);
});
audioCapturer.off('markReach'); // Unsubscribe from the mark reached event. This event will no longer be listened for.
```
8. (Optional) Use **on('periodReach')** to subscribe to the period reached event, and use **off('periodReach')** to unsubscribe from the event.
After the period reached event is subscribed to, each time the number of frames collected by the audio capturer reaches the specified value, a callback is triggered and the specified value is returned.
```js
audioCapturer.on('periodReach', (reachNumber) => {
console.info('Period reach event Received');
console.info(`In this period, the Capturer reached frame: ${reachNumber}`);
});
audioCapturer.off('periodReach'); // Unsubscribe from the period reached event. This event will no longer be listened for.
```
9. If your application needs to perform some operations when the audio capturer state is updated, it can subscribe to the state change event. When the audio capturer state is updated, the application receives a callback containing the event type.
```js
audioCapturer.on('stateChange', (state) => {
console.info(`AudioCapturerLog: Changed State to : ${state}`)
switch (state) {
case audio.AudioState.STATE_PREPARED:
console.info('--------CHANGE IN AUDIO STATE----------PREPARED--------------');
console.info('Audio State is : Prepared');
break;
case audio.AudioState.STATE_RUNNING:
console.info('--------CHANGE IN AUDIO STATE----------RUNNING--------------');
console.info('Audio State is : Running');
break;
case audio.AudioState.STATE_STOPPED:
console.info('--------CHANGE IN AUDIO STATE----------STOPPED--------------');
console.info('Audio State is : stopped');
break;
case audio.AudioState.STATE_RELEASED:
console.info('--------CHANGE IN AUDIO STATE----------RELEASED--------------');
console.info('Audio State is : released');
break;
default:
console.info('--------CHANGE IN AUDIO STATE----------INVALID--------------');
console.info('Audio State is : invalid');
break;
}
});
```
# Audio Interruption Mode Development # Audio Interruption Mode Development
## When to Use ## Introduction
The audio interruption mode is used to control the playback of multiple audio streams.<br> The audio interruption mode is used to control the playback of multiple audio streams.
Audio applications can set the audio interruption mode to independent or shared under **AudioRenderer**.<br>
In shared mode, multiple audio streams share one session ID. In independent mode, each audio stream has an independent session ID. Audio applications can set the audio interruption mode to independent or shared under **AudioRenderer**.
### Asynchronous Operations In shared mode, multiple audio streams share one session ID. In independent mode, each audio stream has an independent session ID.
To prevent the UI thread from being blocked, most **AudioRenderer** calls are asynchronous. Each API provides the callback and promise functions. The following examples use the promise functions. **Asynchronous operation**: To prevent the UI thread from being blocked, most **AudioRenderer** calls are asynchronous. Each API provides the callback and promise functions. The following examples use the promise functions.
## How to Develop ## How to Develop
For details about the APIs, see [AudioRenderer in Audio Management](../reference/apis/js-apis-audio.md#audiorenderer8). For details about the APIs, see [AudioRenderer in Audio Management](../reference/apis/js-apis-audio.md#audiorenderer8).
1. Use **createAudioRenderer()** to create an **AudioRenderer** instance.
Set parameters of the **AudioRenderer** instance in **audioRendererOptions**.
1. Use **createAudioRenderer()** to create an **AudioRenderer** instance.<br> This instance is used to render audio, control and obtain the rendering status, and register a callback for notification.
Set parameters of the **AudioRenderer** instance in **audioRendererOptions**.<br>
This instance is used to render audio, control and obtain the rendering status, and register a callback for notification.<br> ```js
```js
import audio from '@ohos.multimedia.audio'; import audio from '@ohos.multimedia.audio';
var audioStreamInfo = {
samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
channels: audio.AudioChannel.CHANNEL_1,
sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
}
var audioRendererInfo = { var audioStreamInfo = {
content: audio.ContentType.CONTENT_TYPE_SPEECH, samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
usage: audio.StreamUsage.STREAM_USAGE_VOICE_COMMUNICATION, channels: audio.AudioChannel.CHANNEL_1,
rendererFlags: 1 sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
} encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
}
var audioRendererInfo = {
content: audio.ContentType.CONTENT_TYPE_SPEECH,
usage: audio.StreamUsage.STREAM_USAGE_VOICE_COMMUNICATION,
rendererFlags: 1
}
var audioRendererOptions = { var audioRendererOptions = {
streamInfo: audioStreamInfo, streamInfo: audioStreamInfo,
rendererInfo: audioRendererInfo rendererInfo: audioRendererInfo
} }
let audioRenderer = await audio.createAudioRenderer(audioRendererOptions); let audioRenderer = await audio.createAudioRenderer(audioRendererOptions);
``` ```
2. Set the audio interruption mode.
2. Set the audio interruption mode.
After the **AudioRenderer** instance is initialized, you can set the audio interruption mode.<br> After the **AudioRenderer** instance is initialized, you can set the audio interruption mode.<br>
```js ```js
......
# Audio Playback Development # Audio Playback Development
## When to Use ## Introduction
You can use audio playback APIs to convert audio data into audible analog signals, play the signals using output devices, and manage playback tasks. You can use audio playback APIs to convert audio data into audible analog signals and play the signals using output devices. You can also manage playback tasks. For example, you can start, suspend, stop playback, release resources, set the volume, seek to a playback position, and obtain track information.
**Figure 1** Playback status ## Working Principles
The following figures show the audio playback status changes and the interaction with external modules for audio playback.
**Figure 1** Audio playback state transition
![en-us_image_audio_state_machine](figures/en-us_image_audio_state_machine.png) ![en-us_image_audio_state_machine](figures/en-us_image_audio_state_machine.png)
**Note**: If the status is **Idle**, setting the **src** attribute does not change the status. In addition, after the **src** attribute is set successfully, you must call **reset()** before setting it to another value. **NOTE**: If the status is **Idle**, setting the **src** attribute does not change the status. In addition, after the **src** attribute is set successfully, you must call **reset()** before setting it to another value.
**Figure 2** Layer 0 diagram of audio playback **Figure 2** Interaction with external modules for audio playback
![en-us_image_audio_player](figures/en-us_image_audio_player.png) ![en-us_image_audio_player](figures/en-us_image_audio_player.png)
**NOTE**: When a third-party application calls the JS interface provided by the JS interface layer to implement a feature, the framework layer invokes the audio component through the media service of the native framework and outputs the audio data decoded by the software to the audio HDI of the hardware interface layer to implement audio playback.
## How to Develop ## How to Develop
For details about the APIs, see [AudioPlayer in the Media API](../reference/apis/js-apis-media.md#audioplayer). For details about the APIs, see [AudioPlayer in the Media API](../reference/apis/js-apis-media.md#audioplayer).
> **NOTE**
>
> The method for obtaining the path in the FA model is different from that in the stage model. **pathDir** used in the sample code below is an example. You need to obtain the path based on project requirements. For details about how to obtain the path, see [Application Sandbox Path Guidelines](../reference/apis/js-apis-fileio.md#guidelines).
### Full-Process Scenario ### Full-Process Scenario
The full audio playback process includes creating an instance, setting the URI, playing audio, seeking to the playback position, setting the volume, pausing playback, obtaining track information, stopping playback, resetting the player, and releasing resources. The full audio playback process includes creating an instance, setting the URI, playing audio, seeking to the playback position, setting the volume, pausing playback, obtaining track information, stopping playback, resetting the player, and releasing resources.
...@@ -99,8 +109,9 @@ async function audioPlayerDemo() { ...@@ -99,8 +109,9 @@ async function audioPlayerDemo() {
setCallBack(audioPlayer); // Set the event callbacks. setCallBack(audioPlayer); // Set the event callbacks.
// 2. Set the URI of the audio file. // 2. Set the URI of the audio file.
let fdPath = 'fd://' 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 pathDir = "/data/storage/el2/base/haps/entry/files" // The method for obtaining pathDir in the FA model is different from that in the stage model. For details, see NOTE just below How to Develop. You need to obtain pathDir based on project requirements.
let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile/01.mp3'; // The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" command.
let path = pathDir + '/01.mp3'
await fileIO.open(path).then((fdNumber) => { await fileIO.open(path).then((fdNumber) => {
fdPath = fdPath + '' + fdNumber; fdPath = fdPath + '' + fdNumber;
console.info('open fd success fd is' + fdPath); console.info('open fd success fd is' + fdPath);
...@@ -118,6 +129,7 @@ async function audioPlayerDemo() { ...@@ -118,6 +129,7 @@ async function audioPlayerDemo() {
```js ```js
import media from '@ohos.multimedia.media' import media from '@ohos.multimedia.media'
import fileIO from '@ohos.fileio' import fileIO from '@ohos.fileio'
export class AudioDemo { export class AudioDemo {
// Set the player callbacks. // Set the player callbacks.
setCallBack(audioPlayer) { setCallBack(audioPlayer) {
...@@ -139,8 +151,9 @@ export class AudioDemo { ...@@ -139,8 +151,9 @@ export class AudioDemo {
let audioPlayer = media.createAudioPlayer(); // Create an AudioPlayer instance. let audioPlayer = media.createAudioPlayer(); // Create an AudioPlayer instance.
this.setCallBack(audioPlayer); // Set the event callbacks. this.setCallBack(audioPlayer); // Set the event callbacks.
let fdPath = 'fd://' 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 pathDir = "/data/storage/el2/base/haps/entry/files" // The method for obtaining pathDir in the FA model is different from that in the stage model. For details, see NOTE just below How to Develop. You need to obtain pathDir based on project requirements.
let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile/01.mp3'; // The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" command.
let path = pathDir + '/01.mp3'
await fileIO.open(path).then((fdNumber) => { await fileIO.open(path).then((fdNumber) => {
fdPath = fdPath + '' + fdNumber; fdPath = fdPath + '' + fdNumber;
console.info('open fd success fd is' + fdPath); console.info('open fd success fd is' + fdPath);
...@@ -159,6 +172,7 @@ export class AudioDemo { ...@@ -159,6 +172,7 @@ export class AudioDemo {
```js ```js
import media from '@ohos.multimedia.media' import media from '@ohos.multimedia.media'
import fileIO from '@ohos.fileio' import fileIO from '@ohos.fileio'
export class AudioDemo { export class AudioDemo {
// Set the player callbacks. // Set the player callbacks.
private isNextMusic = false; private isNextMusic = false;
...@@ -185,8 +199,9 @@ export class AudioDemo { ...@@ -185,8 +199,9 @@ export class AudioDemo {
async nextMusic(audioPlayer) { async nextMusic(audioPlayer) {
this.isNextMusic = true; this.isNextMusic = true;
let nextFdPath = 'fd://' let nextFdPath = 'fd://'
// The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\02.mp3 /data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile" command. let pathDir = "/data/storage/el2/base/haps/entry/files" // The method for obtaining pathDir in the FA model is different from that in the stage model. For details, see NOTE just below How to Develop. You need to obtain pathDir based on project requirements.
let nextpath = '/data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile/02.mp3'; // The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\02.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" command.
let nextpath = pathDir + '/02.mp3'
await fileIO.open(nextpath).then((fdNumber) => { await fileIO.open(nextpath).then((fdNumber) => {
nextFdPath = nextFdPath + '' + fdNumber; nextFdPath = nextFdPath + '' + fdNumber;
console.info('open fd success fd is' + nextFdPath); console.info('open fd success fd is' + nextFdPath);
...@@ -202,8 +217,9 @@ export class AudioDemo { ...@@ -202,8 +217,9 @@ export class AudioDemo {
let audioPlayer = media.createAudioPlayer(); // Create an AudioPlayer instance. let audioPlayer = media.createAudioPlayer(); // Create an AudioPlayer instance.
this.setCallBack(audioPlayer); // Set the event callbacks. this.setCallBack(audioPlayer); // Set the event callbacks.
let fdPath = 'fd://' 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 pathDir = "/data/storage/el2/base/haps/entry/files" // The method for obtaining pathDir in the FA model is different from that in the stage model. For details, see NOTE just below How to Develop. You need to obtain pathDir based on project requirements.
let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile/01.mp3'; // The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" command.
let path = pathDir + '/01.mp3'
await fileIO.open(path).then((fdNumber) => { await fileIO.open(path).then((fdNumber) => {
fdPath = fdPath + '' + fdNumber; fdPath = fdPath + '' + fdNumber;
console.info('open fd success fd is' + fdPath); console.info('open fd success fd is' + fdPath);
...@@ -222,6 +238,7 @@ export class AudioDemo { ...@@ -222,6 +238,7 @@ export class AudioDemo {
```js ```js
import media from '@ohos.multimedia.media' import media from '@ohos.multimedia.media'
import fileIO from '@ohos.fileio' import fileIO from '@ohos.fileio'
export class AudioDemo { export class AudioDemo {
// Set the player callbacks. // Set the player callbacks.
setCallBack(audioPlayer) { setCallBack(audioPlayer) {
...@@ -239,8 +256,9 @@ export class AudioDemo { ...@@ -239,8 +256,9 @@ export class AudioDemo {
let audioPlayer = media.createAudioPlayer(); // Create an AudioPlayer instance. let audioPlayer = media.createAudioPlayer(); // Create an AudioPlayer instance.
this.setCallBack(audioPlayer); // Set the event callbacks. this.setCallBack(audioPlayer); // Set the event callbacks.
let fdPath = 'fd://' 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 pathDir = "/data/storage/el2/base/haps/entry/files" // The method for obtaining pathDir in the FA model is different from that in the stage model. For details, see NOTE just below How to Develop. You need to obtain pathDir based on project requirements.
let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile/01.mp3'; // The stream in the path can be pushed to the device by running the "hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" command.
let path = pathDir + '/01.mp3'
await fileIO.open(path).then((fdNumber) => { await fileIO.open(path).then((fdNumber) => {
fdPath = fdPath + '' + fdNumber; fdPath = fdPath + '' + fdNumber;
console.info('open fd success fd is' + fdPath); console.info('open fd success fd is' + fdPath);
......
# Audio Recording Development # Audio Recording Development
## When to Use ## Introduction
During audio recording, audio signals are captured, encoded, and saved to files. You can specify parameters such as the sampling rate, number of audio channels, encoding format, encapsulation format, and file path for audio recording. During audio recording, audio signals are captured, encoded, and saved to files. You can specify parameters such as the sampling rate, number of audio channels, encoding format, encapsulation format, and output file path for audio recording.
## Working Principles
The following figures show the audio recording state transition and the interaction with external modules for audio recording.
**Figure 1** Audio recording state transition **Figure 1** Audio recording state transition
...@@ -10,10 +14,16 @@ During audio recording, audio signals are captured, encoded, and saved to files. ...@@ -10,10 +14,16 @@ During audio recording, audio signals are captured, encoded, and saved to files.
**Figure 2** Layer 0 diagram of audio recording **Figure 2** Interaction with external modules for audio recording
![en-us_image_audio_recorder_zero](figures/en-us_image_audio_recorder_zero.png) ![en-us_image_audio_recorder_zero](figures/en-us_image_audio_recorder_zero.png)
**NOTE**: When a third-party recording application or recorder calls the JS interface provided by the JS interface layer to implement a feature, the framework layer invokes the audio component through the media service of the native framework to obtain the audio data captured through the audio HDI. The framework layer then encodes the audio data through software and saves the encoded and encapsulated audio data to a file to implement audio recording.
## Constraints
Before developing audio recording, configure the **ohos.permission.MICROPHONE** permission for your application. For details about the configuration, see [Permission Application Guide](../security/accesstoken-guidelines.md).
## How to Develop ## How to Develop
For details about the APIs, see [AudioRecorder in the Media API](../reference/apis/js-apis-media.md#audiorecorder). For details about the APIs, see [AudioRecorder in the Media API](../reference/apis/js-apis-media.md#audiorecorder).
......
此差异已折叠。
此差异已折叠。
# OpenSL ES Audio Recording Development # OpenSL ES Audio Recording Development
## When to Use ## Introduction
You can use OpenSL ES to develop the audio recording 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. You can use OpenSL ES to develop the audio recording 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.
......
# OpenSL ES Audio Playback Development # OpenSL ES Audio Playback Development
## When to Use ## Introduction
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. 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.
...@@ -58,7 +58,7 @@ To use OpenSL ES to develop the audio playback function in OpenHarmony, perform ...@@ -58,7 +58,7 @@ To use OpenSL ES to develop the audio playback function in OpenHarmony, perform
5. Obtain the **bufferQueueItf** instance of the **SL_IID_OH_BUFFERQUEUE** interface. 5. Obtain the **bufferQueueItf** instance of the **SL_IID_OH_BUFFERQUEUE** interface.
``` ```c++
SLOHBufferQueueItf bufferQueueItf; SLOHBufferQueueItf bufferQueueItf;
(*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf); (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
``` ```
......
# Video Playback Development # Video Playback Development
## When to Use ## Introduction
You can use video playback APIs to convert video data into visible signals, play the signals using output devices, and manage playback tasks. This document describes development for the following video playback scenarios: full-process, normal playback, video switching, and loop playback. You can use video playback APIs to convert audio data into audible analog signals and play the signals using output devices. You can also manage playback tasks. For example, you can start, suspend, stop playback, release resources, set the volume, seek to a playback position, set the playback speed, and obtain track information. This document describes development for the following video playback scenarios: full-process, normal playback, video switching, and loop playback.
## Working Principles
The following figures show the video playback state transition and the interaction with external modules for video playback.
**Figure 1** Video playback state transition **Figure 1** Video playback state transition
![en-us_image_video_state_machine](figures/en-us_image_video_state_machine.png) ![en-us_image_video_state_machine](figures/en-us_image_video_state_machine.png)
**Figure 2** Layer 0 diagram of video playback **Figure 2** Interaction with external modules for video playback
![en-us_image_video_player](figures/en-us_image_video_player.png) ![en-us_image_video_player](figures/en-us_image_video_player.png)
**NOTE**: When a third-party application calls a JS interface provided by the JS interface layer, the framework layer invokes the audio component through the media service of the native framework to output the audio data decoded by the software to the audio HDI. The graphics subsystem outputs the image data decoded by the codec HDI at the hardware interface layer to the display HDI. In this way, video playback is implemented.
*Note: Video playback requires hardware capabilities such as display, audio, and codec.* *Note: Video playback requires hardware capabilities such as display, audio, and codec.*
1. A third-party application obtains a surface ID from the XComponent. 1. A third-party application obtains a surface ID from the XComponent.
......
...@@ -4,5 +4,4 @@ ...@@ -4,5 +4,4 @@
- [Drawing Development](drawing-guidelines.md) - [Drawing Development](drawing-guidelines.md)
- [Raw File Development](rawfile-guidelines.md) - [Raw File Development](rawfile-guidelines.md)
- [Native Window Development](native-window-guidelines.md) - [Native Window Development](native-window-guidelines.md)
- [Using MindSpore Lite for Model Inference](mindspore-lite-guidelines.md)
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册