提交 8f932b9b 编写于 作者: W wangshuainan1 提交者: Gitee

Merge branch 'OpenHarmony-3.2-Beta3' of gitee.com:openharmony/docs into OpenHarmony-3.2-Beta3

Signed-off-by: Nwangshuainan1 <wangshuainan1@huawei.com>

要显示的变更太多。

To preserve performance only 1000 of 1000+ files are displayed.
...@@ -29,11 +29,22 @@ zh-cn/device-dev/quick-start/quickstart-lite-env-setup.md @li-yan339 @chenmudan ...@@ -29,11 +29,22 @@ zh-cn/device-dev/quick-start/quickstart-lite-env-setup.md @li-yan339 @chenmudan
zh-cn/device-dev/porting/porting-thirdparty-overview.md @Austin23 @chenmudan zh-cn/device-dev/porting/porting-thirdparty-overview.md @Austin23 @chenmudan
zh-cn/device-dev/porting/porting-thirdparty-makefile.md @Austin23 @chenmudan zh-cn/device-dev/porting/porting-thirdparty-makefile.md @Austin23 @chenmudan
zh-cn/device-dev/porting/porting-thirdparty-cmake.md @Austin23 @chenmudan zh-cn/device-dev/porting/porting-thirdparty-cmake.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-build-mini-lite.md @Austin23 @chenmudan zh-cn/device-dev/subsystems/subsys-build-all.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-build-standard-large.md @Austin23 @chenmudan zh-cn/device-dev/subsystems/subsys-build-gn-coding-style-and-best-practice.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-build-gn-coding-style-and-best-practice.md @Austin23 @chenmudan zh-cn/device-dev/subsystems/subsys-build-gn-kconfig-visual-config-guide.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-build-gn-kconfig-visual-config-guid.md @Austin23 @chenmudan zh-cn/device-dev/subsystems/subsys-build-product.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-build-gn-hap-compilation-guide.md @Austin23 @chenmudan zh-cn/device-dev/subsystems/subsys-build-zh-cn/device-dev/subsystems/subsystem.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-build-component.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-build-module.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-build-chip_solution.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-build-feature.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-build-syscap.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-build-reference.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-build-reference.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-build-reference.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-build-reference.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-build-gn-hap-compilation-guide.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-build-FAQ.md @Austin23 @chenmudan
zh-cn/device-dev/subsystems/subsys-remote-start.md @duangavin123_admin zh-cn/device-dev/subsystems/subsys-remote-start.md @duangavin123_admin
zh-cn/device-dev/subsystems/subsys-graphics-overview.md @duangavin123_admin zh-cn/device-dev/subsystems/subsys-graphics-overview.md @duangavin123_admin
zh-cn/device-dev/subsystems/subsys-graphics-container-guide.md @duangavin123_admin zh-cn/device-dev/subsystems/subsys-graphics-container-guide.md @duangavin123_admin
...@@ -140,9 +151,9 @@ zh-cn/application-dev/work-scheduler/ @HelloCrease ...@@ -140,9 +151,9 @@ zh-cn/application-dev/work-scheduler/ @HelloCrease
zh-cn/application-dev/internationalization/ @HelloCrease zh-cn/application-dev/internationalization/ @HelloCrease
zh-cn/application-dev/device/usb-overview.md @ge-yafang zh-cn/application-dev/device/usb-overview.md @ge-yafang
zh-cn/application-dev/device/usb-guidelines.md @ge-yafang zh-cn/application-dev/device/usb-guidelines.md @ge-yafang
zh-cn/application-dev/device/device-location-overview.md @sun-yue14 zh-cn/application-dev/device/device-location-overview.md @zengyawen
zh-cn/application-dev/device/device-location-info.md @sun-yue14 zh-cn/application-dev/device/device-location-info.md @zengyawen
zh-cn/application-dev/device/device-location-geocoding.md @sun-yue14 zh-cn/application-dev/device/device-location-geocoding.md @zengyawen
zh-cn/application-dev/device/sensor-overview.md @HelloCrease zh-cn/application-dev/device/sensor-overview.md @HelloCrease
zh-cn/application-dev/device/sensor-guidelines.md @HelloCrease zh-cn/application-dev/device/sensor-guidelines.md @HelloCrease
zh-cn/application-dev/device/vibrator-overview.md @HelloCrease zh-cn/application-dev/device/vibrator-overview.md @HelloCrease
...@@ -210,6 +221,7 @@ zh-cn/application-dev/reference/apis/js-apis-router.md @HelloCrease ...@@ -210,6 +221,7 @@ zh-cn/application-dev/reference/apis/js-apis-router.md @HelloCrease
zh-cn/application-dev/reference/apis/js-apis-display.md @ge-yafang zh-cn/application-dev/reference/apis/js-apis-display.md @ge-yafang
zh-cn/application-dev/reference/apis/js-apis-screenshot.md @ge-yafang zh-cn/application-dev/reference/apis/js-apis-screenshot.md @ge-yafang
zh-cn/application-dev/reference/apis/js-apis-window.md @ge-yafang zh-cn/application-dev/reference/apis/js-apis-window.md @ge-yafang
zh-cn/application-dev/reference/apis/js-apis-effectKit.md @ge-yafang
zh-cn/application-dev/reference/apis/js-apis-application-WindowExtensionAbility.md @ge-yafang zh-cn/application-dev/reference/apis/js-apis-application-WindowExtensionAbility.md @ge-yafang
zh-cn/application-dev/reference/apis/js-apis-screen.md @ge-yafang zh-cn/application-dev/reference/apis/js-apis-screen.md @ge-yafang
zh-cn/application-dev/reference/apis/js-apis-windowAnimationManager.md @ge-yafang zh-cn/application-dev/reference/apis/js-apis-windowAnimationManager.md @ge-yafang
...@@ -265,14 +277,14 @@ zh-cn/application-dev/reference/apis/js-apis-http.md @zengyawen ...@@ -265,14 +277,14 @@ zh-cn/application-dev/reference/apis/js-apis-http.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-request.md @zengyawen zh-cn/application-dev/reference/apis/js-apis-request.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-socket.md @zengyawen zh-cn/application-dev/reference/apis/js-apis-socket.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-webSocket.md @zengyawen zh-cn/application-dev/reference/apis/js-apis-webSocket.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-bluetooth.md @bmeangel zh-cn/application-dev/reference/apis/js-apis-bluetooth.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-nfcTag.md @bmeangel zh-cn/application-dev/reference/apis/js-apis-nfcTag.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-nfcTech.md @bmeangel zh-cn/application-dev/reference/apis/js-apis-nfcTech.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-tagSession.md @bmeangel zh-cn/application-dev/reference/apis/js-apis-tagSession.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-connectedTag.md @bmeangel zh-cn/application-dev/reference/apis/js-apis-connectedTag.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-rpc.md @qinxiaowang zh-cn/application-dev/reference/apis/js-apis-rpc.md @qinxiaowang
zh-cn/application-dev/reference/apis/js-apis-wifi.md @bmeangel zh-cn/application-dev/reference/apis/js-apis-wifi.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-wifiext.md @bmeangel zh-cn/application-dev/reference/apis/js-apis-wifiext.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-accessibility.md @qinxiaowang zh-cn/application-dev/reference/apis/js-apis-accessibility.md @qinxiaowang
zh-cn/application-dev/reference/apis/js-apis-faultLogger.md @zengyawen zh-cn/application-dev/reference/apis/js-apis-faultLogger.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-hiappevent.md @zengyawen zh-cn/application-dev/reference/apis/js-apis-hiappevent.md @zengyawen
...@@ -281,18 +293,18 @@ zh-cn/application-dev/reference/apis/js-apis-hidebug.md @zengyawen ...@@ -281,18 +293,18 @@ zh-cn/application-dev/reference/apis/js-apis-hidebug.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-hilog.md @zengyawen zh-cn/application-dev/reference/apis/js-apis-hilog.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-hitracechain.md @zengyawen zh-cn/application-dev/reference/apis/js-apis-hitracechain.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-hitracemeter.md @zengyawen zh-cn/application-dev/reference/apis/js-apis-hitracemeter.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-inputmethod.md @bmeangel zh-cn/application-dev/reference/apis/js-apis-inputmethod.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-inputmethodengine.md @bmeangel zh-cn/application-dev/reference/apis/js-apis-inputmethodengine.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-pasteboard.md @ge-yafang zh-cn/application-dev/reference/apis/js-apis-pasteboard.md @ge-yafang
zh-cn/application-dev/reference/apis/js-apis-screen-lock.md @bmeangel zh-cn/application-dev/reference/apis/js-apis-screen-lock.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-system-time.md @bmeangel zh-cn/application-dev/reference/apis/js-apis-system-time.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-wallpaper.md @bmeangel zh-cn/application-dev/reference/apis/js-apis-wallpaper.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-timer.md @HelloCrease zh-cn/application-dev/reference/apis/js-apis-timer.md @HelloCrease
zh-cn/application-dev/reference/apis/js-apis-battery-info.md @qinxiaowang zh-cn/application-dev/reference/apis/js-apis-battery-info.md @qinxiaowang
zh-cn/application-dev/reference/apis/js-apis-brightness.md @qinxiaowang zh-cn/application-dev/reference/apis/js-apis-brightness.md @qinxiaowang
zh-cn/application-dev/reference/apis/js-apis-device-info.md @qinxiaowang zh-cn/application-dev/reference/apis/js-apis-device-info.md @qinxiaowang
zh-cn/application-dev/reference/apis/js-apis-device-manager.md zh-cn/application-dev/reference/apis/js-apis-device-manager.md
zh-cn/application-dev/reference/apis/js-apis-geolocation.md @sun-yue14 zh-cn/application-dev/reference/apis/js-apis-geolocation.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-inputconsumer.md @HelloCrease zh-cn/application-dev/reference/apis/js-apis-inputconsumer.md @HelloCrease
zh-cn/application-dev/reference/apis/js-apis-inputdevice.md @HelloCrease zh-cn/application-dev/reference/apis/js-apis-inputdevice.md @HelloCrease
zh-cn/application-dev/reference/apis/js-apis-inputeventclient.md @HelloCrease zh-cn/application-dev/reference/apis/js-apis-inputeventclient.md @HelloCrease
...@@ -305,6 +317,7 @@ zh-cn/application-dev/reference/apis/js-apis-system-parameter.md @qinxiaowang ...@@ -305,6 +317,7 @@ zh-cn/application-dev/reference/apis/js-apis-system-parameter.md @qinxiaowang
zh-cn/application-dev/reference/apis/js-apis-thermal.md @qinxiaowang zh-cn/application-dev/reference/apis/js-apis-thermal.md @qinxiaowang
zh-cn/application-dev/reference/apis/js-apis-update.md @HelloCrease zh-cn/application-dev/reference/apis/js-apis-update.md @HelloCrease
zh-cn/application-dev/reference/apis/js-apis-usb.md @ge-yafang zh-cn/application-dev/reference/apis/js-apis-usb.md @ge-yafang
zh-cn/application-dev/reference/apis/js-apis-colorSpaceManager.mdd @ge-yafang
zh-cn/application-dev/reference/apis/js-apis-vibrator.md @HelloCrease zh-cn/application-dev/reference/apis/js-apis-vibrator.md @HelloCrease
zh-cn/application-dev/reference/apis/js-apis-appAccount.md @zengyawen zh-cn/application-dev/reference/apis/js-apis-appAccount.md @zengyawen
zh-cn/application-dev/reference/apis/js-apis-distributed-account.md @zengyawen zh-cn/application-dev/reference/apis/js-apis-distributed-account.md @zengyawen
...@@ -352,4 +365,8 @@ zh-cn/application-dev/reference/apis/js-apis-buffer.md @zengyawen ...@@ -352,4 +365,8 @@ zh-cn/application-dev/reference/apis/js-apis-buffer.md @zengyawen
zh-cn/application-dev/reference/js-service-widget-ui @HelloCrease zh-cn/application-dev/reference/js-service-widget-ui @HelloCrease
zh-cn/application-dev/website.md @zengyawen zh-cn/application-dev/website.md @zengyawen
zh-cn/application-dev/faqs/ @zengyawen zh-cn/application-dev/faqs/ @zengyawen
zh-cn/application-dev/reference/apis/js-apis-useriam-faceauth.md @zengyawen zh-cn/application-dev/reference/apis/js-apis-useriam-faceauth.md @zengyawen
\ No newline at end of file zh-cn/application-dev/reference/apis/js-apis-userfilemanager.md @qinxiaowang
zh-cn/application-dev/reference/apis/js-apis-cryptoFramework.md @zengyawen
zh-cn/application-dev/reference/apis/Readme-CN.md @zengyawen
zh-cn/application-dev/file-management/ @qinxiaowang
\ No newline at end of file
...@@ -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>
......
...@@ -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 the Traditional Coding Approach](quick-start/start-with-ets.md) - [Getting Started with eTS in Stage Model](quick-start/start-with-ets-stage.md)
- [Getting Started with eTS in the Low-Code Approach](quick-start/start-with-ets-low-code.md) - [Getting Started with eTS in FA Model](quick-start/start-with-ets-fa.md)
- [Getting Started with JavaScript in the Traditional Coding Approach](quick-start/start-with-js.md) - [Getting Started with JavaScript in FA Model](quick-start/start-with-js-fa.md)
- [Getting Started with JavaScript in the Low-Code Approach](quick-start/start-with-js-low-code.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)
...@@ -37,12 +37,16 @@ ...@@ -37,12 +37,16 @@
- Tools - Tools
- [DevEco Studio (OpenHarmony) User Guide](quick-start/deveco-studio-user-guide-for-openharmony.md) - [DevEco Studio (OpenHarmony) User Guide](quick-start/deveco-studio-user-guide-for-openharmony.md)
- Hands-On Tutorials - Hands-On Tutorials
- [Samples](https://gitee.com/openharmony/app_samples/blob/master/README.md) - [Samples](https://gitee.com/openharmony/applications_app_samples/blob/master/README.md)
- [Codelabs](https://gitee.com/openharmony/codelabs) - [Codelabs](https://gitee.com/openharmony/codelabs)
- API References - API References
- [Component Reference (JavaScript-based Web-like Development Paradigm)](reference/arkui-js/Readme-EN.md) - [Component Reference (JavaScript-based Web-like Development Paradigm)](reference/arkui-js/Readme-EN.md)
- [Component Reference (TypeScript-based Declarative Development Paradigm)](reference/arkui-ts/Readme-EN.md) - [Component Reference (TypeScript-based Declarative Development Paradigm)](reference/arkui-ts/Readme-EN.md)
- APIs - APIs
- [JS and TS APIs](reference/apis/Readme-EN.md) - [JS and TS APIs](reference/apis/Readme-EN.md)
- Native APIs
- [Standard Libraries](reference/native-lib/third_party_libc/musl.md)
- [Node_API](reference/native-lib/third_party_napi/napi.md)
- [FAQs](faqs/Readme-EN.md)
- Contribution - Contribution
- [How to Contribute](../contribute/documentation-contribution.md) - [How to Contribute](../contribute/documentation-contribution.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.
......
...@@ -7,9 +7,11 @@ ...@@ -7,9 +7,11 @@
The OpenHarmony application framework has two models: Feature Ability (FA) model and stage model. Correspondingly, there are two sets of context mechanisms. **application/BaseContext** is a common context base class. It uses the **stageMode** attribute to specify whether the context is used for the stage model. The OpenHarmony application framework has two models: Feature Ability (FA) model and stage model. Correspondingly, there are two sets of context mechanisms. **application/BaseContext** is a common context base class. It uses the **stageMode** attribute to specify whether the context is used for the stage model.
- FA model - FA model
Only the methods in **app/Context** can be used for the context in the FA model. Both the application-level context and ability-level context are instances of this type. If an ability-level method is invoked in the application-level context, an error occurs. Therefore, you must pay attention to the actual meaning of the **Context** instance. Only the methods in **app/Context** can be used for the context in the FA model. Both the application-level context and ability-level context are instances of this type. If an ability-level method is invoked in the application-level context, an error occurs. Therefore, you must pay attention to the actual meaning of the **Context** instance.
- Stage model - Stage model
The stage model has the following types of contexts: **application/Context**, **application/ApplicationContext**, **application/AbilityStageContext**, **application/ExtensionContext**, **application/AbilityContext**, and **application/FormExtensionContext**. For details about these contexts and how to use them, see [Context in the Stage Model](#context-in-the-stage-model). The stage model has the following types of contexts: **application/Context**, **application/ApplicationContext**, **application/AbilityStageContext**, **application/ExtensionContext**, **application/AbilityContext**, and **application/FormExtensionContext**. For details about these contexts and how to use them, see [Context in the Stage Model](#context-in-the-stage-model).
![contextIntroduction](figures/contextIntroduction.png) ![contextIntroduction](figures/contextIntroduction.png)
......
...@@ -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).
...@@ -41,7 +41,7 @@ The code snippets provided below are all from [Sample](https://gitee.com/openhar ...@@ -41,7 +41,7 @@ The code snippets provided below are all from [Sample](https://gitee.com/openhar
"module": { "module": {
"abilities": [ "abilities": [
{ {
"continuable": true, "continuable": true
} }
] ]
} }
...@@ -62,7 +62,7 @@ The code snippets provided below are all from [Sample](https://gitee.com/openhar ...@@ -62,7 +62,7 @@ The code snippets provided below are all from [Sample](https://gitee.com/openhar
"module": { "module": {
"abilities": [ "abilities": [
{ {
"launchType": "standard", "launchType": "standard"
} }
] ]
} }
...@@ -76,7 +76,7 @@ The code snippets provided below are all from [Sample](https://gitee.com/openhar ...@@ -76,7 +76,7 @@ The code snippets provided below are all from [Sample](https://gitee.com/openhar
"module": { "module": {
"abilities": [ "abilities": [
{ {
"launchType": "singleton", "launchType": "singleton"
} }
] ]
} }
......
...@@ -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).
# Ability Call Development # Ability Call Development
## When to Use ## When to Use
Ability call is an extension of the ability capabilities. It enables an ability to be invoked by external systems. In this way, the ability can be displayed as a UI page on the foreground and created and run on the background. You can use the **Call** APIs to implement data sharing between different abilities through inter-process communication (IPC). There are two roles in the ability call: caller and callee. The following scenarios are involved in the ability call development: Ability call is an extension of the ability capability. It enables an ability to be invoked by and communicate with external systems. The ability invoked can be either started in the foreground or created and run in the background. You can use the ability call to implement data sharing between two abilities (caller ability and callee ability) through inter-process communication (IPC).
- Creating a callee
- Accessing the callee
The following figure shows the ability call process. The core API used for the ability call is `startAbilityByCall`, which differs from `startAbility` in the following ways:
- `startAbilityByCall` supports ability startup in the foreground and background, whereas `startAbility` supports ability startup in the foreground only.
- The caller ability can use the `Caller` object returned by `startAbilityByCall` to communicate with the callee ability, but `startAbility` does not provide the communication capability.
Ability call is usually used in the following scenarios:
- Communicating with the callee ability
- Starting the callee ability in the background
**Table 1** Terms used in the ability call
|Term|Description|
|:------|:------|
|Caller ability|Ability that triggers the ability call.|
|Callee ability|Ability invoked by the ability call.|
|Caller |Object returned by `startAbilityByCall` and used by the caller ability to communicate with the callee ability.|
|Callee |Object held by the callee ability to communicate with the caller ability.|
|IPC |Inter-process communication.|
The ability call process is as follows:
- The caller ability uses `startAbilityByCall` to obtain a `Caller` object and uses `call()` of the `Caller` object to send data to the callee ability.
- The callee ability, which holds a `Callee` object, uses `on()` of the `Callee` object to register a callback. This callback is invoked when the callee ability receives data from the caller ability.
![stage-call](figures/stage-call.png) ![stage-call](figures/stage-call.png)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br/> > **NOTE**<br/>
> The startup mode of the callee must be **singleton**. > The launch type of the callee ability must be `singleton`.
> Currently, only system applications and Service Extension abilities can use the **Call** APIs to access the callee. > Currently, only system applications can use the ability call.
## Available APIs ## Available APIs
The table below describes the ability call APIs. For details, see [Ability](../reference/apis/js-apis-application-ability.md#caller). The table below describes the ability call APIs. For details, see [Ability](../reference/apis/js-apis-application-ability.md#caller).
**Table 1** Ability call APIs **Table 2** Ability call APIs
|API|Description| |API|Description|
|:------|:------| |:------|:------|
|startAbilityByCall(want: Want): Promise\<Caller>|Obtains the caller interface of the specified ability and, if the specified ability is not running, starts the ability in the background.| |startAbilityByCall(want: Want): Promise\<Caller>|Starts an ability in the foreground (through the `want` configuration) or background (default) and obtains the `Caller` object for communication with the ability. For details, see [AbilityContext](../reference/apis/js-apis-ability-context.md#abilitycontextstartabilitybycall) or [ServiceExtensionContext](../reference/apis/js-apis-service-extension-context.md#serviceextensioncontextstartabilitybycall).|
|on(method: string, callback: CalleeCallBack): void|Callback invoked when the callee registers a method.| |on(method: string, callback: CalleeCallBack): void|Callback invoked when the callee ability registers a method.|
|off(method: string): void|Callback invoked when the callee deregisters a method.| |off(method: string): void|Callback invoked when the callee ability deregisters a method.|
|call(method: string, data: rpc.Sequenceable): Promise\<void>|Sends agreed sequenceable data to the callee.| |call(method: string, data: rpc.Sequenceable): Promise\<void>|Sends agreed sequenceable data to the callee ability.|
|callWithResult(method: string, data: rpc.Sequenceable): Promise\<rpc.MessageParcel>|Sends agreed sequenceable data to the callee and returns the agreed sequenceable data.| |callWithResult(method: string, data: rpc.Sequenceable): Promise\<rpc.MessageParcel>|Sends agreed sequenceable data to the callee ability and obtains the agreed sequenceable data returned by the callee ability.|
|release(): void|Releases the caller interface.| |release(): void|Releases the `Caller` object.|
|onRelease(callback: OnReleaseCallBack): void|Registers a callback that is invoked when the caller is disconnected.| |onRelease(callback: OnReleaseCallBack): void|Callback invoked when the `Caller` object is released.|
## How to Develop ## How to Develop
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br/> The procedure for developing the ability call is as follows:
> The sample code snippets provided in the **How to Develop** section are used to show specific development steps. They may not be able to run independently. 1. Create a callee ability.
### Creating a Callee 2. Access the callee ability.
For the callee, implement the callback to receive data and the methods to marshal and unmarshal data. When data needs to be received, use the **on** API to register a listener. When data does not need to be received, use the **off** API to deregister the listener. > **NOTE**
1. Configure the ability startup mode. >
> The code snippets provided in the **How to Develop** section are used to show specific development steps. They may not be able to run independently.
### Creating a Callee Ability
For the callee ability, implement the callback to receive data and the methods to marshal and unmarshal data. When data needs to be received, use `on()` to register a listener. When data does not need to be received, use `off()` to deregister the listener.
**1. Configure the ability launch type.**
Set the ability of the callee to **singleton** in the **module.json5** file. Set `launchType` of the callee ability to `singleton` in the `module.json5` file.
|JSON Field|Description| |JSON Field|Description|
|:------|:------| |:------|:------|
|"launchType"|Ability startup mode. Set this parameter to **singleton**.| |"launchType"|Ability launch type. Set this parameter to `singleton`.|
An example of the ability configuration is as follows: An example of the ability configuration is as follows:
```json ```json
...@@ -51,13 +71,13 @@ An example of the ability configuration is as follows: ...@@ -51,13 +71,13 @@ An example of the ability configuration is as follows:
"visible": true "visible": true
}] }]
``` ```
2. Import the **Ability** module. **2. Import the Ability module.**
``` ```ts
import Ability from '@ohos.application.Ability' import Ability from '@ohos.application.Ability'
``` ```
3. Define the agreed sequenceable data. **3. Define the agreed sequenceable data.**
The data formats sent and received by the caller and callee must be consistent. In the following example, the data consists of numbers and strings. The sample code snippet is as follows: The data formats sent and received by the caller and callee abilities must be consistent. In the following example, the data formats are number and string. The code snippet is as follows:
```ts ```ts
export default class MySequenceable { export default class MySequenceable {
num: number = 0 num: number = 0
...@@ -81,23 +101,23 @@ export default class MySequenceable { ...@@ -81,23 +101,23 @@ export default class MySequenceable {
} }
} }
``` ```
4. Implement **Callee.on** and **Callee.off**. **4. Implement `Callee.on` and `Callee.off`.**
The time to register a listener for the callee depends on your application. The data sent and received before the listener is registered and that after the listener is deregistered are not processed. In the following example, the **MSG_SEND_METHOD** listener is registered in **onCreate** of the ability and deregistered in **onDestroy**. After receiving sequenceable data, the application processes the data and returns the data result. You need to implement processing based on service requirements. The sample code snippet is as follows: The time to register a listener for the callee ability depends on your application. The data sent and received before the listener is registered and that after the listener is deregistered are not processed. In the following example, the `MSG_SEND_METHOD` listener is registered in `onCreate` of the ability and deregistered in `onDestroy`. After receiving sequenceable data, the application processes the data and returns the data result. You need to implement processing based on service requirements. The code snippet is as follows:
```ts ```ts
const TAG: string = '[CalleeAbility]' const TAG: string = '[CalleeAbility]'
const MSG_SEND_METHOD: string = 'CallSendMsg' const MSG_SEND_METHOD: string = 'CallSendMsg'
function sendMsgCallback(data) { function sendMsgCallback(data) {
Logger.log(TAG, 'CalleeSortFunc called') console.log('CalleeSortFunc called')
// Obtain the sequenceable data sent by the caller. // Obtain the sequenceable data sent by the caller ability.
let receivedData = new MySequenceable(0, '') let receivedData = new MySequenceable(0, '')
data.readSequenceable(receivedData) data.readSequenceable(receivedData)
Logger.log(TAG, `receiveData[${receivedData.num}, ${receivedData.str}]`) console.log(`receiveData[${receivedData.num}, ${receivedData.str}]`)
// Process the data. // Process the data.
// Return the sequenceable data result to the caller. // Return the sequenceable data result to the caller ability.
return new MySequenceable(receivedData.num + 1, `send ${receivedData.str} succeed`) return new MySequenceable(receivedData.num + 1, `send ${receivedData.str} succeed`)
} }
...@@ -106,7 +126,7 @@ export default class CalleeAbility extends Ability { ...@@ -106,7 +126,7 @@ export default class CalleeAbility extends Ability {
try { try {
this.callee.on(MSG_SEND_METHOD, sendMsgCallback) this.callee.on(MSG_SEND_METHOD, sendMsgCallback)
} catch (error) { } catch (error) {
Logger.error(TAG, `${MSG_SEND_METHOD} register failed with error ${JSON.stringify(error)}`) console.log(`${MSG_SEND_METHOD} register failed with error ${JSON.stringify(error)}`)
} }
} }
...@@ -120,15 +140,27 @@ export default class CalleeAbility extends Ability { ...@@ -120,15 +140,27 @@ export default class CalleeAbility extends Ability {
} }
``` ```
### Accessing the Callee ### Accessing the Callee Ability
1. Import the **Ability** module. **1. Import the Ability module.**
``` ```ts
import Ability from '@ohos.application.Ability' import Ability from '@ohos.application.Ability'
``` ```
2. Obtain the caller interface. **2. Obtain the `Caller` object.**
The **context** attribute of the ability implements **startAbilityByCall** to obtain the caller interface of the ability. The following example uses **this.context** to obtain the **context** attribute of the **Ability** instance, uses **startAbilityByCall** to start the callee, obtain the caller interface, and register the **onRelease** listener of the caller. You need to implement processing based on service requirements. The sample code snippet is as follows: The `context` attribute of the ability implements `startAbilityByCall` to obtain the `Caller` object for communication. The following example uses `this.context` to obtain the `context` attribute of the ability, uses `startAbilityByCall` to start the callee ability, obtain the `Caller` object, and register the `onRelease` listener of the caller ability. You need to implement processing based on service requirements. The code snippet is as follows:
```ts ```ts
// Register the onRelease listener of the caller ability.
private regOnRelease(caller) {
try {
caller.onRelease((msg) => {
console.log(`caller onRelease is called ${msg}`)
})
console.log('caller register OnRelease succeed')
} catch (error) {
console.log(`caller register OnRelease failed with ${error}`)
}
}
async onButtonGetCaller() { async onButtonGetCaller() {
try { try {
this.caller = await context.startAbilityByCall({ this.caller = await context.startAbilityByCall({
...@@ -136,73 +168,74 @@ async onButtonGetCaller() { ...@@ -136,73 +168,74 @@ async onButtonGetCaller() {
abilityName: 'CalleeAbility' abilityName: 'CalleeAbility'
}) })
if (this.caller === undefined) { if (this.caller === undefined) {
Logger.error(TAG, 'get caller failed') console.log('get caller failed')
return return
} }
Logger.log(TAG, 'get caller success') console.log('get caller success')
this.regOnRelease(this.caller) this.regOnRelease(this.caller)
} catch (error) { } catch (error) {
Logger.error(TAG, `get caller failed with ${error}`) console.log(`get caller failed with ${error}`)
} }
}.catch((error) => { }
console.error(TAG + 'get caller failed with ' + error)
})
``` ```
In the cross-device scenario, you need to specify the ID of the peer device. The sample code snippet is as follows: In the cross-device scenario, you need to specify the ID of the peer device. The code snippet is as follows:
```ts ```ts
let TAG = '[MainAbility] ' async onButtonGetRemoteCaller() {
var caller = undefined var caller = undefined
let context = this.context var context = this.context
context.startAbilityByCall({ context.startAbilityByCall({
deviceId: getRemoteDeviceId(), deviceId: getRemoteDeviceId(),
bundleName: 'com.samples.CallApplication', bundleName: 'com.samples.CallApplication',
abilityName: 'CalleeAbility' abilityName: 'CalleeAbility'
}).then((data) => { }).then((data) => {
if (data != null) { if (data != null) {
caller = data caller = data
console.log(TAG + 'get remote caller success') console.log('get remote caller success')
// Register the onRelease listener of the caller. // Register the onRelease listener of the caller ability.
caller.onRelease((msg) => { caller.onRelease((msg) => {
console.log(TAG + 'remote caller onRelease is called ' + msg) console.log(`remote caller onRelease is called ${msg}`)
}) })
console.log(TAG + 'remote caller register OnRelease succeed') console.log('remote caller register OnRelease succeed')
} }
}).catch((error) => { }).catch((error) => {
console.error(TAG + 'get remote caller failed with ' + error) console.error(`get remote caller failed with ${error}`)
}) })
}
``` ```
Obtain the ID of the peer device from **DeviceManager**. Note that the **getTrustedDeviceListSync** API is open only to system applications. The sample code snippet is as follows: Obtain the ID of the peer device from `DeviceManager`. Note that the `getTrustedDeviceListSync` API is open only to system applications. The code snippet is as follows:
```ts ```ts
import deviceManager from '@ohos.distributedHardware.deviceManager'; import deviceManager from '@ohos.distributedHardware.deviceManager';
var dmClass; var dmClass;
function getRemoteDeviceId() { function getRemoteDeviceId() {
if (typeof dmClass === 'object' && dmClass != null) { if (typeof dmClass === 'object' && dmClass != null) {
var list = dmClass.getTrustedDeviceListSync(); var list = dmClass.getTrustedDeviceListSync()
if (typeof (list) == 'undefined' || typeof (list.length) == 'undefined') { if (typeof (list) == 'undefined' || typeof (list.length) == 'undefined') {
console.log("MainAbility onButtonClick getRemoteDeviceId err: list is null"); console.log("MainAbility onButtonClick getRemoteDeviceId err: list is null")
return; return
} }
console.log("MainAbility onButtonClick getRemoteDeviceId success:" + list[0].deviceId); console.log("MainAbility onButtonClick getRemoteDeviceId success:" + list[0].deviceId)
return list[0].deviceId; return list[0].deviceId
} else { } else {
console.log("MainAbility onButtonClick getRemoteDeviceId err: dmClass is null"); console.log("MainAbility onButtonClick getRemoteDeviceId err: dmClass is null")
} }
} }
``` ```
In the cross-device scenario, the application must also apply for the data synchronization permission from end users. The sample code snippet is as follows: In the cross-device scenario, your application must also apply for the data synchronization permission from end users. The code snippet is as follows:
```ts ```ts
let context = this.context requestPermission() {
let permissions: Array<string> = ['ohos.permission.DISTRIBUTED_DATASYNC'] let context = this.context
context.requestPermissionsFromUser(permissions).then((data) => { let permissions: Array<string> = ['ohos.permission.DISTRIBUTED_DATASYNC']
console.log("Succeed to request permission from user with data: "+ JSON.stringify(data)) context.requestPermissionsFromUser(permissions).then((data) => {
}).catch((error) => { console.log("Succeed to request permission from user with data: "+ JSON.stringify(data))
console.log("Failed to request permission from user with error: "+ JSON.stringify(error)) }).catch((error) => {
}) console.log("Failed to request permission from user with error: "+ JSON.stringify(error))
})
}
``` ```
3. Send agreed sequenceable data. **3. Send agreed sequenceable data.**
The sequenceable data can be sent to the callee with or without a return value. The method and sequenceable data must be consistent with those of the callee. The following example describes how to invoke the **Call** API to send data to the callee. The sample code snippet is as follows: The sequenceable data can be sent to the callee ability with or without a return value. The method and sequenceable data must be consistent with those of the callee ability. The following example describes how to send data to the callee ability. The code snippet is as follows:
```ts ```ts
const MSG_SEND_METHOD: string = 'CallSendMsg' const MSG_SEND_METHOD: string = 'CallSendMsg'
async onButtonCall() { async onButtonCall() {
...@@ -210,12 +243,12 @@ async onButtonCall() { ...@@ -210,12 +243,12 @@ async onButtonCall() {
let msg = new MySequenceable(1, 'origin_Msg') let msg = new MySequenceable(1, 'origin_Msg')
await this.caller.call(MSG_SEND_METHOD, msg) await this.caller.call(MSG_SEND_METHOD, msg)
} catch (error) { } catch (error) {
Logger.error(TAG, `caller call failed with ${error}`) console.log(`caller call failed with ${error}`)
} }
} }
``` ```
In the following, **CallWithResult** is used to send data **originMsg** to the callee and assign the data processed by the **CallSendMsg** method to **backMsg**. The sample code snippet is as follows: In the following, `CallWithResult` is used to send data `originMsg` to the callee ability and assign the data processed by the `CallSendMsg` method to `backMsg`. The code snippet is as follows:
```ts ```ts
const MSG_SEND_METHOD: string = 'CallSendMsg' const MSG_SEND_METHOD: string = 'CallSendMsg'
originMsg: string = '' originMsg: string = ''
...@@ -224,26 +257,28 @@ async onButtonCallWithResult(originMsg, backMsg) { ...@@ -224,26 +257,28 @@ async onButtonCallWithResult(originMsg, backMsg) {
try { try {
let msg = new MySequenceable(1, originMsg) let msg = new MySequenceable(1, originMsg)
const data = await this.caller.callWithResult(MSG_SEND_METHOD, msg) const data = await this.caller.callWithResult(MSG_SEND_METHOD, msg)
Logger.log(TAG, 'caller callWithResult succeed') console.log('caller callWithResult succeed')
let result = new MySequenceable(0, '') let result = new MySequenceable(0, '')
data.readSequenceable(result) data.readSequenceable(result)
backMsg(result.str) backMsg(result.str)
Logger.log(TAG, `caller result is [${result.num}, ${result.str}]`) console.log(`caller result is [${result.num}, ${result.str}]`)
} catch (error) { } catch (error) {
Logger.error(TAG, `caller callWithResult failed with ${error}`) console.log(`caller callWithResult failed with ${error}`)
} }
} }
``` ```
4. Release the caller interface. **4. Release the `Caller` object.**
When the caller interface is no longer required, call the **release** API to release it. The sample code snippet is as follows: When the `Caller` object is no longer required, use `release()` to release it. The code snippet is as follows:
```ts ```ts
try { releaseCall() {
this.caller.release() try {
this.caller = undefined this.caller.release()
Logger.log(TAG, 'caller release succeed') this.caller = undefined
} catch (error) { console.log('caller release succeed')
Logger.error(TAG, `caller release failed with ${error}`) } catch (error) {
console.log(`caller release failed with ${error}`)
}
} }
``` ```
# WantAgent Development # WantAgent Development
## When to Use ## When to Use
The **WantAgent** class encapsulates want information that specifies a particular action, which can be starting an ability or publishing a common event. You can either call **wantAgent.trigger** to trigger a **WantAgent** directly or add a **WantAgent** to a notification so that it will be triggered when users tap the notification. The **WantAgent** class encapsulates want information that specifies a particular action, which can be starting an ability or publishing a common event. You can either call **wantAgent.trigger** to trigger a **WantAgent** directly or add a **WantAgent** to a notification so that it will be triggered when users tap the notification.
## Available APIs ## Available APIs
| API | Description| | API | Description|
...@@ -21,7 +23,7 @@ The **WantAgent** class encapsulates want information that specifies a particula ...@@ -21,7 +23,7 @@ The **WantAgent** class encapsulates want information that specifies a particula
``` ```
private wantAgentObj = null // Save the WantAgent object created. It will be used to complete the trigger operations. private wantAgentObj = null // Save the WantAgent object created. It will be used to complete the trigger operations.
//wantAgentInfo // wantAgentInfo
var wantAgentInfo = { var wantAgentInfo = {
wants: [ wants: [
{ {
...@@ -45,7 +47,7 @@ The **WantAgent** class encapsulates want information that specifies a particula ...@@ -45,7 +47,7 @@ The **WantAgent** class encapsulates want information that specifies a particula
``` ```
private wantAgentObj = null // Save the WantAgent object created. It will be used to complete the trigger operations. private wantAgentObj = null // Save the WantAgent object created. It will be used to complete the trigger operations.
//wantAgentInfo // wantAgentInfo
var wantAgentInfo = { var wantAgentInfo = {
wants: [ wants: [
{ {
......
...@@ -47,7 +47,7 @@ DevEco Studio is a high-performance integrated development environment (IDE) rec ...@@ -47,7 +47,7 @@ DevEco Studio is a high-performance integrated development environment (IDE) rec
### Hands-On Tutorials ### Hands-On Tutorials
To make you better understand how functions work together and jumpstart your application development projects, we provide stripped-down, real-world [samples](https://gitee.com/openharmony/app_samples/blob/master/README.md) and [codelabs](https://gitee.com/openharmony/codelabs). To make you better understand how functions work together and jumpstart your application development projects, we provide stripped-down, real-world [samples](https://gitee.com/openharmony/applications_app_samples/blob/master/README.md) and [codelabs](https://gitee.com/openharmony/codelabs).
### API References ### API References
......
...@@ -47,7 +47,7 @@ DevEco Studio is a high-performance integrated development environment (IDE) rec ...@@ -47,7 +47,7 @@ DevEco Studio is a high-performance integrated development environment (IDE) rec
### Hands-On Tutorials ### Hands-On Tutorials
To make you better understand how functions work together and jumpstart your application development projects, we provide stripped-down, real-world [samples](https://gitee.com/openharmony/app_samples/blob/master/README.md) and [codelabs](https://gitee.com/openharmony/codelabs). To make you better understand how functions work together and jumpstart your application development projects, we provide stripped-down, real-world [samples](https://gitee.com/openharmony/applications_app_samples/blob/master/README.md) and [codelabs](https://gitee.com/openharmony/codelabs).
### API References ### API References
......
...@@ -13,7 +13,7 @@ The **DataShare** module allows an application to manage its own data and share ...@@ -13,7 +13,7 @@ The **DataShare** module allows an application to manage its own data and share
|query?(uri: string, predicates: DataSharePredicates, columns: Array&lt;string&gt;, callback: AsyncCallback&lt;Object&gt;): void|Queries data from the database.| |query?(uri: string, predicates: DataSharePredicates, columns: Array&lt;string&gt;, callback: AsyncCallback&lt;Object&gt;): void|Queries data from the database.|
|delete?(uri: string, predicates: DataSharePredicates, callback: AsyncCallback&lt;number&gt;): void|Deletes data from the database.| |delete?(uri: string, predicates: DataSharePredicates, callback: AsyncCallback&lt;number&gt;): void|Deletes data from the database.|
For more details, see [DataShareExtensionAbility](../reference/apis/js-apis-application-DataShareExtensionAbility.md). For more information, see [DataShareExtensionAbility](../reference/apis/js-apis-application-DataShareExtensionAbility.md).
**Table 2** APIs of the data consumer **Table 2** APIs of the data consumer
...@@ -25,11 +25,11 @@ For more details, see [DataShareExtensionAbility](../reference/apis/js-apis-appl ...@@ -25,11 +25,11 @@ For more details, see [DataShareExtensionAbility](../reference/apis/js-apis-appl
| query(uri: string, predicates: DataSharePredicates, columns: Array&lt;string&gt;, callback: AsyncCallback&lt;DataShareResultSet&gt;): void | Queries data from the database. | | query(uri: string, predicates: DataSharePredicates, columns: Array&lt;string&gt;, callback: AsyncCallback&lt;DataShareResultSet&gt;): void | Queries data from the database. |
| delete(uri: string, predicates: DataSharePredicates, callback: AsyncCallback&lt;number&gt;): void | Deletes one or more data records from the database.| | delete(uri: string, predicates: DataSharePredicates, callback: AsyncCallback&lt;number&gt;): void | Deletes one or more data records from the database.|
For more details, see [DataShareHelper](../reference/apis/js-apis-data-dataShare.md). For more information, see [DataShareHelper](../reference/apis/js-apis-data-dataShare.md).
## When to Use ## When to Use
There are two roles in **DataShare**. There are two roles in **DataShare**:
- Data provider: adds, deletes, modifies, and queries data, opens files, and shares data. - Data provider: adds, deletes, modifies, and queries data, opens files, and shares data.
- Data consumer: accesses the data provided by the provider using **DataShareHelper**. - Data consumer: accesses the data provided by the provider using **DataShareHelper**.
...@@ -41,10 +41,10 @@ Examples are given below. ...@@ -41,10 +41,10 @@ Examples are given below.
1. Import the dependencies. 1. Import the dependencies.
```ts ```ts
import Extension from '@ohos.application.DataShareExtensionAbility' import Extension from '@ohos.application.DataShareExtensionAbility';
import rdb from '@ohos.data.rdb'; import rdb from '@ohos.data.rdb';
import fileIo from '@ohos.fileio' import fileIo from '@ohos.fileio';
import dataSharePredicates from '@ohos.data.dataSharePredicates' import dataSharePredicates from '@ohos.data.dataSharePredicates';
``` ```
2. Override **DataShareExtensionAbility** APIs based on actual requirements. For example, if the data provider provides only data query, override only the **query()** API. 2. Override **DataShareExtensionAbility** APIs based on actual requirements. For example, if the data provider provides only data query, override only the **query()** API.
...@@ -80,7 +80,7 @@ Examples are given below. ...@@ -80,7 +80,7 @@ Examples are given below.
} }
// Override the query() API. // Override the query() API.
query(uri, predicates, columns, callback) { query(uri, predicates, columns, callback) {
if (predicates == null || predicates == undefined) { if (predicates == null || predicates == undefined) {
console.info('invalid predicates'); console.info('invalid predicates');
} }
...@@ -144,48 +144,49 @@ Examples are given below. ...@@ -144,48 +144,49 @@ Examples are given below.
let dseUri = ("datashare:///com.samples.datasharetest.DataShare"); let dseUri = ("datashare:///com.samples.datasharetest.DataShare");
``` ```
2. Create a **DataShareHelper** instance. 3. Create a **DataShareHelper** instance.
```ts ```ts
let dsHelper; let dsHelper;
let abilityContext; let abilityContext;
export default class MainAbility extends Ability { export default class MainAbility extends Ability {
onWindowStageCreate(windowStage) { onWindowStageCreate(windowStage) {
abilityContext = this.context; abilityContext = this.context;
dataShare.createDataShareHelper(abilityContext, dseUri, (err,data)=>{ dataShare.createDataShareHelper(abilityContext, dseUri, (err, data)=>{
dsHelper = data; dsHelper = data;
}); });
} }
} }
``` ```
3. Use the APIs provided by **DataShareHelper** to access the services provided by the provider, for example, adding, deleting, modifying, and querying data. 4. Use the APIs provided by **DataShareHelper** to access the services provided by the provider, for example, adding, deleting, modifying, and querying data.
```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])}; var 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])}; var updateBucket = { "name": "LiSi", "age": 18, "isStudent": true, "Binary": new Uint8Array([1, 2, 3]) };
let da = new dataSharePredicates.DataSharePredicates(); let da = new dataSharePredicates.DataSharePredicates();
var valArray =new Array("*"); var valArray = new Array("*");
let people = new Array( let people = new Array(
{"name": "LiSi", "age": 41, "Binary": ar}, { "name": "LiSi", "age": 41, "Binary": ar },
{"name": "WangWu", "age": 21, "Binary": arr}, { "name": "WangWu", "age": 21, "Binary": arr },
{"name": "ZhaoLiu", "age": 61, "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. // Delete data.
dsHelper.delete(dseUri, da, (err,data) => { dsHelper.delete(dseUri, da, (err, data) => {
console.log("dsHelper delete result: " + data); console.log("dsHelper delete result: " + data);
}); });
// Update data. // Update data.
dsHelper.update(dseUri, da, updateBucket, (err,data) => { dsHelper.update(dseUri, da, 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, da, valArray, (err, data) => {
console.log("dsHelper query result: " + data); console.log("dsHelper query result: " + data);
}); });
``` ```
...@@ -14,23 +14,23 @@ The data provider can directly use the **DataShare** framework to share data wit ...@@ -14,23 +14,23 @@ The data provider can directly use the **DataShare** framework to share data wit
Before you get started, familiarize yourself with the following concepts: Before you get started, familiarize yourself with the following concepts:
- Data provider - **Data provider**
An application that provides data and implements related services. It is also called a producer or server. An application that provides data and implements related services. It is also called a producer or server.
- Data consumer - **Data consumer**
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.
- Result set - **Result set**
A collection of query results. Flexible data access modes are provided for users to obtain data. A collection of query results. Flexible data access modes are provided for users to obtain data.
- Predicate - **Predicate**
Conditions specified for updating, deleting, or querying data in the database. Conditions specified for updating, deleting, or querying data in the database.
......
...@@ -2,14 +2,13 @@ ...@@ -2,14 +2,13 @@
## When to Use ## When to Use
Distributed data objects allow data traversing across devices to be processed like local variables by shielding complex data interaction between devices. For the devices that form a Super Device, when data in the distributed data object of an application is added, deleted, or modified on a device, the data for the same application is also updated on the other devices. The devices can listen for data changes and online and offline status changes of other devices. The **distributedDataObject** module provides APIs to implement data collaboration of the same application across multiple devices. In addition, the devices that form a Super Device can listen for object status and data changes with each other.
The distributed data objects support basic data types, such as number, string, and Boolean, as well as complex data types, such as array and nested basic types.
For example, when the data of a distributed data object is added, deleted, or modified for application A on device 1, application A on device 2 can obtain the updated data. In addition, device 2 can listen for data changes and online/offline of the data objects on device 1.
## Available APIs ## Available APIs
For details about the APIs related to the distributed data object, see [Distributed Data Object](../reference/apis/js-apis-data-distributedobject.md). For details about the APIs, see [Distributed Data Object](../reference/apis/js-apis-data-distributedobject.md).
### Creating a Distributed Data Object Instance ### Creating a Distributed Data Object Instance
...@@ -17,53 +16,54 @@ Call **createDistributedObject()** to create a distributed data object instance. ...@@ -17,53 +16,54 @@ Call **createDistributedObject()** to create a distributed data object instance.
**Table 1** API for creating a distributed data object instance **Table 1** API for creating a distributed data object instance
| Package | API | Description | | Package| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
| ohos.data.distributedDataObject| createDistributedObject(source: object): DistributedObject | Creates a distributed data object instance for data operations.<br>- **source**: attributes of the **distributedObject** set.<br>- **DistributedObject**: returns the distributed object created.| | ohos.data.distributedDataObject| createDistributedObject(source: object): DistributedObject | Creates a distributed data object instance for data operations.<br>- **source**: attributes of the distributed data object to set.<br>- **DistributedObject**: returns the distributed data object created. |
### Generating a Session ID ### Generating a Session ID
Call **genSessionId()** to generate a session ID randomly. The generated session ID can be used to set the session ID of a distributed data object. Call **genSessionId()** to generate a session ID randomly. The generated session ID can be used to set the session ID of a distributed data object.
**Table 2** API for generating a session ID randomly **Table 2** API for generating a session ID randomly
| Package | API | Description | | Package| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
| ohos.data.distributedDataObject| genSessionId(): string | Generates a session ID, which can be used as the session ID of a distributed data object.| | ohos.data.distributedDataObject| genSessionId(): string | Generates a session ID, which can be used as the session ID of a distributed data object.|
### Setting a SessionID for Distributed Data Objects ### Setting a Session ID for a Distributed Data Object
Call **setSessionId()** to set a session ID for a distributed data object. The session ID is a unique identifier for one collaboration across devices. The distributed data objects to be synchronized must be associated with the same session ID. Call **setSessionId()** to set a session ID for a distributed data object. The session ID is a unique identifier for one collaboration across devices. The distributed data objects to be synchronized must be associated with the same session ID.
**Table 3** API for setting a session ID **Table 3** API for setting a session ID
| Class| API| Description| | Class| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
| DistributedDataObject | setSessionId(sessionId?: string): boolean | Sets a session ID for distributed data objects.<br>**sessionId**: session ID of a distributed object in a trusted network. To remove a distributed data object from the network, set this parameter to "" or leave it empty.| | DistributedDataObject | setSessionId(sessionId?: string): boolean | Sets a session ID for a distributed data object.<br>**sessionId**: session ID of a distributed data object in a trusted network. To remove a distributed data object from the network, set this parameter to "" or leave it empty. |
### Observing Data Changes ### Observing Data Changes
Call **on()** to subscribe to data changes of a distributed data object. In the case of data change, a callback will be invoked to return the data changes. You can use **off()** to unsubscribe from the data changes. Call **on()** to subscribe to data changes of a distributed data object. When the data changes, a callback will be invoked to return the data changes. You can use **off()** to unsubscribe from the data changes.
**Table 4** APIs for observing data changes of a distributed data object **Table 4** APIs for observing data changes of a distributed data object
| Class | API | Description |
| Class| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
| DistributedDataObject| on(type: 'change', callback: Callback<{ sessionId: string, fields: Array&lt;string&gt; }>): void | Subscribes to data changes.| | DistributedDataObject| on(type: 'change', callback: Callback<{ sessionId: string, fields: Array&lt;string&gt; }>): void | Subscribes to data changes.|
| DistributedDataObject| off(type: 'change', callback?: Callback<{ sessionId: string, fields: Array&lt;string&gt; }>): void | Unsubscribes from data changes.<br>**Callback**: specifies callback used to return changes of the distributed data object. If this parameter is not specified, all callbacks related to data changes will be unregistered.| | DistributedDataObject| off(type: 'change', callback?: Callback<{ sessionId: string, fields: Array&lt;string&gt; }>): void | Unsubscribes from data changes. <br/>**Callback**: callback to unregister. If this parameter is not specified, all data changes of this distributed data object will be unsubscribed from. |
### Observing Online or Offline Status ### Observing Online or Offline Status
Call **on()** to subscribe to status changes of a distributed data object. The status can be online or offline. When the status changes, a callback will be invoked to return the status. You can use **off()** to unsubscribe from the status changes. Call **on()** to subscribe to status changes of a distributed data object. The status can be online or offline. When the status changes, a callback will be invoked to return the status. You can use **off()** to unsubscribe from the status changes.
**Table 5** APIs for observing status changes of a distributed data object **Table 5** APIs for observing status changes of a distributed data object
| Class | API | Description | | Class| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
| DistributedDataObject| on(type: 'status', callback: Callback<{ sessionId: string, networkId: string, status: 'online' \| 'offline' }>): void | Subscribes to the status changes of a distributed data object.| | DistributedDataObject| on(type: 'status', callback: Callback<{ sessionId: string, networkId: string, status: 'online' \| 'offline' }>): void | Subscribes to the status changes of a distributed data object.|
| DistributedDataObject| off(type: 'status', callback?: Callback<{ sessionId: string, deviceId: string, status: 'online' \| 'offline' }>): void | Unsubscribes from status changes of a distributed data object.| | DistributedDataObject| off(type: 'status', callback?: Callback<{ sessionId: string, deviceId: string, status: 'online' \| 'offline' }>): void | Unsubscribes from status changes of a distributed data object.|
### Saving a Distributed Data Object and Revoking the Data Saving Operation ### Saving or Deleting a Distributed Data Object
Call **save()** to save a distributed data object. When the application is active, the saved data will not be released. When the application exits and restarts, the data saved on the device will be restored. Call **save()** to save a distributed data object. When the application is active, the saved data will not be released. When the application exits and restarts, the data saved on the device will be restored.
Call **revokeSave()** to revoke a distributed data object that is no longer required. If the distributed data object is saved on the local device, **revokeSave()** will delete the data from all trusted devices. If the distributed data object is not saved on the local device, **revokeSave()** will delete the data from the local device. Call **revokeSave()** to delete a distributed data object that is no longer required. If the distributed data object is saved on the local device, **revokeSave()** will delete the data from all trusted devices. If the distributed data object is not saved on the local device, **revokeSave()** will delete the data from the local device.
The saved data will be released in the following cases: The saved data will be released in the following cases:
...@@ -71,13 +71,12 @@ The saved data will be released in the following cases: ...@@ -71,13 +71,12 @@ The saved data will be released in the following cases:
- The application has been uninstalled. - The application has been uninstalled.
- Data is successfully restored. - Data is successfully restored.
**Table 6** APIs for saving a distributed data object and revoking the saving **Table 6** APIs for saving and deleting a distributed data object
| Class | API | Description |
| Class| API| Description|
| -------- | -------- | -------- | | -------- | -------- | -------- |
| DistributedDataObject | save(deviceId: string): Promise&lt;SaveSuccessResponse&gt; | Saves a distributed data object. This API uses a promise to return the result. | | DistributedDataObject | save(deviceId: string): Promise&lt;SaveSuccessResponse&gt; | Saves a distributed data object.|
| DistributedDataObject | save(deviceId: string, callback: AsyncCallback&lt;SaveSuccessResponse&gt;): void | Saves a distributed data object. This API uses an asynchronous callback to return the result. | | DistributedDataObject| revokeSave(): Promise&lt;RevokeSaveSuccessResponse&gt; | Deletes a distributed data object. |
| DistributedDataObject | revokeSave(callback: AsyncCallback&lt;RevokeSaveSuccessResponse&gt;): void | Revokes the data saving operation. This API uses an asynchronous callback to return the result. |
| DistributedDataObject | revokeSave(): Promise&lt;RevokeSaveSuccessResponse&gt; | Revokes the data saving operation. This API uses a promise to return the result. |
## How to Develop ## How to Develop
...@@ -89,11 +88,11 @@ The following example shows how to implement distributed data object synchroniza ...@@ -89,11 +88,11 @@ The following example shows how to implement distributed data object synchroniza
import distributedObject from '@ohos.data.distributedDataObject'; import distributedObject from '@ohos.data.distributedDataObject';
``` ```
2. Request the permission. 2. Apply for the permission.
Add the required permission in the **config.json** file. The sample code is as follows: Add the permissions required (FA model) to the **config.json** file. The sample code is as follows:
``` ```json
{ {
"module": { "module": {
"reqPermissions": [ "reqPermissions": [
...@@ -104,11 +103,13 @@ The following example shows how to implement distributed data object synchroniza ...@@ -104,11 +103,13 @@ The following example shows how to implement distributed data object synchroniza
} }
} }
``` ```
This permission must also be authorized by the user through a dialog box when the application is started for the first time. The sample code is as follows: For the apps based on the stage model, see [Declaring Permissions](../security/accesstoken-guidelines.md#stage-model).
``` 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
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();
...@@ -116,93 +117,105 @@ The following example shows how to implement distributed data object synchroniza ...@@ -116,93 +117,105 @@ The following example shows how to implement distributed data object synchroniza
console.info(`result.requestCode=${result.requestCode}`) console.info(`result.requestCode=${result.requestCode}`)
}) })
console.info('end grantPermission'); console.info('end grantPermission');
} }
grantPermission(); grantPermission();
``` ```
3. Obtain a distributed data object instance. 3. Obtain a distributed data object instance.
The sample code is as follows: The sample code is as follows:
```js ```js
var local_object = distributedObject.createDistributedObject({name:undefined, age:undefined, isVis:true, var local_object = distributedObject.createDistributedObject({
parent:undefined, list:undefined}); name: undefined,
age: undefined,
isVis: true,
parent: undefined,
list: undefined
});
var sessionId = distributedObject.genSessionId(); var sessionId = distributedObject.genSessionId();
``` ```
4. Add the distributed data object instance to a network for data synchronization. The data objects in the synchronization network include the local and remote objects.
4. Add the synchronization network. The data objects in the synchronization network include the local and remote objects.
The sample code is as follows: The sample code is as follows:
```js ```js
// Local object // Local object
var local_object = distributedObject.createDistributedObject({name:"jack", age:18, isVis:true, var local_object = distributedObject.createDistributedObject({
parent:{mother:"jack mom", father:"jack Dad"}, list:[{mother:"jack mom"}, {father:"jack Dad"}]}); name: "jack",
age: 18,
isVis: true,
parent: { mother: "jack mom", father: "jack Dad" },
list: [{ mother: "jack mom" }, { father: "jack Dad" }]
});
local_object.setSessionId(sessionId); local_object.setSessionId(sessionId);
// Remote object // Remote object
var remote_object = distributedObject.createDistributedObject({name:undefined, age:undefined, isVis:true, var remote_object = distributedObject.createDistributedObject({
parent:undefined, list:undefined}); name: undefined,
age: undefined,
isVis: true,
parent: undefined,
list: undefined
});
// After learning that the local device goes online, the remote object synchronizes data. That is, name changes to jack and age to 18.
remote_object.setSessionId(sessionId); remote_object.setSessionId(sessionId);
// After learning that the device goes online, the remote object synchronizes data. That is, name changes to jack and age to 18.
``` ```
5. Observe the data changes of the distributed data object. 5. Observe the data changes of the distributed data object.
You can subscribe to data changes of the peer object. When the data in the peer object changes, a callback will be called to return the data changes. You can subscribe to data changes of the remote object. When the data in the remote object changes, a callback will be called to return the data changes.
The sample code is as follows: The sample code is as follows:
```js ```js
function changeCallback(sessionId, changeData) { function changeCallback(sessionId, changeData) {
console.info("change" + sessionId); console.info("change" + sessionId);
if (changeData != null && changeData != undefined) { if (changeData != null && changeData != undefined) {
changeData.forEach(element => { changeData.forEach(element => {
console.info("changed !" + element + " " + local_object[element]); console.info("changed !" + element + " " + local_object[element]);
}); });
} }
} }
// To refresh the page in changeCallback, correctly bind (this) to the changeCallback. // To refresh the page in changeCallback, correctly bind (this) to the changeCallback.
local_object.on("change", this.changeCallback.bind(this)); local_object.on("change", this.changeCallback.bind(this));
``` ```
6. Modify object attributes. 6. Modify attributes of the distributed data object.
The object attributes support basic data types (such as number, Boolean, and string) and complex data types (array and nested basic types). The object attributes support basic data types (such as number, Boolean, and string) and complex data types (array and nested basic types).
The sample code is as follows: The sample code is as follows:
```js ```js
local_object.name = "jack"; local_object.name = "jack";
local_object.age = 19; local_object.age = 19;
local_object.isVis = false; local_object.isVis = false;
local_object.parent = {mother:"jack mom", father:"jack Dad"}; local_object.parent = { mother: "jack mom", father: "jack Dad" };
local_object.list = [{mother:"jack mom"}, {father:"jack Dad"}]; local_object.list = [{ mother: "jack mom" }, { father: "jack Dad" }];
``` ```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE** > **NOTE**<br>
> > For the distributed data object of the complex type, only the root attribute can be modified. The subordinate attributes cannot be modified. Example:
> For the distributed data object of the complex type, only the root attribute can be modified. The subordinate attributes cannot be modified.
Example:
```js ```js
// Supported modification. // Supported modification.
local_object.parent = {mother:"mom", father:"dad"}; local_object.parent = { mother: "mom", father: "dad" };
// Modification not supported. // Modification not supported.
local_object.parent.mother = "mom"; local_object.parent.mother = "mom";
``` ```
7. Access the distributed data object. 7. Access the distributed data object.
Obtain the distributed data object attribute, which is the latest data on the network. Obtain the distributed data object attributes, which are the latest data on the network.
The sample code is as follows: The sample code is as follows:
```js ```js
console.info("name " + local_object["name"]); console.info("name " + local_object["name"]);
``` ```
...@@ -221,7 +234,6 @@ The following example shows how to implement distributed data object synchroniza ...@@ -221,7 +234,6 @@ The following example shows how to implement distributed data object synchroniza
``` ```
9. Subscribe to the status (online/offline) changes of the distributed data object. A callback will be invoked to report the status change when the target distributed data object goes online or offline. 9. Subscribe to the status (online/offline) changes of the distributed data object. A callback will be invoked to report the status change when the target distributed data object goes online or offline.
The sample code is as follows: The sample code is as follows:
```js ```js
...@@ -232,55 +244,31 @@ The following example shows how to implement distributed data object synchroniza ...@@ -232,55 +244,31 @@ The following example shows how to implement distributed data object synchroniza
local_object.on("status", this.statusCallback); local_object.on("status", this.statusCallback);
``` ```
10. Save a distributed data object and revoke the data saving operation. 10. Save a distributed data object and delete it.
- Callback
``` ```js
​```js // Save a distributed data object.
// Save a distributed data object. g_object.save("local").then((result) => {
local_object.save("local", (result, data) => { console.info("save sessionId " + result.sessionId);
console.log("save callback"); console.info("save version " + result.version);
console.info("save sessionId " + data.sessionId); console.info("save deviceId " + result.deviceId);
console.info("save version " + data.version); }, (result) => {
console.info("save deviceId " + data.deviceId); console.info("save local failed.");
}); });
// Revoke the data saving operation. // Delete a distributed data object..
local_object.revokeSave((result, data) => { g_object.revokeSave().then((result) => {
console.log("revokeSave callback"); console.info("revokeSave success.");
console.info("revokeSave sessionId " + data.sessionId); }, (result) => {
}); console.info("revokeSave failed.");
​``` });
``` ```
- Promise
```
​```js
// Save a distributed data object.
g_object.save("local").then((result) => {
console.info("save sessionId " + result.sessionId);
console.info("save version " + result.version);
console.info("save deviceId " + result.deviceId);
}, (result)=>{
console.info("save local failed.");
});
// Revoke the data saving operation.
g_object.revokeSave().then((result) => {
console.info("revokeSave success.");
}, (result)=>{
console.info("revokeSave failed.");
});
​```
```
11. Unsubscribe from the status changes of the distributed data object. 11. Unsubscribe from the status changes of the distributed data object.
You can specify the callback to unregister. If you do not specify the callback, this API unregisters all callbacks of this distributed data object. You can specify the callback to unregister. If you do not specify the callback, all status change callbacks of this distributed data object will be unregistered.
The sample code is as follows: The sample code is as follows:
```js ```js
// Unregister the specified status change callback. // Unregister the specified status change callback.
local_object.off("status", this.statusCallback); local_object.off("status", this.statusCallback);
...@@ -290,7 +278,8 @@ The following example shows how to implement distributed data object synchroniza ...@@ -290,7 +278,8 @@ The following example shows how to implement distributed data object synchroniza
12. Remove a distributed data object from the synchronization network. Data changes on the local object will not be synchronized to the removed distributed data object. 12. Remove a distributed data object from the synchronization network. Data changes on the local object will not be synchronized to the removed distributed data object.
The sample code is as follows: The sample code is as follows:
```js
local_object.setSessionId(""); ```js
``` local_object.setSessionId("");
```
# Distributed Data Object Overview # Distributed Data Object Overview
The distributed data object management framework is an object-oriented in-memory data management framework. It provides application developers with basic data object management capabilities, such as creating, querying, deleting, modifying, and subscribing to in-memory objects. This management framework also provides distributed capabilities to implement data object collaboration for the same application between multiple devices that form a Super Device. The distributed data object management framework provides object-oriented in-memory data management. It provides basic data management capabilities, such as creating, querying, deleting, and modifying distributed data objects, and observing data and status changes of the distributed data objects. This management framework also provides distributed capabilities to implement data object collaboration for the same application between multiple devices that form a Super Device.
## Key Concepts ## Basic Concepts
- **Distributed in-memory database** - **Distributed in-memory database**
The distributed in-memory database caches data in the memory, so that applications can quickly access data. This database, however, does not store data persistently. If the database is closed, the data is not retained. The distributed in-memory database caches data in the memory so that applications can quickly access data. This database, however, does not store data persistently. If the database is closed, the data is not retained.
- **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 or assigning values to distributed data objects is automatically mapped to the **put** or **get** operation of the corresponding database. 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.
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:
- **Uninitialized**: The distributed data object is not instantiated or has been destroyed. - **Uninitialized**: The distributed data object is not instantiated or has been destroyed.
- **Local**: The data table is created, but the data cannot be synchronized. - **Local**: The data table is created, but the data cannot be synchronized.
- **Distributed**: The data table is created, there are at least two online with the same session ID, and data can be synchronized across devices. If the device is offline or the session ID is empty, the distributed data object changes to the local state. - **Distributed**: The data table is created, and there are at least two online devices with the same session ID. In this case, data can be synchronized across devices. If a device is offline or the session ID is empty, the distributed data object changes to the local state.
## Working Principles ## Working Principles
The distributed data objects are encapsulated into JS objects in distributed in-memory databases, which allows the distributed data objects to be operated in the same way as local variables. The system automatically implements cross-device data synchronization. The distributed data objects are encapsulated into JS objects in distributed in-memory databases. This allows the distributed data objects to be operated in the same way as local variables. The system automatically implements cross-device data synchronization.
**Figure 1** Working mechanism **Figure 1** Working mechanism
...@@ -34,7 +34,7 @@ The distributed data objects are encapsulated into JS objects in distributed in- ...@@ -34,7 +34,7 @@ The distributed data objects are encapsulated into JS objects in distributed in-
## Constraints ## Constraints
- Data synchronization can be implemented across devices only for the applications with the same bundleName. - Data synchronization can be implemented across devices only for the applications with the same **bundleName**.
- Each distributed data object occupies 100 KB to 150 KB of memory. Therefore, you are advised not to create too many distributed data objects. - Each distributed data object occupies 100 KB to 150 KB of memory. Therefore, you are advised not to create too many distributed data objects.
......
...@@ -6,113 +6,181 @@ The Distributed Data Service (DDS) implements synchronization of application dat ...@@ -6,113 +6,181 @@ The Distributed Data Service (DDS) implements synchronization of application dat
## Available APIs ## Available APIs
For details about the APIs related to distributed data, see [Distributed Data Management](../reference/apis/js-apis-distributed-data.md). For details about the APIs, see [Distributed Data Management](../reference/apis/js-apis-distributed-data.md).
**Table 1** APIs provided by the DDS **Table 1** APIs provided by the DDS
| API | Description | | API | Description |
| ------------------------------------------------------------ | ----------------------------------------------- | | ------------------------------------------------------------ | ----------------------------------------------- |
| createKVManager(config:KVManagerConfig,callback:AsyncCallback&lt;KVManager&gt;):void<br>createKVManager(config:KVManagerConfig):Promise&lt;KVManager> | Creates a **KVManager** object for database management.| | createKVManager(config: KVManagerConfig, callback: AsyncCallback&lt;KVManager&gt;): void<br>createKVManager(config: KVManagerConfig): Promise&lt;KVManager> | Creates a **KVManager** object for database management.|
| getKVStore&lt;TextendsKVStore&gt;(storeId:string,options:Options,callback:AsyncCallback&lt;T&gt;):void<br>getKVStore&lt;TextendsKVStore&gt;(storeId:string,options:Options):Promise&lt;T&gt; | Obtains a KV store with the specified **Options** and **storeId**.| | getKVStore&lt;TextendsKVStore&gt;(storeId: string, options: Options, callback: AsyncCallback&lt;T&gt;): void<br>getKVStore&lt;TextendsKVStore&gt;(storeId: string, options: Options): Promise&lt;T&gt; | Obtains a KV store with the specified **Options** and **storeId**.|
| put(key:string,value:Uint8Array\|string\|number\|boolean,callback:AsyncCallback&lt;void&gt;):void<br>put(key:string,value:Uint8Array\|string\|number\|boolean):Promise&lt;void> | Inserts and updates data. | | put(key: string, value: Uint8Array\|string\|number\|boolean, callback: AsyncCallback&lt;void&gt;): void<br>put(key: string, value: Uint8Array\|string\|number\|boolean): Promise&lt;void> | Inserts and updates data. |
| delete(key:string,callback:AsyncCallback&lt;void&gt;):void<br>delete(key:string):Promise&lt;void> | Deletes data. | | delete(key: string, callback: AsyncCallback&lt;void&gt;): void<br>delete(key: string): Promise&lt;void> | Deletes data. |
| get(key:string,callback:AsyncCallback&lt;Uint8Array\|string\|boolean\|number&gt;):void<br>get(key:string):Promise&lt;Uint8Array\|string\|boolean\|number> | Queries data. | | get(key: string, callback: AsyncCallback&lt;Uint8Array\|string\|boolean\|number&gt;): void<br>get(key: string): Promise&lt;Uint8Array\|string\|boolean\|number> | Queries data. |
| on(event:'dataChange',type:SubscribeType,observer:Callback&lt;ChangeNotification&gt;):void<br>on(event:'syncComplete',syncCallback:Callback&lt;Array&lt;[string,number]&gt;&gt;):void | Subscribes to data changes in the KV store. | | on(event: 'dataChange', type: SubscribeType, observer: Callback&lt;ChangeNotification&gt;): void<br>on(event: 'syncComplete', syncCallback: Callback&lt;Array&lt;[string,number]&gt;&gt;): void | Subscribes to data changes in the KV store. |
| sync(deviceIdList:string[],mode:SyncMode,allowedDelayMs?:number):void | Triggers database synchronization in manual mode. | | sync(deviceIdList: string[], mode: SyncMode, allowedDelayMs?: number): void | Triggers database synchronization in manual mode. |
## How to Develop ## How to Develop
The following uses a single KV store as an example to describe the development procedure. The following uses a single KV store as an example to describe the development procedure.
1. Import the distributed data module. 1. Import the distributed data module.
```js ```js
import distributedData from '@ohos.data.distributedData'; import distributedData from '@ohos.data.distributedData';
``` ```
2. Apply for the required permission if data synchronization is required.
2. Create a **KvManager** instance based on the specified **KvManagerConfig** object. Add the permission required (FA model) in the **config.json** file. The sample code is as follows:
(1) Create a **KvManagerConfig** object based on the application context. ```json
{
"module": {
"reqPermissions": [
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC"
}
]
}
}
```
For the apps based on the stage model, see [Declaring Permissions](../security/accesstoken-guidelines.md#stage-model).
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
// FA model
import featureAbility from '@ohos.ability.featureAbility';
function grantPermission() {
console.info('grantPermission');
let context = featureAbility.getContext();
context.requestPermissionsFromUser(['ohos.permission.DISTRIBUTED_DATASYNC'], 666).then((data) => {
console.info('success: ${data}');
}).catch((error) => {
console.info('failed: ${error}');
})
}
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();
```
3. Create a **kvManager** instance based on the specified **kvManagerConfig** object.
1. Create a **kvManagerConfig** object based on the application context.
2. Create a **kvManager** instance.
(2) Create a **KvManager** instance.
The sample code is as follows: The sample code is as follows:
``` ```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: {
userId : '0', context:context,
userType : distributedData.UserType.SAME_USER_ID userId: '0',
} userType: distributedData.UserType.SAME_USER_ID
} }
distributedData.createKVManager(kvManagerConfig, function (err, manager) { }
if (err) { distributedData.createKVManager(kvManagerConfig, function (err, manager) {
console.log("createKVManager err: " + JSON.stringify(err)); if (err) {
return; console.log('Failed to create KVManager: ${error}');
} return;
console.log("createKVManager success"); }
kvManager = manager; console.log('Created KVManager successfully');
}); kvManager = manager;
});
} catch (e) { } catch (e) {
console.log("An unexpected error occurred. Error:" + e); console.log('An unexpected error occurred. Error: ${e}');
} }
``` ```
3. Create and obtain a single KV store.
(1) Declare the ID of the single KV store to create. 4. Create and obtain a single KV store.
(2) Create a single KV store. You are advised to disable automatic synchronization (**autoSync:false**) and call **sync** when a synchronization is required. 1. Declare the ID of the single KV store to create.
2. Create a single KV store. You are advised to disable automatic synchronization (`autoSync:false`) and call `sync` when a synchronization is required.
The sample code is as follows: The sample code is as follows:
```js ```js
let kvStore; let kvStore;
try { try {
const options = { const options = {
createIfMissing : true, createIfMissing: true,
encrypt : false, encrypt: false,
backup : false, backup: false,
autoSync : false, autoSync: false,
kvStoreType : distributedData.KVStoreType.SINGLE_VERSION, kvStoreType: distributedData.KVStoreType.SINGLE_VERSION,
securityLevel : distributedData.SecurityLevel.S0, securityLevel: distributedData.SecurityLevel.S0
}; };
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}');
} }
``` ```
> **NOTE** > **NOTE**<br>
> >
> For data synchronization between networked devices, you are advised to open the distributed KV store during application startup to obtain the database handle. With this database handle (`kvStore` in this example), you can perform operations, such as inserting data into the KV store, without creating the KV store repeatedly during the lifecycle of the handle. > For data synchronization between networked devices, you are advised to open the distributed KV store during application startup to obtain the database handle. With this database handle (`kvStore` in this example), you can perform operations, such as inserting data into the KV store, without creating the KV store repeatedly during the lifecycle of the handle.
5. Subscribe to changes in the distributed data.
4. Subscribe to changes in the distributed data.<br/>
The following is the sample code for subscribing to the data changes of a single KV store: The following is the sample code for subscribing to the data changes of a single KV store:
```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}");
}); });
``` ```
5. Write data to the single KV store. 6. Write data to the single KV store.
(1) Construct the key and value to be written into the single KV store.
(2) Write key-value pairs into the single KV store. 1. Construct the `Key` and `Value` to be written into the single KV store.
2. Write key-value pairs into the single KV store.
The following is the sample code for writing key-value pairs of the string type into the single KV store: The following is the sample code for writing key-value pairs of the string type into the single KV store:
...@@ -120,58 +188,60 @@ The following uses a single KV store as an example to describe the development p ...@@ -120,58 +188,60 @@ The following uses a single KV store as an example to describe the development p
const KEY_TEST_STRING_ELEMENT = 'key_test_string'; const KEY_TEST_STRING_ELEMENT = 'key_test_string';
const VALUE_TEST_STRING_ELEMENT = 'value-test-string'; const VALUE_TEST_STRING_ELEMENT = 'value-test-string';
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}');
} }
``` ```
6. Query data in the single KV store. 7. Query data in the single KV store.
(1) Construct the key to be queried from the single KV store. 1. Construct the `Key` to be queried from the single KV store.
2. Query data from the single KV store.
(2) Query data from the single KV store.
The following is the sample code for querying data of the string type from the single KV store: The following is the sample code for querying data of the string type from the single KV store:
```js ```js
const KEY_TEST_STRING_ELEMENT = 'key_test_string'; const KEY_TEST_STRING_ELEMENT = 'key_test_string';
const VALUE_TEST_STRING_ELEMENT = 'value-test-string'; const VALUE_TEST_STRING_ELEMENT = 'value-test-string';
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}');
} }
``` ```
7. Synchronize data to other devices.<br/> 8. Synchronize data to other devices.
Select the devices in the same network and the synchronization mode to synchronize data. Select the devices in the same network and the synchronization mode to synchronize data.
> **NOTE** > **NOTE**<br>
> >
> The APIs of the `deviceManager` module are system interfaces. > The APIs of the `deviceManager` module are system interfaces.
The following is the example code for synchronizing data in a single KV store:
The following is the sample code for synchronizing data in a single KV store:
```js ```js
import deviceManager from '@ohos.distributedHardware.deviceManager'; import deviceManager from '@ohos.distributedHardware.deviceManager';
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().
...@@ -185,8 +255,8 @@ The following uses a single KV store as an example to describe the development p ...@@ -185,8 +255,8 @@ The following uses a single KV store as an example to describe the development p
try{ try{
// 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.
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
> **NOTE** > **NOTE**
> >
> This feature is supported since API Version 9. For the versions earlier than API version 9, use [Lightweight Storage](../reference/apis/js-apis-data-storage.md) APIs. > This feature is supported since API version 9. For the versions earlier than API version 9, use [Lightweight Storage](../reference/apis/js-apis-data-storage.md) APIs.
## When to Use ## When to Use
...@@ -88,8 +88,30 @@ Use the following APIs to delete a **Preferences** instance or data file. ...@@ -88,8 +88,30 @@ 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:
```js ```js
let promise = data_preferences.getPreferences(this.context, 'mystore'); // Obtain the context.
import featureAbility from '@ohos.ability.featureAbility'
var context = featureAbility.getContext()
let promise = data_preferences.getPreferences(context, 'mystore');
```
Stage model:
```ts
// Obtain the context.
import Ability from '@ohos.application.Ability'
var context
class MainAbility extends Ability{
onWindowStageCreate(windowStage){
context = this.context
}
}
let promise = data_preferences.getPreferences(context, 'mystore');
``` ```
3. Write data. 3. Write data.
...@@ -115,12 +137,12 @@ Use the following APIs to delete a **Preferences** instance or data file. ...@@ -115,12 +137,12 @@ Use the following APIs to delete a **Preferences** instance or data file.
```js ```js
promise.then((preferences) => { 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) => { }).catch((err) => {
console.info("Failed to get the value of 'startup'. Cause: " + 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 preferences.")
}); });
...@@ -139,24 +161,24 @@ Use the following APIs to delete a **Preferences** instance or data file. ...@@ -139,24 +161,24 @@ 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) { var 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) { preferences.put('startup', 'auto', 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;
} }
console.info("Put the value of 'startup' successfully."); console.info("Put the value of 'startup' successfully.");
preferences.flush(function (err) { preferences.flush(function (err) {
if (err) { if (err) {
console.info("Failed to flush data. Cause: " + err); console.info("Failed to flush data. Cause: " + err);
return; return;
} }
console.info("Flushed data successfully."); // The observer will be called. console.info("Flushed data successfully."); // The observer will be called.
}) })
}) })
``` ```
7. Delete the specified file. 7. Delete the specified file.
...@@ -164,10 +186,10 @@ Use the following APIs to delete a **Preferences** instance or data file. ...@@ -164,10 +186,10 @@ Use the following APIs to delete a **Preferences** instance or data file.
Use the **deletePreferences** method to delete the **Preferences** instance and its persistent file and backup and corrupted files. After the specified files are deleted, the application cannot use that instance to perform any data operation. Otherwise, data inconsistency will be caused. The deleted data and files cannot be restored. Use the **deletePreferences** method to delete the **Preferences** instance and its persistent file and backup and corrupted files. After the specified files are deleted, the application cannot use that instance to perform any data operation. Otherwise, data inconsistency will be caused. The deleted data and files cannot be restored.
```js ```js
let proDelete = data_preferences.deletePreferences(context, 'mystore'); let proDelete = data_preferences.deletePreferences(context, 'mystore');
proDelete.then(() => { proDelete.then(() => {
console.info("Deleted data successfully."); console.info("Deleted data successfully.");
}).catch((err) => { }).catch((err) => {
console.info("Failed to delete data. Cause: " + err); console.info("Failed to delete data. Cause: " + err);
}) })
``` ```
...@@ -30,9 +30,10 @@ The RDB provides APIs for inserting, deleting, updating, and querying data in th ...@@ -30,9 +30,10 @@ The RDB provides APIs for inserting, deleting, updating, and querying data in th
**Table 2** API for inserting data **Table 2** API for inserting data
| Class | API | Description | | Class | API | Description |
| -------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | -------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| RdbStore | insert(table:string,values:ValuesBucket):Promise&lt;number&gt; | Inserts a row of data into a table. This API uses a promise to return the result.<br>If the operation is successful, the row ID will be returned; otherwise, **-1** will be returned.<br>- **table**: name of the target table.<br>- **values**: data to be inserted into the table.| | RdbStore | insert(table: string, values: ValuesBucket): Promise&lt;number&gt; | Inserts a row of data into a table. This API uses a promise to return the result.<br>If the operation is successful, the row ID will be returned; otherwise, **-1** will be returned.<br>- **table**: name of the target table.<br>- **values**: data to be inserted into the table.|
- **Updating Data** - **Updating Data**
...@@ -40,9 +41,10 @@ The RDB provides APIs for inserting, deleting, updating, and querying data in th ...@@ -40,9 +41,10 @@ The RDB provides APIs for inserting, deleting, updating, and querying data in th
**Table 3** API for updating data **Table 3** API for updating data
| Class | API | Description |
| Class | API | Description |
| -------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | -------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| RdbStore | update(values:ValuesBucket,predicates:RdbPredicates):Promise&lt;number&gt; | Updates data based on the specified **RdbPredicates** object. This API uses a promise to return the result.<br/>- **values**: data to update, which is stored in **ValuesBucket**.<br>- **predicates**: conditions for updating data.<br/>Return value: number of rows updated. | | RdbStore | update(values: ValuesBucket, predicates: RdbPredicates): Promise&lt;number&gt; | Updates data based on the specified **RdbPredicates** object. This API uses a promise to return the result.<br>the number of rows updated.<br>- **values**: data to update, which is stored in **ValuesBucket**.<br>- **predicates**: conditions for updating data.|
- **Deleting Data** - **Deleting Data**
...@@ -50,11 +52,10 @@ The RDB provides APIs for inserting, deleting, updating, and querying data in th ...@@ -50,11 +52,10 @@ The RDB provides APIs for inserting, deleting, updating, and querying data in th
**Table 4** API for deleting data **Table 4** API for deleting data
| Class | API | Description |
| -------- | ------------------------------------------------------ | ------------------------------------------------------------ | | Class | API | Description |
| RdbStore | delete(predicates:RdbPredicates):Promise&lt;number&gt; | Deletes data from the RDB store based on the specified **RdbPredicates** object. This API uses a promise to return the result.<br>- **predicates**: conditions for deleting data.<br/>Return value: number of rows updated. | | -------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| RdbStore | delete(predicates: RdbPredicates): Promise&lt;number&gt; | Deletes data from the RDB store based on the specified **RdbPredicates** object. This API uses a promise to return<br>the number of rows updated.<br>- **predicates**: conditions for deleting data.|
- **Querying Data** - **Querying Data**
...@@ -65,10 +66,11 @@ The RDB provides APIs for inserting, deleting, updating, and querying data in th ...@@ -65,10 +66,11 @@ The RDB provides APIs for inserting, deleting, updating, and querying data in th
**Table 5** APIs for querying data **Table 5** APIs for querying data
| Class | API | Description | | Class | API | Description |
| -------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | -------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| RdbStore | query(predicates:RdbPredicates,columns?:Array&lt;string&gt;):Promise&lt;ResultSet&gt; | Queries data from the RDB store based on specified conditions. This API uses a promise to return the result.<br>- **predicates**: conditions for querying data.<br>- **columns**: columns to query. If this parameter is not specified, the query applies to all columns.| | RdbStore | query(predicates: RdbPredicates, columns?: Array&lt;string&gt;): Promise&lt;ResultSet&gt; | Queries data from the RDB store based on specified conditions. This API uses a promise to return the result.<br>- **predicates**: conditions for querying data.<br>- **columns**: columns to query. If this parameter is not specified, the query applies to all columns.|
| RdbStore | querySql(sql:string,bindArgs?:Array&lt;ValueType&gt;):Promise&lt;ResultSet&gt; | Queries data using the specified SQL statement. This API uses a promise to return the result.<br>- **sql**: SQL statement.<br>- **bindArgs**: arguments in the SQL statement.| | RdbStore | querySql(sql: string, bindArgs?: Array&lt;ValueType&gt;): Promise&lt;ResultSet&gt; | Queries data using the specified SQL statement. This API uses a promise to return the result.<br>- **sql**: SQL statement.<br>- **bindArgs**: arguments in the SQL statement.|
| RdbStore | remoteQuery(device: string, table: string, predicates: RdbPredicates, columns: Array&lt;string&gt;): Promise&lt;ResultSet&gt; | Queries data from the database of a remote device based on specified conditions. This API uses a promise to return the result.<br>- **device**: network ID of the remote device.<br>- **table**: name of the table to be queried.<br>- **predicates**: **RdbPredicates** that specifies the query condition.<br>- **columns**: columns to query. If this parameter is not specified, the query applies to all columns.| | RdbStore | remoteQuery(device: string, table: string, predicates: RdbPredicates, columns: Array&lt;string&gt;): Promise&lt;ResultSet&gt; | Queries data from the database of a remote device based on specified conditions. This API uses a promise to return the result.<br>- **device**: network ID of the remote device.<br>- **table**: name of the table to be queried.<br>- **predicates**: **RdbPredicates** that specifies the query condition.<br>- **columns**: columns to query. If this parameter is not specified, the query applies to all columns.|
### Using Predicates ### Using Predicates
...@@ -81,11 +83,11 @@ The following lists common predicates. For more information about predicates, se ...@@ -81,11 +83,11 @@ The following lists common predicates. For more information about predicates, se
| Class | API | Description | | Class | API | Description |
| ------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | ------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| RdbPredicates | equalTo(field:string,value:ValueType):RdbPredicates | Sets an **RdbPredicates** to match the field with data type **ValueType** and value equal to the specified value.<br>- **field**: column name in the database table.<br>- **value**: value to match the **RdbPredicates**.<br>- **RdbPredicates**: **RdbPredicates** object that matches the specified field.| | RdbPredicates | equalTo(field: string, value: ValueType): RdbPredicates | Sets an **RdbPredicates** to match the field with data type **ValueType** and value equal to the specified value.<br>- **field**: column name in the database table.<br>- **value**: value to match the **RdbPredicates**.<br>- **RdbPredicates**: **RdbPredicates** object that matches the specified field.|
| RdbPredicates | notEqualTo(field:string,value:ValueType):RdbPredicates | Sets an **RdbPredicates** to match the field with data type **ValueType** and value not equal to the specified value.<br>- **field**: column name in the database table.<br>- **value**: value to match the **RdbPredicates**.<br>- **RdbPredicates**: **RdbPredicates** object that matches the specified field.| | RdbPredicates | notEqualTo(field: string, value: ValueType): RdbPredicates | Sets an **RdbPredicates** to match the field with data type **ValueType** and value not equal to the specified value.<br>- **field**: column name in the database table.<br>- **value**: value to match the **RdbPredicates**.<br>- **RdbPredicates**: **RdbPredicates** object that matches the specified field.|
| RdbPredicates | or():RdbPredicates | Adds the OR condition to the **RdbPredicates**.<br>- **RdbPredicates**: **RdbPredicates** with the OR condition.| | RdbPredicates | or(): RdbPredicates | Adds the OR condition to the **RdbPredicates**.<br>- **RdbPredicates**: **RdbPredicates** with the OR condition.|
| RdbPredicates | and():RdbPredicates | Adds the AND condition to the **RdbPredicates**.<br>- **RdbPredicates**: **RdbPredicates** with the AND condition.| | RdbPredicates | and(): RdbPredicates | Adds the AND condition to the **RdbPredicates**.<br>- **RdbPredicates**: **RdbPredicates** with the AND condition.|
| RdbPredicates | contains(field:string,value:string):RdbPredicates | Sets an **RdbPredicates** to match a string containing the specified value.<br>- **field**: column name in the database table.<br>- **value**: value to match the **RdbPredicates**.<br>- **RdbPredicates**: **RdbPredicates** object that matches the specified field.| | RdbPredicates | contains(field: string, value: string): RdbPredicates | Sets an **RdbPredicates** to match a string containing the specified value.<br>- **field**: column name in the database table.<br>- **value**: value to match the **RdbPredicates**.<br>- **RdbPredicates**: **RdbPredicates** object that matches the specified field.|
### Using the Result Set ### Using the Result Set
...@@ -101,12 +103,12 @@ For details about how to use result set APIs, see [Result Set](../reference/apis ...@@ -101,12 +103,12 @@ For details about how to use result set APIs, see [Result Set](../reference/apis
| Class | API | Description | | Class | API | Description |
| --------- | ---------------------------------------------------- | ------------------------------------------ | | --------- | ---------------------------------------------------- | ------------------------------------------ |
| ResultSet | goToFirstRow():boolean | Moves to the first row of the result set. | | ResultSet | goToFirstRow(): boolean | Moves to the first row of the result set. |
| ResultSet | getString(columnIndex:number):string | Obtains the value in the form of a string based on the specified column and current row. | | ResultSet | getString(columnIndex: number): string | Obtains the value in the form of a string based on the specified column and current row. |
| ResultSet | getBlob(columnIndex:number):Uint8Array | Obtains the value in the form of a byte array based on the specified column and the current row.| | ResultSet | getBlob(columnIndex: number): Uint8Array | Obtains the value in the form of a byte array based on the specified column and the current row.|
| ResultSet | getDouble(columnIndex:number):number | Obtains the value in the form of double based on the specified column and current row. | | ResultSet | getDouble(columnIndex: number): number | Obtains the value in the form of double based on the specified column and current row. |
| ResultSet | getLong(columnIndex:number):number | Obtains the value in the form of a long integer based on the specified column and current row. | | ResultSet | getLong(columnIndex: number): number | Obtains the value in the form of a long integer based on the specified column and current row. |
| ResultSet | close():void | Closes the result set. | | ResultSet | close(): void | Closes the result set. |
...@@ -164,7 +166,7 @@ You can obtain the distributed table name for a remote device based on the local ...@@ -164,7 +166,7 @@ You can obtain the distributed table name for a remote device based on the local
| Class | API | Description | | Class | API | Description |
| -------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | -------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| RdbStore | backup(destName:string): Promise&lt;void&gt; | Backs up an RDB store. This API uses a promise to return the result.<br>- **destName**: name of the RDB backup file.| | RdbStore | backup(destName: string): Promise&lt;void&gt; | Backs up an RDB store. This API uses a promise to return the result.<br>- **destName**: name of the RDB backup file.|
**Restoring an RDB Store** **Restoring an RDB Store**
...@@ -172,7 +174,7 @@ You can obtain the distributed table name for a remote device based on the local ...@@ -172,7 +174,7 @@ You can obtain the distributed table name for a remote device based on the local
| Class | API | Description | | Class | API | Description |
| -------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | -------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| RdbStore | restore(srcName:string): Promise&lt;void&gt; | Restores an RDB store from a backup file. This API uses a promise to return the result.<br>- **srcName**: name of the backup file used to restore the RDB store.| | RdbStore | restore(srcName: string): Promise&lt;void&gt; | Restores an RDB store from a backup file. This API uses a promise to return the result.<br>- **srcName**: name of the backup file used to restore the RDB store.|
**Transaction** **Transaction**
...@@ -180,9 +182,9 @@ Table 15 Transaction APIs ...@@ -180,9 +182,9 @@ Table 15 Transaction APIs
| Class | API | Description | | Class | API | Description |
| -------- | ----------------------- | --------------------------------- | | -------- | ----------------------- | --------------------------------- |
| RdbStore | beginTransaction():void | Starts the transaction before executing SQL statements.| | RdbStore | beginTransaction(): void | Starts the transaction before executing SQL statements.|
| RdbStore | commit():void | Commits the executed SQL statements. | | RdbStore | commit(): void | Commits the executed SQL statements. |
| RdbStore | rollBack():void | Rolls back the SQL statements that have been executed. | | RdbStore | rollBack(): void | Rolls back the SQL statements that have been executed. |
## How to Develop ## How to Develop
...@@ -194,17 +196,41 @@ Table 15 Transaction APIs ...@@ -194,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.
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)"; import featureAbility from '@ohos.ability.featureAbility'
const STORE_CONFIG = {name: "rdbstore.db"} let context = featureAbility.getContext()
data_rdb.getRdbStore(this.context, STORE_CONFIG, 1, function (err, rdbStore) {
rdbStore.executeSql(CREATE_TABLE_TEST) 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)";
console.info('create table done.')
}) const STORE_CONFIG = { name: "RdbTest.db" }
data_rdb.getRdbStore(context, STORE_CONFIG, 1, function (err, rdbStore) {
rdbStore.executeSql(CREATE_TABLE_TEST)
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.
...@@ -217,7 +243,7 @@ Table 15 Transaction APIs ...@@ -217,7 +243,7 @@ Table 15 Transaction APIs
```js ```js
var u8 = new Uint8Array([1, 2, 3]) var u8 = new Uint8Array([1, 2, 3])
const valueBucket = {"name": "Tom", "age": 18, "salary": 100.5, "blobType": u8} const valueBucket = { "name": "Tom", "age": 18, "salary": 100.5, "blobType": u8 }
let insertPromise = rdbStore.insert("test", valueBucket) let insertPromise = rdbStore.insert("test", valueBucket)
``` ```
...@@ -316,6 +342,7 @@ Table 15 Transaction APIs ...@@ -316,6 +342,7 @@ Table 15 Transaction APIs
console.log('device=' + device[i] + 'data changed') console.log('device=' + device[i] + 'data changed')
} }
} }
try { try {
rdbStore.on('dataChange', data_rdb.SubscribeType.SUBSCRIBE_TYPE_REMOTE, storeObserver) rdbStore.on('dataChange', data_rdb.SubscribeType.SUBSCRIBE_TYPE_REMOTE, storeObserver)
} catch (err) { } catch (err) {
...@@ -366,9 +393,7 @@ Table 15 Transaction APIs ...@@ -366,9 +393,7 @@ Table 15 Transaction APIs
(1) Back up the current RDB store. (1) Back up the current RDB store.
(2) Restore the RDB store using the backup file. The sample code is as follows:
The sample code is as follows:
```js ```js
let promiseBackup = rdbStore.backup("dbBackup.db") let promiseBackup = rdbStore.backup("dbBackup.db")
...@@ -378,6 +403,10 @@ Table 15 Transaction APIs ...@@ -378,6 +403,10 @@ Table 15 Transaction APIs
console.info('Backup failed, err: ' + err) console.info('Backup failed, err: ' + err)
}) })
``` ```
(2) Restore the RDB store using the backup file.
The sample code is as follows:
```js ```js
let promiseRestore = rdbStore.restore("dbBackup.db") let promiseRestore = rdbStore.restore("dbBackup.db")
promiseRestore.then(() => { promiseRestore.then(() => {
...@@ -386,4 +415,3 @@ Table 15 Transaction APIs ...@@ -386,4 +415,3 @@ Table 15 Transaction APIs
console.info('Restore failed, err: ' + err) console.info('Restore failed, err: ' + err)
}) })
``` ```
...@@ -7,21 +7,21 @@ With device usage statistics APIs, you can have a better understanding of the ap ...@@ -7,21 +7,21 @@ With device usage statistics APIs, you can have a better understanding of the ap
Currently you can have access to statistics on the application usage, and the notification and system usage statistics feature will be available for use in later versions. Currently you can have access to statistics on the application usage, and the notification and system usage statistics feature will be available for use in later versions.
- **The application usage statistics is updated**: - **The application usage statistics is updated**:
1. Every 30 minutes 1. Every 30 minutes
2. Upon system time change 2. Upon system time change
3. Upon start of a new day 3. Upon start of a new day
- **The application usage statistics can include the following**: - **The application usage statistics can include the following**:
1. Events of all applications based on the specified start time and end time 1. Events of all applications based on the specified start time and end time
2. Application usage duration statistics based on the specified start time and end time 2. Application usage duration statistics based on the specified start time and end time
3. Events of the current application based on the specified start time and end time 3. Events of the current application based on the specified start time and end time
4. Application usage duration statistics in the specified time frame at the specified interval (daily, weekly, monthly, or annually) 4. Application usage duration statistics in the specified time frame at the specified interval (daily, weekly, monthly, or annually)
5. Priority group of the current invoker application 5. Priority group of the current invoker application
6. Whether a specific application is in the idle state 6. Whether a specific application is in the idle state
7. Number of FA usage records specified by **maxNum**, sorted by time (most recent first). If **maxNum** is not specified, the default value **1000** will be used. 7. Number of FA usage records specified by **maxNum**, sorted by time (most recent first). If **maxNum** is not specified, the default value **1000** will be used.
8. Number of notifications from applications based on the specified start time and end time 8. Number of notifications from applications based on the specified start time and end time
9. Statistics about system events (hibernation, wakeup, unlocking, and screen locking) that occur between the specified start time and end time 9. Statistics about system events (hibernation, wakeup, unlocking, and screen locking) that occur between the specified start time and end time
10. Priority group of the invoker application or a specified application 10. Priority group of the invoker application or a specified application
- **The setters can be used to:** - **The setters can be used to:**
...@@ -35,6 +35,6 @@ Currently you can have access to statistics on the application usage, and the no ...@@ -35,6 +35,6 @@ Currently you can have access to statistics on the application usage, and the no
Deregister the callback for application group changes. Deregister the callback for application group changes.
### Required Permissions ## Required Permissions
- Before calling the following system APIs, you need to apply for the **ohos.permission.BUNDLE_ACTIVE_INFO** permission: **queryBundleActiveStates**, **queryBundleStateInfos**, **queryBundleStateInfoByInterval**, **queryBundleActiveEventStates**, **queryAppNotificationNumber**, **queryAppUsagePriorityGroup(bundleName?)**, **setBundleGroup**, **registerGroupCallBack**, and **unRegisterGroupCallBack**. - Before calling the following system APIs, you need to apply for the **ohos.permission.BUNDLE_ACTIVE_INFO** permission: **queryBundleActiveStates**, **queryBundleStateInfos**, **queryBundleStateInfoByInterval**, **queryBundleActiveEventStates**, **queryAppNotificationNumber**, **queryAppUsagePriorityGroup(bundleName?)**, **setBundleGroup**, **registerGroupCallBack**, and **unRegisterGroupCallBack**.
- This permission is not required for calling third-party APIs: **queryCurrentBundleActiveStates**, **queryAppUsagePriorityGroup()**, and **isIdleState**. - This permission is not required for calling third-party APIs: **queryCurrentBundleActiveStates**, **queryAppUsagePriorityGroup()**, and **isIdleState**.
...@@ -16,7 +16,7 @@ For details about the APIs, see [Vibrator](../reference/apis/js-apis-vibrator.md ...@@ -16,7 +16,7 @@ For details about the APIs, see [Vibrator](../reference/apis/js-apis-vibrator.md
| ohos.vibrator | vibrate(duration: number, callback?: AsyncCallback&lt;void&gt;): void | Triggers vibration with the specified duration. This API uses a callback to return the result. | | ohos.vibrator | vibrate(duration: number, callback?: AsyncCallback&lt;void&gt;): void | Triggers vibration with the specified duration. This API uses a callback to return the result. |
| ohos.vibrator | vibrate(effectId: EffectId): Promise&lt;void&gt; | Triggers vibration with the specified effect. This API uses a promise to return the result. | | ohos.vibrator | vibrate(effectId: EffectId): Promise&lt;void&gt; | Triggers vibration with the specified effect. This API uses a promise to return the result. |
| ohos.vibrator | vibrate(effectId: EffectId, callback?: AsyncCallback&lt;void&gt;): void | Triggers vibration with the specified effect. This API uses a callback to return the result.| | ohos.vibrator | vibrate(effectId: EffectId, callback?: AsyncCallback&lt;void&gt;): void | Triggers vibration with the specified effect. This API uses a callback to return the result.|
| ohos.vibrator | stop(stopMode: VibratorStopMode): Promise&lt;void&gt; | Stops vibration. This API uses a promise to return the result. | | ohos.vibrator | stop(stopMode: VibratorStopMode): Promise&lt;void&gt;| Stops vibration. This API uses a promise to return the result. |
| ohos.vibrator | stop(stopMode: VibratorStopMode, callback?: AsyncCallback&lt;void&gt;): void | Stops vibration. This API uses a callback to return the result. | | ohos.vibrator | stop(stopMode: VibratorStopMode, callback?: AsyncCallback&lt;void&gt;): void | Stops vibration. This API uses a callback to return the result. |
...@@ -55,7 +55,7 @@ For details about the APIs, see [Vibrator](../reference/apis/js-apis-vibrator.md ...@@ -55,7 +55,7 @@ For details about the APIs, see [Vibrator](../reference/apis/js-apis-vibrator.md
], ],
"when": "inuse" "when": "inuse"
} }
}, }
] ]
``` ```
......
...@@ -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 sensitivity level 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. The authorization mode of this permission is **system_grant**.
...@@ -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.
...@@ -49,12 +47,12 @@ For details about the result codes, see [Event Verification Result Codes](#event ...@@ -49,12 +47,12 @@ For details about the result codes, see [Event Verification Result Codes](#event
| Result Code| Cause | Verification Rules | Handling Method | | Result Code| Cause | Verification Rules | Handling Method |
| ------ | ----------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------- | | ------ | ----------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------- |
| 0 | N/A | Event verification is successful. | Event logging is normal. No action is required. | | 0 | N/A | Event verification is successful. | Event logging is normal. No action is required. |
| -1 | Invalid event name | The name is not empty and contains a maximum of 48 characters.<br>The name consists of only the following characters: digits (0 to 9), letters (a to z), and underscore \(_).<br>The name does not start with a digit or underscore \(_).| Ignore this event and do not perform logging. | | -1 | Invalid event name | The name is not empty and contains a maximum of 48 characters.<br>The name consists of only the following characters: digits (0 to 9), letters (a to z), and underscore (\_).<br>The name does not start with a digit or underscore (\_).| Ignore this event and do not perform logging. |
| -2 | Invalid event parameter type | The event name must be a string.<br>The event type must be a number.<br>The event parameter must be an object.| Ignore this event and do not perform logging. | | -2 | Invalid event parameter type | The event name must be a string.<br>The event type must be a number.<br>The event parameter must be an object.| Ignore this event and do not perform logging. |
| -4 | Invalid event domain name | The name is not empty and contains a maximum of 32 characters.<br>The name consists of only the following characters: digits (0 to 9), letters (a to z), and underscore \(_).<br>The name does not start with a digit or underscore \(_).| Ignore this event and do not perform logging. | | -4 | Invalid event domain name | The name is not empty and contains a maximum of 32 characters.<br>The name consists of only the following characters: digits (0 to 9), letters (a to z), and underscore (\_).<br>The name does not start with a digit or underscore (\_).| Ignore this event and do not perform logging. |
| -99 | Application event logging disabled | Application event logging is disabled. | Ignore this event and do not perform logging. | | -99 | Application event logging disabled | Application event logging is disabled. | Ignore this event and do not perform logging. |
| -100 | Unknown error | None. | Ignore this event and do not perform logging. | | -100 | Unknown error | None. | Ignore this event and do not perform logging. |
| 1 | Invalid key name | The name is not empty and contains a maximum of 16 characters.<br>The name consists of only the following characters: digits (0 to 9), letters (a to z), and underscore \(_).<br>The name does not start with a digit or underscore \(_).<br>The name does not end with an underscore \(_).| Ignore the key-value pair and continue to perform logging. | | 1 | Invalid key name | The name is not empty and contains a maximum of 16 characters.<br>The name consists of only the following characters: digits (0 to 9), letters (a to z), and underscore (\_).<br>The name does not start with a digit or underscore (\_).<br>The name does not end with an underscore (\_).| Ignore the key-value pair and continue to perform logging. |
| 2 | Invalid key type | The key must be a string. | Ignore the key-value pair and continue to perform logging. | | 2 | Invalid key type | The key must be a string. | Ignore the key-value pair and continue to perform logging. |
| 3 | Invalid value type | The supported value types vary depending on the programming language:<br>boolean, number, string, or Array [basic element]| Ignore the key-value pair and continue to perform logging. | | 3 | Invalid value type | The supported value types vary depending on the programming language:<br>boolean, number, string, or Array [basic element]| Ignore the key-value pair and continue to perform logging. |
| 4 | Invalid length for values of the string type| For a value of the string type, the maximum length is 8*1024 characters. | Truncate the value with the first 8*1024 characters retained, and continue to perform logging.| | 4 | Invalid length for values of the string type| For a value of the string type, the maximum length is 8*1024 characters. | Truncate the value with the first 8*1024 characters retained, and continue to perform logging.|
...@@ -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"
}) })
...@@ -157,9 +164,3 @@ The following uses a one-time event watcher as an example to illustrate the deve ...@@ -157,9 +164,3 @@ The following uses a one-time event watcher as an example to illustrate the deve
``` ```
5. On the application UI, touch button 3 to remove the event watcher. Then, touch button 1 for multiple times to perform application event logging. In such a case, there will be no log information about the callback invoked by the event watcher. 5. On the application UI, touch button 3 to remove the event watcher. Then, touch button 1 for multiple times to perform application event logging. In such a case, there will be no log information about the callback invoked by the event watcher.
## Samples
The following sample is provided to help you better understand how to develop the application event logging feature:
- [`JsDotTest` (JS) (API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/DFX/JsDotTest)
# FAQs
- [Ability Framework Development](faqs-ability.md)
- [ArkUI (JavaScript) Development](faqs-ui-js.md)
- [ArkUI (eTS) Development](faqs-ui-ets.md)
- [Graphics and Image Development](faqs-graphics.md)
- [File Management Development](faqs-file-management.md)
- [Data Management Development](faqs-data-management.md)
- [Device Management Development](faqs-device-management.md)
- [Native API Usage](faqs-native.md)
- [Usage of Third- and Fourth-Party Libraries](faqs-third-party-library.md)
- [Development Board](faqs-development-board.md)
# Ability Framework Development
## Is a guide similar to the Data ability development in the FA model available for the stage model?
Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
A guide is available for the **DataShareExtensionAbility** class in the stage model, which provides APIs for sharing data with other applications and managing the data.
Reference: [DataShare Development](../database/database-datashare-guidelines.md)
## What should I do if the UI does not respond when an ability is started?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
1. If the ability is started using **startAbility**, check whether the **abilityName** field in **want** uses the bundle name as the prefix. If yes, delete the bundle name.
2. Make sure the ability's home page file configured by **onWindowStageCreate** in the **MainAbility.ts** file is defined in the **main_pages.json** file.
3. You are advised to use the SDK and OpenHarmony SDK versions released on the same day.
Reference: [Release Testing Version](https://gitee.com/openharmony-sig/oh-inner-release-management/blob/master/Release-Testing-Version.md)
## How do I prevent "this" in a method from changing to "undefined" when the method is called?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
Method 1: Add **.bind(this)** when calling the method.
Method 2: Use the arrow function.
## What should I do when the message "must have required property 'startWindowIcon'" is displayed?
Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
Configure the **startWindowIcon** attribute under **abilities** in the **module.json5** file.
Reference: [Application Package Structure Configuration File](../quick-start/stage-structure.md)
Example:
```
{
"module": {
// Do something.
"abilities": [{
// Do something.
"startWindowIcon": "$media:space",
"startWindowBackground": "$color:white",
}]
}
}
```
## How do I obtain a notification when the device orientation changes?
Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
Implement the **onConfigurationUpdated** callback in the **Ability** class. The callback is triggered when the system language, color mode, or display parameters (such as the orientation and density) change.
Reference: [Ability Development](../ability/stage-ability.md)
# Device Management Development
## How Do I Save PixelMap data to a database?
Applicable to: OpenHarmony SDK 3.2.3.5
You can convert a **PixelMap** into a **ArrayBuffer** and save the **ArrayBuffer** to your database.
Reference: [readPixelsToBuffer](../reference/apis/js-apis-image.md#readpixelstobuffer7-1)
## How Do I Obtain RDB Store Files?
Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
Run the hdc_std command to copy the .db, .db-shm, and .db-wal files from **/data/app/el2/100/database/Bundle name/entry/db/**, and then use the SQLite tool to open the files.
Example:
```
hdc_std file recv /data/app/el2/100/database/com.xxxx.xxxx/entry/db/test.db ./test.db
```
# Development Board
## How do I take screenshots on a development board?
Applicable to: OpenHarmony SDK 3.2.2.5, stage model of API version 9
- Method 1: Click the screenshot button in the Control Panel from the development board UI. The screenshot is displayed in Gallery.
- Method 2: Run the screenshot script. Connect to the development board to a computer running Windows. Create a text file on the computer, copy the following script content to the file, change the file name extension to **.bat** (the HDC environment variables must be configured in advance), and click **Run**. The screenshot is saved to the same directory as the **.bat** script file.
Example:
```
set filepath=/data/%date:~0,4%%date:~5,2%%date:~8,2%%time:~1,1%%time:~3,2%%time:~6,2%.png
echo %filepath%
: pause
hdc_std shell snapshot_display -f %filepath%
: pause
hdc_std file recv %filepath% .
: pause
```
## How do I adjust Previewer in DevEco Studio so that the preview looks the same as what's displayed on a real RK3568 development board?
Applicable to: DevEco Studio 3.0.0.991
1. Create a profile in Previewer.
![en-us_image_0000001361254285](figures/en-us_image_0000001361254285.png)
2. Set the profile parameters as follows:
Device type : default
Resolution: 720\*1280
DPI: 240
## What should I do if Device Manager incorrectly identifies a development board as FT232R USB UART even when the development board already has a driver installed?
Possible cause: The USB serial driver of the development version is not installed.
Solution: Search for **FT232R USB UART**, and download and install the driver.
## How do I complete authentication when logging in to the development board?
Applicable to: OpenHarmony SDK 3.2.2.5
When connecting to the network that requires authentication, open any web page in the browser to access the authentication page.
If there is no browser on the development board, you can install the [sample browser application](https://gitee.com/openharmony/app_samples/tree/master/device/Browser).
# Device Management Development
## How do I obtain the DPI of a device?
Applicable to: OpenHarmony SDK 3.2.2.5, stage model of API version 9
Import the **@ohos.display** module and call the **getDefaultDisplay** API.
Example:
```
import display from '@ohos.display';
display.getDefaultDisplay((err, data) => {
if (err.code) {
console.error('Test Failed to obtain the default display object. Code: ' + JSON.stringify(err));
return;
}
console.info('Test Succeeded in obtaining the default display object. Data:' + JSON.stringify(data));
console.info('Test densityDPI:' + JSON.stringify(data.densityDPI));
});https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-device-info.md)
```
# File Management Development
## What If There is No Return Value or Error Captured After getAlbums Is Called?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
The **ohos.permission.READ_MEDIA** permission is required for calling **getAlbums**, and this permission needs user authorization. For details, see OpenHarmony [Application Permission List](../security/permission-list.md).
1. Configure the required permission in the **module.json5** file.
```
"requestPermissions": [
{
"name": "ohos.permission.READ_MEDIA"
}
]
```
2. Add the code for user authorization before the **MainAbility.ts -> onWindowStageCreate** page is loaded.
```
private requestPermissions() {
let permissionList: Array<string> = [
"ohos.permission.READ_MEDIA"
];
this.context.requestPermissionsFromUser(permissionList)
.then(data => {
console.info(`request permission data result = ${data.authResults}`)
})
.catch(err => {
console.error(`fail to request permission error:${err}`)
})
}
```
# Graphics and Image Development
## Why do the isStatusBarLightIcon and isNavigationBarLightIcon attributes not take effect when window.setSystemBarProperties() is called?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
In effect, the **isStatusBarLightIcon** and **isNavigationBarLightIcon** attributes turn the font white when set to **true**. If **statusBarContentColor** is also set in **window.setSystemBarProperties()**, the **isStatusBarLightIcon** attribute does not take effect. Similarly, if **navigationBarContentColor** is set, the **isNavigationBarLightIcon** attribute does not take effect.
## How do I set the style of the system bar?
Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
Import the **\@ohos.window** module, and call **window.setSystemBarProperties()**.
# Native API Usage
## When a native HAP is running, the error message "Obj is not a valid object" is displayed for the imported namespace. What should I do?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
Check the **abiFilters** parameter value in the **build-profile.json5** file in the root directory of the module (not the root directory of the project). If the device is 32-bit, the value must be **armeabi-v7a**. If the device is 64-bit, the value must be **arm64-v8a**.
## How do I obtain the value of version in the package.json file of a module in the C++ code developed using native APIs?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
1. In the script file **hvigorfile.js** of Hvigor, use **subModule.getPackageJsonPath** to obtain the location of the **package.json** file in the module.
2. Use Node.js to read the **version** field in the **package.json** file and write the value to the **buildOption.cppFlags** field in the **build-profile.json5** file.
Example
```
// Module-level hvigorfile.js
const subModule = require('@ohos/hvigor')(__filename)
const fs = require("fs-extra")
const path = require("path")
const packageJsonPath = subModule.getPackageJsonPath()
const buildProfilePath = path.resolve(packageJsonPath, '../build-profile.json5')
const packageJsonData = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
let buildProfileData = fs.readFileSync(buildProfilePath, 'utf8')
buildProfileData = buildProfileData.replace(/\"cppFlags\"\:(.*)\,/, `"cppFlags": "-D NWEBEX_VERSION=${packageJsonData.version}",`)
fs.writeFileSync(buildProfilePath, buildProfileData, 'utf8')
const ohosPlugin = require('@ohos/hvigor-ohos-plugin').hapTasks(subModule) // The plug-in executes the C++ build task and reads the build-profile.json5 file.
module.exports = {
ohos: ohosPlugin
}
```
```
// Read the hello.cpp file.
#define _NWEBEX_VERSION(v) #v
#define _NWEBEX_VER2STR(v) _NWEBEX_VERSION(v)
static napi_value Add(napi_env env, napi_callback_info info)
{
napi_value fixed_version_value = nullptr;
napi_create_string_utf8(env, _NWEBEX_VER2STR(NWEBEX_VERSION), NAPI_AUTO_LENGTH, &fixed_version_value);
return fixed_version_value;
}
```
# Usage of Third- and Fourth-Party Libraries
## What does the following error message mean : "Stage model module... does not support including OpenHarmony npm packages or modules in FA model. OpenHarmony build tasks will not be executed, and OpenHarmony resources will not be packed."
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
The third- and fourth-party libraries are not yet compatible with the stage model of API version 9 and cannot be used.
# ArkUI (eTS) Development
## What are the restrictions on using generator functions in TypeScript?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
Below are the restrictions on using generator functions in TypeScript:
- Expressions can be used only in character strings (in the ${expression} format), **if** conditions, **ForEach** parameters, and component parameters.
- No expressions should cause any application state variables (including **\@State**, **\@Link**, and **\@Prop**) to change. Otherwise, undefined and potentially unstable framework behavior may occur.
- The generator function cannot contain local variables.
None of the above restrictions apply to anonymous function implementations of event handlers (such as **onClick**).
Negative example:
```
build() {
let a: number = 1 // invalid: variable declaration not allowed
Column() {
Text('Hello ${this.myName.toUpperCase()}') // ok.
ForEach(this.arr.reverse(), ..., ...) // invalid: Array.reverse modifies the @State array varible in place
}
buildSpecial() // invalid: no function calls
Text(this.calcTextValue()) // this function call is ok.
}
```
## How do I use router to implement page redirection in the stage model?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
To implement page redirection through **router**, add all redirected-to pages to the pages list in the **main_pages.json** file.
Page routing APIs in **router** can be invoked only after page rendering is complete. Do not call these APIs in **onInit** or **onReady** when the page is still in the rendering phase.
## Will a page pushed into the stack through router.push be reclaimed?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
After being pushed to the stack through **router.push**, a page can be reclaimed only when it is popped from the stack through **router.back**.
## How do I dynamically replace the %s placeholder in a resource file?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
In an application, you can replace the %s placeholder by using the second parameter in `$r('app.string.xx')`, which is used to reference application resources.
Example:
```
build() {
//do something
// The second parameter indicates the referenced string resource, which can be used to replace the %s placeholder.
Text($r('app.string.entry_desc','aaa'))
.fontSize(100)
.fontColor(Color.Black)
//do something
}
```
## How do I read an XML file in Resource and convert data in it to the string type?
Applicable to: OpenHarmony SDK 3.2.2.5, stage model of API version 9
1. Obtain data in Uint8Array format by calling the **RawFile** API of **resourceManager**.
2. Convert data in Uint8Array format to the string type by calling the **String.fromCharCode** API.
Reference: [Resource Management](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-resource-manager.md)
Example:
```
resourceManager.getRawFile(path, (error, value) => {
if (error != null) {
console.log("error is " + error);
} else {
let rawFile = value;
let xml = String.fromCharCode.apply(null, rawFile)
}
});
```
## How do I convert a Resource object to the string type?
Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
Use the **resourceManager.getString()** API of the **\@ohos.resourceManager** module.
Reference: [Resource Management](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-resource-manager.md#getstring)
## What should I do if the global static variables of a class do not work?
Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
Objects imported to abilities and pages are packaged into two different closures, that is, two global objects. In this case, a static variable referenced by the abilities is not the same object as that referenced by the pages. Therefore, global variables cannot be defined by defining static variables in the class. You are advised to use AppStorage to manage global variables.
Reference: [AppStorage](https://docs.openharmony.cn/pages/v3.2Beta/en/application-dev/ui/ts-application-states-appstorage.md/)
## How do I obtain resources in the stage model?
Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
The stage model allows an application to obtain a **ResourceManager** object based on **context** and call its resource management APIs without first importing the required bundle. This method, however, is not applicable to the FA model.
Example:
```
const context = getContext(this) as any
context
.resourceManager
.getString($r('app.string.entry_desc').id)
.then(value => {
this.message = value.toString()
})
```
## How do I position a container component to the bottom of the screen?
Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
Create a **<Stack\>** component, and set the target container at the bottom of the **<Stack\>** component.
Example:
```
build() {
Stack({alignContent : Alignment.Bottom}) {
// The container is at the bottom.
Stack() {
Column()
.width('100%')
.height('100%')
.backgroundColor(Color.Yellow)
}
.width('100%')
.height('10%')
}
.width('100%')
.height('100%')
.backgroundColor('rgba(255,255,255, 0)')
}
```
## Can CustomDialog be used in TypeScript files?
Applicable to: OpenHarmony SDK 3.2.2.5, stage model of API version 9
No. Currently, **CustomDialog** can be used only on eTS pages.
Reference: [Custom Dialog Box](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/arkui-ts/ts-methods-custom-dialog-box.md)
## How do I transfer variables in CustomDialog to variables on pages?
Applicable to: OpenHarmony SDK 3.2.2.5, stage model of API version 9
Use a custom callback so that when the confirm button in the custom dialog box is clicked, the value of **data** is transferred from the dialog box to the current page.
Example:
```
// CustomDialog component
@CustomDialog
struct MyDialog {
controller: CustomDialogController
title: string
data: string
cancel: () => void
confirm: (data: string) => void
Button('confirm')
.onClick(() => {
this.controller.close()
this.data = 'test'
this.confirm(this.data)
}).backgroundColor(0xffffff).fontColor(Color.Red)
// Page
@Entry
@Component
struct DialogTest {
dialogController: CustomDialogController = new CustomDialogController({
builder: MyDialog({ title:'Custom Title',cancel: this.onCancel,
confirm: this.onAccept.bind(this)}), // Bind the custom callback to the button.
cancel: this.existApp,
autoCancel: true
})
onAccept(data:string) {
console.info('Callback when the second button is clicked ' + data)
}
}
```
## What should I do if the \<List> component cannot be dragged to the bottom after it has a \<Text> component added?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
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?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
By default, child components in a **\<GridContainer>** are horizontally aligned to the left. To center them, perform the following steps:
Nest a **\<Row>** component and set it to **justifyContent(FlexAlign.Center)**. For details, see [Grid Layout](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/ui/ui-ts-layout-grid-container.md).
Example:
```
GridContainer({ sizeType: SizeType.SM, columns: 12 }) {
Row() {
Text('1')
.useSizeType({
sm: { span: 4, offset: 0 },
})
.backgroundColor(0x46F2B4)
}.justifyContent(FlexAlign.Center) // Center child components.
}
```
## How do I obtain the height of the status bar and navigation bar?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
Before the window content is loaded, enable listening for the **systemAvoidAreaChange** event.
Example:
```
// MainAbility.ts
import window from '@ohos.window';
/**
* Set the immersive window and obtain the height of the status bar and navigation bar.
* @param mainWindow Indicates the main window.
*/
async function enterImmersion(mainWindow: window.Window) {
mainWindow.on("systemAvoidAreaChange", (area: window.AvoidArea) => {
AppStorage.SetOrCreate<number>("topHeight", area.topRect.height);
AppStorage.SetOrCreate<number>("bottomHeight", area.bottomRect.height);
})
await mainWindow.setFullScreen(true)
await mainWindow.setSystemBarEnable(["status", "navigation"])
await mainWindow.setSystemBarProperties({
navigationBarColor: "#00000000",
statusBarColor: "#00000000",
navigationBarContentColor: "#FF0000",
statusBarContentColor: "#FF0000"
})
}
export default class MainAbility extends Ability {
// do something
async onWindowStageCreate(windowStage: window.WindowStage) {
let mainWindow = await windowStage.getMainWindow()
await enterImmersion(mainWindow)
windowStage.loadContent('pages/index')
}
// do something
}
```
## How do I execute JavaScript functions in the \<Web> component in eTS code?
Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
Call the **runJavaScript** API in the **WebController** to asynchronously execute JavaScript scripts. This API uses a callback to return the execution result. Note: **runJavaScript** can only be called after **loadUrl** has been completed. For example, it can be called in **onPageEnd**.
Reference: [Web](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/arkui-ts/ts-basic-components-web.md)
## How do I fix misidentification of the pan gesture where container nesting is involved?
Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9
Set the **distance** attribute to **1** for the gesture. By default, this attribute is set to **5**.
# ArkUI (JavaScript) Development
## How do I convert the fields in an XML file into JavaScript objects?
Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
To convert fields in an XML file into JavaScript objects, call the **convert** API in the **convertxml** module.
Example:
```
import convertxml from '@ohos.convertxml';
// Code snippet
xml =
'<?xml version="1.0" encoding="utf-8"?>' +
'<note importance="high" logged="true">' +
' <title>Happy</title>' +
' <todo>Work</todo>' +
' <todo>Play</todo>' +
'</note>';
let conv = new convertxml.ConvertXML();
// Options for conversion. For details, see the reference document.
let options = {trim : false, declarationKey:"_declaration",
instructionKey : "_instruction", attributesKey : "_attributes",
textKey : "_text", cdataKey:"_cdata", doctypeKey : "_doctype",
commentKey : "_comment", parentKey : "_parent", typeKey : "_type",
nameKey : "_name", elementsKey : "_elements"}
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: ' + 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
```
Reference: [XML-to-JavaScript Conversion](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-convertxml.md)
## What are the differences between JavaScript, TypeScript, and eTS?
Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9
- JavaScript: a lightweight, weakly-typed programming language, most commonly known as the scripting language for web pages.
- TypeScript: a superset of JavaScript, with additions of static typing and more object-oriented APIs, enums, etc.
- eTS: a superset of TypeScript and the programming language for OpenHarmony ArkUI development, which powers UI development through a declarative development paradigm.
## How do I convert the time to the HHMMSS format?
Example:
```
export default class DateTimeUtil{
/**
* HHMMSS
*/
getTime() {
const DATETIME = new Date()
return this.concatTime(DATETIME.getHours(),DATETIME.getMinutes(),DATETIME.getSeconds())
}
/**
* YYYYMMDD
*/
getDate() {
const DATETIME = new Date()
return this.concatDate(DATETIME.getFullYear(),DATETIME.getMonth()+1,DATETIME.getDate())
}
/**
* If the date is less than 10, add a leading zero, for example, **07**.
* @param value Indicates the value.
*/
fill(value:number) {
return (value> 9 ? '' : '0') + value
}
/**
* Concatenate year, month, and date fields.
* @param year
* @param month
* @param date
*/
concatDate(year: number, month: number, date: number){
return `${year}${this.fill(month)}${this.fill(date)}`
}
/**
Concatenate hours, minutes, and seconds fields.
* @param hours
* @param minutes
* @param seconds
*/
concatTime(hours:number,minutes:number,seconds:number){
return `${this.fill(hours)}${this.fill(minutes)}${this.fill(seconds)}`
}
}
```
...@@ -20,4 +20,4 @@ ...@@ -20,4 +20,4 @@
- Camera - Camera
- [Camera Development](camera.md) - [Camera Development](camera.md)
- [Distributed Camera Development](remote-camera.md)
...@@ -8,7 +8,7 @@ You can use the APIs provided by **AudioCapturer** to record raw audio files. ...@@ -8,7 +8,7 @@ You can use the APIs provided by **AudioCapturer** to record raw audio files.
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.
For details about the APIs, see [AudioCapturer in Audio Management](../reference/apis/js-apis-audio.md). For details about the APIs, see [AudioCapturer in Audio Management](../reference/apis/js-apis-audio.md#audiocapturer8).
**Figure 1** Audio capturer state **Figure 1** Audio capturer state
......
...@@ -18,7 +18,7 @@ You can use audio playback APIs to convert audio data into audible analog signal ...@@ -18,7 +18,7 @@ You can use audio playback APIs to convert audio data into audible analog signal
## How to Develop ## How to Develop
For details about the APIs, see [AudioPlayer in the Media API](../reference/apis/js-apis-media.md). For details about the APIs, see [AudioPlayer in the Media API](../reference/apis/js-apis-media.md#audioplayer).
### Full-Process Scenario ### Full-Process Scenario
......
...@@ -16,7 +16,7 @@ During audio recording, audio signals are captured, encoded, and saved to files. ...@@ -16,7 +16,7 @@ During audio recording, audio signals are captured, encoded, and saved to files.
## How to Develop ## How to Develop
For details about the APIs, see [AudioRecorder in the Media API](../reference/apis/js-apis-media.md). For details about the APIs, see [AudioRecorder in the Media API](../reference/apis/js-apis-media.md#audiorecorder).
### Full-Process Scenario ### Full-Process Scenario
...@@ -185,4 +185,3 @@ export class AudioRecorderDemo { ...@@ -185,4 +185,3 @@ export class AudioRecorderDemo {
} }
} }
``` ```
...@@ -12,7 +12,7 @@ For details about the APIs, see [AudioStreamManager](../reference/apis/js-apis-a ...@@ -12,7 +12,7 @@ For details about the APIs, see [AudioStreamManager](../reference/apis/js-apis-a
**Figure 1** Audio stream management invoking relationship **Figure 1** Audio stream management invoking relationship
![](figures/zh-ch_image_audio_stream_manager.png) ![](figures/en-us_image_audio_stream_manager.png)
## How to Develop ## How to Develop
...@@ -117,7 +117,7 @@ This API can be used to obtain the unique ID of the audio stream, UID of the aud ...@@ -117,7 +117,7 @@ This API can be used to obtain the unique ID of the audio stream, UID of the aud
console.info('Address:' + i + ':' + AudioRendererChangeInfo.deviceDescriptors[j].address); console.info('Address:' + i + ':' + AudioRendererChangeInfo.deviceDescriptors[j].address);
console.info('SampleRates:' + i + ':' + AudioRendererChangeInfo.deviceDescriptors[j].sampleRates[0]); console.info('SampleRates:' + i + ':' + AudioRendererChangeInfo.deviceDescriptors[j].sampleRates[0]);
console.info('ChannelCounts' + i + ':' + AudioRendererChangeInfo.deviceDescriptors[j].channelCounts[0]); console.info('ChannelCounts' + i + ':' + AudioRendererChangeInfo.deviceDescriptors[j].channelCounts[0]);
console.info('ChannnelMask:' + i + ':' + AudioRendererChangeInfo.deviceDescriptors[j].channelMasks); console.info('ChannelMask:' + i + ':' + AudioRendererChangeInfo.deviceDescriptors[j].channelMasks);
} }
} }
} }
......
...@@ -54,7 +54,7 @@ await cameraManager.getCameras((err, cameras) => { ...@@ -54,7 +54,7 @@ await cameraManager.getCameras((err, cameras) => {
cameraArray = cameras cameraArray = cameras
}) })
for(let cameraIndex = 0; cameraIndex < cameraArray.length; cameraIndex) { for(let cameraIndex = 0; cameraIndex < cameraArray.length; cameraIndex++) {
console.log('cameraId : ' + cameraArray[cameraIndex].cameraId) // Obtain the camera ID. console.log('cameraId : ' + cameraArray[cameraIndex].cameraId) // Obtain the camera ID.
console.log('cameraPosition : ' + cameraArray[cameraIndex].cameraPosition) // Obtain the camera position. console.log('cameraPosition : ' + cameraArray[cameraIndex].cameraPosition) // Obtain the camera position.
console.log('cameraType : ' + cameraArray[cameraIndex].cameraType) // Obtain the camera type. console.log('cameraType : ' + cameraArray[cameraIndex].cameraType) // Obtain the camera type.
...@@ -292,7 +292,7 @@ await captureSession.start().then(() => { ...@@ -292,7 +292,7 @@ await captureSession.start().then(() => {
##### Switching a Session ##### Switching a Session
```js ```js
// Stop the current session. // Stop the session.
await captureSession.stop((err) => { await captureSession.stop((err) => {
if (err) { if (err) {
console.error('Failed to stop the session ${err.message}'); console.error('Failed to stop the session ${err.message}');
...@@ -347,8 +347,8 @@ await captureSession.start().then(() => { ...@@ -347,8 +347,8 @@ await captureSession.start().then(() => {
```js ```js
let settings = { let settings = {
quality: camera.QualityLevel.QUALITY_LEVEL_HIGH // Set the image quality to high. quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, // Set the image quality to high.
rotation: camera.ImageRotation.ROTATION_0, // Set the image rotation angle to 0. rotation: camera.ImageRotation.ROTATION_0 // Set the image rotation angle to 0.
} }
// Use the current photographing settings to take photos. // Use the current photographing settings to take photos.
photoOutput.capture(settings, (err) => { photoOutput.capture(settings, (err) => {
...@@ -395,7 +395,7 @@ await videoOutput.stop((err) => { ...@@ -395,7 +395,7 @@ await videoOutput.stop((err) => {
#### Releasing Resources #### Releasing Resources
```js ```js
// Stop the current session. // Stop the session.
await captureSession.stop((err) => { await captureSession.stop((err) => {
if (err) { if (err) {
console.error('Failed to stop the session ${err.message}'); console.error('Failed to stop the session ${err.message}');
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
You can call the APIs provided by the **Camera** module to develop a distributed camera that provides the basic camera functions such as shooting and video recording. You can call the APIs provided by the **Camera** module to develop a distributed camera that provides the basic camera functions such as shooting and video recording.
## How to Develop ## How to Develop
Connect your calculator to a distributed device. Your calculator will call **getCameras()** to obtain the camera list and traverse the returned camera list to check **ConnctionType** of the **Camera** objects. If **ConnctionType** of a **Camera** object is **CAMERA_CONNECTION_REMOTE**, your calculator will use this object to create a **CameraInput** object. The subsequent call process is the same as that of the local camera development. For details about the local camera development, see [Camera Development](./camera.md). Connect your calculator to a distributed device. Your calculator will call **getCameras()** to obtain the camera list and traverse the returned camera list to check **ConnectionType** of the **Camera** objects. If **ConnectionType** of a **Camera** object is **CAMERA_CONNECTION_REMOTE**, your calculator will use this object to create a **CameraInput** object. The subsequent call process is the same as that of the local camera development. For details about the local camera development, see [Camera Development](./camera.md).
For details about the APIs, see [Camera Management](../reference/apis/js-apis-camera.md). For details about the APIs, see [Camera Management](../reference/apis/js-apis-camera.md).
...@@ -52,7 +52,7 @@ await cameraManager.getCameras((err, cameras) => { ...@@ -52,7 +52,7 @@ await cameraManager.getCameras((err, cameras) => {
cameraArray = cameras cameraArray = cameras
}) })
for(let cameraIndex = 0; cameraIndex < cameraArray.length; cameraIndex) { for(let cameraIndex = 0; cameraIndex < cameraArray.length; cameraIndex++) {
console.log('cameraId : ' + cameraArray[cameraIndex].cameraId) // Obtain the camera ID. console.log('cameraId : ' + cameraArray[cameraIndex].cameraId) // Obtain the camera ID.
console.log('cameraPosition : ' + cameraArray[cameraIndex].cameraPosition) // Obtain the camera position. console.log('cameraPosition : ' + cameraArray[cameraIndex].cameraPosition) // Obtain the camera position.
console.log('cameraType : ' + cameraArray[cameraIndex].cameraType) // Obtain the camera type. console.log('cameraType : ' + cameraArray[cameraIndex].cameraType) // Obtain the camera type.
......
...@@ -33,7 +33,7 @@ The table below lists the mainstream playback formats and resolutions. ...@@ -33,7 +33,7 @@ The table below lists the mainstream playback formats and resolutions.
## How to Develop ## How to Develop
For details about the APIs, see [VideoPlayer in the Media API](../reference/apis/js-apis-media.md). For details about the APIs, see [VideoPlayer in the Media API](../reference/apis/js-apis-media.md#videoplayer8).
### Full-Process Scenario ### Full-Process Scenario
......
...@@ -14,7 +14,7 @@ During video recording, audio and video signals are captured, encoded, and saved ...@@ -14,7 +14,7 @@ During video recording, audio and video signals are captured, encoded, and saved
## How to Develop ## How to Develop
For details about the APIs, see [VideoRecorder in the Media API](../reference/apis/js-apis-media.md). For details about the APIs, see [VideoRecorder in the Media API](../reference/apis/js-apis-media.md#videorecorder9).
### Full-Process Scenario ### Full-Process Scenario
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
- [Using Native APIs in Application Projects](napi-guidelines.md) - [Using Native APIs in Application Projects](napi-guidelines.md)
- [Drawing Development](drawing-guidelines.md) - [Drawing Development](drawing-guidelines.md)
- [Native Window Development](native-window-guidelines.md)
- [Raw File Development](rawfile-guidelines.md) - [Raw File Development](rawfile-guidelines.md)
- [Native Window Development](native-window-guidelines.md)
...@@ -89,7 +89,7 @@ Register four synchronous APIs (`getSync`, `setSync`, `removeSync`, and`clearSyn ...@@ -89,7 +89,7 @@ Register four synchronous APIs (`getSync`, `setSync`, `removeSync`, and`clearSyn
/*********************************************** /***********************************************
* Module export and register * Module export and register
***********************************************/ ***********************************************/
static napi_value StorgeExport(napi_env env, napi_value exports) static napi_value StorageExport(napi_env env, napi_value exports)
{ {
napi_property_descriptor desc[] = { napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("get", JSStorageGet), DECLARE_NAPI_FUNCTION("get", JSStorageGet),
...@@ -110,7 +110,7 @@ static napi_value StorgeExport(napi_env env, napi_value exports) ...@@ -110,7 +110,7 @@ static napi_value StorgeExport(napi_env env, napi_value exports)
static napi_module storage_module = {.nm_version = 1, static napi_module storage_module = {.nm_version = 1,
.nm_flags = 0, .nm_flags = 0,
.nm_filename = nullptr, .nm_filename = nullptr,
.nm_register_func = StorgeExport, .nm_register_func = StorageExport,
.nm_modname = "storage", .nm_modname = "storage",
.nm_priv = ((void*)0), .nm_priv = ((void*)0),
.reserved = {0}}; .reserved = {0}};
......
...@@ -37,9 +37,7 @@ For details about the APIs, see [reminderAgent](../reference/apis/js-apis-remind ...@@ -37,9 +37,7 @@ For details about the APIs, see [reminderAgent](../reference/apis/js-apis-remind
import reminderAgent from '@ohos.reminderAgent'; import reminderAgent from '@ohos.reminderAgent';
import notification from '@ohos.notification'; import notification from '@ohos.notification';
export default { export default {
// For a JS project: // eTS project:
// timer: {
// For an eTS project:
let timer : reminderAgent.ReminderRequestTimer = { let timer : reminderAgent.ReminderRequestTimer = {
reminderType: reminderAgent.ReminderType.REMINDER_TYPE_TIMER, reminderType: reminderAgent.ReminderType.REMINDER_TYPE_TIMER,
triggerTimeInSeconds: 10, triggerTimeInSeconds: 10,
...@@ -69,9 +67,7 @@ For details about the APIs, see [reminderAgent](../reference/apis/js-apis-remind ...@@ -69,9 +67,7 @@ For details about the APIs, see [reminderAgent](../reference/apis/js-apis-remind
Sample code for defining a reminder agent for a calendar event: Sample code for defining a reminder agent for a calendar event:
```js ```js
// For a JS project: // eTS project:
// calendar: {
// For an eTS project:
let calendar : reminderAgent.ReminderRequestCalendar = { let calendar : reminderAgent.ReminderRequestCalendar = {
reminderType: reminderAgent.ReminderType.REMINDER_TYPE_CALENDAR, reminderType: reminderAgent.ReminderType.REMINDER_TYPE_CALENDAR,
dateTime: { dateTime: {
...@@ -117,9 +113,7 @@ For details about the APIs, see [reminderAgent](../reference/apis/js-apis-remind ...@@ -117,9 +113,7 @@ For details about the APIs, see [reminderAgent](../reference/apis/js-apis-remind
Sample code for defining a reminder agent for an alarm: Sample code for defining a reminder agent for an alarm:
```js ```js
// For a JS project: // eTS project:
// alarm: {
// For an eTS project:
let alarm : reminderAgent.ReminderRequestAlarm = { let alarm : reminderAgent.ReminderRequestAlarm = {
reminderType: reminderAgent.ReminderType.REMINDER_TYPE_ALARM, reminderType: reminderAgent.ReminderType.REMINDER_TYPE_ALARM,
hour: 11, hour: 11,
...@@ -171,4 +165,3 @@ For details about the APIs, see [reminderAgent](../reference/apis/js-apis-remind ...@@ -171,4 +165,3 @@ For details about the APIs, see [reminderAgent](../reference/apis/js-apis-remind
<button type="text" value="publishReminder" onclick="startTimer"></button> <button type="text" value="publishReminder" onclick="startTimer"></button>
</div> </div>
``` ```
...@@ -13,14 +13,14 @@ Each application can subscribe to common events as required. After your applicat ...@@ -13,14 +13,14 @@ Each application can subscribe to common events as required. After your applicat
## Common Event Subscription Development ## Common Event Subscription Development
### When to Use ### When to Use
You can create a subscriber object to subscribe to a common event to obtain the parameters passed in the event. Certain system common events require specific permissions to subscribe to. For details, see [Required Permissions](../reference/apis/js-apis-commonEvent.md). You can create a subscriber object to subscribe to a common event to obtain the parameters passed in the event. Certain system common events require specific permissions to subscribe to. For details, see [Required Permissions](../reference/apis/js-apis-commonEvent.md#required-permissions).
### Available APIs ### Available APIs
| API | Description| | API | Description|
| ---------------------------------------------------------------------------------------------- | ----------- | | ---------------------------------------------------------------------------------------------- | ----------- |
| commonEvent.createSubscriber(subscribeInfo: CommonEventSubscribeInfo, callback: AsyncCallback) | Creates a subscriber. This API uses a callback to return the result.| | createSubscriber(subscribeInfo: CommonEventSubscribeInfo, callback: AsyncCallback) | Creates a subscriber. This API uses a callback to return the result.|
| commonEvent.createSubscriber(subscribeInfo: CommonEventSubscribeInfo) | Creates a subscriber. This API uses a promise to return the result. | | createSubscriber(subscribeInfo: CommonEventSubscribeInfo) | Creates a subscriber. This API uses a promise to return the result. |
| commonEvent.subscribe(subscriber: CommonEventSubscriber, callback: AsyncCallback) | Subscribes to common events.| | subscribe(subscriber: CommonEventSubscriber, callback: AsyncCallback) | Subscribes to common events.|
### How to Develop ### How to Develop
1. Import the **commonEvent** module. 1. Import the **commonEvent** module.
...@@ -82,8 +82,8 @@ You can use the **publish** APIs to publish a custom common event, which can car ...@@ -82,8 +82,8 @@ You can use the **publish** APIs to publish a custom common event, which can car
### Available APIs ### Available APIs
| API | Description| | API | Description|
| ---------------------------------- | ------ | | ---------------------------------- | ------ |
| commonEvent.publish(event: string, callback: AsyncCallback) | Publishes a common event.| | publish(event: string, callback: AsyncCallback) | Publishes a common event.|
| commonEvent.publish(event: string, options: CommonEventPublishData, callback: AsyncCallback) | Publishes a common event with given attributes.| | publish(event: string, options: CommonEventPublishData, callback: AsyncCallback) | Publishes a common event with given attributes.|
### How to Develop ### How to Develop
#### Development for Publishing a Common Event #### Development for Publishing a Common Event
...@@ -119,7 +119,7 @@ import commonEvent from '@ohos.commonEvent' ...@@ -119,7 +119,7 @@ import commonEvent from '@ohos.commonEvent'
// Attributes of a common event. // Attributes of a common event.
var options = { var options = {
code: 1, // Result code of the common event code: 1, // Result code of the common event
data: "initial data",// Result data of the common event data: "initial data";// Result data of the common event
} }
``` ```
...@@ -144,7 +144,7 @@ You can use the **unsubscribe** API to unsubscribe from a common event. ...@@ -144,7 +144,7 @@ You can use the **unsubscribe** API to unsubscribe from a common event.
### Available APIs ### Available APIs
| API | Description| | API | Description|
| ---------------------------------- | ------ | | ---------------------------------- | ------ |
| commonEvent.unsubscribe(subscriber: CommonEventSubscriber, callback?: AsyncCallback) | Unsubscribes from a common event.| | unsubscribe(subscriber: CommonEventSubscriber, callback?: AsyncCallback) | Unsubscribes from a common event.|
### How to Develop ### How to Develop
1. Import the **commonEvent** module. 1. Import the **commonEvent** module.
......
...@@ -7,16 +7,13 @@ Common Event Service (CES) enables applications to publish, subscribe to, and un ...@@ -7,16 +7,13 @@ Common Event Service (CES) enables applications to publish, subscribe to, and un
![ces](figures/ces.png) ![ces](figures/ces.png)
- System common event: sent by the system based on system policies to the applications that have subscribed to the event. This type of event includes the screen-on/off events that the users are aware of and the system events published by key system services, such as USB device attachment or detachment, network connection, and system update events. - System common event: sent by the system based on system policies to the applications that have subscribed to the event. This type of event includes the screen-on/off events that the users are aware of and the system events published by key system services, such as USB device attachment or detachment, network connection, and system update events.
- Custom common event: customized by applications to be received by specific subscribers. This type of event is usually related to the service logic of the sender applications. - Custom common event: customized by applications to be received by specific subscribers. This type of event is usually related to the service logic of the sender applications.
The Advanced Notification Service (ANS) enables applications to publish notifications. Below are some typical use cases for publishing notifications: The Advanced Notification Service (ANS) enables applications to publish notifications. Below are some typical use cases for publishing notifications:
- Display received SMS messages and instant messages. - Display received SMS messages and instant messages.
- Display push messages of applications, such as advertisements, version updates, and news notifications.
- Display push messages of applications, such as advertisements, version updates, and news notifications. - Display ongoing events, such as music playback, navigation information, and download progress.
- Display ongoing events, such as music playback, navigation information, and download progress.
Notifications are displayed in the notification panel. Uses can delete a notification or click the notification to trigger predefined actions. Notifications are displayed in the notification panel. Uses can delete a notification or click the notification to trigger predefined actions.
......
...@@ -28,14 +28,14 @@ System applications also support notification-related configuration options, suc ...@@ -28,14 +28,14 @@ System applications also support notification-related configuration options, suc
## Available APIs ## Available APIs
Certain APIs can be invoked only by system applications that have been granted the **SystemCapability.Notification.Notification** permission. The APIs use either a callback or promise to return the result. The tables below list the APIs that use a callback, which provide same functions as their counterparts that use a promise. For details about the APIs, see the [API document](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-notification.md). Certain APIs can be called only by system applications that have been granted the **SystemCapability.Notification.Notification** permission. The APIs use either a callback or promise to return the result. The tables below list the APIs that use a callback, which provide the same functions as their counterparts that use a promise. For details about the APIs, see the [API document](../reference/apis/js-apis-notification.md).
**Table 1** APIs for notification enabling **Table 1** APIs for notification enabling
| API | Description | | API | Description |
| ------------------------------------------------------------ | ---------------- | | ------------------------------------------------------------ | ---------------- |
| isNotificationEnabled(bundle: BundleOption, callback: AsyncCallback<boolean>): void | Checks whether notification is enabled.| | isNotificationEnabled(bundle: BundleOption, callback: AsyncCallback\<boolean>): void | Checks whether notification is enabled.|
| enableNotification(bundle: BundleOption, enable: boolean, callback: AsyncCallback<void>): void | Sets whether to enable notification. | | enableNotification(bundle: BundleOption, enable: boolean, callback: AsyncCallback\<void>): void | Sets whether to enable notification. |
If the notification function of an application is disabled, it cannot send notifications. If the notification function of an application is disabled, it cannot send notifications.
...@@ -45,11 +45,11 @@ If the notification function of an application is disabled, it cannot send notif ...@@ -45,11 +45,11 @@ If the notification function of an application is disabled, it cannot send notif
| API | Description | | API | Description |
| ------------------------------------------------------------ | ---------------- | | ------------------------------------------------------------ | ---------------- |
| subscribe(subscriber: NotificationSubscriber, info: NotificationSubscribeInfo, callback: AsyncCallback<void>): void | Subscribes to a notification with the subscription information specified.| | subscribe(subscriber: NotificationSubscriber, info: NotificationSubscribeInfo, callback: AsyncCallback\<void>): void | Subscribes to a notification with the subscription information specified.|
| subscribe(subscriber: NotificationSubscriber, callback: AsyncCallback<void>): void | Subscribes to all notifications. | | subscribe(subscriber: NotificationSubscriber, callback: AsyncCallback\<void>): void | Subscribes to all notifications. |
| unsubscribe(subscriber: NotificationSubscriber, callback: AsyncCallback<void>): void | Unsubscribes from a notification. | | unsubscribe(subscriber: NotificationSubscriber, callback: AsyncCallback\<void>): void | Unsubscribes from a notification. |
The subscription APIs support subscription to all notifications or notifications from specific applications. The subscription APIs support subscription to all notifications and notifications from specific applications.
...@@ -69,10 +69,10 @@ The subscription APIs support subscription to all notifications or notifications ...@@ -69,10 +69,10 @@ The subscription APIs support subscription to all notifications or notifications
| API | Description | | API | Description |
| ------------------------------------------------------------ | ------------------------ | | ------------------------------------------------------------ | ------------------------ |
| publish(request: NotificationRequest, callback: AsyncCallback<void>): void | Publishes a notification. | | publish(request: NotificationRequest, callback: AsyncCallback\<void>): void | Publishes a notification. |
| publish(request: NotificationRequest, userId: number, callback: AsyncCallback<void>): void | Publishes a notification to the specified user. | | publish(request: NotificationRequest, userId: number, callback: AsyncCallback\<void>): void | Publishes a notification to the specified user. |
| cancel(id: number, label: string, callback: AsyncCallback<void>): void | Cancels a specified notification. | | cancel(id: number, label: string, callback: AsyncCallback\<void>): void | Cancels a specified notification. |
| cancelAll(callback: AsyncCallback<void>): void; | Cancels all notifications published by the application.| | cancelAll(callback: AsyncCallback\<void>): void; | Cancels all notifications published by the application.|
The **publish** API that carries **userId** can be used to publish notifications to subscribers of a specified user. The **publish** API that carries **userId** can be used to publish notifications to subscribers of a specified user.
...@@ -136,7 +136,7 @@ var subscriber = { ...@@ -136,7 +136,7 @@ var subscriber = {
Before publishing a notification, check whether the notification feature is enabled for your application. By default, the feature is disabled. The application calls **Notification.requestEnableNotification** to prompt the user to enable the feature. Before publishing a notification, check whether the notification feature is enabled for your application. By default, the feature is disabled. The application calls **Notification.requestEnableNotification** to prompt the user to enable the feature.
```js ```js
Notification.requestEnableNotification() .then((data) => { Notification.requestEnableNotification().then((data) => {
console.info('===>requestEnableNotification success'); console.info('===>requestEnableNotification success');
}).catch((err) => { }).catch((err) => {
console.error('===>requestEnableNotification failed because ' + JSON.stringify(err)); console.error('===>requestEnableNotification failed because ' + JSON.stringify(err));
...@@ -166,7 +166,7 @@ var notificationRequest = { ...@@ -166,7 +166,7 @@ var notificationRequest = {
} }
// Publish the notification. // Publish the notification.
Notification.publish(notificationRequest) .then((data) => { Notification.publish(notificationRequest).then((data) => {
console.info('===>publish promise success req.id : ' + notificationRequest.id); console.info('===>publish promise success req.id : ' + notificationRequest.id);
}).catch((err) => { }).catch((err) => {
console.error('===>publish promise failed because ' + JSON.stringify(err)); console.error('===>publish promise failed because ' + JSON.stringify(err));
...@@ -235,7 +235,7 @@ var notificationRequest = { ...@@ -235,7 +235,7 @@ var notificationRequest = {
} }
// Publish the notification. // Publish the notification.
Notification.publish(notificationRequest) .then((data) => { Notification.publish(notificationRequest).then((data) => {
console.info('===>publish promise success req.id : ' + notificationRequest.id); console.info('===>publish promise success req.id : ' + notificationRequest.id);
}).catch((err) => { }).catch((err) => {
console.error('===>publish promise failed because ' + JSON.stringify(err)); console.error('===>publish promise failed because ' + JSON.stringify(err));
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册