diff --git a/CODEOWNERS b/CODEOWNERS index 638941c1a2a1765ad2a55dd81cf65ca72dce37be..74369f93b5bd83ef4503414d2d0d5f18326aadfd 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -187,7 +187,8 @@ zh-cn/application-dev/dfx/errormanager-guidelines.md @littlejerry1 @ccllee @chen zh-cn/application-dev/key-features/multi-device-app-dev/ @lingminghw @crazyracing0726 zh-cn/application-dev/database/ @ge-yafang @feng-aiwen @gong-a-shi @logic42 zh-cn/application-dev/napi/native-window-guidelines.md @ge-yafang @zhangqiang183 @zhouyaoying @zxg-gitee -zh-cn/application-dev/napi/mindspore-lite-guidelines.md @ge-yafang @grbuzhidao @jianghui58 @auraxu +zh-cn/application-dev/napi/mindspore-lite-guidelines.md @ge-yafang @principal87 @jianghui58 +zh-cn/application-dev/napi/neural-network-runtime-guidelines.md @ge-yafang @principal87 @win10wei zh-cn/application-dev/napi/rawfile_guidelines.md @ningningW zh-cn/application-dev/background-agent-scheduled-reminder/ @RayShih zh-cn/application-dev/background-task-management/ @ningningW @wangwenli_wolf @tangtiantian2021 @nan-xiansen @@ -321,6 +322,8 @@ zh-cn/application-dev/reference/apis/js-apis-data-DataShareResultSet.md @feng-ai zh-cn/application-dev/reference/apis/js-apis-data-distributedobject.md @feng-aiwen @ge-yafang @gong-a-shi @logic42 zh-cn/application-dev/reference/apis/js-apis-data-preferences.md @feng-aiwen @ge-yafang @gong-a-shi @logic42 zh-cn/application-dev/reference/apis/js-apis-data-rdb.md @feng-aiwen @ge-yafang @gong-a-shi @logic42 +zh-cn/application-dev/reference/apis/js-apis-data-udmf.md @feng-aiwen @ge-yafang @gong-a-shi @logic42 +zh-cn/application-dev/reference/apis/js-apis-data-cloudData.md @feng-aiwen @ge-yafang @gong-a-shi @logic42 zh-cn/application-dev/reference/apis/js-apis-data-relationStore.md @feng-aiwen @ge-yafang @gong-a-shi @logic42 zh-cn/application-dev/reference/apis/js-apis-data-resultset.md @feng-aiwen @ge-yafang @gong-a-shi @logic42 zh-cn/application-dev/reference/apis/js-apis-data-storage.md @feng-aiwen @ge-yafang @gong-a-shi @logic42 diff --git a/en/OpenHarmony-Overview.md b/en/OpenHarmony-Overview.md index 1aecb0171e73b02bcbcb9347497f594bf96c912e..567e303175ce4908ac4a0e1b1c81f016de47966a 100644 --- a/en/OpenHarmony-Overview.md +++ b/en/OpenHarmony-Overview.md @@ -1,5 +1,9 @@ # OpenHarmony Project +> **NOTE** +> +> You are reading documents of OpenHarmony 4.0 Beta1. Obtain the [compatible SDK](release-notes/OpenHarmony-v4.0-beta1.md#version-mapping) during your application development. + ## Introduction OpenHarmony is an open-source project incubated and operated by the OpenAtom Foundation. The purpose of this project is to build an open-source, distributed operating system (OS) framework for smart devices in all scenarios of a fully-connected world. @@ -146,7 +150,7 @@ The following table describes the subsystems of OpenHarmony. For details about t ## Supported Development Boards -Currently, the OpenHarmony community supports 22 types of development boards, which are listed in [Development Boards Supported](device-dev/dev-board-on-the-master.md). The following table describes three of them, which are the first three integrated into the OpenHarmony master. You can visit http://ci.openharmony.cn/dailys/dailybuilds to obtain daily builds. +Currently, the OpenHarmony community supports 22 types of development boards, which are listed in [Development Boards Supported](device-dev/dev-board-on-the-master.md). The following table describes three of them, which are the first three integrated into the OpenHarmony master. You can visit http://ci.openharmony.cn/workbench/cicd/dailybuild/dailylist to obtain daily builds. | System Type| Board Model| Chip Model|
Function Description and Use Case
| Application Scenario| Code Repository | | -------- | -------- | -------- | -------- | -------- | -------- | diff --git a/en/application-dev/IDL/idl-guidelines.md b/en/application-dev/IDL/idl-guidelines.md index a7ce0ec46adeeca0dd697cd8dabde834b7cc14fc..102992de24a2879f9b08a5274058c2cdf4c0a280 100644 --- a/en/application-dev/IDL/idl-guidelines.md +++ b/en/application-dev/IDL/idl-guidelines.md @@ -1,4 +1,4 @@ -# OpenHarmony IDL Specifications and User Guide +# IDL Specifications and User Guide ## IDL Overview To ensure successful communications between the client and server, interfaces recognized by both parties must be defined. The OpenHarmony Interface Definition Language (IDL) is a tool for defining such interfaces. OpenHarmony IDL decomposes objects to be transferred into primitives that can be understood by the operating system and encapsulates cross-boundary objects based on developers' requirements. @@ -162,7 +162,7 @@ Go to the local installation path, choose **toolchains > 3.x.x.x** (the folder n If the executable file does not exist, download the SDK package from the mirror as instructed in the [Release Notes](../../release-notes). The following uses [3.2 Beta3](../../release-notes/OpenHarmony-v3.2-beta3.md) as an example. -For details about how to replace the SDK package, see [Full SDK Compilation Guide](../quick-start/full-sdk-compile-guide.md). +For details about how to replace the SDK package, see [Full SDK Compilation Guide](../faqs/full-sdk-compile-guide.md). After obtaining the executable file, perform subsequent development steps based on your scenario. diff --git a/en/application-dev/Readme-EN.md b/en/application-dev/Readme-EN.md index f71b814661e652486bf1a61ee3e7c7dd23dbcf4a..66ce310670de99071b5ff7e642803e04d78e5d6f 100644 --- a/en/application-dev/Readme-EN.md +++ b/en/application-dev/Readme-EN.md @@ -4,18 +4,16 @@ - About OpenHarmony - [OpenHarmony Project](../OpenHarmony-Overview.md) - [Glossary](../glossary.md) - - [OpenHarmony Release Notes](../release-notes/Readme.md) + - [Release Notes](../release-notes/Readme.md) - Quick Start - Getting Started - [Before You Start](quick-start/start-overview.md) - [Getting Started with ArkTS in Stage Model](quick-start/start-with-ets-stage.md) - - [Getting Started with ArkTS in FA Model](quick-start/start-with-ets-fa.md) - - [Getting Started with JavaScript in FA Model](quick-start/start-with-js-fa.md) - Development Fundamentals - Application Package Fundamentals - [Application Package Overview](quick-start/application-package-overview.md) - Application Package Structure - - [Application Package Structure in Stage Model)](quick-start/application-package-structure-stage.md) + - [Application Package Structure in Stage Model](quick-start/application-package-structure-stage.md) - [Application Package Structure in FA Model](quick-start/application-package-structure-fa.md) - Multi-HAP Mechanism - [Multi-HAP Design Objectives](quick-start/multi-hap-objective.md) @@ -37,9 +35,9 @@ - Application Configuration Files in FA Model - [Application Configuration File Overview (FA Model)](quick-start/application-configuration-file-overview-fa.md) - [Internal Structure of the app Tag](quick-start/app-structure.md) - - [Internal structure of deviceConfig Tag](quick-start/deviceconfig-structure.md) + - [Internal Structure of the deviceConfig Tag](quick-start/deviceconfig-structure.md) - [Internal Structure of the module Tag](quick-start/module-structure.md) - - [Resource Categories and Access](quick-start/resource-categories-and-access.md) + - [Resource Categories and Access](quick-start/resource-categories-and-access.md) - Learning ArkTS - [Getting Started with ArkTS](quick-start/arkts-get-started.md) - Basic Syntax @@ -48,19 +46,19 @@ - Custom Component - [Creating a Custom Component](quick-start/arkts-create-custom-components.md) - [Page and Custom Component Lifecycle](quick-start/arkts-page-custom-components-lifecycle.md) - - [\@Builder: Custom Builder Function](quick-start/arkts-builder.md) - - [\@BuilderParam: @Builder Function Reference](quick-start/arkts-builderparam.md) - - [\@Styles: Definition of Resusable Styles](quick-start/arkts-style.md) - - [\@Extend: Extension of Built-in Components](quick-start/arkts-extend.md) + - [\@Builder Decorator: Custom Builder Function](quick-start/arkts-builder.md) + - [\@BuilderParam Decorator: \@Builder Function Reference](quick-start/arkts-builderparam.md) + - [\@Styles Decorator: Definition of Resusable Styles](quick-start/arkts-style.md) + - [\@Extend Decorator: Extension of Built-in Components](quick-start/arkts-extend.md) - [stateStyles: Polymorphic Style](quick-start/arkts-statestyles.md) - State Management - [State Management Overview](quick-start/arkts-state-management-overview.md) - Component State Management - - [\@State: State Owned by Component](quick-start/arkts-state.md) - - [\@Prop: One-Way Synchronization from Parent to Child Components](quick-start/arkts-prop.md) - - [\@Link: Two-Way Synchronization Between Parent and Child Components](quick-start/arkts-link.md) - - [\@Provide and \@Consume: Two-Way Synchronization with Descendant Components](quick-start/arkts-provide-and-consume.md) - - [\@Observed and \@ObjectLink: Observing Attribute Changes in Nested Class Objects](quick-start/arkts-observed-and-objectlink.md) + - [\@State Decorator: State Owned by Component](quick-start/arkts-state.md) + - [\@Prop Decorator: One-Way Synchronization from Parent to Child Components](quick-start/arkts-prop.md) + - [\@Link Decorator: Two-Way Synchronization Between Parent and Child Components](quick-start/arkts-link.md) + - [\@Provide and \@Consume Decorators: Two-Way Synchronization with Descendant Components](quick-start/arkts-provide-and-consume.md) + - [\@Observed and \@ObjectLink Decorators: Observing Attribute Changes in Nested Class Objects](quick-start/arkts-observed-and-objectlink.md) - Application State Management - [Application State Management Overview](quick-start/arkts-application-state-management-overview.md) - [LocalStorage: UI State Storage](quick-start/arkts-localstorage.md) @@ -69,10 +67,10 @@ - [Environment: Device Environment Query](quick-start/arkts-environment.md) - Other State Management Features - [Overview of Other State Management Features](quick-start/arkts-other-state-mgmt-functions-overview.md) - - [\@Watch: Getting Notified of State Variable Changes](quick-start/arkts-watch.md) + - [\@Watch Decorator: Getting Notified of State Variable Changes](quick-start/arkts-watch.md) - [$$ Syntax: Two-Way Synchronization of Built-in Components](quick-start/arkts-two-way-sync.md) - Rendering Control - - [Rendering Control Overview](quick-start/arkts-rendering-control-overview.md) + - [Overview of Rendering Control](quick-start/arkts-rendering-control-overview.md) - [if/else: Conditional Rendering](quick-start/arkts-rendering-control-ifelse.md) - [ForEach: Rendering of Repeated Content](quick-start/arkts-rendering-control-foreach.md) - [LazyForEach: Lazy Data Loading](quick-start/arkts-rendering-control-lazyforeach.md) @@ -95,28 +93,27 @@ - [DFX](dfx/Readme-EN.md) - [Internationalization](internationalization/Readme-EN.md) - [Application Test](application-test/Readme-EN.md) - - [OpenHarmony IDL Specifications and User Guide](IDL/idl-guidelines.md) + - [IDL Specifications and User Guide](IDL/idl-guidelines.md) - [Native APIs](napi/Readme-EN.md) - Tools - [DevEco Studio (OpenHarmony) User Guide](quick-start/deveco-studio-user-guide-for-openharmony.md) - [Debugging Tools](tools/Readme-EN.md) - Hands-On Tutorials - - [Samples](https://gitee.com/openharmony/applications_app_samples/blob/master/README.md) - - [Codelabs](https://gitee.com/openharmony/codelabs) + - [Samples](https://gitee.com/openharmony/applications_app_samples/blob/OpenHarmony-4.0-Beta1/README.md) + - [Codelabs](https://gitee.com/openharmony/codelabs/tree/master) - API References - [SystemCapability](reference/syscap.md) - [SystemCapability List](reference/syscap-list.md) - [Component Reference (TypeScript-based Declarative Development Paradigm)](reference/arkui-ts/Readme-EN.md) - [Component Reference (JavaScript-based Web-like Development Paradigm)](reference/arkui-js/Readme-EN.md) - - [JS Service Widget UI Components](reference/js-service-widget-ui/Readme-EN.md) - - APIs - - [ArkTS and JS APIs](reference/apis/Readme-EN.md) + - [JavaScript Service Widget UI Component Reference](reference/js-service-widget-ui/Readme-EN.md) + - API Reference + - [ArkTS and JavaScript APIs](reference/apis/Readme-EN.md) - [Error Codes](reference/errorcodes/Readme-EN.md) - - Native APIs + - Native API Reference - [Native APIs](reference/native-apis/Readme-EN.md) - [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 - [How to Contribute](../contribute/documentation-contribution.md) - \ No newline at end of file diff --git a/en/application-dev/application-dev-guide-for-gitee.md b/en/application-dev/application-dev-guide-for-gitee.md index 1ad5989d2cf8258c46e219a239a2c8c5a1d1274c..94a6427aa51f9c4f8769ba140f40063fc77023f2 100644 --- a/en/application-dev/application-dev-guide-for-gitee.md +++ b/en/application-dev/application-dev-guide-for-gitee.md @@ -51,7 +51,7 @@ DevEco Studio is a high-performance integrated development environment (IDE) rec ### Hands-On Tutorials -To make you better understand how functions work together and jumpstart your application development projects, we provide stripped-down, real-world [samples](https://gitee.com/openharmony/applications_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/OpenHarmony-4.0-Beta1/README.md) and [codelabs](https://gitee.com/openharmony/codelabs). ### API References diff --git a/en/application-dev/application-dev-guide.md b/en/application-dev/application-dev-guide.md index 8170d075cf08e8258b7c8b3731661f0e4959c6aa..4f94d594adaee317ae68d2f58272cb2dfcbbec95 100644 --- a/en/application-dev/application-dev-guide.md +++ b/en/application-dev/application-dev-guide.md @@ -1,12 +1,16 @@ # Application Development Overview +> **NOTE** +> +> You are reading documents of OpenHarmony 4.0 Beta1. Obtain the [compatible SDK](../release-notes/OpenHarmony-v4.0-beta1.md#version-mapping) during your application development. + The application development documents provide reference for you to develop applications using the APIs provided by OpenHarmony. They walk you through how to use JavaScript APIs to develop applications on the standard system. The documents are carefully organized as follows: ## Getting Started -[Here](quick-start/start-overview.md) you'll learn how to quickly get started with OpenHarmony application development. +[Here](quick-start/start-overview.md) you can learn how to better prepare yourself for application development. Browse the documents on the instructions for quickly building your first application and the basics about OpenHarmony applications. @@ -36,12 +40,12 @@ Then, equip yourself for developing the key features, with the following guideli - [Data Management](database/data-mgmt-overview.md) - [File Management](file-management/file-management-overview.md) - [Task Management](task-management/background-task-overview.md) -- [Device](device/usb-overview.md) +- [Device Management](device/usb-overview.md) - [Device Usage Statistics](device-usage-statistics/device-usage-statistics-overview.md) - [DFX](dfx/hiappevent-guidelines.md) - [Internationalization](internationalization/international-overview.md) - [Application Test](application-test/arkxtest-guidelines.md) -- [OpenHarmony IDL Specifications and User Guide](IDL/idl-guidelines.md) +- [IDL Specifications and User Guide](IDL/idl-guidelines.md) - [Using Native APIs in Application Projects](napi/napi-guidelines.md) ## Tools @@ -51,7 +55,7 @@ DevEco Studio is a high-performance integrated development environment (IDE) rec ## Hands-On Tutorials -To make you better understand how functions work together and jumpstart your application development projects, we provide stripped-down, real-world [samples](https://gitee.com/openharmony/applications_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/OpenHarmony-4.0-Beta1/README.md) and [codelabs](https://gitee.com/openharmony/codelabs). ## API References @@ -59,13 +63,12 @@ API references encompass all components and APIs available in OpenHarmony, helpi They are organized as follows: +- [ArkTS API Reference](reference/apis/development-intro.md) - [Component Reference (TypeScript-based Declarative Development Paradigm)](reference/arkui-ts/ts-components-summary.md) - [Component Reference (JavaScript-compatible Web-like Development Paradigm-ArkUI.Full)](reference/arkui-js/js-components-common-attributes.md) - [Component Reference (JavaScript-compatible Web-like Development Paradigm-ArkUI.Lite)](reference/arkui-js-lite/js-framework-file.md) -- [JS Service Widget UI Components](reference/js-service-widget-ui/js-service-widget-file.md) -- [JS and TS APIs](reference/apis/development-intro.md) -- Native APIs - - [Standard Library](reference/native-lib/third_party_libc/musl.md) +- [JavaScript Service Widget UI Component Reference](reference/js-service-widget-ui/js-service-widget-file.md) +- Native API Reference + - [Native APIs](reference/native-apis/_o_h___native_x_component.md) + - [Standard Libraries](reference/native-lib/third_party_libc/musl.md) - [Node_API](reference/native-lib/third_party_napi/napi.md) - - \ No newline at end of file diff --git a/en/application-dev/application-models/Readme-EN.md b/en/application-dev/application-models/Readme-EN.md index b38074f214762a1d42474e7e12005314427d3ee1..f89f2164e5941ae42c326caf17adbdfe1fe7c26f 100644 --- a/en/application-dev/application-models/Readme-EN.md +++ b/en/application-dev/application-models/Readme-EN.md @@ -8,27 +8,52 @@ - Stage Mode Application Components - [Application- or Component-Level Configuration](application-component-configuration-stage.md) - UIAbility Component - - [UIAbility Component Overview](uiability-overview.md) - - [UIAbility Component Lifecycle](uiability-lifecycle.md) - - [UIAbility Component Launch Type](uiability-launch-type.md) - - [UIAbility Component Usage](uiability-usage.md) - - [Data Synchronization Between UIAbility and UI](uiability-data-sync-with-ui.md) + - [UIAbility Overview](uiability-overview.md) + - [UIAbility Lifecycle](uiability-lifecycle.md) + - [UIAbility Launch Type](uiability-launch-type.md) + - [UIAbility Usage](uiability-usage.md) + - [Data Synchronization Between UIAbility and UI Page](uiability-data-sync-with-ui.md) - [Interaction Between Intra-Device UIAbility Components](uiability-intra-device-interaction.md) - ExtensionAbility Component - - [ExtensionAbility Component Overview](extensionability-overview.md) + - [ExtensionAbility Overview](extensionability-overview.md) - [ServiceExtensionAbility](serviceextensionability.md) - - [FormExtensionAbility (Widget)](widget-development-stage.md) - [AccessibilityExtensionAbility](accessibilityextensionability.md) - [EnterpriseAdminExtensionAbility](enterprise-extensionAbility.md) - [InputMethodExtensionAbility](inputmethodextentionability.md) - - [WindowExtensionAbility](windowextensionability.md) + - [WindowExtensionAbility (for System Applications Only)](windowextensionability.md) + - Service Widget Development in Stage Model + - [Service Widget Overview](service-widget-overview.md) + - Developing an ArkTS Widget + - [ArkTS Widget Working Principles](arkts-ui-widget-working-principles.md) + - [ArkTS Widget Related Modules](arkts-ui-widget-modules.md) + - ArkTS Widget Development + - [Creating an ArkTS Widget](arkts-ui-widget-creation.md) + - [Configuring Widget Configuration Files](arkts-ui-widget-configuration.md) + - [Widget Lifecycle Management](arkts-ui-widget-lifecycle.md) + - Widget Page Development + - [Widget Page Capability Overview](arkts-ui-widget-page-overview.md) + - [Using Animations in the Widget](arkts-ui-widget-page-animation.md) + - [Applying Custom Drawing in the Widget](arkts-ui-widget-page-custom-drawing.md) + - Widget Event Development + - [Widget Event Capability Overview](arkts-ui-widget-event-overview.md) + - [Redirecting to a UIAbility Through the router Event](arkts-ui-widget-event-router.md) + - [Launching a UIAbility in the Background Through the call Event](arkts-ui-widget-event-call.md) + - [Updating Widget Content Through the message Event](arkts-ui-widget-event-formextensionability.md) + - [Updating Widget Content Through the router or call Event](arkts-ui-widget-event-uiability.md) + - Widget Data Interaction + - [Widget Data Interaction Overview](arkts-ui-widget-interaction-overview.md) + - [Configuring a Widget to Update Periodically](arkts-ui-widget-update-by-time.md) + - [Updating Local and Online Images in the Widget](arkts-ui-widget-image-update.md) + - [Updating Widget Content by State](arkts-ui-widget-update-by-status.md) + - [Updating Widget Content by Widget Host (for System Applications Only)](arkts-ui-widget-content-update.md) + - [Developing a JS Widget](js-ui-widget-development.md) - [AbilityStage Component Container](abilitystage.md) - [Context](application-context-stage.md) - Want - [Want Overview](want-overview.md) - [Matching Rules of Explicit Want and Implicit Want](explicit-implicit-want-mappings.md) - [Common action and entities Values](actions-entities.md) - - [Using Explicit Want to Start an Ability](ability-startup-with-explicit-want.md) + - [Using Explicit Want to Start an Application Component](ability-startup-with-explicit-want.md) - [Using Implicit Want to Open a Website](ability-startup-with-implicit-want.md) - [Using Want to Share Data Between Applications](data-share-via-want.md) - [Component Startup Rules](component-startup-rules.md) @@ -37,8 +62,8 @@ - [Cross-Device Migration (for System Applications Only)](hop-cross-device-migration.md) - [Multi-device Collaboration (for System Applications Only)](hop-multi-device-collaboration.md) - [Subscribing to System Environment Variable Changes](subscribe-system-environment-variable-changes.md) - - IPC - - [Process Model](process-model-stage.md) + - Process Model + - [Process Model Overview](process-model-stage.md) - Common Events - [Introduction to Common Events](common-event-overview.md) - Common Event Subscription @@ -47,14 +72,15 @@ - [Subscribing to Common Events in Static Mode (for System Applications Only)](common-event-static-subscription.md) - [Unsubscribing from Common Events](common-event-unsubscription.md) - [Publishing Common Events](common-event-publish.md) + - [Removing Sticky Common Events (for System Applications Only)](common-event-remove-sticky.md) - [Background Services](background-services.md) - - Inter-Thread Communication - - [Thread Model](thread-model-stage.md) + - Thread Model + - [Thread Model Overview](thread-model-stage.md) - [Using Emitter for Inter-Thread Communication](itc-with-emitter.md) - [Using Worker for Inter-Thread Communication](itc-with-worker.md) - Mission Management - [Mission Management Scenarios](mission-management-overview.md) - - [Mission Management and Launch Type](mission-management-launch-type.md) + - [Mission and Launch Type](mission-management-launch-type.md) - [Page Stack and MissionList](page-mission-stack.md) - [Setting the Icon and Name of a Mission Snapshot](mission-set-icon-name-for-task-snapshot.md) - [Application Configuration File](config-file-stage.md) @@ -63,8 +89,8 @@ - FA Mode Application Components - [Application- or Component-Level Configuration](application-component-configuration-fa.md) - PageAbility Component Development - - [PageAbility Component Overview](pageability-overview.md) - - [PageAbility Component Configuration](pageability-configuration.md) + - [PageAbility Overview](pageability-overview.md) + - [PageAbility Configuration](pageability-configuration.md) - [PageAbility Lifecycle](pageability-lifecycle.md) - [PageAbility Launch Type](pageability-launch-type.md) - [Creating a PageAbility](create-pageability.md) @@ -76,15 +102,15 @@ - [Requesting Permissions](request-permissions.md) - [Redirection Rules](redirection-rules.md) - ServiceAbility Component Development - - [ServiceAbility Component Overview](serviceability-overview.md) - - [ServiceAbility Component Configuration](serviceability-configuration.md) + - [ServiceAbility Overview](serviceability-overview.md) + - [ServiceAbility Configuration](serviceability-configuration.md) - [ServiceAbility Lifecycle](serviceability-lifecycle.md) - [Creating a ServiceAbility](create-serviceability.md) - [Starting a ServiceAbility](start-serviceability.md) - [Connecting to a ServiceAbility](connect-serviceability.md) - DataAbility Component Development - - [DataAbility Component Overview](dataability-overview.md) - - [DataAbility Component Configuration](dataability-configuration.md) + - [DataAbility Overview](dataability-overview.md) + - [DataAbility Configuration](dataability-configuration.md) - [DataAbility Lifecycle](dataability-lifecycle.md) - [Creating a DataAbility](create-dataability.md) - [Starting a DataAbility](start-dataability.md) @@ -94,12 +120,12 @@ - [Context](application-context-fa.md) - [Want](want-fa.md) - [Component Startup Rules](component-startup-rules-fa.md) - - IPC - - [Process Model](process-model-fa.md) + - Process Model + - [Process Model Overview](process-model-fa.md) - [Common Events](common-event-fa.md) - [Background Services](rpc.md) - - Inter-Thread Communication - - [Thread Model](thread-model-fa.md) + - Thread Model + - [Thread Model Overview](thread-model-fa.md) - [Inter-Thread Communication](itc-fa-overview.md) - [Mission Management](mission-management-fa.md) - [Application Configuration File](config-file-fa.md) diff --git a/en/application-dev/application-models/ability-startup-with-explicit-want.md b/en/application-dev/application-models/ability-startup-with-explicit-want.md index 6b61b06311a519e959e87d826e4a27c8b2b3d208..36d41c555bd8d4a5cd0d4d0b7bd291bb2569cee3 100644 --- a/en/application-dev/application-models/ability-startup-with-explicit-want.md +++ b/en/application-dev/application-models/ability-startup-with-explicit-want.md @@ -1,4 +1,4 @@ -# Using Explicit Want to Start an Ability +# Using Explicit Want to Start an Application Component When a user touches a button in an application, the application often needs to start a UIAbility component to complete a specific task. If the **abilityName** and **bundleName** parameters are specified when starting a UIAbility, then the explicit Want is used. diff --git a/en/application-dev/application-models/ability-startup-with-implicit-want.md b/en/application-dev/application-models/ability-startup-with-implicit-want.md index dbd65bb560d7531bb6e00b21c004815fda1a997c..7d92fbccbd1ebb49dc2a89de0ea825a1e2a8c873 100644 --- a/en/application-dev/application-models/ability-startup-with-implicit-want.md +++ b/en/application-dev/application-models/ability-startup-with-implicit-want.md @@ -5,21 +5,21 @@ This section uses the operation of using a browser to open a website as an examp ```json { "module": { - // ... + ... "abilities": [ { - // ... + ... "skills": [ { "entities": [ "entity.system.home", "entity.system.browsable" - // ... + ... ], "actions": [ "action.system.home", "ohos.want.action.viewData" - // ... + ... ], "uris": [ { @@ -31,9 +31,9 @@ This section uses the operation of using a browser to open a website as an examp }, { "scheme": "http", - // ... + ... } - // ... + ... ] } ] @@ -59,19 +59,18 @@ function implicitStartAbility() { 'uri': 'https://www.test.com:8080/query/student' } context.startAbility(wantInfo).then(() => { - // ... + ... }).catch((err) => { - // ... + ... }) } ``` The matching process is as follows: -1. If **action** in the passed **want** parameter is specified and is included in **actions** under **skills** of the ability to match, the matching is successful. -2. If **entities** in the passed **want** parameter is specified and is included in **entities** under **skills** of the ability to match, the matching is successful. -3. If **uri** in the passed **want** parameter is included in **uris** under **skills** of the ability to match, which is concatenated into https://www.test.com:8080/query* (where * is a wildcard), the matching is successful. -4. If **type** in the passed **want** parameter is specified and is included in **type** under **skills** of the ability to match, the matching is successful. +1. If **action** in the passed **want** parameter is specified and is included in **actions** under **skills** of the application component to match, the matching is successful. +2. If **entities** in the passed **want** parameter is specified and is included in **entities** under **skills** of the application component to match, the matching is successful. +3. If **uri** in the passed **want** parameter is included in **uris** under **skills** of the application component to match, which is concatenated into https://www.test.com:8080/query* (where * is a wildcard), the matching is successful. If there are multiple matching applications, the system displays a dialog box for you to select one of them. The following figure shows an example. diff --git a/en/application-dev/application-models/abilitystage.md b/en/application-dev/application-models/abilitystage.md index 9a4e71d3fa696ee6f2707545b80456df34fe85ac..da764a445a6d1a79a601719f069798191641a986 100644 --- a/en/application-dev/application-models/abilitystage.md +++ b/en/application-dev/application-models/abilitystage.md @@ -12,7 +12,7 @@ AbilityStage is not automatically generated in the default project of DevEco Stu 1. In the **ets** directory of the **Module** project, right-click and choose **New > Directory** to create a directory named **myabilitystage**. -2. In the **myabilitystage** directory, right-click and choose **New > ts File** to create a file named **MyAbilityStage.ts**. +2. In the **myabilitystage** directory, right-click and choose **New > TypeScript File** to create a file named **MyAbilityStage.ts**. 3. Open the **MyAbilityStage.ts** file, and import the dependency package of AbilityStage. Customize a class that inherits from AbilityStage, and add the required lifecycle callbacks. The following code snippet adds the **onCreate()** lifecycle callback. @@ -20,29 +20,28 @@ AbilityStage is not automatically generated in the default project of DevEco Stu import AbilityStage from '@ohos.app.ability.AbilityStage'; export default class MyAbilityStage extends AbilityStage { - onCreate() { - // When the HAP of the application is loaded for the first time, initialize the module. - } - onAcceptWant(want) { - // Triggered only for the ability with the specified launch type. - return "MyAbilityStage"; - } + onCreate() { + // When the HAP of the application is loaded for the first time, initialize the module. + } + onAcceptWant(want) { + // Triggered only for the UIAbility with the specified launch type. + return "MyAbilityStage"; + } } ``` -4. Set **srcEntry** in the [module.json5 file](../quick-start/module-configuration-file.md) to the code path of the module. +4. In the [module.json5 file](../quick-start/module-configuration-file.md), set **srcEntry** to specify the code path of the module as the entry for loading the HAP. ```json { "module": { "name": "entry", "type": "entry", "srcEntry": "./ets/myabilitystage/MyAbilityStage.ts", - // ... + ... } } ``` - [AbilityStage](../reference/apis/js-apis-app-ability-abilityStage.md) has the lifecycle callback [onCreate()](../reference/apis/js-apis-app-ability-abilityStage.md#abilitystageoncreate) and the event callbacks [onAcceptWant()](../reference/apis/js-apis-app-ability-abilityStage.md#abilitystageonacceptwant), [onConfigurationUpdated()](../reference/apis/js-apis-app-ability-abilityStage.md#abilitystageonconfigurationupdate), and [onMemoryLevel()](../reference/apis/js-apis-app-ability-abilityStage.md#abilitystageonmemorylevel). @@ -53,7 +52,6 @@ AbilityStage is not automatically generated in the default project of DevEco Stu - **onConfigurationUpdated()** event callback: triggered when the global system configuration changes. The global system configuration, such as the system language and theme, are defined in the [Configuration](../reference/apis/js-apis-app-ability-configuration.md) class before project configuration. - **onMemoryLevel()** event callback: triggered when the system adjusts the memory. - When an application is switched to the background, it is cached in the background. This adversely affects the overall system performance. When system resources are insufficient, the system reclaims memory from applications in multiple ways. For example, the system may stop applications to release memory for executing key tasks. To further maintain the balance of the system memory and prevent the system from stopping application processes, you can subscribe to the system memory changes in the **onMemoryLevel()** lifecycle callback of AbilityStage to release unnecessary resources. @@ -62,8 +60,8 @@ When an application is switched to the background, it is cached in the backgroun import AbilityStage from '@ohos.app.ability.AbilityStage'; export default class MyAbilityStage extends AbilityStage { - onMemoryLevel(level) { - // Release unnecessary memory based on the change of available system memory. - } + onMemoryLevel(level) { + // Release unnecessary memory based on the change of available system memory. + } } ``` diff --git a/en/application-dev/application-models/access-dataability.md b/en/application-dev/application-models/access-dataability.md index 24dc9305f194a61c974c63db224f2e7727689f5f..b32d38354e7e67fb8757c022fc6e65c737bb297e 100644 --- a/en/application-dev/application-models/access-dataability.md +++ b/en/application-dev/application-models/access-dataability.md @@ -11,7 +11,7 @@ The basic dependency packages include: - @ohos.data.dataAbility -- @ohos.data.rdb +- @ohos.data.relationalStore The sample code for accessing a DataAbility is as follows: @@ -23,7 +23,7 @@ The sample code for accessing a DataAbility is as follows: // Different from the URI defined in the config.json file, the URI passed in the parameter has an extra slash (/), three slashes in total. import featureAbility from '@ohos.ability.featureAbility' import ohos_data_ability from '@ohos.data.dataAbility' - import ohos_data_rdb from '@ohos.data.rdb' + import relationalStore from '@ohos.data.relationalStore' let urivar = "dataability:///com.ix.DataAbility" let DAHelper = featureAbility.acquireDataAbilityHelper(urivar); diff --git a/en/application-dev/application-models/access-datashareextensionability-from-fa.md b/en/application-dev/application-models/access-datashareextensionability-from-fa.md index 0abc7e3b8e948529b9916f936bf59b4a60a93637..5be8c5a7c9f848e0818b280fc5f5df8f4c15de22 100644 --- a/en/application-dev/application-models/access-datashareextensionability-from-fa.md +++ b/en/application-dev/application-models/access-datashareextensionability-from-fa.md @@ -27,12 +27,14 @@ Instead of manual modification, OpenHarmony adopts the following processing: ## Constraints -1. When you switch a DataAbility to a DataShareExtensionAbility, only the URI prefix can be modified.![FAvsStage-uri](figures/FAvsStage-uri.png) +1. When you switch a DataAbility to a DataShareExtensionAbility, only the URI prefix can be modified. -2. The **DataShareHelper** class implements only certain APIs of **DataAbilityHelper**. For details about the APIs, see the table below. + ![FAvsStage-uri](figures/FAvsStage-uri.png) + +3. The **DataShareHelper** class implements only certain APIs of **DataAbilityHelper**. For details about the APIs, see the table below. + + **Table 1** API compatibility when the FA model accesses a DataShareExtensionAbility of the stage model - **Table 1** APIs invoked when the FA model accesses a DataShareExtensionAbility of the stage model - | API| Provided by DataAbilityHelper| Provided by DataShareHelper| Compatible| | -------- | -------- | -------- | -------- | | on | Yes| Yes| Yes| diff --git a/en/application-dev/application-models/accessibilityextensionability.md b/en/application-dev/application-models/accessibilityextensionability.md index 4c912d5e58a1b8083ba1037cccf449dd953d245c..42968456fe88c836e5befe9c096eb2f3892729e1 100644 --- a/en/application-dev/application-models/accessibilityextensionability.md +++ b/en/application-dev/application-models/accessibilityextensionability.md @@ -1,4 +1,4 @@ -# AccessibilityExtensionAbility Development +# AccessibilityExtensionAbility The **AccessibilityExtensionAbility** module provides accessibility extension capabilities based on the **ExtensionAbility** framework. You can develop your accessibility applications by applying the **AccessibilityExtensionAbility** template to enhance usability. @@ -10,16 +10,25 @@ The **AccessibilityExtensionAbility** module provides accessibility extension ca > > Model: stage -This document is organized as follows: +## AccessibilityExtensionAbility Overview -- [Creating an AccessibilityExtAbility File](#creating-an-accessibility-extension-service) -- [Processing an Accessibility Event](#processing-an-accessibility-event) -- [Declaring Capabilities of Accessibility Extension Services](#declaring-capabilities-of-accessibility-extension-services) -- [Enabling a Custom Accessibility Extension Service](#enabling-a-custom-accessibility-extension-service) +Accessibility is about giving equal access to everyone so that they can access and use information equally and conveniently under any circumstances. It helps narrow the digital divide between people of different classes, regions, ages, and health status in terms of information understanding, information exchange, and information utilization, so that they can participate in social life more conveniently and enjoy the benefits of technological advances. + +AccessibilityExtensionAbility is an accessibility extension service framework. It allows you to develop your own extension services and provides a standard mechanism for exchanging information between applications and extension services. You can make use of the provided capabilities and APIs to develop accessibility features for users with disabilities or physical limitations. For example, you can develop a screen reader for users with vision impairments. + +Below shows the AccessibilityExtensionAbility framework. + +![AccessibilityFramework](figures/AccessibilityFramework.png) + +1. Accessibility app: extension service application developed based on the AccessibilityExtensionAbility framework, for example, a screen reader application. +2. Target app: application assisted by the accessibility app. +3. AccessibilityAbilityManagerService (AAMS): main service of the AccessibilityExtensionAbility framework, which is used to manage the lifecycle of accessibility apps and provide a bridge for information exchange between accessibility apps and target apps. +4. AccessibilityAbility (AAkit): ability that is used by the accessibility app to build an extension service ability operating environment and that provides interfaces for the accessibility app to query and operate the target app, including performing click/long press operations. +5. AccessibilitySystemAbilityClient (ASACkit): used by the target app to send accessibility events, such as content change events, to AAMS, and respond to the instructions (such as performing click/long press operations) sent by the accessibility app through AAMS. ## Creating an Accessibility Extension Service -You can create an accessibility extension service by creating a project from scratch or adding the service to an existing project. +You can create an accessibility extension service by creating a project from scratch or adding the service to an existing project. Only one accessibility extension service can be created for a project. ### Creating a Project @@ -37,15 +46,15 @@ import AccessibilityExtensionAbility from '@ohos.application.AccessibilityExtens class AccessibilityExtAbility extends AccessibilityExtensionAbility { onConnect() { - console.log('AccessibilityExtAbility onConnect'); + console.info('AccessibilityExtAbility onConnect'); } onDisconnect() { - console.log('AccessibilityExtAbility onDisconnect'); + console.info('AccessibilityExtAbility onDisconnect'); } onAccessibilityEvent(accessibilityEvent) { - console.log('AccessibilityExtAbility onAccessibilityEvent: ' + JSON.stringify(accessibilityEvent)); + console.info('AccessibilityExtAbility onAccessibilityEvent: ' + JSON.stringify(accessibilityEvent)); } } @@ -66,9 +75,9 @@ You can process the service logic for accessibility events in the **onAccessibil ```typescript onAccessibilityEvent(accessibilityEvent) { - console.log('AccessibilityExtAbility onAccessibilityEvent: ' + JSON.stringify(accessibilityEvent)); + console.info('AccessibilityExtAbility onAccessibilityEvent: ' + JSON.stringify(accessibilityEvent)); if (accessibilityEvent.eventType === 'pageStateUpdate') { - console.log('AccessibilityExtAbility onAccessibilityEvent: pageStateUpdate'); + console.info('AccessibilityExtAbility onAccessibilityEvent: pageStateUpdate'); // TODO: Develop custom logic. } } @@ -79,13 +88,13 @@ You can also process physical key events in the accessibility extension service. ## Declaring Capabilities of Accessibility Extension Services -After developing the custom logic for an accessibility extension service, you must add the configuration information of the service to the corresponding module-level **module.json5** file in the project directory. In the file, the **srcEntrance** tag indicates the path to the accessibility extension service. Make sure the value of the **type** tag is fixed at **accessibility**. Otherwise, the connection to the service will fail. +After developing the custom logic for an accessibility extension service, you must add the configuration information of the service to the corresponding module-level **module.json5** file in the project directory. In the file, the **srcEntry** tag indicates the path to the accessibility extension service. Make sure the value of the **type** tag is fixed at **accessibility**. Otherwise, the connection to the service will fail. ```json "extensionAbilities": [ { "name": "AccessibilityExtAbility", - "srcEntrance": "./ets/AccessibilityExtAbility/AccessibilityExtAbility.ts", + "srcEntry": "./ets/AccessibilityExtAbility/AccessibilityExtAbility.ts", "label": "$string:MainAbility_label", "description": "$string:MainAbility_desc", "type": "accessibility", @@ -116,3 +125,4 @@ To enable or disable an accessibility extension service, run the following comma In the preceding commands, **AccessibilityExtAbility** indicates the name of the accessibility extension service, **com.example.demo** indicates the bundle name, and **rg** indicates the capabilities (**r** is short for retrieve). If the service is enabled or disabled successfully, the message "enable ability successfully" or "disable ability successfully" is displayed. + diff --git a/en/application-dev/application-models/actions-entities.md b/en/application-dev/application-models/actions-entities.md index 5c5aed302c6f8f570238fac6bd73c263840244d6..38119a1b1fe16067f7e89629811327ad079a5d15 100644 --- a/en/application-dev/application-models/actions-entities.md +++ b/en/application-dev/application-models/actions-entities.md @@ -1,9 +1,8 @@ # Common action and entities Values -**action**: Action to take, such as viewing, sharing, and application details, by the caller. In implicit Want, you can define this field and use it together with **uri** or **parameters** to specify the operation to be performed on the data, for example, viewing URI data. For example, if the URI is a website and the action is **ohos.want.action.viewData**, the ability that supports website viewing is matched. Declaring the **action** field in Want indicates that the invoked application should support the declared operation. The **actions** field under **skills** in the configuration file indicates the operations supported by the application. +The **action** field specifies the common operation (such as viewing, sharing, and application details) to be performed by the caller. In implicit [Want](../reference/apis/js-apis-app-ability-want.md), you can define this field and use it together with **uri** or **parameters** to specify the operation to be performed on the data, for example, viewing URI data. For example, if the URI is a website and the action is **ohos.want.action.viewData**, the application component that supports website viewing is matched. Declaring the **action** field in [Want](../reference/apis/js-apis-app-ability-want.md) indicates that the invoked application is expected to support the declared operation. The **actions** field under **skills** in the configuration file indicates the operations supported by the application. - -**Common action Values** +The following **action** values are available: - **ACTION_HOME**: action of starting the application entry component. It must be used together with **ENTITY_HOME**. The application icon on the home screen is an explicit entry component. Users can touch the icon to start the entry component. Multiple entry components can be configured for an application. @@ -14,14 +13,13 @@ - **ACTION_VIEW_MULTIPLE_DATA**: action of launching the UI for sending multiple data records. -**entities**: Category information (such as browser and video player) of the target ability. It is a supplement to **action** in implicit Want. You can define this field to filter application categories, for example, browser. Declaring the **entities** field in Want indicates that the invoked application should belong to the declared category. The **entities** field under **skills** in the configuration file indicates the categories supported by the application. - +The **entities** field specify the category information (such as browser and video player) of the target application component. It is a supplement to **action** in implicit Want. You can define this field to filter application categories, for example, browser. Declaring the **entities** field in Want indicates that the invoked application should belong to the declared category. The **entities** field under **skills** in the configuration file indicates the categories supported by the application. -**Common entities Values** +The following **entities** values are available: - **ENTITY_DEFAULT**: default category, which is meaningless. -- **ENTITY_HOME**: abilities with an icon displayed on the home screen. +- **ENTITY_HOME**: application components with an icon displayed on the home screen. - **ENTITY_BROWSABLE**: browser type. diff --git a/en/application-dev/application-models/api-switch-overview.md b/en/application-dev/application-models/api-switch-overview.md index bf8223b5a6c047af46e960dad6713f20e251d02f..93db02670718e56943aba99b81ca4775423278e8 100644 --- a/en/application-dev/application-models/api-switch-overview.md +++ b/en/application-dev/application-models/api-switch-overview.md @@ -1,7 +1,7 @@ # API Switching Overview -Due to the differences in the thread model and process model, certain APIs (marked with **FAModelOnly** in the SDK) can be used only in the FA model. When switching an application from the FA model to the stage model, replace the APIs marked with **FAModelOnly** in the application with the APIs supported in the stage model. This topic uses the switching of **startAbility()** as an example. +Due to the differences in the thread model and process model, certain APIs can be used only in the FA model. They are marked with **FAModelOnly** in the SDK. When switching an application from the FA model to the stage model, replace the APIs marked with **FAModelOnly** in the application with the APIs supported in the stage model. This topic uses the switching of **startAbility()** as an example. ![api-switch-overview](figures/api-switch-overview.png) @@ -27,7 +27,7 @@ Due to the differences in the thread model and process model, certain APIs (mark - Sample code of **startAbility()** in the stage model: ```ts - // context is a member of the ability object and is required for invoking inside a non-ability object. + // Context is a member of the ability object and is required for invoking inside a non-ability object. // Pass in the Context object. let wantInfo = { bundleName: "com.example.myapplication", diff --git a/en/application-dev/application-models/app-deviceconfig-switch.md b/en/application-dev/application-models/app-deviceconfig-switch.md index 1092c21081cd9a8d62c92a1a68ba434efee7c8c9..6c872f0c167bd4779516d611ee07d9036ca550ee 100644 --- a/en/application-dev/application-models/app-deviceconfig-switch.md +++ b/en/application-dev/application-models/app-deviceconfig-switch.md @@ -22,7 +22,7 @@ OpenHarmony has reconstructed the [deviceConfig](../quick-start/deviceconfig-str | deviceConfig in the FA Model| Description| Stage Model| Difference| | -------- | -------- | -------- | -------- | | deviceConfig| Device information.| / | This tag is no longer available in the stage model. In the stage model, device information is configured under the **app** tag.| -| process | Name of the process running the application or ability. If the **process** attribute is configured in the **deviceConfig** tag, all abilities of the application run in this process. You can set the **process** attribute for a specific ability in the **abilities** attribute, so that the ability can run in the particular process.| / | The stage model does not support the configuration of process names.| +| process | Name of the process running the application or UIAbility. If the **process** attribute is configured in the **deviceConfig** tag, all UIAbilities of the application run in this process. You can set the **process** attribute for a specific UIAbility in the **abilities** attribute, so that the UIAbility can run in the particular process.| / | The stage model does not support the configuration of process names.| | keepAlive | Whether the application is always running. This attribute applies only to system applications and does not take effect for third-party applications.| / | The stage model does not support changing of the model control mode for system applications.| | supportBackup | Whether the application supports data backup and restore.| / | This configuration is not supported in the stage model.| | compressNativeLibs | Whether the **libs** libraries are packaged in the HAP file after being compressed.| / | This configuration is not supported in the stage model.| diff --git a/en/application-dev/application-models/application-component-configuration-fa.md b/en/application-dev/application-models/application-component-configuration-fa.md index 4cc1c9ad6831f0e54ae4c70f4f7229a7abc7c62f..336ad698d0f2298045b00fe0af1563574bccfd24 100644 --- a/en/application-dev/application-models/application-component-configuration-fa.md +++ b/en/application-dev/application-models/application-component-configuration-fa.md @@ -22,7 +22,7 @@ When developing an application, you may need to configure certain tags to identi "actions": ["action.system.home"] } ] - // ... + ... } ``` diff --git a/en/application-dev/application-models/application-component-configuration-stage.md b/en/application-dev/application-models/application-component-configuration-stage.md index bcf9b095464ba0110c35be9cfef44b078a091ffb..555964ca58a6e21380ac67aa389280504d9c7dce 100644 --- a/en/application-dev/application-models/application-component-configuration-stage.md +++ b/en/application-dev/application-models/application-component-configuration-stage.md @@ -1,17 +1,19 @@ # Application- or Component-Level Configuration (Stage Model) +When developing an application, you may need to configure certain tags to identify the application, such as the bundle name and application icon. This topic describes key tags that need to be configured during application development. -When developing an application, you may need to configure certain tags to identify the application, such as the bundle name and application icon. This topic describes key tags that need to be configured during application development. Icons and labels are usually configured together. There is the application icon, application label, entry icon, and entry label, which correspond to the **icon** and **label** fields in the [app.json5 file](../quick-start/app-configuration-file.md) and [module.json5 file](../quick-start/module-configuration-file.md). The application icon and label are used in **Settings**. For example, they are displayed in the application list in **Settings**. The entry icon is displayed on the device's home screen after the application is installed. The entry icon maps to a [UIAbility](uiability-overview.md) component. Therefore, an application can have multiple entry icons and labels. When you touch one of them, the corresponding UIAbility page is displayed. +Icons and labels are usually configured together. There is the application icon, application label, entry icon, and entry label, which correspond to the **icon** and **label** fields in the [app.json5 file](../quick-start/app-configuration-file.md) and [module.json5 file](../quick-start/module-configuration-file.md). +The application icon and label are used in **Settings**. For example, they are displayed in the application list in **Settings**. The entry icon is displayed on the device's home screen after the application is installed. The entry icon maps to a [UIAbility](uiability-overview.md) component. Therefore, an application can have multiple entry icons and entry labels. When you touch one of them, the corresponding UIAbility page is displayed. - **Figure 1** Icons and labels +**Figure 1** Icons and labels ![application-component-configuration-stage](figures/application-component-configuration-stage.png) - **Configuring the bundle name** - The bundle name is specified by the **bundleName** field in the [app.json5 file](../quick-start/app-configuration-file.md) in the **AppScope** directory of the project. This field uniquely identifies an application. You are advised to use the reverse domain name notion, for example, *com.example.demo*, where the first part is the domain suffix **com**, the second part is the vendor/individual name, and the third part is the application name, which can be of multiple levels. + The bundle name is specified by the **bundleName** field in the [app.json5 file](../quick-start/app-configuration-file.md) in the **AppScope** directory of the project. This field uniquely identifies an application. You are advised to use the reverse domain name notation, for example, *com.example.demo*, where the first part is the domain suffix **com**, the second part is the vendor/individual name, and the third part is the application name, which can be of multiple levels. - **Configuring the application icon and label** @@ -19,28 +21,28 @@ When developing an application, you may need to configure certain tags to identi The application icon is specified by the **icon** field in the [app.json5 file](../quick-start/app-configuration-file.md) in the **AppScope** directory of the project. The **icon** field must be set to the index of an image so that the image is displayed as the application icon. - The application label is specified by the **label** field in the [app.json5 file](../quick-start/app-configuration-file.md) in the **AppScope** module of the project. The **label** field specifies the application name displayed to users. It must be set to the index of a string resource. + The application label is specified by the **label** field in the [app.json5 file](../quick-start/app-configuration-file.md) in the **AppScope** directory of the project. The **label** field specifies the application name displayed to users. It must be set to the index of a string resource. ```json - { - "app": { - "icon": "$media:app_icon", - "label": "$string:app_name" - // ... - } + { + "app": { + "icon": "$media:app_icon", + "label": "$string:app_name" + ... } + } ``` - **Configuring the entry icon and label** On the stage model, you can configure an entry icon and label for each application component. The entry icon and label are displayed on the home screen. - The entry icon is configured by specifying **icon** under **abilities** in the [module.json5 file](../quick-start/module-configuration-file.md). For example, if you want to display the icon of the UIAbility component on the home screen, add **entity.system.home** to **entities** and **ohos.want.action.home** to **actions** under **skills**. If this field is configured for multiple UIAbility components of an application, multiple icons are displayed on the home screen, corresponding to their respective UIAbility component. + The entry icon is configured by specifying **icon** under **abilities** in the [module.json5 file](../quick-start/module-configuration-file.md). For example, if you want to display the icon of the UIAbility component on the home screen, add **entity.system.home** to **entities** and **ohos.want.action.home** to **actions** under **skills**. If this field is configured for multiple UIAbility components of an application, multiple icons are displayed on the home screen, corresponding to their respective UIAbility components. ```json { "module": { - // ... + ... "abilities": [ { // The information starting with $ is the resource value. @@ -61,6 +63,35 @@ When developing an application, you may need to configure certain tags to identi } } ``` + OpenHarmony strictly controls applications without icons to prevent malicious applications from deliberately configuring no icon to block uninstall attempts. + + To hide an application icon on the home screen, you must configure the **AllowAppDesktopIconHide** privilege. For details, see [Application Privilege Configuration Guide](../../device-dev/subsystems/subsys-app-privilege-config-guide.md). The rules for displaying the entry icon and entry label are as follows: + + 1. The HAP file contains UIAbility configuration. + * An entry icon is set in the **abilities** field of the **module.json5** file. + * The application does not have the privilege to hide its icon on the home screen. + * The system uses the icon configured for the UIAbility as the entry icon and displays it on the home screen. Touching this icon will direct the user to the home page of the UIAbility. + * The system uses the label configured for the UIAbility as the entry label and displays it on the home screen. If no label is configured, the system uses the label specified in the **app.json5** file as the entry label and displays it on the home screen. + * The application has the privilege to hide its icon on the home screen. + * The application information is not returned when the home screen queries the information, and the entry icon and label of the application are not displayed on the home screen. + * No entry icon is set in the **abilities** field of the **module.json5** file. + * The application does not have the privilege to hide its icon on the home screen. + * The system uses the icon specified in the **app.json5** file as the entry icon and displays it on the home screen. Touching this icon will direct the user to the application details page, as shown below. + * The system uses the label specified in the **app.json5** file as the entry label and displays it on the home screen. + * The application has the privilege to hide its icon on the home screen. + * The application information is not returned when the home screen queries the information, and the entry icon and label of the application are not displayed on the home screen. + + 2. The HAP file does not contain UIAbility configuration. + * The application does not have the privilege to hide its icon on the home screen. + * The system uses the icon specified in the **app.json5** file as the entry icon and displays it on the home screen. Touching this icon will direct the user to the application details page, as shown below. + * The system uses the label specified in the **app.json5** file as the entry label and displays it on the home screen. + * The application has the privilege to hide its icon on the home screen. + * The application information is not returned when the home screen queries the information, and the entry icon and label of the application are not displayed on the home screen. + + **Figure 2** Application details page + +![Application details page](figures/application_details.jpg) + - **Configuring application version declaration** To declare the application version, configure the **versionCode** and **versionName** fields in the [app.json5 file](../quick-start/app-configuration-file.md) in the **AppScope** directory of the project. **versionCode** specifies the version number of the application. The value is a 32-bit non-negative integer. It is used only to determine whether a version is later than another version. A larger value indicates a later version. **versionName** provides the text description of the version number. diff --git a/en/application-dev/application-models/application-context-fa.md b/en/application-dev/application-models/application-context-fa.md index 9f68b42a873782c9fd1693c73724354cbf347ced..6ea4445778aba90c668f19839a367b5a4a168925 100644 --- a/en/application-dev/application-models/application-context-fa.md +++ b/en/application-dev/application-models/application-context-fa.md @@ -44,17 +44,17 @@ For details about the APIs, see [API Reference](../reference/apis/js-apis-inner- } ``` -2. Set the display orientation of the host featureAbility. +2. Set the display orientation of the **featureAbility**. ```ts import featureAbility from '@ohos.ability.featureAbility' - import bundle from '@ohos.bundle'; + import bundleManager from '@ohos.bundle.bundleManager'; export default { onCreate() { // Obtain the context and call related APIs. let context = featureAbility.getContext(); - context.setDisplayOrientation(bundle.DisplayOrientation.LANDSCAPE).then(() => { + context.setDisplayOrientation(bundleManager.DisplayOrientation.LANDSCAPE).then(() => { console.info("Set display orientation.") }) console.info('Application onCreate') diff --git a/en/application-dev/application-models/application-context-stage.md b/en/application-dev/application-models/application-context-stage.md index 5308d1899a46ffb9907a18bd74a7920627ac720b..47fdeeedf1fe5238b0f0a2e56945be35208e0391 100644 --- a/en/application-dev/application-models/application-context-stage.md +++ b/en/application-dev/application-models/application-context-stage.md @@ -3,16 +3,16 @@ ## Overview -[Context](../reference/apis/js-apis-inner-application-context.md) is the context of an object in an application. It provides basic information about the application, for example, **resourceManager**, **applicationInfo**, **dir** (application development path), and **area** (encrypted area). It also provides basic methods such as **createBundleContext()** and **getApplicationContext()**. The UIAbility component and ExtensionAbility derived class components have their own **Context** classes, for example, the base class **Context**, **ApplicationContext**, **AbilityStageContext**, **UIAbilityContext**, **ExtensionContext**, and **ServiceExtensionContext**. +[Context](../reference/apis/js-apis-inner-application-context.md) is the context of an object in an application. It provides basic information about the application, for example, **resourceManager**, **applicationInfo**, **dir** (application file path), and **area** (encryption level). It also provides basic methods such as **createBundleContext()** and **getApplicationContext()**. The UIAbility component and ExtensionAbility derived class components have their own **Context** classes, for example, the base class **Context**, **ApplicationContext**, **AbilityStageContext**, **UIAbilityContext**, **ExtensionContext**, and **ServiceExtensionContext**. -- The figure below illustrates the inheritance relationship of contexts. +- The figure below illustrates the inheritance relationship of contexts. ![context-inheritance](figures/context-inheritance.png) - -- The figure below illustrates the holding relationship of contexts. + +- The figure below illustrates the holding relationship of contexts. ![context-holding](figures/context-holding.png) - + - The following describes the information provided by different contexts. - [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md): Each UIAbility has the **Context** attribute, which provides APIs to operate an application component, obtain the application component configuration, and more. @@ -21,7 +21,7 @@ export default class EntryAbility extends UIAbility { onCreate(want, launchParam) { let uiAbilityContext = this.context; - // ... + ... } } ``` @@ -36,7 +36,7 @@ export default class MyService extends ServiceExtensionAbility { onCreate(want) { let serviceExtensionContext = this.context; - // ... + ... } } ``` @@ -47,7 +47,7 @@ export default class MyAbilityStage extends AbilityStage { onCreate() { let abilityStageContext = this.context; - // ... + ... } } ``` @@ -58,7 +58,7 @@ export default class EntryAbility extends UIAbility { onCreate(want, launchParam) { let applicationContext = this.context.getApplicationContext(); - // ... + ... } } ``` @@ -70,108 +70,117 @@ This topic describes how to use the context in the following scenarios: -- [Obtaining the Application Development Path](#obtaining-the-application-development-path) -- [Obtaining and Modifying Encryption Areas](#obtaining-and-modifying-encryption-areas) +- [Obtaining Application File Paths](#obtaining-application-file-paths) +- [Obtaining and Modifying Encryption Levels](#obtaining-and-modifying-encryption-levels) - [Creating Context of Another Application or Module](#creating-context-of-another-application-or-module) - [Subscribing to UIAbility Lifecycle Changes in a Process](#subscribing-to-uiability-lifecycle-changes-in-a-process) -### Obtaining the Application Development Path - -The following table describes the application development paths obtained from context. +### Obtaining Application File Paths -**Table 1** Application development paths +The base class [Context](../reference/apis/js-apis-inner-application-context.md) provides the capability of obtaining application file paths. **ApplicationContext**, **AbilityStageContext**, **UIAbilityContext**, and **ExtensionContext** inherit this capability. The application file paths are a type of application sandbox paths. For details, see [Application Sandbox Directory](../file-management/app-sandbox-directory.md). -| Name| Type| Readable| Writable| Description| -| -------- | -------- | -------- | -------- | -------- | -| bundleCodeDir | string | Yes | No | Path for storing the application's installation package, that is, installation directory of the application on the internal storage. | -| cacheDir | string | Yes| No| Path for storing the application's cache files, that is, cache directory of the application on the internal storage.
It is the content of **Storage** of an application under **Settings > Apps & services > Apps**.| -| filesDir | string | Yes | No | Path for storing the application's common files, that is, file directory of the application on the internal storage.
Files in this directory may be synchronized to other directories during application migration or backup.| -| preferencesDir | string | Yes | Yes | Path for storing the application's preference files, that is, preferences directory of the application. | -| tempDir | string | Yes | No | Path for storing the application's temporary files.
Files in this directory are deleted after the application is uninstalled.| -| databaseDir | string | Yes | No | Path for storing the application's database, that is, storage directory of the local database. | -| distributedFilesDir | string | Yes| No| Path for storing the application's distributed files.| +The application file paths obtained by the preceding contexts are different. -The capability of obtaining the application development path is provided by the base class **Context**. This capability is also provided by **ApplicationContext**, **AbilityStageContext**, **UIAbilityContext**, and **ExtensionContext**. However, the paths obtained from different contexts may differ, as shown below. +- The application file path obtained through **ApplicationContext** is at the application level. This path is recommended for storing global application information, and the files in the path will be deleted when the application is uninstalled. -**Figure 1** Application development paths obtained from context - -![context-dir](figures/context-dir.png) - -- Obtain the application-level path through **ApplicationContext**. It is recommended that global application information be stored in this path. Files stored in this path will be deleted only when the application is uninstalled. - | Name| Path| + | Name| Path| | -------- | -------- | - | bundleCodeDir | {Path prefix}/el1/bundle/| - | cacheDir | {Path prefix}/{Encryption level}/base/cache/| - | filesDir | {Path prefix}/{Encryption level}/base/files/| - | preferencesDir | {Path prefix}/{Encryption level}/base/preferences/| - | tempDir | {Path prefix}/{Encryption level}/base/temp/| - | databaseDir | {Path prefix}/{Encryption level}/database/| - | distributedFilesDir | {Path prefix}/el2/distributedFiles/| - -- Obtain the HAP level path through **AbilityStageContext**, **UIAbilityContext**, and **ExtensionContext**. It is recommended that the HAP information be stored in this path. The file content stored in this path will be deleted when the HAP is uninstalled. The file content in the application-level path will be deleted only after all the HAPs of the application are uninstalled. - | Name| Path| - | -------- | -------- | - | bundleCodeDir | {Path prefix}/el1/bundle/| - | cacheDir | {Path prefix}/{Encryption level}/base/**haps/{moduleName}**/cache/| - | filesDir | {Path prefix}/{Encryption level}/base/**haps/{moduleName}**/files/| - | preferencesDir | {Path prefix}/{Encryption level}/base/**haps/{moduleName}**/preferences/| - | tempDir | {Path prefix}/{Encryption level}/base/**haps/{moduleName}**/temp/| - | databaseDir | {Path prefix}/{Encryption level}/database/**{moduleName}**/| - | distributedFilesDir | {Path prefix}/el2/distributedFiles/**{moduleName}**/| + | bundleCodeDir | \/el1/bundle| + | cacheDir | \/\/base/cache| + | filesDir | \/\/base/files| + | preferencesDir | \/\/base/preferences| + | tempDir | \/\/base/temp| + | databaseDir | \/\/database| + | distributedFilesDir | \/el2/distributedFiles| + + The sample code is as follows: + + ```ts + import UIAbility from '@ohos.app.ability.UIAbility'; + + export default class EntryAbility extends UIAbility { + onCreate(want, launchParam) { + let applicationContext = this.context.getApplicationContext(); + let cacheDir = applicationContext.cacheDir; + let tempDir = applicationContext.tempDir; + let filesDir = applicationContext.filesDir; + let databaseDir = applicationContext.databaseDir; + let bundleCodeDir = applicationContext.bundleCodeDir; + let distributedFilesDir = applicationContext.distributedFilesDir; + let preferencesDir = applicationContext.preferencesDir; + ... + // Obtain the application file path. + let filePath = tempDir + 'test.txt'; + console.info(`filePath: ${filePath}`); + } + } + ``` -The sample code for obtaining the application development paths is as follows: +- The application file path obtained through **AbilityStageContext**, **UIAbilityContext**, or **ExtensionContext** is at the HAP level. This path is recommended for storing HAP-related information, and the files in this path are deleted when the HAP is uninstalled. However, the deletion does not affect the files in the application-level path unless all HAPs of the application are uninstalled. + | Name| Path| + | -------- | -------- | + | bundleCodeDir | \/el1/bundle| + | cacheDir | \/\/base/**haps/\**/cache| + | filesDir | \/\/base/**haps/\**/files| + | preferencesDir | \/\/base/**haps/\**/preferences| + | tempDir | \/\/base/**haps/\**/temp| + | databaseDir | \/\/database/**\**| + | distributedFilesDir | \/el2/distributedFiles/**\**| -```ts -import UIAbility from '@ohos.app.ability.UIAbility'; + The sample code is as follows: -export default class EntryAbility extends UIAbility { - onCreate(want, launchParam) { - let cacheDir = this.context.cacheDir; - let tempDir = this.context.tempDir; - let filesDir = this.context.filesDir; - let databaseDir = this.context.databaseDir; - let bundleCodeDir = this.context.bundleCodeDir; - let distributedFilesDir = this.context.distributedFilesDir; - let preferencesDir = this.context.preferencesDir; - // ... + ```ts + import UIAbility from '@ohos.app.ability.UIAbility'; + + export default class EntryAbility extends UIAbility { + onCreate(want, launchParam) { + let cacheDir = this.context.cacheDir; + let tempDir = this.context.tempDir; + let filesDir = this.context.filesDir; + let databaseDir = this.context.databaseDir; + let bundleCodeDir = this.context.bundleCodeDir; + let distributedFilesDir = this.context.distributedFilesDir; + let preferencesDir = this.context.preferencesDir; + ... + // Obtain the application file path. + let filePath = tempDir + 'test.txt'; + console.info(`filePath: ${filePath}`); + } } -} -``` + ``` -> **NOTE** -> -> The sample code obtains the sandbox path of the application development path. The absolute path can be obtained by running the **find / -name ** command in the hdc shell after file creation or modification. -### Obtaining and Modifying Encryption Areas +### Obtaining and Modifying Encryption Levels -Encrypting application files enhances data security by preventing files from unauthorized access. Different application files require different levels of protection. For private files, such as alarms and wallpapers, the application must place them in the device-level encryption area (EL1) to ensure that they can be accessed before the user enters the password. For sensitive files, such as personal privacy data, the application must place them in the user-level encryption area (EL2). +Encrypting application files enhances data security by preventing files from unauthorized access. Different application files require different levels of protection. For private files, such as alarms and wallpapers, the application must place them in a directory with the device-level encryption (EL1) to ensure that they can be accessed before the user enters the password. For sensitive files, such as personal privacy data, the application must place them in a directory with the user-level encryption (EL2). -In practice, you need to select a proper encrypted area based on scenario-specific requirements to protect application data security. The proper use of EL1 and the EL2 can efficiently improve the security. +In practice, you need to select a proper encryption level based on scenario-specific requirements to protect application data security. The proper use of EL1 and the EL2 can efficiently improve the security. > **NOTE** > -> - AreaMode.EL1: device-level encryption area, which is accessible after the device is powered on. +> - AreaMode.EL1: device-level encryption. Directories with this encryption level are accessible after the device is powered on. > -> - AreaMode.EL2: user-level encryption area, which is accessible only after the device is powered on and the password is entered (for the first time). +> - AreaMode.EL2: user-level encryption. Directories with this encryption level are accessible only after the device is powered on and the password is entered (for the first time). -You can obtain and set the encryption area by reading and writing the [area attribute in Context](../reference/apis/js-apis-inner-application-context.md). +You can obtain and set the encryption level by reading and writing the **area** attribute in [Context](../reference/apis/js-apis-inner-application-context.md). ```ts import UIAbility from '@ohos.app.ability.UIAbility'; +import contextConstant from '@ohos.app.ability.contextConstant'; export default class EntryAbility extends UIAbility { onCreate(want, launchParam) { // Before storing common information, switch the encryption level to EL1. - if (this.context.area === 1) {// Obtain the area. - this.context.area = 0; // Modify the area. + if (this.context.area === contextConstant.AreaMode.EL2) { // Obtain the area. + this.context.area = contextConstant.AreaMode.EL1; // Modify the area. } // Store common information. // Before storing sensitive information, switch the encryption level to EL2. - if (this.context.area === 0) { // Obtain the area. - this.context.area = 1; // Modify the area. + if (this.context.area === contextConstant.AreaMode.EL1) { // Obtain the area. + this.context.area = contextConstant.AreaMode.EL2; // Modify the area. } // Store sensitive information. } @@ -181,7 +190,7 @@ export default class EntryAbility extends UIAbility { ### Creating Context of Another Application or Module -The base class **Context** provides [createBundleContext(bundleName:string)](../reference/apis/js-apis-inner-application-context.md#contextcreatebundlecontext), [createModuleContext(moduleName:string)](../reference/apis/js-apis-inner-application-context.md#contextcreatemodulecontext), and [createModuleContext(bundleName:string, moduleName:string)](../reference/apis/js-apis-inner-application-context.md#contextcreatemodulecontext-1) to create the context of other applications or modules, so as to obtain the resource information, for example, [obtaining the application development paths](#obtaining-the-application-development-path) of other modules. +The base class **Context** provides [createBundleContext(bundleName:string)](../reference/apis/js-apis-inner-application-context.md#contextcreatebundlecontext), [createModuleContext(moduleName:string)](../reference/apis/js-apis-inner-application-context.md#contextcreatemodulecontext), and [createModuleContext(bundleName:string, moduleName:string)](../reference/apis/js-apis-inner-application-context.md#contextcreatemodulecontext-1) to create the context of other applications or modules, so as to obtain the resource information, for example, [obtaining application file paths](#obtaining-application-development-paths) of other modules. - Call **createBundleContext(bundleName:string)** to create the context of another application. > **NOTE** @@ -191,9 +200,9 @@ The base class **Context** provides [createBundleContext(bundleName:string)](../ > - Request the **ohos.permission.GET_BUNDLE_INFO_PRIVILEGED** permission. For details, see [Declaring Permissions in the Configuration File](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file). > > - This is a system API and cannot be called by third-party applications. - + For example, application information displayed on the home screen includes the application name and icon. The home screen application calls the foregoing method to obtain the context information, so as to obtain the resource information including the application name and icon. - + ```ts import UIAbility from '@ohos.app.ability.UIAbility'; @@ -202,11 +211,11 @@ The base class **Context** provides [createBundleContext(bundleName:string)](../ let bundleName2 = 'com.example.application'; let context2 = this.context.createBundleContext(bundleName2); let label2 = context2.applicationInfo.label; - // ... + ... } } ``` - + - Call **createModuleContext(bundleName:string, moduleName:string)** to obtain the context of a specified module of another application. After obtaining the context, you can obtain the resource information of that module. > **NOTE** > @@ -224,7 +233,7 @@ The base class **Context** provides [createBundleContext(bundleName:string)](../ let bundleName2 = 'com.example.application'; let moduleName2 = 'module1'; let context2 = this.context.createModuleContext(bundleName2, moduleName2); - // ... + ... } } ``` @@ -238,7 +247,7 @@ The base class **Context** provides [createBundleContext(bundleName:string)](../ onCreate(want, launchParam) { let moduleName2 = 'module1'; let context2 = this.context.createModuleContext(moduleName2); - // ... + ... } } ``` @@ -248,7 +257,7 @@ The base class **Context** provides [createBundleContext(bundleName:string)](../ In the DFX statistics scenario of an application, if you need to collect statistics on the stay duration and access frequency of a page, you can subscribe to UIAbility lifecycle changes in a process. -[ApplicationContext](../reference/apis/js-apis-inner-application-applicationContext) provides APIs for subscribing to UIAbility lifecycle changes in a process. When the UIAbility lifecycle changes in a process, for example, being created or destroyed, becoming visible or invisible, or gaining or losing focus, the corresponding callback is triggered. Each time the callback is registered, a listener lifecycle ID is returned, with the value incremented by 1 each time. When the number of listeners exceeds the upper limit (2^63-1), **-1** is returned. The following uses [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) as an example. +[ApplicationContext](../reference/apis/js-apis-inner-application-applicationContext.md) provides APIs for subscribing to UIAbility lifecycle changes in a process. When the UIAbility lifecycle changes in a process, for example, being created or destroyed, becoming visible or invisible, or gaining or losing focus, the corresponding callback is triggered. Each time the callback is registered, a listener lifecycle ID is returned, with the value incremented by 1 each time. When the number of listeners exceeds the upper limit (2^63-1), **-1** is returned. The following uses [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) as an example. ```ts @@ -266,53 +275,53 @@ export default class EntryAbility extends UIAbility { let abilityLifecycleCallback = { // Called when a UIAbility is created. onAbilityCreate(uiAbility) { - console.log(TAG, `onAbilityCreate uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); + console.info(TAG, `onAbilityCreate uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); }, // Called when a window is created. onWindowStageCreate(uiAbility, windowStage: window.WindowStage) { - console.log(TAG, `onWindowStageCreate uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); - console.log(TAG, `onWindowStageCreate windowStage: ${JSON.stringify(windowStage)}`); + console.info(TAG, `onWindowStageCreate uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); + console.info(TAG, `onWindowStageCreate windowStage: ${JSON.stringify(windowStage)}`); }, // Called when the window becomes active. onWindowStageActive(uiAbility, windowStage: window.WindowStage) { - console.log(TAG, `onWindowStageActive uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); - console.log(TAG, `onWindowStageActive windowStage: ${JSON.stringify(windowStage)}`); + console.info(TAG, `onWindowStageActive uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); + console.info(TAG, `onWindowStageActive windowStage: ${JSON.stringify(windowStage)}`); }, // Called when the window becomes inactive. onWindowStageInactive(uiAbility, windowStage: window.WindowStage) { - console.log(TAG, `onWindowStageInactive uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); - console.log(TAG, `onWindowStageInactive windowStage: ${JSON.stringify(windowStage)}`); + console.info(TAG, `onWindowStageInactive uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); + console.info(TAG, `onWindowStageInactive windowStage: ${JSON.stringify(windowStage)}`); }, // Called when the window is destroyed. onWindowStageDestroy(uiAbility, windowStage: window.WindowStage) { - console.log(TAG, `onWindowStageDestroy uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); - console.log(TAG, `onWindowStageDestroy windowStage: ${JSON.stringify(windowStage)}`); + console.info(TAG, `onWindowStageDestroy uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); + console.info(TAG, `onWindowStageDestroy windowStage: ${JSON.stringify(windowStage)}`); }, // Called when the UIAbility is destroyed. onAbilityDestroy(uiAbility) { - console.log(TAG, `onAbilityDestroy uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); + console.info(TAG, `onAbilityDestroy uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); }, // Called when the UIAbility is switched from the background to the foreground. onAbilityForeground(uiAbility) { - console.log(TAG, `onAbilityForeground uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); + console.info(TAG, `onAbilityForeground uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); }, // Called when the UIAbility is switched from the foreground to the background. onAbilityBackground(uiAbility) { - console.log(TAG, `onAbilityBackground uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); + console.info(TAG, `onAbilityBackground uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); }, // Called when UIAbility is continued on another device. onAbilityContinue(uiAbility) { - console.log(TAG, `onAbilityContinue uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); + console.info(TAG, `onAbilityContinue uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); } } // Obtain the application context. let applicationContext = this.context.getApplicationContext(); // Register the application lifecycle callback. this.lifecycleId = applicationContext.on('abilityLifecycle', abilityLifecycleCallback); - console.log(TAG, `register callback number: ${this.lifecycleId}`); + console.info(TAG, `register callback number: ${this.lifecycleId}`); } - // ... + ... onDestroy() { // Obtain the application context. diff --git a/en/application-dev/application-models/application-model-description.md b/en/application-dev/application-models/application-model-description.md index 0cdfa7323c6ef367a47a44e2c30104d3201ca159..20fa9019d10c8d242e34b309debec78e722e6c27 100644 --- a/en/application-dev/application-models/application-model-description.md +++ b/en/application-dev/application-models/application-model-description.md @@ -12,10 +12,9 @@ Along its evolution, OpenHarmony has provided two application models: The stage model is designed based on the following considerations, which make it become the recommended model: 1. **Designed for complex applications** - - In the stage model, multiple application components share an ArkTS engine (VM running the programming language ArkTS) instance, making it easy for application components to share objects and status while requiring less memory. - The object-oriented development mode makes the code of complex applications easy to read, maintain, and scale. - + 2. **Native support for [cross-device migration](hop-cross-device-migration.md) and [multi-device collaboration](hop-multi-device-collaboration.md) at the application component level** The stage model decouples application components from User Interfaces (UIs). @@ -38,7 +37,7 @@ The stage model is designed based on the following considerations, which make it The stage model redefines the boundary of application capabilities to well balance application capabilities and system management costs. - - Diverse application components (such as widgets and input methods) for specific scenarios. + - Diverse application components (such as service widgets and input methods) for specific scenarios. - Standardized background process management. To deliver a better user experience, the stage model manages background application processes in a more orderly manner. Applications cannot reside in the background randomly, and their background behavior is strictly managed to minimize malicious behavior. @@ -52,8 +51,8 @@ The table below describes their differences in detail. | Item| FA model| Stage model| | -------- | -------- | -------- | -| **Application component**| 1. Component classification
![fa-model-component](figures/fa-model-component.png)
- PageAbility: has the UI and supports user interaction For details, see [PageAbility Component Overview](pageability-overview.md).
- ServiceAbility: provides background services and has no UI. For details, see [ServiceAbility Component Overview](serviceability-overview.md).
- DataAbility: provides the data sharing capability and has no UI. For details, see [DataAbility Component Overview](dataability-overview.md).
2. Development mode
Application components are specified by exporting anonymous objects and fixed entry files. You cannot perform derivation. It is inconvenient for capability expansion. | 1. Component classification
![stage-model-component](figures/stage-model-component.png)
- UIAbility: has the UI and supports user interaction. For details, see [UIAbility Component Overview](uiability-overview.md).
- ExtensionAbility: provides extension capabilities (such as widget and input methods) for specific scenarios. For details, see [ExtensionAbility Component Overview](extensionability-overview.md).
2. Development mode
The object-oriented mode is used to provide open application components as classes. You can derive application components for capability expansion. | -| **Process model**| There are two types of processes:
1. Main process
2. Rendering process
For details, see [Process Model (FA Model)](process-model-fa.md).| There are three types of processes:
1. Main process
2. ExtensionAbility process
3. Rendering process
For details, see [Process Model (Stage Model)](process-model-stage.md).| -| **Thread model**| 1. ArkTS engine instance creation
A process can run multiple application component instances, and each application component instance runs in an independent ArkTS engine instance.
2. Thread model
Each ArkTS engine instance is created on an independent thread (non-main thread). The main thread does not have an ArkTS engine instance.
3. Intra-process object sharing: not supported.
For details, see [Thread Model (FA Model)](thread-model-fa.md).| 1. ArkTS engine instance creation
A process can run multiple application component instances, and all application component instances share one ArkTS engine instance.
2. Thread model
The ArkTS engine instance is created on the main thread.
3. Intra-process object sharing: supported.
For details, see [Thread Model (Stage Model)](thread-model-stage.md).| +| **Application component**| 1. Component classification
![fa-model-component](figures/fa-model-component.png)
- PageAbility: has the UI and supports user interaction For details, see [PageAbility Component Overview](pageability-overview.md).
- ServiceAbility: provides background services and has no UI. For details, see [ServiceAbility Component Overview](serviceability-overview.md).
- DataAbility: provides the data sharing capability and has no UI. For details, see [DataAbility Component Overview](dataability-overview.md).
2. Development mode
Application components are specified by exporting anonymous objects and fixed entry files. You cannot perform derivation. It is inconvenient for capability expansion.| 1. Component classification
![stage-model-component](figures/stage-model-component.png)
- UIAbility: has the UI and supports user interaction. For details, see [UIAbility Component Overview](uiability-overview.md).
- ExtensionAbility: provides extension capabilities (such as widget and input methods) for specific scenarios. For details, see [ExtensionAbility Component Overview](extensionability-overview.md).
2. Development mode
The object-oriented mode is used to provide open application components as classes. You can derive application components for capability expansion.| +| **Process model**| There are two types of processes:
1. Main process
2. Rendering process
For details, see [Process Model Overview (FA Model)](process-model-fa.md). | There are three types of processes:
1. Main process
2. ExtensionAbility process
3. Rendering process
For details, see [Process Model Overview (Stage Model)](process-model-stage.md). | +| **Thread model**| 1. ArkTS engine instance creation
A process can run multiple application component instances, and each application component instance runs in an independent ArkTS engine instance.
2. Thread model
Each ArkTS engine instance is created on an independent thread (non-main thread). The main thread does not have an ArkTS engine instance.
3. Intra-process object sharing: not supported.
For details, see [Thread Model Overview (FA Model)](thread-model-fa.md). | 1. ArkTS engine instance creation
A process can run multiple application component instances, and all application component instances share one ArkTS engine instance.
2. Thread model
The ArkTS engine instance is created on the main thread.
3. Intra-process object sharing: supported.
For details, see [Thread Model Overview (Stage Model)](thread-model-stage.md). | | **Mission management model**| - A mission is created for each PageAbility component instance.
- Missions are stored persistently until the number of missions exceeds the maximum (customized based on the product configuration) or users delete missions.
- PageAbility components do not form a stack structure.
For details, see [Mission Management Scenarios](mission-management-overview.md).| - A mission is created for each UIAbility component instance.
- Missions are stored persistently until the number of missions exceeds the maximum (customized based on the product configuration) or users delete missions.
- UIAbility components do not form a stack structure.
For details, see [Mission Management Scenarios](mission-management-overview.md).| | **Application configuration file**| The **config.json** file is used to describe the application, HAP, and application component information.
For details, see [Application Configuration File Overview (FA Model)](../quick-start/application-configuration-file-overview-fa.md).| The **app.json5** file is used to describe the application information, and the **module.json5** file is used to describe the HAP and application component information.
For details, see [Application Configuration File Overview (Stage Model)](../quick-start/application-configuration-file-overview-stage.md).| diff --git a/en/application-dev/application-models/arkts-ui-widget-configuration.md b/en/application-dev/application-models/arkts-ui-widget-configuration.md new file mode 100644 index 0000000000000000000000000000000000000000..7e438ce4215a583c4ad7ccebc8cfc591b5251ad6 --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-configuration.md @@ -0,0 +1,84 @@ +# Configuring Widget Configuration Files + + +Widget-related configuration includes **FormExtensionAbility** configuration and widget configuration. + + +1. Configure FormExtensionAbility information under **extensionAbilities** in the [module.json5 file](../quick-start/module-configuration-file.md). For a FormExtensionAbility, you must specify **metadata**. Specifically, set **name** to **ohos.extension.form** (fixed), and set **resource** to the index of the widget configuration information. + + Example configuration: + + + ```json + { + "module": { + ... + "extensionAbilities": [ + { + "name": "EntryFormAbility", + "srcEntry": "./ets/entryformability/EntryFormAbility.ts", + "label": "$string:EntryFormAbility_label", + "description": "$string:EntryFormAbility_desc", + "type": "form", + "metadata": [ + { + "name": "ohos.extension.form", + "resource": "$profile:form_config" + } + ] + } + ] + } + } + ``` + +2. Configure the widget configuration information. In the **metadata** configuration item of FormExtensionAbility, you can specify the resource index of specific configuration information of the widget. For example, if resource is set to **$profile:form_config**, **form_config.json** in the **resources/base/profile/** directory of the development view is used as the profile configuration file of the widget. The following table describes the internal field structure. + + **Table 1** form_config.json file + + | Field| Description| Data Type| Default Value Allowed| + | -------- | -------- | -------- | -------- | + | name | Class name of the widget. The value is a string with a maximum of 127 bytes.| String| No| + | description | Description of the widget. The value can be a string or a resource index to descriptions in multiple languages. The value is a string with a maximum of 255 bytes.| String| Yes (initial value: left empty)| + | src | Full path of the UI code corresponding to the widget. For an ArkTS widget, the full path must contain the widget file name extension, for example, **./ets/widget/pages/WidgetCard.ets**. For a JS widget, the full path does not need to contain the widget file name extension, for example, **./js/widget/pages/WidgetCard**.| String| No| + | uiSyntax | Type of the widget.
- **arkts**: ArkTS widget
- **hml**: JS widget| String| Yes (initial value: **hml**)| + | window | Window-related configurations.| Object| Yes| + | isDefault | Whether the widget is a default one. Each UIAbility has only one default widget.
- **true**: The widget is the default one.
- **false**: The widget is not the default one.| Boolean| No| + | colorMode | Color mode of the widget.
- **auto**: auto-adaptive color mode
- **dark**: dark color mode
- **light**: light color mode| String| Yes (initial value: **auto**)| + | supportDimensions | Grid styles supported by the widget.
- **1 * 2**: indicates a grid with one row and two columns.
- **2 * 2**: indicates a grid with two rows and two columns.
- **2 * 4**: indicates a grid with two rows and four columns.
- **4 * 4**: indicates a grid with four rows and four columns.| String array| No| + | defaultDimension | Default grid style of the widget. The value must be available in the **supportDimensions** array of the widget.| String| No| + | updateEnabled | Whether the widget can be updated periodically.
- **true**: The widget can be updated at a specified interval (**updateDuration**) or at the scheduled time (**scheduledUpdateTime**). **updateDuration** takes precedence over **scheduledUpdateTime**.
- **false**: The widget cannot be updated periodically.| Boolean| No| + | scheduledUpdateTime | Scheduled time to update the widget. The value is in 24-hour format and accurate to minute.
**NOTE**
**updateDuration** takes precedence over **scheduledUpdateTime**. If both are specified, the value specified by **updateDuration** is used.| String| Yes (initial value: The widget cannot be updated periodically.)| + | updateDuration | Interval to update the widget. The value is a natural number, in the unit of 30 minutes.
If the value is **0**, this field does not take effect.
If the value is a positive integer *N*, the interval is calculated by multiplying *N* and 30 minutes.
**NOTE**
**updateDuration** takes precedence over **scheduledUpdateTime**. If both are specified, the value specified by **updateDuration** is used.| Number| Yes (initial value: **0**)| + | formConfigAbility | Link to a specific page of the application. The value is a URI.| String| Yes (initial value: left empty)| + | formVisibleNotify | Whether the widget is allowed to use the widget visibility notification.| String| Yes (initial value: left empty)| + | metadata | Metadata of the widget. This field contains the array of the **customizeData** field.| Object| Yes (initial value: left empty)| + + Example configuration: + + + ```json + { + "forms": [ + { + "name": "widget", + "description": "This is a service widget.", + "src": "./ets/widget/pages/WidgetCard.ets", + "uiSyntax": "arkts", + "window": { + "designWidth": 720, + "autoDesignWidth": true + }, + "colorMode": "auto", + "isDefault": true, + "updateEnabled": true, + "scheduledUpdateTime": "10:30", + "updateDuration": 1, + "defaultDimension": "2*2", + "supportDimensions": [ + "2*2" + ] + } + ] + } + ``` diff --git a/en/application-dev/application-models/arkts-ui-widget-content-update.md b/en/application-dev/application-models/arkts-ui-widget-content-update.md new file mode 100644 index 0000000000000000000000000000000000000000..c0f4c840b6c11b497405ce8777a04317b5ffca4d --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-content-update.md @@ -0,0 +1,30 @@ +# Updating Widget Content by Widget Host (for System Applications Only) + + +Widgets that are updated periodically are subject to the scheduled time or interval settings. To offer more flexible updates, the widget host can provide a button to proactively trigger a widget update. Specifically, the widget host calls the [requestForm](../reference/apis/js-apis-app-form-formHost.md#requestform) API to request a widget update. The system then calls the [onUpdateForm](../reference/apis/js-apis-app-form-formExtensionAbility.md#onupdateform) lifecycle callback in the FormExtensionAbility of the widget provider. In the callback, the [updateForm](../reference/apis/js-apis-app-form-formProvider.md#updateform) API can be used to update the widget content. For details about the **onUpdateForm** lifecycle callback, see [Updating Widget Content Through FormExtensionAbility](arkts-ui-widget-event-formextensionability.md). + +```ts +import formHost from '@ohos.app.form.formHost'; + +@Entry() +@Component +struct WidgetCard { + formId = ...; // Widget ID + + build() { + Button (`Update Widget`) + .type(ButtonType.Capsule) + .width('50%') + .height(50) + .onClick(() => { + console.info('FormAbility update form click'); + // formId is the ID of the widget to be updated. + formHost.requestForm(this.formId.toString()).then(() => { + console.info('Succeeded in requestForming.'); + }); + }) + + ... + } +} +``` diff --git a/en/application-dev/application-models/arkts-ui-widget-creation.md b/en/application-dev/application-models/arkts-ui-widget-creation.md new file mode 100644 index 0000000000000000000000000000000000000000..cc8843c0294cf745e7737164e46cb8f69256efa2 --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-creation.md @@ -0,0 +1,19 @@ +# Creating an ArkTS Widget + +To create an ArkTS widget in an existing application project, perform the following steps: + +1. Create a widget. + + ![WidgetProjectCreate1](figures/WidgetProjectCreate1.png) + +2. Select a widget template based on the actual service scenario. + + ![WidgetProjectCreate2](figures/WidgetProjectCreate2.png) + +3. Set **Language** to **ArkTS** and click **Finish**. + + ![WidgetProjectCreate3](figures/WidgetProjectCreate3.png) + +After an ArkTS widget is created, the following widget-related files are added to the project directory: **EntryFormAbility.ts** (widget lifecycle management file), **WidgetCard.ets** (widget page file), and **form_config.json** (widget configuration file). + +![WidgetProjectView](figures/WidgetProjectView.png) diff --git a/en/application-dev/application-models/arkts-ui-widget-event-call.md b/en/application-dev/application-models/arkts-ui-widget-event-call.md new file mode 100644 index 0000000000000000000000000000000000000000..69189afb06c941158047462015519499961c9b95 --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-event-call.md @@ -0,0 +1,91 @@ +# Launching a UIAbility in the Background Through the call Event + + +There may be cases you want to provide in a widget access to features available in your application running in the foreground, for example, the play, pause, and stop buttons in a music application widget. This is where the **call** capability of the **postCardAction** API comes in handy. This capability, when used in a widget, can start the specified UIAbility of the widget provider in the background. It also allows the widget to call the specified method of the application and transfer data so that the application, while in the background, can behave accordingly in response to touching of the buttons on the widget. + + +Typically, the call event is triggered for touching of buttons. Below is an example. + + +- In this example, two buttons are laid out on the widget page. When one button is clicked, the **postCardAction** API is called to send a call event to the target UIAbility. Note that the **method** parameter in the API indicates the method to call in the target UIAbility. It is mandatory and of the string type. + + ```ts + @Entry + @Component + struct WidgetCard { + build() { + Column() { + Button ('Feature A') + .margin('20%') + .onClick(() => { + console.info('call EntryAbility funA'); + postCardAction(this, { + 'action': 'call', + 'abilityName': 'EntryAbility', // Only the UIAbility of the current application is allowed. + 'params': { + 'method': 'funA' // Set the name of the method to call in the EntryAbility. + } + }); + }) + + Button ('Feature B') + .margin('20%') + .onClick(() => { + console.info('call EntryAbility funB'); + postCardAction(this, { + 'action': 'call', + 'abilityName': 'EntryAbility', // Only the UIAbility of the current application is allowed. + 'params': { + 'method': 'funB', // Set the name of the method to call in the EntryAbility. + 'num': 1 // Set other parameters to be passed in. + } + }); + }) + } + .width('100%') + .height('100%') + } + } + ``` + +- The UIAbility receives the call event and obtains the transferred parameters. It then executes the target method specified by the **method** parameter. Other data can be obtained in readString mode. Listen for the method required by the call event in the **onCreate** callback of the UIAbility. + + ```ts + import UIAbility from '@ohos.app.ability.UIAbility'; + + function FunACall(data) { + // Obtain all parameters passed in the call event. + console.info('FunACall param:' + JSON.stringify(data.readString())); + return null; + } + + function FunBCall(data) { + console.info('FunBCall param:' + JSON.stringify(data.readString())); + return null; + } + + export default class CameraAbility extends UIAbility { + // If the UIAbility is started for the first time, onCreate is triggered afte the call event is received. + onCreate(want, launchParam) { + try { + // Listen for the method required by the call event. + this.callee.on('funA', FunACall); + this.callee.on('funB', FunBCall); + } catch (err) { + console.error(`Failed to register callee on. Cause: ${JSON.stringify(err)}`); + } + } + + ... + + // Deregister the listener when the process exits. + onDestroy() { + try { + this.callee.off('funA'); + this.callee.off('funB'); + } catch (err) { + console.error(`Failed to register callee off. Cause: ${JSON.stringify(err)}`); + } + } + }; + ``` diff --git a/en/application-dev/application-models/arkts-ui-widget-event-formextensionability.md b/en/application-dev/application-models/arkts-ui-widget-event-formextensionability.md new file mode 100644 index 0000000000000000000000000000000000000000..be7761d8d78da5102afadd2c37043c228dfcd53e --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-event-formextensionability.md @@ -0,0 +1,66 @@ +# Updating Widget Content Through the message Event + + +On the widget page, the **postCardAction** API can be used to trigger a message event to start a FormExtensionAbility, which then updates the widget content. The following is an example of this widget update mode. + + +- On the widget page, register the **onClick** event callback of the button and call the **postCardAction** API in the callback to trigger the event to the FormExtensionAbility. + + ```ts + let storage = new LocalStorage(); + @Entry(storage) + @Component + struct WidgetCard { + @LocalStorageProp('title') title: string = 'init'; + @LocalStorageProp('detail') detail: string = 'init'; + + build() { + Column() { + Button ('Update') + .onClick(() => { + postCardAction(this, { + 'action': 'message', + 'params': { + 'msgTest': 'messageEvent' + } + }); + }) + Text(`${this.title}`) + Text(`${this.detail}`) + } + .width('100%') + .height('100%') + } + } + ``` + +- Call the [updateForm](../reference/apis/js-apis-app-form-formProvider.md#updateform) API to update the widget in the **onFormEvent** callback of the FormExtensionAbility. + + ```ts + import formBindingData from '@ohos.app.form.formBindingData'; + import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility'; + import formProvider from '@ohos.app.form.formProvider'; + + export default class EntryFormAbility extends FormExtensionAbility { + onFormEvent(formId, message) { + // Called when a specified message event defined by the form provider is triggered. + console.info(`FormAbility onEvent, formId = ${formId}, message: ${JSON.stringify(message)}`); + let formData = { + 'title':'Title Update Success.', // Matches the widget layout. + 'detail':'Detail Update Success.', // Matches the widget layout. + }; + let formInfo = formBindingData.createFormBindingData(formData) + formProvider.updateForm(formId, formInfo).then((data) => { + console.info('FormAbility updateForm success.' + JSON.stringify(data)); + }).catch((error) => { + console.error('FormAbility updateForm failed: ' + JSON.stringify(error)); + }) + } + + ... + } + ``` + + The figure below shows the effect. + + ![WidgetUpdatePage](figures/WidgetUpdatePage.png) diff --git a/en/application-dev/application-models/arkts-ui-widget-event-overview.md b/en/application-dev/application-models/arkts-ui-widget-event-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..299a279c9117dad71e6fea658bb8da3298ed8f05 --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-event-overview.md @@ -0,0 +1,63 @@ +# Widget Event Capability Overview + +The ArkTS widget provides the **postCardAction()** API for interaction between the widget internal and the widget provider. Currently, this API supports the router, message, and call events and can be called only in the widget. + +![WidgetPostCardAction](figures/WidgetPostCardAction.png) + +**Definition**: postCardAction(component: Object, action: Object): void + +**Parameters** + + +| Name| Type| Mandatory| Description| +| -------- | -------- | -------- | -------- | +| component | Object | Yes| Instance of the current custom component. Generally, **this** is passed in.| +| action | Object | Yes| Action description. For details, see the following table.| + +**Description of the action parameter** + + +| Key | Value | Description| +| -------- | -------- | -------- | +| "action" | string | Action type.
- **"router"**: redirection to the specified UIAbility of the widget provider.
- **"message"**: custom message. If this type of action is triggered, the [onFormEvent()](../reference/apis/js-apis-app-form-formExtensionAbility.md#onformevent) lifecycle callback of the provider FormExtensionAbility is called.
- **"call"**: launch of the widget provider in the background. If this type of action is triggered, the specified UIAbility (whose [launch type](uiability-launch-type.md) must be singleton) of the widget provider is started in the background, but not displayed in the foreground. This action type requires that the widget provider should have the [ohos.permission.KEEP_BACKGROUND_RUNNING](../security/permission-list.md#ohospermissionkeep_background_running) permission.| +| "bundleName" | string | Name of the target bundle when **action** is **"router"** or **"call"**. This parameter is optional.| +| "moduleName" | string | Name of the target module when **action** is **"router"** or **"call"**. This parameter is optional.| +| "abilityName" | string | Name of the target UIAbility when **action** is **"router"** or **"call"**. This parameter is mandatory.| +| "params" | Object | Additional parameters carried in the current action. The value is a key-value pair in JSON format. For the **"call"** action type, the **method** parameter (mandatory) must be set and its value type must be string.| + + +Sample code of the **postCardAction()** API: + +```typescript +Button ('Redirect') + .width('40%') + .height('20%') + .onClick(() => { + postCardAction(this, { + 'action': 'router', + 'bundleName': 'com.example.myapplication', + 'abilityName': 'EntryAbility', + 'params': { + 'message': 'testForRouter' // Customize the message to send. + } + }); + }) + +Button ('Start in Background') + .width('40%') + .height('20%') + .onClick(() => { + postCardAction(this, { + 'action': 'call', + 'bundleName': 'com.example.myapplication', + 'abilityName': 'EntryAbility', + 'params': { + 'method': 'fun', // Set the name of the method to call. It is mandatory. + 'message': 'testForCall' // Customize the message to send. + } + }); + }) +``` + + +Read on to learn the typical widget development scenarios that can be implemented through widget events. diff --git a/en/application-dev/application-models/arkts-ui-widget-event-router.md b/en/application-dev/application-models/arkts-ui-widget-event-router.md new file mode 100644 index 0000000000000000000000000000000000000000..733ff7f59b57ec4295fa21cb4d83ae8a5b2b8eb4 --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-event-router.md @@ -0,0 +1,108 @@ +# Redirecting to a UIAbility Through the router Event + +The **router** capability of the **postCardAction** API can be used in a widget to quickly start a specific UIAbility of the widget provider. By leveraging this capability, an application can provide in the widget multiple buttons, each of which targets a different target UIAbility. For example, a camera widget can provide the buttons that redirect the user to the UIAbility for taking a photo and the UIAbility for recording a video. + +![WidgerCameraCard](figures/WidgerCameraCard.png) + + +Generally, a button is used to start a page. + + +- Design two buttons on the widget page. When one of the buttons is clicked, **postCardAction** is called to send a router event to the specified UIAbility, with the content to be transferred defined in the event. + + ```ts + @Entry + @Component + struct WidgetCard { + build() { + Column() { + Button ('Function A') + .margin('20%') + .onClick(() => { + console.info('Jump to EntryAbility funA'); + postCardAction(this, { + 'action': 'router', + 'abilityName': 'EntryAbility', // Only the UIAbility of the current application is allowed. + 'params': { + 'targetPage': 'funA' // Process the information in the EntryAbility. + } + }); + }) + + Button ('Function B') + .margin('20%') + .onClick(() => { + console.info('Jump to EntryAbility funB'); + postCardAction(this, { + 'action': 'router', + 'abilityName': 'EntryAbility', // Only the UIAbility of the current application is allowed. + 'params': { + 'targetPage': 'funB' // Process the information in the EntryAbility. + } + }); + }) + } + .width('100%') + .height('100%') + } + } + ``` + +- The UIAbility receives the router event and obtains parameters. It then starts the page specified in the received message. + + ```ts + import UIAbility from '@ohos.app.ability.UIAbility'; + import window from '@ohos.window'; + + let selectPage = ""; + let currentWindowStage = null; + + export default class CameraAbility extends UIAbility { + // If the UIAbility is started for the first time, the onCreate lifecycle callback is triggered after the router event is received. + onCreate(want, launchParam) { + // Obtain the targetPage parameter passed in the router event. + console.info("onCreate want:" + JSON.stringify(want)); + if (want.parameters.params !== undefined) { + let params = JSON.parse(want.parameters.params); + console.info("onCreate router targetPage:" + params.targetPage); + selectPage = params.targetPage; + } + } + // If the UIAbility is running in the background, the onNewWant lifecycle callback is triggered after the router event is received. + onNewWant(want, launchParam) { + console.info("onNewWant want:" + JSON.stringify(want)); + if (want.parameters.params !== undefined) { + let params = JSON.parse(want.parameters.params); + console.info("onNewWant router targetPage:" + params.targetPage); + selectPage = params.targetPage; + } + if (currentWindowStage != null) { + this.onWindowStageCreate(currentWindowStage); + } + } + + onWindowStageCreate(windowStage: window.WindowStage) { + let targetPage; + // Start the page specified by targetPage. + switch (selectPage) { + case 'funA': + targetPage = 'pages/FunA'; + break; + case 'funB': + targetPage = 'pages/FunB'; + break; + default: + targetPage = 'pages/Index'; + } + if (currentWindowStage === null) { + currentWindowStage = windowStage; + } + windowStage.loadContent(targetPage, (err, data) => { + if (err && err.code) { + console.info('Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + }); + } + }; + ``` diff --git a/en/application-dev/application-models/arkts-ui-widget-event-uiability.md b/en/application-dev/application-models/arkts-ui-widget-event-uiability.md new file mode 100644 index 0000000000000000000000000000000000000000..17a211188704609e5bc60dcbcf6b058a8a8a0dbe --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-event-uiability.md @@ -0,0 +1,187 @@ +# Updating Widget Content Through the router or call Event + + +On the widget page, the **postCardAction** API can be used to trigger a router or call event to start a UIAbility, which then updates the widget content. The following is an example of this widget update mode. + +## Updating Widget Content Through the router Event + +- On the widget page, register the **onClick** event callback of the button and call the **postCardAction** API in the callback to trigger the router event to the FormExtensionAbility. + + ```ts + let storage = new LocalStorage(); + @Entry(storage) + @Component + struct WidgetCard { + @LocalStorageProp('detail') detail: string = 'init'; + + build() { + Column() { + Button ('Redirect') + .margin('20%') + .onClick(() => { + console.info('postCardAction to EntryAbility'); + postCardAction(this, { + 'action': 'router', + 'abilityName': 'EntryAbility', // Only the UIAbility of the current application is allowed. + 'params': { + 'detail': 'RouterFromCard' + } + }); + }) + Text(`${this.detail}`).margin('20%') + } + .width('100%') + .height('100%') + } + } + ``` + +- In the **onCreate()** or **onNewWant()** lifecycle callback of the UIAbility, use the input parameter **want** to obtain the ID (**formID**) and other information of the widget, and then call the [updateForm](../reference/apis/js-apis-app-form-formProvider.md#updateform) API to update the widget. + + ```ts + import UIAbility from '@ohos.app.ability.UIAbility'; + import formBindingData from '@ohos.app.form.formBindingData'; + import formProvider from '@ohos.app.form.formProvider'; + import formInfo from '@ohos.app.form.formInfo'; + + export default class EntryAbility extends UIAbility { + // If the UIAbility is started for the first time, onCreate is triggered after the router event is received. + onCreate(want, launchParam) { + console.info('Want:' + JSON.stringify(want)); + if (want.parameters[formInfo.FormParam.IDENTITY_KEY] !== undefined) { + let curFormId = want.parameters[formInfo.FormParam.IDENTITY_KEY]; + let message = JSON.parse(want.parameters.params).detail; + console.info(`UpdateForm formId: ${curFormId}, message: ${message}`); + let formData = { + "detail": message +': onCreate UIAbility.', // Matches the widget layout. + }; + let formMsg = formBindingData.createFormBindingData(formData) + formProvider.updateForm(curFormId, formMsg).then((data) => { + console.info('updateForm success.' + JSON.stringify(data)); + }).catch((error) => { + console.error('updateForm failed:' + JSON.stringify(error)); + }) + } + } + // If the UIAbility is running in the background, onNewWant is triggered after the router event is received. + onNewWant(want, launchParam) { + console.info('onNewWant Want:' + JSON.stringify(want)); + if (want.parameters[formInfo.FormParam.IDENTITY_KEY] !== undefined) { + let curFormId = want.parameters[formInfo.FormParam.IDENTITY_KEY]; + let message = JSON.parse(want.parameters.params).detail; + console.info(`UpdateForm formId: ${curFormId}, message: ${message}`); + let formData = { + "detail": message +': onNewWant UIAbility.', // Matches the widget layout. + }; + let formMsg = formBindingData.createFormBindingData(formData) + formProvider.updateForm(curFormId, formMsg).then((data) => { + console.info('updateForm success.' + JSON.stringify(data)); + }).catch((error) => { + console.error('updateForm failed:' + JSON.stringify(error)); + }) + } + } + + ... + } + ``` + +## Updating Widget Content Through the call Event + +- When using the call event of the **postCardAction** API, the value of **formId** must be updated in the **onAddForm** callback of the FormExtensionAbility. + + ```ts + import formBindingData from '@ohos.app.form.formBindingData'; + import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility'; + + export default class EntryFormAbility extends FormExtensionAbility { + onAddForm(want) { + let formId = want.parameters["ohos.extra.param.key.form_identity"]; + let dataObj1 = { + "formId": formId + }; + let obj1 = formBindingData.createFormBindingData(dataObj1); + return obj1; + } + + ... + }; + ``` + +- On the widget page, register the **onClick** event callback of the button and call the **postCardAction** API in the callback to trigger the event to the UIAbility. + + ```ts + let storage = new LocalStorage(); + @Entry(storage) + @Component + struct WidgetCard { + @LocalStorageProp('detail') detail: string = 'init'; + @LocalStorageProp('formId') formId: string = '0'; + + build() { + Column() { + Button ('Start in Background') + .margin('20%') + .onClick(() => { + console.info('postCardAction to EntryAbility'); + postCardAction(this, { + 'action': 'call', + 'abilityName': 'EntryAbility', // Only the UIAbility of the current application is allowed. + 'params': { + 'method': 'funA', + 'formId': this.formId, + 'detail': 'CallFromCard' + } + }); + }) + Text(`${this.detail}`).margin('20%') + } + .width('100%') + .height('100%') + } + } + ``` + +- Listen for the method required by the call event in the **onCreate** callback of the UIAbility, and then call the [updateForm](../reference/apis/js-apis-app-form-formProvider.md#updateform) API in the corresponding method to update the widget. + + ```ts + import UIAbility from '@ohos.app.ability.UIAbility'; + import formBindingData from '@ohos.app.form.formBindingData'; + import formProvider from '@ohos.app.form.formProvider'; + + const MSG_SEND_METHOD: string = 'funA'; + + // After the call event is received, the method listened for by the callee is triggered. + function FunACall(data) { + // Obtain all parameters transferred in the call event. + let params = JSON.parse(data.readString()) + if (params.formId !== undefined) { + let curFormId = params.formId; + let message = params.detail; + console.info(`UpdateForm formId: ${curFormId}, message: ${message}`); + let formData = { + "detail": message + }; + let formMsg = formBindingData.createFormBindingData(formData) + formProvider.updateForm(curFormId, formMsg).then((data) => { + console.info('updateForm success.' + JSON.stringify(data)); + }).catch((error) => { + console.error('updateForm failed:' + JSON.stringify(error)); + }) + } + return null; + } + export default class EntryAbility extends UIAbility { + // If the UIAbility is started for the first time, onCreate is triggered after the call event is received. + onCreate(want, launchParam) { + console.info('Want:' + JSON.stringify(want)); + try { + // Listen for the method required by the call event. + this.callee.on(MSG_SEND_METHOD, FunACall); + } catch (error) { + console.info(`${MSG_SEND_METHOD} register failed with error ${JSON.stringify(error)}`) + } + } + ... + } + ``` diff --git a/en/application-dev/application-models/arkts-ui-widget-image-update.md b/en/application-dev/application-models/arkts-ui-widget-image-update.md new file mode 100644 index 0000000000000000000000000000000000000000..dfe6dbf0e9249c66c3fb1d0723f1c7b296443381 --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-image-update.md @@ -0,0 +1,166 @@ +# Updating Local and Online Images in the Widget + + +Typically, a widget includes local images or online images downloaded from the network. To obtain local and online images, use the FormExtensionAbility. The following exemplifies how to show local and online images on a widget. + + +1. For the widget to download online images, declare the **ohos.permission.INTERNET** permission for the widget. For details, see [Declaring Permissions in the Configuration File](../security/accesstoken-guidelines.md). + +2. Update local files in the **onAddForm** lifecycle callback of the EntryFormAbility. + + ```ts + import formBindingData from '@ohos.app.form.formBindingData'; + import formProvider from '@ohos.app.form.formProvider'; + import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility'; + import request from '@ohos.request'; + import fs from '@ohos.file.fs'; + + export default class EntryFormAbility extends FormExtensionAbility { + ... + // When the widget is added, a local image is opened and transferred to the widget page for display. + onAddForm(want) { + // Assume that the local image head.PNG is in the tmp directory of the current widget. + let tempDir = this.context.getApplicationContext().tempDir; + // Open the local image and obtain the FD after the image is opened. + let file; + try { + file = fs.openSync(tempDir + '/' + 'head.PNG'); + } catch (e) { + console.error(`openSync failed: ${JSON.stringify(e)}`); + } + let formData = { + 'text': 'Image: Bear', + 'imgName': 'imgBear', + 'formImages': { + 'imgBear': file.fd + }, + 'loaded': true + } + // Encapsulate the FD in formData and return it to the widget page. + return formBindingData.createFormBindingData(formData); + } + + ... + } + ``` + +3. Update online images in the **onFormEvent** lifecycle callback of the EntryFormAbility. + + ```ts + import formBindingData from '@ohos.app.form.formBindingData'; + import formProvider from '@ohos.app.form.formProvider'; + import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility'; + import request from '@ohos.request'; + import fs from '@ohos.file.fs'; + + export default class EntryFormAbility extends FormExtensionAbility { + // When the message event is triggered on the widget page, an online image is downloaded and transferred to the widget page for display. + onFormEvent(formId, message) { + let formInfo = formBindingData.createFormBindingData({ + 'text': 'Updating...' + }) + formProvider.updateForm(formId, formInfo) + // Note: After being started with the triggering of the lifecycle callback, the FormExtensionAbility can run in the background for only 5 seconds. + // When possible, limit the size of the image to download. If an image cannot be downloaded within 5 seconds, it will not be updated to the widget page. + let netFile = 'https://xxxx/xxxx.png'; // Specify the URL of the image to download. + let tempDir = this.context.getApplicationContext().tempDir; + let fileName = 'file' + Date.now(); + let tmpFile = tempDir + '/' + fileName; + request.downloadFile(this.context, { + url: netFile, filePath: tmpFile, enableMetered: true, enableRoaming: true + }).then((task) => { + task.on('complete', function callback() { + console.info('ArkTSCard download complete:' + tmpFile); + let file; + try { + file = fs.openSync(tmpFile); + } catch (e) { + console.error(`openSync failed: ${JSON.stringify(e)}`); + } + let fileInfo = {}; + fileInfo[fileName] = file.fd; + let formData = { + 'text': 'Image:' + fileName, + 'imgName': fileName, + 'formImages': fileInfo, + 'loaded': true + }; + let formInfo = formBindingData.createFormBindingData(formData) + formProvider.updateForm(formId, formInfo).then((data) => { + console.info('FormAbility updateForm success.' + JSON.stringify(data)); + }).catch((error) => { + console.error('FormAbility updateForm failed: ' + JSON.stringify(error)); + }) + }) + task.on('fail', function callBack(err) { + console.info('ArkTSCard download task failed. Cause:' + err); + let formInfo = formBindingData.createFormBindingData({ + 'text':'Update failed.' + }) + formProvider.updateForm(formId, formInfo) + }); + }).catch((err) => { + console.error('Failed to request the download. Cause: ' + JSON.stringify(err)); + }); + } + + ... + }; + ``` + +4. On the widget page, use the **\** component to display the widget content transferred from the EntryFormAbility. + + ```ts + let storage = new LocalStorage(); + @Entry(storage) + @Component + struct WidgetCard { + @LocalStorageProp('text') text: string = 'Loading...'; + @LocalStorageProp('loaded') loaded: boolean = false; + @LocalStorageProp('imgName') imgName: string = 'name'; + + build() { + Column() { + Text(this.text) + .fontSize('12vp') + .textAlign(TextAlign.Center) + .width('100%') + .height('15%') + + Row() { + if (this.loaded) { + Image('memory://' + this.imgName) + .width('50%') + .height('50%') + .margin('5%') + } else { + Image('common/start.PNG') + .width('50%') + .height('50%') + .margin('5%') + } + }.alignItems(VerticalAlign.Center) + .justifyContent(FlexAlign.Center) + + Button ('Update') + .height('15%') + .onClick(() => { + postCardAction(this, { + 'action': 'message', + 'params': { + 'info': 'refreshImage' + } + }); + }) + } + .width('100%').height('100%') + .alignItems(HorizontalAlign.Center) + .padding('5%') + } + } + ``` + +> **NOTE** +> - The **\** component displays images in the remote memory based on the **memory://** identifier in the input parameter (**memory://fileName**). The value of **fileName** must be consistent with the key in the object (**'formImages': {key: fd}**) passed by the EntryFormAbility. +> +> - The **\** component determines whether to update the image by comparing the values of **imgName** consecutively passed by the EntryFormAbility. It updates the image only when the values are different. diff --git a/en/application-dev/application-models/arkts-ui-widget-interaction-overview.md b/en/application-dev/application-models/arkts-ui-widget-interaction-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..76c4a202543c00f3df44f71b0a33d417831b5f53 --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-interaction-overview.md @@ -0,0 +1,20 @@ +# Widget Data Interaction + + +The ArkTS widget framework provides the **updateForm()** and **requestForm()** APIs to proactively trigger widget updates. + + +![WidgetLocalStorageProp](figures/WidgetLocalStorageProp.png) + + +| API| System Capability| Constraints| +| -------- | -------- | -------- | +| updateForm | No| 1. Invoked by the provider.
2. Allows only the widget provider to update its own widgets. It cannot be used to update widgets by other providers.| +| requestForm | Yes| 1. Invoked by the host.
2. Allows only the widget host to update the widgets added to it. It cannot be used to update widgets added to other hosts.| + +The following describes the typical use cases of widget updates: + +- [Configuring a Widget to Update Periodically](arkts-ui-widget-update-by-time.md) +- [Updating Local and Online Images](arkts-ui-widget-image-update.md) +- [Updating Widget Content by State](arkts-ui-widget-update-by-status.md) +- [Updating Widget Content by Widget Host (for System Applications Only)](arkts-ui-widget-content-update.md) diff --git a/en/application-dev/application-models/arkts-ui-widget-lifecycle.md b/en/application-dev/application-models/arkts-ui-widget-lifecycle.md new file mode 100644 index 0000000000000000000000000000000000000000..fb25fd362f67646d65853b870a6a9cb518c4d760 --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-lifecycle.md @@ -0,0 +1,96 @@ +# Widget Lifecycle Management + + +When creating an ArkTS widget, you need to implement the [FormExtensionAbility](../reference/apis/js-apis-app-form-formExtensionAbility.md) lifecycle APIs. + + +1. Import related modules to **EntryFormAbility.ts**. + + ```ts + import formInfo from '@ohos.app.form.formInfo'; + import formBindingData from '@ohos.app.form.formBindingData'; + import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility'; + import formProvider from '@ohos.app.form.formProvider'; + ``` + +2. In **EntryFormAbility.ts**, implement the [FormExtensionAbility](../reference/apis/js-apis-app-form-formExtensionAbility.md) lifecycle APIs, including **onAddForm**, whose **want** parameter can be used to obtain the widget information through [FormParam](../reference/apis/js-apis-app-form-formInfo.md#formparam). + + ```typescript + import formInfo from '@ohos.app.form.formInfo'; + import formBindingData from '@ohos.app.form.formBindingData'; + import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility'; + import formProvider from '@ohos.app.form.formProvider'; + + export default class EntryFormAbility extends FormExtensionAbility { + onAddForm(want) { + console.info('[EntryFormAbility] onAddForm'); + // Obtain the unique widget ID formId from the want parameter. + let formId: string = want.parameters[formInfo.FormParam.IDENTITY_KEY]; + // Called when the widget is created. The widget provider should return the widget data binding class. + let obj = { + 'title': 'titleOnAddForm', + 'detail': 'detailOnAddForm' + }; + let formData = formBindingData.createFormBindingData(obj); + return formData; + } + + onCastToNormalForm(formId) { + // Called when the form provider is notified that a temporary form is successfully + // converted to a normal form. + // Called when the widget host converts the temporary widget into a normal one. The widget provider should do something to respond to the conversion. + console.info(`[EntryFormAbility] onCastToNormalForm, formId: ${formId}`); + } + + onUpdateForm(formId) { + // Override this method to support scheduled updates, periodic updates, or updates requested by the widget host. + console.info('[EntryFormAbility] onUpdateForm'); + let obj = { + 'title': 'titleOnUpdateForm', + 'detail': 'detailOnUpdateForm' + }; + let formData = formBindingData.createFormBindingData(obj); + formProvider.updateForm(formId, formData).catch((err) => { + if (err) { + // Print errors. + console.error(`[EntryFormAbility] Failed to updateForm. Code: ${err.code}, message: ${err.message}`); + return; + } + }); + } + + onChangeFormVisibility(newStatus) { + // Called when the form provider receives form events from the system. + // The callback is performed only when formVisibleNotify is set to true and the application is a system application. + console.info('[EntryFormAbility] onChangeFormVisibility'); + } + + onFormEvent(formId, message) { + // Called when a specified message event defined by the form provider is triggered. + // If the widget supports event triggering, override this method and implement the trigger. + console.info('[EntryFormAbility] onFormEvent'); + } + + onRemoveForm(formId) { + // Called to notify the form provider that a specified form has been destroyed. + // Called when the corresponding widget is deleted. The input parameter is the ID of the deleted card. + console.info('[EntryFormAbility] onRemoveForm'); + } + + onConfigurationUpdate(config) { + // Called when the system configuration is updated. + console.info('[EntryFormAbility] configurationUpdate:' + JSON.stringify(config)); + } + + onAcquireFormState(want) { + // Called to return a {@link FormState} object. + // Called when the widget provider receives the status query result of a widget. By default, the initial state of the widget is returned. + return formInfo.FormState.READY; + } + } + ``` + + +> **NOTE** +> +> The FormExtensionAbility cannot reside in the background. It persists for 5 seconds after the lifecycle callback is completed and exist if no new lifecycle callback is invoked during this time frame. This means that continuous tasks cannot be processed in the widget lifecycle callbacks. For the service logic that may take more than 5 seconds to complete, it is recommended that you [start the application](arkts-ui-widget-event-uiability.md) for processing. After the processing is complete, use [updateForm()](../reference/apis/js-apis-app-form-formProvider.md#updateform) to notify the widget of the update. diff --git a/en/application-dev/application-models/arkts-ui-widget-modules.md b/en/application-dev/application-models/arkts-ui-widget-modules.md new file mode 100644 index 0000000000000000000000000000000000000000..b9a411426db84a4c1af12e70eab956adc8f25806 --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-modules.md @@ -0,0 +1,24 @@ +# ArkTS Widget Related Modules + +**Figure 1** ArkTS widget related modules + +![WidgetModules](figures/WidgetModules.png) + + +- [FormExtensionAbility](../reference/apis/js-apis-app-form-formExtensionAbility.md): provides lifecycle callbacks invoked when a widget is created, destroyed, or updated. + +- [FormExtensionContext](../reference/apis/js-apis-inner-application-formExtensionContext.md): provides context for FormExtensionAbilities. You can use the APIs of this module to start FormExtensionAbilities. + +- [formProvider](../reference/apis/js-apis-app-form-formProvider.md): provides APIs related to the widget provider. You can use the APIs to update a widget, set the next update time for a widget, obtain widget information, and request a widget release. + +- [formInfo](../reference/apis/js-apis-app-form-formInfo.md): provides types and enums related to the widget information and state. + +- [formBindingData](../reference/apis/js-apis-app-form-formBindingData.md): provides APIs for widget data binding. You can use the APIs to create a **FormBindingData** object and obtain related information. + +- [Page layout (Card.ets)](arkts-ui-widget-page-overview.md): provides APIs for a declarative paradigm UI. + - [Capabilities exclusive to ArkTS widgets](arkts-ui-widget-event-overview.md): include the **postCardAction** API used for interaction between the widget internal and the provider application and can be called only in the widget. + - [ArkTS widget capability list](arkts-ui-widget-page-overview.md#page-capabilities-supported-by-arkts-widgets): contain the APIs, components, events, attributes, and lifecycle callbacks that can be used in ArkTS widgets. + +- [Widget configuration](arkts-ui-widget-configuration.md): includes FormExtensionAbility configuration and widget configuration. + - Configure the FormExtensionAbility information under **extensionAbilities** in the [module.json5 file](../quick-start/module-configuration-file.md). + - Configure the widget configuration information (**WidgetCard.ets**) in the [form_config.json](arkts-ui-widget-configuration.md) file in **resources/base/profile**. diff --git a/en/application-dev/application-models/arkts-ui-widget-page-animation.md b/en/application-dev/application-models/arkts-ui-widget-page-animation.md new file mode 100644 index 0000000000000000000000000000000000000000..0cb8e356c61155d367e55c0f39bbf491d03e2e12 --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-page-animation.md @@ -0,0 +1,41 @@ +# Using Animations in the Widget + + +To make your ArkTS widget more engaging, you can apply animations to it, including [explicit animation](../reference/arkui-ts/ts-explicit-animation.md), [attribute animation](../reference/arkui-ts/ts-animatorproperty.md), and [component transition](../reference/arkui-ts/ts-transition-animation-component.md). Just note the following restrictions when using the animations in ArkTS widgets. + + +**Table 1** Restrictions on animation parameters + +| Name| Description| Description| +| -------- | -------- | -------- | +| duration | Animation playback duration| The maximum value is 1 second. If a larger value is set, the animation is still played for 1 second.| +| tempo | Animation playback speed.| Do not set this parameter in the widget. Use the default value 1.| +| delay | Animation delay duration.| Do not set this parameter in the widget. Use the default value 0.| +| iterations | Number of times that the animation is played.| Do not set this parameter in the widget. Use the default value 1.| + +The following sample code implements the animation effect of button rotation: + +![WidgetAnimation](figures/WidgetAnimation.gif) + +```ts +@Entry +@Component +struct AttrAnimationExample { + @State rotateAngle: number = 0; + + build() { + Column() { + Button('change rotate angle') + .onClick(() => { + this.rotateAngle = 90; + }) + .margin(50) + .rotate({ angle: this.rotateAngle }) + .animation({ + curve: Curve.EaseOut, + playMode: PlayMode.AlternateReverse + }) + }.width('100%').margin({ top: 20 }) + } +} +``` diff --git a/en/application-dev/application-models/arkts-ui-widget-page-custom-drawing.md b/en/application-dev/application-models/arkts-ui-widget-page-custom-drawing.md new file mode 100644 index 0000000000000000000000000000000000000000..3fb83498972a425ef11821c3292a74bbdb81016d --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-page-custom-drawing.md @@ -0,0 +1,90 @@ +# Applying Custom Drawing in the Widget + + +You can apply custom drawing in your ArkTS widget to create a more vibrant experience. Use the [\](../reference/arkui-ts/ts-components-canvas-canvas.md) component to create a canvas on the widget, and then use the [CanvasRenderingContext2D](../reference/arkui-ts/ts-canvasrenderingcontext2d.md) object to draw custom graphics on the canvas. The following code snippet draws a smiling face in the center of a canvas. + +```ts +@Entry +@Component +struct WidgetCard { + private canvasWidth: number = 0; + private canvasHeight: number = 0; + // Initialize CanvasRenderingContext2D and RenderingContextSettings. + private settings: RenderingContextSettings = new RenderingContextSettings(true); + private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); + + build() { + Column() { + Row() { + Canvas(this.context) + .margin('5%') + .width('90%') + .height('90%') + .onReady(() => { + console.info('[ArkTSCard] onReady for canvas draw content'); + // Obtain the actual width and height of the canvas in the onReady callback. + this.canvasWidth = this.context.width; + this.canvasHeight = this.context.height; + // Draw the background of the canvas. + this.context.fillStyle = '#EEF0FF'; + this.context.fillRect(0, 0, this.canvasWidth, this.canvasHeight); + // Draw a circle in the center of the canvas. + this.context.beginPath(); + let radius = this.context.width / 3; + let circleX = this.context.width / 2; + let circleY = this.context.height / 2; + this.context.moveTo(circleX - radius, circleY); + this.context.arc(circleX, circleY, radius, 2 * Math.PI, 0, true); + this.context.closePath(); + this.context.fillStyle = '#5A5FFF'; + this.context.fill(); + // Draw the left eye of the smiling face. + let leftR = radius / 13; + let leftX = circleX - (radius / 2.3); + let leftY = circleY - (radius / 4.5); + this.context.beginPath(); + this.context.arc(leftX, leftY, leftR, 0, 2 * Math.PI, true); + this.context.strokeStyle = '#FFFFFF'; + this.context.lineWidth = 15; + this.context.stroke(); + // Draw the right eye of the smiling face. + let rightR = radius / 13; + let rightX = circleX + (radius / 2.3); + let rightY = circleY - (radius / 4.5); + this.context.beginPath(); + this.context.arc(rightX, rightY, rightR, 0, 2 * Math.PI, true); + this.context.strokeStyle = '#FFFFFF'; + this.context.lineWidth = 15; + this.context.stroke(); + // Draw the nose of the smiling face. + let startX = circleX; + let startY = circleY - 20; + this.context.beginPath(); + this.context.moveTo(startX, startY); + this.context.lineTo(startX - 8, startY + 40); + this.context.lineTo(startX + 8, startY + 40); + this.context.strokeStyle = '#FFFFFF'; + this.context.lineWidth = 15; + this.context.lineCap = 'round' + this.context.lineJoin = 'round' + this.context.stroke(); + // Draw the mouth of the smiling face. + let mouthR = radius / 2; + let mouthX = circleX; + let mouthY = circleY + 10; + this.context.beginPath(); + this.context.arc(mouthX, mouthY, mouthR, Math.PI / 1.4, Math.PI / 3.4, true); + this.context.strokeStyle = '#FFFFFF'; + this.context.lineWidth = 15; + this.context.stroke(); + this.context.closePath(); + }) + } + }.height('100%').width('100%') + } +} +``` + +The figure below shows the effect. + +![WidgetCanvasDemo](figures/WidgetCanvasDemo.jpeg) \ No newline at end of file diff --git a/en/application-dev/application-models/arkts-ui-widget-page-overview.md b/en/application-dev/application-models/arkts-ui-widget-page-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..2c709ff5c7c13c09e5a303f0adfeebe5c97690bd --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-page-overview.md @@ -0,0 +1,21 @@ +# Widget Page Capability Overview + + +You can leverage the ArkUI declarative paradigm to develop ArkTS widget pages. The following widget pages are automatically generated by a DevEco Studio template. You can adjust the pages based on the real-world service scenarios. + + +![WidgetPreviewPage](figures/WidgetPreviewPage.png) + + +ArkTS widgets have full capabilities of JS widgets, with added animation and custom drawing capabilities plus partial support for components, events, animations, data management, and state management capabilities of the [declarative paradigm](../reference/arkui-ts/ts-components-summary.md). For details, see [Page Capabilities Supported by ArkTS Widgets](#page-capabilities-supported-by-arkts-widgets). + + +## Page Capabilities Supported by ArkTS Widgets + +For details about the page capabilities supported by ArkTS widgets, see [Learning ArkTS](../quick-start/arkts-create-custom-components.md) and [ArkTS-based Declarative Development Paradigm](../reference/arkui-ts/ts-components-summary.md). + +Only the APIs marked with "supported in ArkTS widgets" can be used for ArkTS widgets. Pay special attention to the capability differences with applications. + +For example, the following description indicates that the @Component decorator can be used in ArkTS widgets. + +![WidgetSupportApi](figures/WidgetSupportApi.png) diff --git a/en/application-dev/application-models/arkts-ui-widget-update-by-status.md b/en/application-dev/application-models/arkts-ui-widget-update-by-status.md new file mode 100644 index 0000000000000000000000000000000000000000..dac1faa6f344e8774b4a42538ef9c034441cce94 --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-update-by-status.md @@ -0,0 +1,195 @@ +# Updating Widget Content by State + +There are cases where multiple copies of the same widget are added to the home screen to accommodate different needs. In these cases, the widget content needs to be dynamically updated based on the state. This topic exemplifies how this is implemented. + +In the following example, two copies of the weather widget are added to the home screen: one for displaying the weather of London, and the other Beijing, both configured to be updated at 07:00 every morning. The widget provider detects the target city, and then displays the city-specific weather information on the widgets. + + +- Widget configuration file: Configure the widget to be updated at 07:00 every morning. + + ```json + { + "forms": [ + { + "name": "widget", + "description": "This is a service widget.", + "src": "./ets/widget/pages/WidgetCard.ets", + "uiSyntax": "arkts", + "window": { + "designWidth": 720, + "autoDesignWidth": true + }, + "colorMode": "auto", + "isDefault": true, + "updateEnabled": true, + "scheduledUpdateTime": "07:00", + "updateDuration": 0, + "defaultDimension": "2*2", + "supportDimensions": ["2*2"] + } + ] + } + ``` + +- Widget page: A widget has different states and needs to be updated by state. When the state changes, **postCardAction** is called to notify the EntryFormAbility. + + ```ts + let storage = new LocalStorage(); + @Entry(storage) + @Component + struct WidgetCard { + @LocalStorageProp('textA') textA: string = 'To be updated...'; + @LocalStorageProp('textB') textB: string ='To be updated...'; + @State selectA: boolean = false; + @State selectB: boolean = false; + + build() { + Column() { + Row() { + Checkbox({ name: 'checkbox1', group: 'checkboxGroup' }) + .select(false) + .onChange((value: boolean) => { + this.selectA = value; + postCardAction(this, { + 'action': 'message', + 'params': { + 'selectA': JSON.stringify(value) + } + }); + }) + Text ('State A') + } + + Row() { + Checkbox({ name: 'checkbox2', group: 'checkboxGroup' }) + .select(false) + .onChange((value: boolean) => { + this.selectB = value; + postCardAction(this, { + 'action': 'message', + 'params': { + 'selectB': JSON.stringify(value) + } + }); + }) + Text ('State B') + } + + Row() {// Content that is updated only in state A + Text ('State A:') + Text(this.textA) + } + + Row() { // Content that is updated only in state B + Text ('State B:') + Text(this.textB) + } + }.padding('10%') + } + } + ``` + +- EntryFormAbility: The widget state data is stored in the local database. When the update event callback is triggered, the current widget state is obtained through **formId**, and then content is updated based on the state obtained. + + ```ts + import formInfo from '@ohos.app.form.formInfo' + import formProvider from '@ohos.app.form.formProvider'; + import formBindingData from '@ohos.app.form.formBindingData'; + import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility'; + import dataPreferences from '@ohos.data.preferences'; + + export default class EntryFormAbility extends FormExtensionAbility { + onAddForm(want) { + let formId = want.parameters[formInfo.FormParam.IDENTITY_KEY]; + let isTempCard: boolean = want.parameters[formInfo.FormParam.TEMPORARY_KEY]; + if (isTempCard === false) {// If the widget is a normal one, the widget information is persisted. + console.info('Not temp card, init db for:' + formId); + let promise = dataPreferences.getPreferences(this.context, 'myStore'); + promise.then(async (storeDB) => { + console.info("Succeeded to get preferences."); + await storeDB.put('A' + formId, 'false'); + await storeDB.put('B' + formId, 'false'); + await storeDB.flush(); + }).catch((err) => { + console.info(`Failed to get preferences. ${JSON.stringify(err)}`); + }) + } + let formData = {}; + return formBindingData.createFormBindingData(formData); + } + + onRemoveForm(formId) { + console.info('onRemoveForm, formId:' + formId); + let promise = dataPreferences.getPreferences(this.context, 'myStore'); + promise.then(async (storeDB) => { + console.info("Succeeded to get preferences."); + await storeDB.delete('A' + formId); + await storeDB.delete('B' + formId); + }).catch((err) => { + console.info(`Failed to get preferences. ${JSON.stringify(err)}`); + }) + } + + // If the widget is a temporary one, it is recommended that the widget information be persisted when the widget is converted to a normal one. + onCastToNormalForm(formId) { + console.info('onCastToNormalForm, formId:' + formId); + let promise = dataPreferences.getPreferences(this.context, 'myStore'); + promise.then(async (storeDB) => { + console.info("Succeeded to get preferences."); + await storeDB.put('A' + formId, 'false'); + await storeDB.put('B' + formId, 'false'); + await storeDB.flush(); + }).catch((err) => { + console.info(`Failed to get preferences. ${JSON.stringify(err)}`); + }) + } + + onUpdateForm(formId) { + let promise = dataPreferences.getPreferences(this.context, 'myStore'); + promise.then(async (storeDB) => { + console.info("Succeeded to get preferences."); + let stateA = await storeDB.get('A' + formId, 'false'); + let stateB = await storeDB.get('B' + formId, 'false'); + // Update textA in state A. + if (stateA === 'true') { + let formInfo = formBindingData.createFormBindingData({'textA': 'AAA'}); + await formProvider.updateForm(formId, formInfo); + } + // Update textB in state B. + if (stateB === 'true') { + let formInfo = formBindingData.createFormBindingData({'textB': 'BBB'}); + await formProvider.updateForm(formId, formInfo); + } + console.info(`Update form success stateA:${stateA} stateB:${stateB}.`); + }).catch((err) => { + console.info(`Failed to get preferences. ${JSON.stringify(err)}`); + }) + } + + onFormEvent(formId, message) { + // Store the widget state. + console.info('onFormEvent formId:' + formId + 'msg:' + message); + let promise = dataPreferences.getPreferences(this.context, 'myStore'); + promise.then(async (storeDB) => { + console.info("Succeeded to get preferences."); + let msg = JSON.parse(message); + if (msg.selectA != undefined) { + console.info('onFormEvent selectA info:' + msg.selectA); + await storeDB.put('A' + formId, msg.selectA); + } + if (msg.selectB != undefined) { + console.info('onFormEvent selectB info:' + msg.selectB); + await storeDB.put('B' + formId, msg.selectB); + } + await storeDB.flush(); + }).catch((err) => { + console.info(`Failed to get preferences. ${JSON.stringify(err)}`); + }) + } + }; + ``` + + +> **NOTE** +> +> When the local database is used for widget information persistence, it is recommended that [TEMPORARY_KEY](../reference/apis/js-apis-app-form-formInfo.md#formparam) be used in the [onAddForm](../reference/apis/js-apis-app-form-formExtensionAbility.md#onaddform) lifecycle callback to determine whether the currently added widget is a normal one. If the widget is a normal one, the widget information is directly persisted. If the widget is a temporary one, the widget information is persisted when the widget is converted to a normal one ([onCastToNormalForm](../reference/apis/js-apis-app-form-formExtensionAbility.md#oncasttonormalform)). In addition, the persistent widget information needs to be deleted when the widget is destroyed ([onRemoveForm](../reference/apis/js-apis-app-form-formExtensionAbility.md#onremoveform)), preventing the database size from continuously increasing due to repeated widget addition and deletion. diff --git a/en/application-dev/application-models/arkts-ui-widget-update-by-time.md b/en/application-dev/application-models/arkts-ui-widget-update-by-time.md new file mode 100644 index 0000000000000000000000000000000000000000..2c2643c802aff436656f5855d67c00e1a3c38dcd --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-update-by-time.md @@ -0,0 +1,99 @@ +# Configuring a Widget to Update Periodically + +Before configuring a widget to update periodically, enable the periodic update feature by setting the **updateEnabled** field to **true** in the **form_config.json** file. + +The widget framework provides the following modes of updating widgets periodically: + + +- Set the update interval: The widget will be updated at the specified interval by calling [onUpdateForm](../reference/apis/js-apis-app-form-formExtensionAbility.md#onupdateform). You can specify the interval by setting the [updateDuration](arkts-ui-widget-configuration.md) field in the **form_config.json** file. For example, you can configure the widget to update once an hour. + + > **NOTE** + > + > **updateDuration** takes precedence over **scheduledUpdateTime**. If both are specified, the value specified by **updateDuration** is used. + + ```json + { + "forms": [ + { + "name": "widget", + "description": "This is a service widget.", + "src": "./ets/widget/pages/WidgetCard.ets", + "uiSyntax": "arkts", + "window": { + "designWidth": 720, + "autoDesignWidth": true + }, + "colorMode": "auto", + "isDefault": true, + "updateEnabled": true, // Enable the periodic update feature. + "scheduledUpdateTime": "10:30", + "updateDuration": 2, // Set the interval to update the widget. The value is a natural number, in the unit of 30 minutes. + "defaultDimension": "2*2", + "supportDimensions": ["2*2"] + } + ] + } + ``` + +- Set the scheduled update time: The widget will be updated at the scheduled time every day. You can specify the time by setting the [scheduledUpdateTime](arkts-ui-widget-configuration.md) field in the **form_config.json** file. For example, you can configure the widget to update at 10:30 a.m. every day. + + > **NOTE** + > + > **updateDuration** takes precedence over **scheduledUpdateTime**. For the **scheduledUpdateTime** settings to take effect, set **updateDuration** to **0**. + + + ```json + { + "forms": [ + { + "name": "widget", + "description": "This is a service widget.", + "src": "./ets/widget/pages/WidgetCard.ets", + "uiSyntax": "arkts", + "window": { + "designWidth": 720, + "autoDesignWidth": true + }, + "colorMode": "auto", + "isDefault": true, + "updateEnabled": true, // Enable the periodic update feature. + "scheduledUpdateTime": "10:30", // Set the scheduled time to update the widget. + "updateDuration": 0, + "defaultDimension": "2*2", + "supportDimensions": ["2*2"] + } + ] + } + ``` + +- Set the next update time: The widget will be updated next time at the specified time. You can specify the time by calling the [setFormNextRefreshTime()](../reference/apis/js-apis-app-form-formProvider.md#setformnextrefreshtime) API. The minimum update interval is 5 minutes. For example, you can configure the widget to update within 5 minutes after the API is called. + + ```ts + import formProvider from '@ohos.app.form.formProvider'; + + let formId = '123456789'; // Use the actual widget ID in real-world scenarios. + try { + // Configure the widget to update in 5 minutes. + formProvider.setFormNextRefreshTime(formId, 5, (err, data) => { + if (err) { + console.error(`Failed to setFormNextRefreshTime. Code: ${err.code}, message: ${err.message}`); + return; + } else { + console.info('Succeeded in setFormNextRefreshTimeing.'); + } + }); + } catch (err) { + console.error(`Failed to setFormNextRefreshTime. Code: ${err.code}, message: ${err.message}`); + } + ``` + + +When periodic update is triggered, the system calls the [onUpdateForm()](../reference/apis/js-apis-app-form-formExtensionAbility.md#onupdateform) lifecycle callback of the FormExtensionAbility. In the callback, [updateForm()](../reference/apis/js-apis-app-form-formProvider.md#updateform) can be used to update the widget by the provider. For details about how to use **onUpdateForm()**, see [Updating Widget Content Through FormExtensionAbility](arkts-ui-widget-event-formextensionability.md). + + +> **NOTE** +> 1. Each widget can be updated at the specified interval for a maximum of 50 times every day, including updates triggered by setting [updateDuration](arkts-ui-widget-configuration.md) or calling [setFormNextRefreshTime()](../reference/apis/js-apis-app-form-formProvider.md#setformnextrefreshtime). When the limit is reached, the widget cannot be updated in this mode again. The number of update times is reset at 00:00 every day. +> +> 2. The same timer is used for timing updates at the specified interval. Therefore, the first scheduled update of widgets may have a maximum deviation of 30 minutes. For example, the first widget A (updated every half an hour) is added at 03:20. The timer starts and triggers an update every half an hour. The second widget B (updated every half an hour) is added at 03:40. When the timer event is triggered at 03:50, widget A is updated, and widget B will be updated at 04:20 next time. +> +> 3. Updates at the specified interval and updates at the scheduled time are triggered only when the screen is on. When the screen is off, the update action is merely recorded. When the screen is on, the update action is performed. diff --git a/en/application-dev/application-models/arkts-ui-widget-working-principles.md b/en/application-dev/application-models/arkts-ui-widget-working-principles.md new file mode 100644 index 0000000000000000000000000000000000000000..b1b09dc409380da8e530f571b2e5711ec63edd10 --- /dev/null +++ b/en/application-dev/application-models/arkts-ui-widget-working-principles.md @@ -0,0 +1,62 @@ +# ArkTS Widget Working Principles + + +## Implementation Principles + +**Figure 1** ArkTS widget implementation principles + +![WidgetPrinciple](figures/WidgetPrinciple.png) + +- Widget host: an application that displays the widget content and controls the widget location. Only the system application can function as a widget host. + +- Widget provider: an application that provides the widget content to display and controls how widget components are laid out and how they interact with users. + +- Widget Manager: a resident agent that manages widgets in the system. It provides the [formProvider](../reference/apis/js-apis-app-form-formProvider.md) and [formHost](../reference/apis/js-apis-app-form-formHost.md) APIs as well as the APIs for widget management, usage, and periodic updates. + +- Widget rendering service: a service that manages widget rendering instances. Widget rendering instances are bound to the [widget components](../reference/arkui-ts/ts-basic-components-formcomponent.md) on the widget host on a one-to-one basis. The widget rendering service runs the widget page code **widgets.abc** for rendering, and sends the rendered data to the corresponding widget component on the widget host. + + **Figure 2** Working principles of the ArkTS widget rendering service +![WidgetRender](figures/WidgetRender.png) + +Unlike JS widgets, ArkTS widgets support logic code running. The widget page code **widgets.abc** is executed by the widget rendering service, which is managed by the Widget Manager. Each widget component of a widget host corresponds to a rendering instance in the widget rendering service. Rendering instances of a widget provider run in the same virtual machine operating environment, and rendering instances of different widget providers run in different virtual machine operating environments. In this way, the resources and state data are isolated between widgets of different widget providers. During development, pay attention to the use of the [globalThis](uiability-data-sync-with-ui.md#using-globalthis-between-uiability-and-page) object. Use one **globalThis** object for widgets from the same widget provider, and different **globalThis** objects for widgets from different widget providers. + + +## Advantages of ArkTS Widgets + +As a quick entry to applications, ArkTS widgets outperform JS widgets in the following aspects: + +- Improved development experience and efficiency, thanks to the unified development paradigm + + ArkTS widgets share the same declarative UI development framework as application pages. This means that the page layouts can be directly reused in widgets, improving development experience and efficiency. + + **Figure 3** Comparison of widget project structures + + ![WidgetProject](figures/WidgetProject.png) + +- More widget features + - Animation: ArkTS widgets support the [attribute animation](../reference/arkui-ts/ts-animatorproperty.md) and [explicit animation](../reference/arkui-ts/ts-explicit-animation.md) capabilities, which can be leveraged to deliver a more engaging experience. + - Custom drawing: ArkTS widgets allow you to draw graphics with the [\](../reference/arkui-ts/ts-components-canvas-canvas.md) component to present information more vividly. + - Logic code execution: The capability to run logic code in widgets means that service logic can be self-closed in widgets, expanding the use cases of widgets. + + +## Constraints on ArkTS Widgets + +Compared with JS widgets, ArkTS widgets provide more capabilities, but they are also more prone to malicious behavior. To account for the impact on the widget host – typically the home screen, ArkTS widgets are subject to the following restrictions: + +- The .so file cannot be loaded. + +- The native programming language cannot be used for development. + +- Only [partial](arkts-ui-widget-page-overview.md) components, events, animations, data management, state management, and API capabilities of the declarative paradigm are supported. + +- The event processing of the widget is independent of that of the widget host. To prevent gesture conflicts, avoid using swipers in the widget when the widget host supports left and right swipes. + +In addition, ArkTS widgets do not support the following features: + +- Importing modules + +- Instant preview + +- Breakpoint debugging. + +- Hot reload diff --git a/en/application-dev/application-models/common-event-overview.md b/en/application-dev/application-models/common-event-overview.md index e8be9abaa3015a5512c47af55d2f364be0de79ad..3f532865e686592282b9080f234c088ee24a64f8 100644 --- a/en/application-dev/application-models/common-event-overview.md +++ b/en/application-dev/application-models/common-event-overview.md @@ -7,8 +7,7 @@ OpenHarmony provides Common Event Service (CES) for applications to subscribe to Common events are classified into system common events and custom common events. -- System common events: defined in CES. Only system applications and system services can publish system common events, such as HAP installation, update, and uninstall. For details about the supported system common events, see [Support](../reference/apis/js-apis-commonEventManager.md#support). - +- System common events: defined in CES. Currently, only system applications and system services can publish system common events, such as HAP installation, update, and uninstall. For details about the supported system common events, see [System Common Events](../reference/apis/commonEventManager-definitions.md). - Custom common events: customized by applications to implement cross-process event communication. @@ -16,9 +15,7 @@ Common events are also classified into unordered, ordered, and sticky common eve - Unordered common events: common events that CES forwards regardless of whether subscribers receive the events and when they subscribe to the events. - -- Ordered common events: common events that CES forwards based on the subscriber priority. CES forwards common events to the subscriber with lower priority only after receiving a reply from the previous subscriber with higher priority. Subscribers with the same priority receive common events in a random order. - +- Ordered common events: common events that CES forwards based on the subscriber priority. CES preferentially forwards an ordered common event to the subscriber with higher priority, waits until the subscriber receives the event, and then forwards the events to the subscriber with lower priority. Subscribers with the same priority receive common events in a random order. - Sticky common events: common events that can be sent to a subscriber before or after they initiate a subscription. Only system applications and system services can send sticky common events, which remain in the system after being sent. The sends must first request the **ohos.permission.COMMONEVENT_STICKY** permission. For details about the configuration, see [Permission Application Guide](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file). diff --git a/en/application-dev/application-models/common-event-remove-sticky.md b/en/application-dev/application-models/common-event-remove-sticky.md new file mode 100644 index 0000000000000000000000000000000000000000..2ad907a9c7962d496f0a791c88a25aaab54a9d25 --- /dev/null +++ b/en/application-dev/application-models/common-event-remove-sticky.md @@ -0,0 +1,41 @@ +# Removing Sticky Common Events (for System Applications Only) + + +## When to Use + +Subscribers can receive sticky common events that have been sent. If the events are no longer forwarded, the event publisher needs to remove them. OpenHarmony provides an API for removing sticky common events. + +## Available APIs + +For details, see [Common Event](../reference/apis/js-apis-commonEventManager.md) + +| Name| Description| +| -------- | -------- | +| removeStickyCommonEvent(event: string, callback: AsyncCallback\): void | Removes a sticky common event.| + + +## How to Develop + +1. Request the **ohos.permission.COMMONEVENT_STICKY** permission. For details, see [Declaring Permissions in the Configuration File](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file). + +2. Import the module. + + ```ts + import commonEventManager from '@ohos.commonEventManager'; + ``` + +3. Call the [removeStickyCommonEvent()](../reference/apis/js-apis-commonEventManager.md#commoneventmanagerremovestickycommonevent10) API to remove the target sticky common event. + + > **NOTE** + > + > The sticky common event to be removed must have been released by the application. For details about how to release sticky common events, see [Publishing Common Events](common-event-publish.md). + + ```ts + commonEventManager.removeStickyCommonEvent("sticky_event", (err) => { // sticky_event indicates the name of the target sticky common event. + if (err) { + console.error(`Failed to remove sticky common event. Code is ${err.code}, message is ${err.message}`); + return; + } + console.info(`Succeeded in removeing sticky event.`); + }); + ``` diff --git a/en/application-dev/application-models/common-event-static-subscription.md b/en/application-dev/application-models/common-event-static-subscription.md index 85852f5712df84107c6593160d276ed33557baf9..465fc236129d4c78967e6122c318132933043fb6 100644 --- a/en/application-dev/application-models/common-event-static-subscription.md +++ b/en/application-dev/application-models/common-event-static-subscription.md @@ -2,45 +2,49 @@ ## When to Use -A static subscriber is started once it receives a target event published by the system or application. At the same time, the **onReceiveEvent** callback is triggered, in which you can implement the service logic. For example, if an application needs to execute some initialization tasks during device power-on, the application can subscribe to the power-on event in static mode. After receiving the power-on event, the application is started to execute the initialization tasks. Subscribing to a common event in static mode is achieved by configuring a declaration file and implementing a class that inherits from **StaticSubscriberExtensionAbility**. Note that this subscribing mode has negative impact on system power consumption. Therefore, exercise caution when using this mode. +A static subscriber is started once it receives a target event published by the system or application. At the same time, the [onReceiveEvent()](../reference/apis/js-apis-application-staticSubscriberExtensionAbility.md#staticsubscriberextensionabilityonreceiveevent) callback is triggered, in which you can implement the service logic. For example, if an application needs to execute some initialization tasks during device power-on, the application can subscribe to the power-on event in static mode. After receiving the power-on event, the application is started to execute the initialization tasks. + +Subscribing to a common event in static mode is achieved by configuring a declaration file and implementing a class that inherits from [StaticSubscriberExtensionAbility](../reference/apis/js-apis-application-staticSubscriberExtensionAbility.md). + +> **NOTE** +> +> The static subscription mode has negative impact on system power consumption. Therefore, exercise caution when using this mode. ## How to Develop -1. Declaring a Static Subscriber +1. Declaring a static subscriber. + + To declare a static subscriber, create an ExtensionAbility, which is derived from the **StaticSubscriberExtensionAbility** class, in the project. - To declare a static subscriber, create an ExtensionAbility, which is derived from the **StaticSubscriberExtensionAbility** class, in the project. The sample code is as follows: + You can implement service logic in the [**onReceiveEvent()**](../reference/apis/js-apis-application-staticSubscriberExtensionAbility.md#staticsubscriberextensionabilityonreceiveevent) callback. ```ts import StaticSubscriberExtensionAbility from '@ohos.application.StaticSubscriberExtensionAbility' export default class StaticSubscriber extends StaticSubscriberExtensionAbility { - onReceiveEvent(event) { - console.log('onReceiveEvent, event:' + event.event); - } + onReceiveEvent(event) { + console.info('onReceiveEvent, event: ' + event.event); + } } ``` - You can implement service logic in the **onReceiveEvent** callback. - - - -2. Project Configuration for a Static Subscriber +2. Configure static subscriber settings. - After writing the static subscriber code, configure the subscriber in the **module.json5** file. The configuration format is as follows: + After writing the static subscriber code, configure the subscriber in the [module.json5](../quick-start/module-configuration-file.md) file. ```ts { "module": { - ...... + ... "extensionAbilities": [ { "name": "StaticSubscriber", - "srcEntrance": "./ets/StaticSubscriber/StaticSubscriber.ts", + "srcEntry": "./ets/staticsubscriber/StaticSubscriber.ts", "description": "$string:StaticSubscriber_desc", "icon": "$media:icon", "label": "$string:StaticSubscriber_label", "type": "staticSubscriber", - "visible": true, + "exported": true, "metadata": [ { "name": "ohos.extension.staticSubscriber", @@ -49,14 +53,14 @@ A static subscriber is started once it receives a target event published by the ] } ] - ...... + ... } } ``` - Pay attention to the following fields in the JSON file: + Some fields in the file are described as follows: - - **srcEntrance**: entry file path of the ExtensionAbility, that is, the file path of the static subscriber declared in Step 2. + - **srcEntry **: entry file path of the ExtensionAbility, that is, the file path of the static subscriber declared in Step 2. - **type**: ExtensionAbility type. For a static subscriber, set this field to **staticSubscriber**. @@ -64,42 +68,47 @@ A static subscriber is started once it receives a target event published by the - **name**: name of the ExtensionAbility. For a static subscriber, declare the name as **ohos.extension.staticSubscriber** for successful identification. - **resource**: path that stores the ExtensionAbility configuration, which is customizable. In this example, the path is **resources/base/profile/subscribe.json**. - A level-2 configuration file pointed to by **metadata** must be in the following format: - ```ts - { - "commonEvents": [ - { - "name": "xxx", - "permission": "xxx", - "events":[ - "xxx" - ] - } - ] - } - ``` - - If the level-2 configuration file is not declared in this format, the file cannot be identified. The fields are described as follows: +3. Configure the level-2 configuration file to which the metadata points. - - **name**: name of the ExtensionAbility, which must be the same as the name of **extensionAbility** declared in **module.json5**. + ```json + { + "commonEvents": [ + { + "name": "xxx", + "permission": "xxx", + "events":[ + "xxx" + ] + } + ] + } + ``` - - **permission**: permission required for the publisher. If a publisher without the required permission attempts to publish an event, the event is regarded as invalid and will not be published. + If the level-2 configuration file is not declared in this format, the file cannot be identified. Some fields in the file are described as follows: - - **events**: list of target events to subscribe to. + - **name**: name of the ExtensionAbility, which must be the same as the name of **extensionAbility** declared in **module.json5**. + - **permission**: permission required for the publisher. If a publisher without the required permission attempts to publish an event, the event is regarded as invalid and will not be published. + - **events**: list of target events to subscribe to. -3. Device System Configuration +4. Modify the [preset configuration file](https://gitee.com/openharmony/vendor_hihope/blob/master/rk3568/preinstall-config/install_list_capability.json) of the device, that is, the **/system/etc/app/install_list_capability.json** file on the device. When the device is started, this file is read. During application installation, the common event type specified by **allowCommonEvent** in the file is authorized. The **install_list_capability.json** file contains the following fields: - In the device system configuration file **/system/etc/app/install_list_capability.json**, add the bundle name of the static subscriber. + - **bundleName**: bundle name of the application. + - **app_signature**: fingerprint information of the application. For details, see [Configuration in install_list_capability.json](../../device-dev/subsystems/subsys-app-privilege-config-guide.md#configuration-in-install_list_capabilityjson). + - **allowCommonEvent**: type of common event that can be started by static broadcast. - ```json - { - "install_list": [ - { - "bundleName": "ohos.extension.staticSubscriber", - "allowCommonEvent": ["usual.event.A", "usual.event.B"], - } - ] - } + ```json + [ + ... + { + "bundleName": "com.example.myapplication", // Bundle name. + "app_signature": ["****"], // Fingerprint information. + "allowCommonEvent": ["usual.event.A", "usual.event.B"] // Type of common event that can be started by static broadcast. + } + ] ``` + + > **NOTE** + > + > The **install_list_capability.json** file is available only for preinstalled applications. diff --git a/en/application-dev/application-models/common-event-subscription-overview.md b/en/application-dev/application-models/common-event-subscription-overview.md index 20064af92d3df2e6f7ab7d62c4f71f911848057a..262f30c87e6018fed4e417a196dcaeeb58e42ae2 100644 --- a/en/application-dev/application-models/common-event-subscription-overview.md +++ b/en/application-dev/application-models/common-event-subscription-overview.md @@ -1,7 +1,7 @@ # Common Event Subscription Overview -​The common event service provides two subscription modes: dynamic and static. The biggest difference between these two modes is that dynamic subscription requires the application to be running, while static subscription does not. +The common event service provides two subscription modes: dynamic and static. The biggest difference between these two modes is that dynamic subscription requires the application to be running, while static subscription does not. - In dynamic subscription mode, a subscriber subscribes to common events by calling an API during the running period. For details, see [Subscribing to Common Events in Dynamic Mode](common-event-subscription.md). -- In static subscription mode, a subscriber subscribes to common events by configuring a declaration file and implementing a class that inherits from StaticSubscriberExtensionAbility. For details, see [Subscribing to Common Events in Static Mode](common-event-static-subscription.md). +- In static subscription mode, a subscriber subscribes to common events by configuring a declaration file and implementing a class that inherits from **StaticSubscriberExtensionAbility**. For details, see [Subscribing to Common Events in Static Mode](common-event-static-subscription.md). diff --git a/en/application-dev/application-models/common-event-subscription.md b/en/application-dev/application-models/common-event-subscription.md index 6cdc52ef9b798e48a911892f965db8fbf2aaa67f..c3e3ebfa52415d5e0ebade26973f78a589fb348f 100644 --- a/en/application-dev/application-models/common-event-subscription.md +++ b/en/application-dev/application-models/common-event-subscription.md @@ -32,7 +32,7 @@ For details about the APIs, see [API Reference](../reference/apis/js-apis-common let subscriber = null; // Subscriber information. let subscribeInfo = { - events: ["usual.event.SCREEN_OFF"], // Subscribe to the common event screen-off. + events: ["usual.event.SCREEN_OFF"], // Subscribe to the common event screen-off. } ``` @@ -41,13 +41,13 @@ For details about the APIs, see [API Reference](../reference/apis/js-apis-common ```ts // Callback for subscriber creation. commonEventManager.createSubscriber(subscribeInfo, (err, data) => { - if (err) { - console.error(`[CommonEvent] CreateSubscriberCallBack err=${JSON.stringify(err)}`); - } else { - console.info(`[CommonEvent] CreateSubscriber success`); - subscriber = data; - // Callback for common event subscription. - } + if (err) { + console.error(`Failed to create subscriber. Code is ${err.code}, message is ${err.message}`); + return; + } + console.info('Succeeded in creating subscriber.'); + subscriber = data; + // Callback for common event subscription. }) ``` @@ -56,14 +56,13 @@ For details about the APIs, see [API Reference](../reference/apis/js-apis-common ```ts // Callback for common event subscription. if (subscriber !== null) { - commonEventManager.subscribe(subscriber, (err, data) => { - if (err) { - console.error(`[CommonEvent] SubscribeCallBack err=${JSON.stringify(err)}`); - } else { - console.info(`[CommonEvent] SubscribeCallBack data=${JSON.stringify(data)}`); - } - }) + commonEventManager.subscribe(subscriber, (err, data) => { + if (err) { + console.error(`Failed to subscribe common event. Code is ${err.code}, message is ${err.message}`); + return; + } + }) } else { - console.error(`[CommonEvent] Need create subscriber`); + console.error(`Need create subscriber`); } ``` diff --git a/en/application-dev/application-models/component-startup-rules-fa.md b/en/application-dev/application-models/component-startup-rules-fa.md index db64e8c093df679a9e52d6bc753e4935a21c25be..431fdbd8e7841ecb1e58a2226e661564edb98854 100644 --- a/en/application-dev/application-models/component-startup-rules-fa.md +++ b/en/application-dev/application-models/component-startup-rules-fa.md @@ -12,7 +12,7 @@ Component startup refers to the behavior of starting or connecting to an applica To deliver a better user experience, OpenHarmony restricts the following behavior: -- A background application randomly displays a dialog box, such as an ads pop-up. +- A background application randomly displays a dialog box, such as an ad pop-up. - Background applications wake up each other. This type of behavior occupies system resources and increases power consumption, or even causes system frozen. @@ -34,14 +34,14 @@ In view of this, OpenHarmony formulates a set of component startup rules, as fol - **Before starting the ServiceAbility or DataAbility component of an application, verify the AssociateWakeUp field of the target application.** - This rule applies only to cross-application scenarios. - This rule is valid only when the target component is ServiceAbility or DataAbility. - - The ServiceAbility and DataAbility of an application can be accessed by others only when **AssociateWakeUp** of the target application is set to **true**. + - The ServiceAbility and DataAbility of an application can be accessed by other applications only when **AssociateWakeUp** of the target application is set to **true**. - The **AssociateWakeUp** field can be configured only for preset applications. For other applications, this field is set to **false** by default. > **NOTE** > 1. Component startup control has been implemented since OpenHarmony v3.2 Release. > -> 2. The new component startup rules are more strict than the original ones. You must be familiar with the new startup rules to prevent service exceptions. +> 2. The new component startup rules are more strict than the original ones. Get familiar with the new startup rules to prevent service exceptions. diff --git a/en/application-dev/application-models/component-startup-rules.md b/en/application-dev/application-models/component-startup-rules.md index 26b2446893aea096611f896e878ef15888830afa..bddf63dbc69ea243733e6f60f67f92a854833bf7 100644 --- a/en/application-dev/application-models/component-startup-rules.md +++ b/en/application-dev/application-models/component-startup-rules.md @@ -23,8 +23,8 @@ In view of this, OpenHarmony formulates a set of component startup rules, as fol - **Before starting a component of another application, verify the visible field of the target component.** - - If the **visible** field of the target component is **false**, verify the **ohos.permission.START_INVISIBLE_ABILITY** permission. - - For details, see [Component Visible Configuration](../quick-start/module-configuration-file.md#abilities). + - If the **exported** field of the target component is **false**, verify the **ohos.permission.START_INVISIBLE_ABILITY** permission. + - For details, see [Component exported Configuration](../quick-start/module-configuration-file.md#abilities). - **Before starting a component of a background application, verify the BACKGROUND permission.** - An application is considered as a foreground application only when the application process gains focus or its UIAbility component is running in the foreground. @@ -37,8 +37,8 @@ In view of this, OpenHarmony formulates a set of component startup rules, as fol > **NOTE** > > - Component startup control has been implemented since OpenHarmony v3.2 Release. -> -> - The new component startup rules are more strict than the original ones. You must be familiar with the new startup rules to prevent service exceptions. +> +> - The new component startup rules are more strict than the original ones. You must be familiar with the new startup rules to prevent service exceptions. ## Intra-Device Component Startup Rules diff --git a/en/application-dev/application-models/configuration-file-diff.md b/en/application-dev/application-models/configuration-file-diff.md index 745f2702cab12b8ef99e174c924d49cf2217bf2b..162e50d7839e1419950be809c658afa08d919d2f 100644 --- a/en/application-dev/application-models/configuration-file-diff.md +++ b/en/application-dev/application-models/configuration-file-diff.md @@ -4,8 +4,8 @@ The FA model uses the [config.json file](../quick-start/application-configuration-file-overview-fa.md) to describe the basic information about an application. An application can have multiple modules, and each module has a **config.json** file. The **config.json** file consists of three parts: **app**, **deviceConfig**, and **module**. The **app** tag is used to configure application-level attributes. If an application has multiple modules, the **app** configuration in each **config.json** file must be consistent. -The stage model uses the [app.json5](../quick-start/app-configuration-file.md) and [module.json](../quick-start/module-configuration-file.md) files to describe the basic information about an application. An application can have multiple modules but only one **app.json5** file. This file is used to configure application-level attributes and takes effect for all the modules. Each module has a **module.json5** file, which is used to configure module-level attributes and takes effect only for the current module. +The stage model uses the [app.json5](../quick-start/app-configuration-file.md) and [module.json](../quick-start/module-configuration-file.md) files to describe the basic information about an application. An application can have multiple modules but only one **app.json5** file. This file is used to configure application-level attributes and the configuration applies to all the modules. Each module has a **module.json5** file, which is used to configure module-level attributes and the configuration applies only for the current module. -**Figure 1** Configuration file differences -![comparison-of-configuration-file](figures/comparison-of-configuration-file.png) +**Figure 1** Configuration file differences +![comparison-of-configuration-file](figures/comparison-of-configuration-file.png) \ No newline at end of file diff --git a/en/application-dev/application-models/connect-serviceability.md b/en/application-dev/application-models/connect-serviceability.md index ac2acb898a3bd7ef905b8a33dc10f7980ce74548..15f98d123ad241646cc423a512ab49e6dccf5c50 100644 --- a/en/application-dev/application-models/connect-serviceability.md +++ b/en/application-dev/application-models/connect-serviceability.md @@ -16,14 +16,14 @@ The following sample code enables the PageAbility to create connection callback ```ts import rpc from "@ohos.rpc" -import prompt from '@system.prompt' +import promptAction from '@ohos.promptAction' import featureAbility from '@ohos.ability.featureAbility' let option = { onConnect: function onConnectCallback(element, proxy) { console.info(`onConnectLocalService onConnectDone`) if (proxy === null) { - prompt.showToast({ + promptAction.showToast({ message: "Connect service failed" }) return @@ -33,19 +33,19 @@ let option = { let option = new rpc.MessageOption() data.writeInterfaceToken("connect.test.token") proxy.sendRequest(0, data, reply, option) - prompt.showToast({ + promptAction.showToast({ message: "Connect service success" }) }, onDisconnect: function onDisconnectCallback(element) { console.info(`onConnectLocalService onDisconnectDone element:${element}`) - prompt.showToast({ + promptAction.showToast({ message: "Disconnect service success" }) }, onFailed: function onFailedCallback(code) { console.info(`onConnectLocalService onFailed errCode:${code}`) - prompt.showToast({ + promptAction.showToast({ message: "Connect local service onFailed" }) } diff --git a/en/application-dev/application-models/context-switch.md b/en/application-dev/application-models/context-switch.md index e1d155c8a60f6ca3e225174aece28738663b8079..53047adb03ff8508f1428f62a4f6d982fedc0aeb 100644 --- a/en/application-dev/application-models/context-switch.md +++ b/en/application-dev/application-models/context-switch.md @@ -1,11 +1,11 @@ # Context Switching - | API in the FA Model| Corresponding d.ts File in the Stage Model| Corresponding API or Field in the Stage Model| + | API in the FA Model| Corresponding .d.ts File in the Stage Model| Corresponding API or Field in the Stage Model| | -------- | -------- | -------- | | [getOrCreateLocalDir(callback:AsyncCallback<string>):void;](../reference/apis/js-apis-inner-app-context.md#contextgetorcreatelocaldir7)
[getOrCreateLocalDir():Promise<string>;](../reference/apis/js-apis-inner-app-context.md#contextgetorcreatelocaldir7-1) | There is no corresponding API in the stage model.| Applications developed on the stage model do not have the operation permission in the application root directory. Therefore, no corresponding API is provided.| | [verifyPermission(permission:string,options:PermissionOptions,callback:AsyncCallback<number>):void;](../reference/apis/js-apis-inner-app-context.md#contextverifypermission7)
[verifyPermission(permission:string,callback:AsyncCallback<number>):void;](../reference/apis/js-apis-inner-app-context.md#contextverifypermission7-1)
[verifyPermission(permission:string,options?:PermissionOptions):Promise<number>;](../reference/apis/js-apis-inner-app-context.md#contextverifypermission7-2) | \@ohos.abilityAccessCtrl.d.ts | [verifyAccessTokenSync(tokenID: number, permissionName: Permissions): GrantStatus;](../reference/apis/js-apis-abilityAccessCtrl.md#verifyaccesstokensync9)
[verifyAccessToken(tokenID: number, permissionName: Permissions): Promise<GrantStatus>;](../reference/apis/js-apis-abilityAccessCtrl.md#verifyaccesstoken9) | -| [requestPermissionsFromUser(permissions:Array<string>,requestCode:number,resultCallback:AsyncCallback<PermissionRequestResult>):void;](../reference/apis/js-apis-inner-app-context.md#contextrequestpermissionsfromuser7)
[requestPermissionsFromUser(permissions:Array<string>,requestCode:number):Promise<PermissionRequestResult>;](../reference/apis/js-apis-inner-app-context.md#contextrequestpermissionsfromuser7-1) | \@ohos.abilityAccessCtrl.d.ts | [requestPermissionsFromUser(context: Context, permissionList: Array<Permissions>, requestCallback: AsyncCallback<PermissionRequestResult>) : void;](../reference/apis/js-apis-abilityAccessCtrl.md#requestpermissionsfromuser9)
[requestPermissionsFromUser(context: Context, permissionList: Array<Permissions>) : Promise<PermissionRequestResult>;](../reference/apis/js-apis-abilityAccessCtrl.md#requestpermissionsfromuser9-1) | +| [requestPermissionsFromUser(permissions:Array<string>,requestCode:number,resultCallback:AsyncCallback<PermissionRequestResult>):void;](../reference/apis/js-apis-inner-app-context.md#contextrequestpermissionsfromuser7)
[requestPermissionsFromUser(permissions:Array<string>,requestCode:number):Promise<PermissionRequestResult>;](../reference/apis/js-apis-inner-app-context.md#contextrequestpermissionsfromuser7-1) | \@ohos.abilityAccessCtrl.d.ts | [requestPermissionsFromUser(context: Context, permissionList: Array<Permissions>, requestCallback: AsyncCallback<PermissionRequestResult>) : void;](../reference/apis/js-apis-abilityAccessCtrl.md#requestpermissionsfromuser9)
[requestPermissionsFromUser(context: Context, permissionList: Array<Permissions>) : Promise<PermissionRequestResult>;](../reference/apis/js-apis-abilityAccessCtrl.md#requestpermissionsfromuser9-1) | | [getApplicationInfo(callback:AsyncCallback<ApplicationInfo>):void;](../reference/apis/js-apis-inner-app-context.md#contextgetapplicationinfo7)
[getApplicationInfo():Promise<ApplicationInfo>;](../reference/apis/js-apis-inner-app-context.md#contextgetapplicationinfo7-1) | application\Context.d.ts | [applicationInfo: ApplicationInfo;](../reference/apis/js-apis-inner-application-context.md#attributes)| | [getBundleName(callback : AsyncCallback<string>): void;](../reference/apis/js-apis-inner-app-context.md#contextgetbundlename7)
[getBundleName(): Promise<string>;](../reference/apis/js-apis-inner-app-context.md#contextgetbundlename7-1) | application\UIAbilityContext.d.ts | [abilityInfo.bundleName: string;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#attributes)| | [getDisplayOrientation(callback : AsyncCallback<bundle.DisplayOrientation>): void;](../reference/apis/js-apis-inner-app-context.md#contextgetdisplayorientation7)
[getDisplayOrientation(): Promise<bundle.DisplayOrientation>;](../reference/apis/js-apis-inner-app-context.md#contextgetdisplayorientation7-1) | \@ohos.screen.d.ts | [readonly orientation: Orientation;](../reference/apis/js-apis-screen.md#orientation) | @@ -26,3 +26,5 @@ | [getAbilityInfo(callback:AsyncCallback<AbilityInfo>):void;](../reference/apis/js-apis-inner-app-context.md#contextgetabilityinfo7)
[getAbilityInfo():Promise<AbilityInfo>;](../reference/apis/js-apis-inner-app-context.md#contextgetabilityinfo7-1) | application\UIAbilityContext.d.ts | [abilityInfo: AbilityInfo;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#attributes)| | [isUpdatingConfigurations(callback:AsyncCallback<boolean>):void;](../reference/apis/js-apis-inner-app-context.md#contextisupdatingconfigurations7)
[isUpdatingConfigurations():Promise<boolean>;](../reference/apis/js-apis-inner-app-context.md#contextisupdatingconfigurations7-1) | There is no corresponding API in the stage model.| OpenHarmony applications do not restart when the system environment changes. The **onConfigurationUpdated** callback is invoked to notify the applications of the changes. This API provides an empty implementation in the FA model, and the stage model does not provide a corresponding API.| | [printDrawnCompleted(callback:AsyncCallback<void>):void;](../reference/apis/js-apis-inner-app-context.md#contextprintdrawncompleted7)
[printDrawnCompleted():Promise<void>;](../reference/apis/js-apis-inner-app-context.md#contextprintdrawncompleted7-1) | There is no corresponding API in the stage model.| This API provides an empty implementation in the FA model. The stage model does not provide a corresponding API.| + + \ No newline at end of file diff --git a/en/application-dev/application-models/create-dataability.md b/en/application-dev/application-models/create-dataability.md index 488b0593dbdc23bc1e6ea30c17f9165a92c79f20..9d148a7ba28ffe46484f32b07f7a7660ef49f72d 100644 --- a/en/application-dev/application-models/create-dataability.md +++ b/en/application-dev/application-models/create-dataability.md @@ -9,18 +9,18 @@ The following sample code shows how to create a DataAbility: ```ts import featureAbility from '@ohos.ability.featureAbility' import dataAbility from '@ohos.data.dataAbility' -import dataRdb from '@ohos.data.rdb' +import relationalStore from '@ohos.data.relationalStore' const TABLE_NAME = 'book' -const STORE_CONFIG = { name: 'book.db' } +const STORE_CONFIG = { name: 'book.db',securityLevel: 1 } const SQL_CREATE_TABLE = 'CREATE TABLE IF NOT EXISTS book(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, introduction TEXT NOT NULL)' -let rdbStore: dataRdb.RdbStore = undefined +let rdbStore: relationalStore.RdbStore = undefined export default { onInitialized(abilityInfo) { console.info('DataAbility onInitialized, abilityInfo:' + abilityInfo.bundleName) let context = featureAbility.getContext() - dataRdb.getRdbStore(context, STORE_CONFIG, 1, (err, store) => { + relationalStore.getRdbStore(context, STORE_CONFIG, (err, store) => { console.info('DataAbility getRdbStore callback') store.executeSql(SQL_CREATE_TABLE, []) rdbStore = store diff --git a/en/application-dev/application-models/data-share-via-want.md b/en/application-dev/application-models/data-share-via-want.md index d5512e0c446b94dcf384504f11ff25d458cfeafc..28184edbc9304e7c6fbfbfe673cf1b8deca7d635 100644 --- a/en/application-dev/application-models/data-share-via-want.md +++ b/en/application-dev/application-models/data-share-via-want.md @@ -48,9 +48,9 @@ function implicitStartAbility() { } } context.startAbility(wantInfo).then(() => { - // ... + ... }).catch((err) => { - // ... + ... }) } ``` @@ -66,8 +66,7 @@ In the preceding code, under the custom field **parameters**, the following **ab - **ability.picker.fileSizes**: file size, in bytes. - **ability.picker.fileNames** and **ability.picker.fileSizes** are arrays and have a one-to-one mapping. -The following figure shows an example. - +The following figure shows an example. ![](figures/ability-startup-with-implicit-want2.png) ## Shared Party @@ -77,17 +76,17 @@ To enable the shared party to identify the shared content, configure **skills** ```json { "module": { - // ... + ... "abilities": [ { - // ... + ... "skills": [ { - // ... + ... "actions": [ "action.system.home", "ohos.want.action.sendData" - // ... + ... ], "uris": [ { @@ -102,7 +101,7 @@ To enable the shared party to identify the shared content, configure **skills** } ``` -After the user selects an application, the Want nested in the **ability.want.params.INTENT** field is passed to that application. The UIAbility of the shared party, after being started, can call [onCreate()](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityoncreate) or [onNewWant()](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityonnewwant) to obtain the passed Want. +After the user selects an application, the Want nested in the **ability.want.params.INTENT** field is passed to that application. After the UIAbility of the application starts, the application obtains **want** information from [**onCreate()**](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityoncreate) or [**onNewWant()**](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityonnewwant). The following is an example of the Want obtained. You can use the FD of the shared file to perform required operations. diff --git a/en/application-dev/application-models/dataability-switch.md b/en/application-dev/application-models/dataability-switch.md index b91d50ca37a97fdc1d4824a93a6093bac7cd0f77..88ded48509863aa0e2c5b9d14eeaee590415b4da 100644 --- a/en/application-dev/application-models/dataability-switch.md +++ b/en/application-dev/application-models/dataability-switch.md @@ -7,9 +7,9 @@ The DataAbility component in the FA model corresponds to the DataShareExtensionA The DataShareExtensionAbility class provides system APIs. Only system applications can create DataShareExtensionAbility instances. Therefore, DataAbility switching adopts different policies for system applications and third-party applications. -## Switching a DataAbility of a System Application +## Switching a DataAbility for a System Application -The procedure for switching a DataAbility of a system application is similar to the procedure of PageAbility switching. +The procedure for switching a DataAbility for a system application is similar to the procedure of PageAbility switching. 1. Create a DataShareExtensionAbility in the stage model. @@ -34,7 +34,7 @@ The procedure for switching a DataAbility of a system application is similar to | call?(method: string, arg: string, extras: PacMap, callback: AsyncCallback<PacMap>): void | NA | This method is not provided in the stage model. You need to implement the functionality based on service functions.| -## Switching a DataAbility of a Third-Party Application +## Switching a DataAbility for a Third-Party Application In the stage model, third-party applications cannot provide data services for other third-party applications. You can select a switching solution based on your service requirements. diff --git a/en/application-dev/application-models/dataabilityhelper-switch.md b/en/application-dev/application-models/dataabilityhelper-switch.md index c709e30ae9c25bcbd47f781e1f43a51100960998..2f769679e695be9303548957d7738673d099389a 100644 --- a/en/application-dev/application-models/dataabilityhelper-switch.md +++ b/en/application-dev/application-models/dataabilityhelper-switch.md @@ -1,7 +1,7 @@ # DataAbilityHelper Switching - | API in the FA Model| Corresponding d.ts File in the Stage Model| Corresponding API in the Stage Model| + | API in the FA Model| Corresponding .d.ts File in the Stage Model| Corresponding API in the Stage Model| | -------- | -------- | -------- | | [openFile(uri: string, mode: string, callback: AsyncCallback<number>): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperopenfile)
[openFile(uri: string, mode: string): Promise<number>;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperopenfile-1) | \@ohos.data.fileAccess.d.ts | [openFile(uri: string, flags: OPENFLAGS) : Promise<number>;](../reference/apis/js-apis-fileAccess.md#fileaccesshelperopenfile)
[openFile(uri: string, flags: OPENFLAGS, callback: AsyncCallback<number>) : void;](../reference/apis/js-apis-fileAccess.md#fileaccesshelperopenfile) | | [on(type: 'dataChange', uri: string, callback: AsyncCallback<void>): void;](../reference/apis/js-apis-inner-ability-dataAbilityHelper.md#dataabilityhelperon) | \@ohos.data.dataShare.d.ts | [on(type: 'dataChange', uri: string, callback: AsyncCallback<void>): void;](../reference/apis/js-apis-data-dataShare.md#ondatachange) | diff --git a/en/application-dev/application-models/datashareextensionability.md b/en/application-dev/application-models/datashareextensionability.md deleted file mode 100644 index f671848f890277af92fc23869c5db0d57b02a316..0000000000000000000000000000000000000000 --- a/en/application-dev/application-models/datashareextensionability.md +++ /dev/null @@ -1,4 +0,0 @@ -# DataShareExtensionAbility (for System Applications Only) - - -DataShareExtensionAbility provides the data sharing capability. System applications can implement a DataShareExtensionAbility or access an existing DataShareExtensionAbility in the system. Third-party applications can only access an existing DataShareExtensionAbility. For details, see [DataShare Development](../database/database-datashare-guidelines.md). diff --git a/en/application-dev/application-models/enterprise-extensionAbility.md b/en/application-dev/application-models/enterprise-extensionAbility.md index 0038b41e5b4f654d8c7924ec1232bb342dd616cb..f3bda46a0b91c274aa4d41b4965fb0db34a1e808 100644 --- a/en/application-dev/application-models/enterprise-extensionAbility.md +++ b/en/application-dev/application-models/enterprise-extensionAbility.md @@ -1,4 +1,4 @@ -# EnterpriseAdminExtensionAbility Development +# EnterpriseAdminExtensionAbility ## Introduction to EnterpriseAdminExtensionAbility @@ -8,34 +8,35 @@ EnterpriseAdminExtensionAbility is a mandatory component for Mobile Device Manag EnterpriseAdminExtensionAbility is applicable only to enterprise administrator applications. -## Observing Activation/Deactivation of a Device Administrator Application and Installation/Removal of an Application + +## Observing Activation/Deactivation of a Device Administrator Application and Installation/Uninstallation of an Application ### Overview -**onAdminEnabled**: When an enterprise administrator or employee deploys an MDM application and activates the device administrator application, this callback is invoked to notify the MDM application that the DeviceAdmin permission is activated. The initialization policy of the MDM application can set in **onAdminEnabled**. +**onAdminEnabled**: called when an enterprise administrator or employee deploys an MDM application and enables the DeviceAdmin permission for the application. The MDM application can set the initialization policy in the **onAdminEnabled** callback. -**onAdminDisabled**: When the device administrator application is deactivated, the callback is invoked to notify the MDM application that the DeviceAdmin permission is deactivated. +**onAdminDisabled**: called when the system or employee disables the DeviceAdmin permission to notify the enterprise administrator that the device is no longer managed. -**onBundleAdded**: The enterprise administrator can subscribe to application installation and uninstallation events. When an application is installed on an enterprise device, the MDM application reports the event in this callback to notify the enterprise administrator. +**onBundleAdded**: The enterprise administrator can subscribe to application installation events. When an application is installed on an enterprise device, the MDM application reports the event in this callback to notify the enterprise administrator. -**onBundleRemoved**: When an application is removed from an enterprise device, the MDM application reports the event in this callback to notify the enterprise administrator. +**onBundleRemoved**: The enterprise administrator can subscribe to application uninstallation events. When an application is uninstalled on an enterprise device, the MDM application reports the event in this callback to notify the enterprise administrator. ### Available APIs | Class | API | Description | | ------------------------------ | ----------------------------------------- | ---------------------------- | -| EnterpriseAdminExtensionAbility | onAdminEnabled(): void | Called when a device administrator application is activated. | -| EnterpriseAdminExtensionAbility | onAdminDisabled(): void | Called when a device administrator application is deactivated.| -| EnterpriseAdminExtensionAbility | onBundleAdded(bundleName: string): void | Called when an application is installed on a device. | -| EnterpriseAdminExtensionAbility | onBundleRemoved(bundleName: string): void | Called when an application is removed from a device. | +| EnterpriseAdminExtensionAbility | onAdminEnabled(): void | Called when the device administrator application is disabled. | +| EnterpriseAdminExtensionAbility | onAdminDisabled(): void | Called when the device administrator application is enabled.| +| EnterpriseAdminExtensionAbility | onBundleAdded(bundleName: string): void | Called when the MDM application is installed. | +| EnterpriseAdminExtensionAbility | onBundleRemoved(bundleName: string): void | Called when the MDM application is uninstalled. | ### How to Develop To implement EnterpriseAdminExtensionAbility, you need to activate the device administrator application and create **ExtensionAbility** in the code directory of the device administrator application. The procedure is as follows: 1. In the **ets** directory of the target module, right-click and choose **New > Directory** to create a directory named **EnterpriseExtAbility**. -2. Right-click the **EnterpriseExtAbility** directory, and choose **New > TypeScript File** to create a file named **EnterpriseExtAbility.ts**. -3. Open the **EnterpriseExtAbility.ts** file and import the **EnterpriseAdminExtensionAbility** module. Inherit the **EnterpriseAdminExtensionAbility** module to the custom class and add application notification callbacks, such as **onAdminEnabled()** and **onAdminDisabled()**. When the device administrator application is activated or deactivated, the device administrator can receive notifications. +2. Right-click the **EnterpriseExtAbility** directory and choose **New > TypeScript File** to create a file named **EnterpriseExtAbility.ts**. +3. Open the **EnterpriseExtAbility.ts** file and import the **EnterpriseAdminExtensionAbility** module. Customize a class that inherits from **EnterpriseAdminExtensionAbility** and add the required callbacks, such as **onAdminEnabled()** and **onAdminDisabled()**, When the device administrator application is activated or deactivated, the device administrator can receive notifications. ```ts import EnterpriseAdminExtensionAbility from '@ohos.enterprise.EnterpriseAdminExtensionAbility'; @@ -60,15 +61,15 @@ To implement EnterpriseAdminExtensionAbility, you need to activate the device ad }; ``` -4. Register **ServiceExtensionAbility** in the [**module.json5**](../quick-start/module-configuration-file.md) file corresponding to the project module. Set **type** to **enterpriseAdmin** and **srcEntrance** to the path of the ExtensionAbility code. +4. Register **ServiceExtensionAbility** in the [**module.json5**](../quick-start/module-configuration-file.md) file corresponding to the project module. Set **type** to **enterpriseAdmin** and **srcEntry** to the path of the ExtensionAbility code. ```ts "extensionAbilities": [ { "name": "ohos.samples.enterprise_admin_ext_ability", "type": "enterpriseAdmin", - "visible": true, - "srcEntrance": "./ets/enterpriseextability/EnterpriseAdminAbility.ts" + "exported": true, + "srcEntry": "./ets/enterpriseextability/EnterpriseAdminAbility.ts" } ] ``` diff --git a/en/application-dev/application-models/explicit-implicit-want-mappings.md b/en/application-dev/application-models/explicit-implicit-want-mappings.md index 9e748a31795e3afc713e7091067a8164e8a623cc..454fc89d718fb4adfe84c0eab67ebc332117ed26 100644 --- a/en/application-dev/application-models/explicit-implicit-want-mappings.md +++ b/en/application-dev/application-models/explicit-implicit-want-mappings.md @@ -1,28 +1,28 @@ # Matching Rules of Explicit Want and Implicit Want -Both explicit Want and implicit Want can be used to match an ability to start based on certain rules. These rules determine how the parameters set in Want match the configuration file declared by the target ability. +Both explicit [Want](../reference/apis/js-apis-app-ability-want.md) and implicit [Want](../reference/apis/js-apis-app-ability-want.md) can be used to match an application component to start based on certain rules. These rules determine how the parameters set in [want](../reference/apis/js-apis-app-ability-want.md) match the configuration file declared by the target application component. ## Matching Rules of Explicit Want -The table below describes the matching rules of explicit Want. +The table below describes the matching rules of explicit [Want](../reference/apis/js-apis-app-ability-want.md). | Name| Type| Matching Item| Mandatory| Rule Description| | -------- | -------- | -------- | -------- | -------- | -| deviceId | string | Yes| No| If this field is unspecified, only abilities on the local device are matched.| +| deviceId | string | Yes| No| If this field is unspecified, only application components on the local device are matched.| | bundleName | string | Yes| Yes| If **abilityName** is specified but **bundleName** is unspecified, the matching fails.| -| moduleName | string | Yes| No| If this field is unspecified and multiple modules with the same ability name exist in the application, the first ability is matched by default.| +| moduleName | string | Yes| No| If this field is unspecified and multiple modules with the same ability name exist in the application, the first application component is matched by default.| | abilityName | string | Yes| Yes| To use explicit Want, this field must be specified.| -| uri | string | No| No| This field is not used for matching. It is passed to the target ability as a parameter.| -| type | string | No| No| This field is not used for matching. It is passed to the target ability as a parameter.| -| action | string | No| No| This field is not used for matching. It is passed to the target ability as a parameter.| -| entities | Array<string> | No| No| This field is not used for matching. It is passed to the target ability as a parameter.| +| uri | string | No| No| This field is not used for matching. It is passed to the target application component as a parameter.| +| type | string | No| No| This field is not used for matching. It is passed to the target application component as a parameter.| +| action | string | No| No| This field is not used for matching. It is passed to the target application component as a parameter.| +| entities | Array<string> | No| No| This field is not used for matching. It is passed to the target application component as a parameter.| | flags | number | No| No| This field is not used for matching and is directly transferred to the system for processing. It is generally used to set runtime information, such as URI data authorization.| -| parameters | {[key: string]: any} | No| No| This field is not used for matching. It is passed to the target ability as a parameter.| +| parameters | {[key: string]: any} | No| No| This field is not used for matching. It is passed to the target application component as a parameter.| ## Matching Rules for Implicit Want -The table below describes the matching rules of implicit Want. +The table below describes the matching rules of implicit [Want](../reference/apis/js-apis-app-ability-want.md). | Name | Type | Matching Item| Mandatory| Rule Description | | ----------- | ------------------------------ | ------ | ---- | ------------------------------------------------------------ | @@ -35,30 +35,32 @@ The table below describes the matching rules of implicit Want. | action | string | Yes | No | | | entities | Array<string> | Yes | No | | | flags | number | No | No | This field is not used for matching and is directly transferred to the system for processing. It is generally used to set runtime information, such as URI data authorization.| -| parameters | {[key: string]: any} | No | No | This field is not used for matching. It is passed to the target ability as a parameter. | +| parameters | {[key: string]: any} | No | No | This field is not used for matching. It is passed to the target application component as a parameter. | Get familiar with the following about implicit Want: - The **want** parameter passed by the caller indicates the operation to be performed by the caller. It also provides data and application type restrictions. -- The **skills** field declares the capabilities of the target ability. For details, see [the skills tag](../quick-start/module-configuration-file.md#skills) in the [module.json5 file](../quick-start/module-configuration-file.md). +- The **skills** field declares the capabilities of the target application component. For details, see [the skills tag](../quick-start/module-configuration-file.md#skills) in the [module.json5 file](../quick-start/module-configuration-file.md). -The system matches the **want** parameter (including the **action**, **entities**, **uri**, and **type** attributes) passed by the caller against the **skills** configuration (including the **actions**, **entities**, **uris**, and **type** attributes) of the abilities one by one. When all the four attributes are matched, a dialog box is displayed for users to select a matched application. +The system matches the **want** parameter (including the **action**, **entities**, **uri**, and **type** attributes) passed by the caller against the **skills** configuration (including the **actions**, **entities**, **uris**, and **type** attributes) of the application components one by one. When all the four attributes are matched, a dialog box is displayed for users to select a matched application. ### Matching Rules of action in the want Parameter -The system matches the **action** attribute in the **want** parameter passed by the caller against **actions** under **skills** of the abilities. +The system matches the **action** attribute in the **want** parameter passed by the caller against **actions** under **skills** of the application components. -- If **action** in the passed **want** parameter is specified but **actions** under **skills** of an ability is unspecified, the matching fails. +- If **action** in the passed **want** parameter is unspecified and **actions** under **skills** of an application component is unspecified, the matching fails. -- If **action** in the passed **want** parameter is unspecified but **actions** under **skills** of an ability is specified, the matching is successful. +- If **action** in the passed **want** parameter is specified but **actions** under **skills** of an application component is unspecified, the matching fails. -- If **action** in the passed **want** parameter is specified, and **actions** under **skills** of an ability is specified and contains **action** in the passed **want** parameter, the matching is successful. +- If **action** in the passed **want** parameter is unspecified but **actions** under **skills** of an application component is specified, the matching is successful. -- If **action** in the passed **want** parameter is specified, and **actions** under **skills** of an ability is specified but does not contain **action** in the passed **want** parameter, the matching fails. +- If **action** in the passed **want** parameter is specified, and **actions** under **skills** of an application component is specified and contains **action** in the passed **want** parameter, the matching is successful. + +- If **action** in the passed **want** parameter is specified, and **actions** under **skills** of an application component is specified but does not contain **action** in the passed **want** parameter, the matching fails. **Figure 1** Matching rules of action in the want parameter @@ -67,55 +69,56 @@ The system matches the **action** attribute in the **want** parameter passed by ### Matching Rules of entities in the want Parameter -The system matches the **entities** attribute in the **want** parameter passed by the caller against **entities** under **skills** of the abilities. +The system matches the **entities** attribute in the **want** parameter passed by the caller against **entities** under **skills** of the application components. -- If **entities** in the passed **want** parameter is unspecified but **entities** under **skills** of an ability is specified, the matching is successful. +- If **entities** in the passed **want** parameter is unspecified but **entities** under **skills** of an application component is specified, the matching is successful. -- If **entities** in the passed **want** parameter is unspecified but **entities** under **skills** of an ability is unspecified, the matching is successful. +- If **entities** in the passed **want** parameter is unspecified but **entities** under **skills** of an application component is unspecified, the matching is successful. -- If **entities** in the passed **want** parameter is specified but **entities** under **skills** of an ability is unspecified, the matching fails. +- If **entities** in the passed **want** parameter is specified but **entities** under **skills** of an application component is unspecified, the matching fails. -- If **entities** in the passed **want** parameter is specified, and **entities** under **skills** of an ability is specified and contains **entities** in the passed **want** parameter, the matching is successful. +- If **entities** in the passed **want** parameter is specified, and **entities** under **skills** of an application component is specified and contains **entities** in the passed **want** parameter, the matching is successful. -- If **entities** in the passed **want** parameter is specified, and **entities** under **skills** of an ability is specified but does not contain **entities** in the passed **want** parameter, the matching fails. +- If **entities** in the passed **want** parameter is specified, and **entities** under **skills** of an application component is specified but does not contain **entities** in the passed **want** parameter, the matching fails. - **Figure 2** Matching rule of entities in the want parameter + **Figure 2** Matching rules of entities in the want parameter ![want-entities](figures/want-entities.png) ### Matching Rules of uri and type in the want Parameter -When the **uri** and **type** parameters are specified in the **want** parameter to initiate a component startup request, the system traverses the list of installed components and matches the **uris** array under **skills** of the abilities one by one. If one of the **uris** arrays under **skills** matches the **uri** and **type** in the passed **want**, the matching is successful. +When the **uri** and **type** parameters are specified in the **want** parameter to initiate an application component startup request, the system traverses the list of installed components and matches the **uris** array under **skills** of the application components one by one. If one of the **uris** arrays under **skills** matches the **uri** and **type** in the passed **want**, the matching is successful. There are four combinations of **uri** and **type** settings. The matching rules are as follows: - Neither **uri** or **type** is specified in the **want** parameter. - - If the **uris** array under **skills** of an ability is unspecified, the matching is successful. - - If the **uris** array under **skills** of an ability contains an URI element whose **scheme** and **type** are unspecified, the matching is successful. + - If the **uris** array under **skills** of an application component is unspecified, the matching is successful. + - If the **uris** array under **skills** of an application component contains an URI element whose **scheme** and **type** are unspecified, the matching is successful. - In other cases, the matching fails. - Only **uri** is specified in the **want** parameter. - - If the **uris** array under **skills** of an ability is unspecified, the matching fails. - - If the **uris** array under **skills** of an ability contains an element whose [uri is matched](#matching-rules-of-uri) and **type** is unspecified, the matching is successful. Otherwise, the matching fails. + - If the **uris** array under **skills** of an application component is unspecified, the matching fails. + - If the **uris** array under **skills** of an application component contains an element whose [uri is matched](#matching-rules-of-uri) and **type** is unspecified, the matching is successful. Otherwise, the matching fails. - Only **type** is specified in the **want** parameter. - - If the **uris** array under **skills** of an ability is unspecified, the matching fails. - - If the **uris** array under **skills** of an ability contains an URI element whose **scheme** is unspecified and [type is matched](#matching-rules-of-type), the matching is successful. Otherwise, the matching fails. + - If the **uris** array under **skills** of an application component is unspecified, the matching fails. + - If the **uris** array under **skills** of an application component contains an URI element whose **scheme** is unspecified and [type is matched](#matching-rules-of-type), the matching is successful. Otherwise, the matching fails. -- Both **uri** and **type** are specified in the **want** parameter, as shown in Figure 3. - - If the **uris** array under **skills** of an ability is unspecified, the matching fails. - - If the **uris** array under **skills** of an ability contains an element whose [uri is matched](#matching-rules-of-uri) and [type is matched](#matching-rules-of-type), the matching is successful. Otherwise, the matching fails. +- Both **uri** and **type** are specified in the **want** parameter, as shown below. + - If the **uris** array under **skills** of an application component is unspecified, the matching fails. + - If the **uris** array under **skills** of an application component contains an element whose [uri is matched](#matching-rules-of-uri) and [type is matched](#matching-rules-of-type), the matching is successful. Otherwise, the matching fails. -Leftmost URI matching: When only **scheme**, a combination of **scheme** and **host**, or a combination of **scheme**, **host**, and **port** is configured in the **uris** array under **skills** of the ability, -the matching is successful only if the leftmost URI in the passed **want** parameter matches **scheme**, the combination of **scheme** and **host**, or the combination of **scheme**, **host**, and **port**. +Leftmost URI matching: When only **scheme**, a combination of **scheme** and **host**, or a combination of **scheme**, **host**, and **port** is configured in the **uris** array under **skills** of the application component, the matching is successful only if the leftmost URI in the passed **want** parameter matches **scheme**, the combination of **scheme** and **host**, or the combination of **scheme**, **host**, and **port**. **Figure 3** Matching rules when uri and type are specified in the want parameter - ![want-uri-type1](figures/want-uri-type1.png) +![want-uri-type1](figures/want-uri-type1.png) +To simplify the description: -To simplify the description, **uri** and **type** passed in the **want** parameter are called **w_uri** and **w_type**, respectively; the **uris** array under **skills** of an ability to match is called **s_uris**; each element in the array is called **s_uri**. Matching is performed from top to bottom. +- **uri** in the **want** parameter passed in by the caller is called **w_uri**; each element in the **uris** array under **skills** of the application component to match is called **s_uri**. +- **type** in the **want** parameter passed in by the caller is called **w_type**; the type in the **uris** array under **skills** of the application component to match is called **s_type**. **Figure 4** Matching rules of uri and type in the want parameter @@ -124,7 +127,7 @@ To simplify the description, **uri** and **type** passed in the **want** paramet ### Matching Rules of uri -To simplify the description, **uri** in the passed **want** parameter is called **w_uri**; **uri** under **skills** of an ability to match is called **s_uri**. The matching rules are as follows: +The rules are as follows: - If **scheme** of **s_uri** is unspecified and **w_uri** is unspecified, the matching is successful. Otherwise, the matching fails. @@ -142,18 +145,15 @@ To simplify the description, **uri** in the passed **want** parameter is called > **NOTE** > -> The **scheme**, **host**, **port**, **path**, **pathStartWith**, and **pathRegex** attributes of **uris** under **skills** of an ability are concatenated. If **path**, **pathStartWith**, and **pathRegex** are declared in sequence, **uris** can be concatenated into the following expressions: -> -> - **Full path expression**: `scheme://host:port/path` -> -> - **Prefix expression**: `scheme://host:port/pathStartWith` -> -> - **Regular expression**: `scheme://host:port/pathRegex` +> The **scheme**, **host**, **port**, **path**, **pathStartWith**, and **pathRegex** attributes of **uris** under **skills** of an application component are concatenated. If **path**, **pathStartWith**, and **pathRegex** are declared in sequence, **uris** can be concatenated into the following expressions: > > - **Prefix URI expression**: When only **scheme**, a combination of **scheme** and **host**, or a combination of **scheme**, **host**, and **port** is configured in the configuration file, the matching is successful if a URI prefixed with the configuration file is passed in. > * `scheme://` > * `scheme://host` > * `scheme://host:port` +> - **Full path expression**: `scheme://host:port/path` +> - **Prefix expression**: `scheme://host:port/pathStartWith` +> - **Regular expression**: `scheme://host:port/pathRegex` ### Matching Rules of type @@ -162,7 +162,7 @@ To simplify the description, **uri** in the passed **want** parameter is called > > The matching rules of **type** described in this section are based on the fact that **type** in the **want** parameter is specified. If **type** is unspecified, follow the [matching rules of uri and type in the want parameter](#matching-rules-of-uri-and-type-in-the-want-parameter). -To simplify the description, **uri** in the passed **want** parameter is called **w_type**, and **type** of **uris** under **skills** of an ability to match is called **s_type**. The matching rules are as follows: +The matching rules are as follows: - If **s_type** is unspecified, the matching fails. diff --git a/en/application-dev/application-models/extensionability-overview.md b/en/application-dev/application-models/extensionability-overview.md index a287fe9ac7a590bb8675a0ae0f459463ade4ff1b..dcadce1b16a3f04af0862169e98b7837841716f3 100644 --- a/en/application-dev/application-models/extensionability-overview.md +++ b/en/application-dev/application-models/extensionability-overview.md @@ -1,40 +1,40 @@ -# ExtensionAbility Component Overview +# ExtensionAbility Overview -The ExtensionAbility component is used for specific scenarios such as widgets and input methods. +The ExtensionAbility component is used for specific scenarios such as widget development and input method development. -An [ExtensionAbilityType](../reference/apis/js-apis-bundleManager.md#extensionabilitytype) is provided for every specific scenario. All types of ExtensionAbility components are managed by the corresponding system services in a unified manner. For example, the InputMethodExtensionAbility component is managed by the input method management service. The following ExtensionAbility types are supported: +An [ExtensionAbility type](../reference/apis/js-apis-bundleManager.md#extensionabilitytype) is provided for every specific scenario. All types of ExtensionAbility components are managed by the corresponding system services in a unified manner. For example, the InputMethodExtensionAbility component is managed by the input method management service. The following ExtensionAbility types are supported: - [FormExtensionAbility](../reference/apis/js-apis-app-form-formExtensionAbility.md): ExtensionAbility component of the form type, which provides APIs related to widgets. - [WorkSchedulerExtensionAbility](../reference/apis/js-apis-WorkSchedulerExtensionAbility.md): ExtensionAbility component of the work_scheduler type, which provides callbacks for Work Scheduler tasks. -- [InputMethodExtensionAbility](../reference/apis/js-apis-inputmethod.md): ExtensionAbility component of the input_method type, which provides an input method framework that can be used to hide the keyboard, obtain the list of installed input methods, display the dialog box for input method selection, and more. +- [InputMethodExtensionAbility](../reference/apis/js-apis-inputmethod.md): ExtensionAbility component of the input_method type, which is used to develop input method applications. -- [ServiceExtensionAbility](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md): ExtensionAbility component of the service type, which provides APIs related to background service scenarios. +- [ServiceExtensionAbility](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md): ExtensionAbility component of the service type, which provides APIs related to background services. - [AccessibilityExtensionAbility](../reference/apis/js-apis-application-accessibilityExtensionAbility.md): ExtensionAbility component of the accessibility type, which provides APIs related to the accessibility feature. -- [DataShareExtensionAbility](../reference/apis/js-apis-application-dataShareExtensionAbility.md): ExtensionAbility component of the data_share type, which provides APIs for data sharing. +- [DataShareExtensionAbility (for system applications only)](../reference/apis/js-apis-application-dataShareExtensionAbility.md): ExtensionAbility component of the data_share type, which provides APIs for data sharing. - [StaticSubscriberExtensionAbility](../reference/apis/js-apis-application-staticSubscriberExtensionAbility.md): ExtensionAbility component of the static_subscriber type, which provides APIs for static broadcast. -- [WindowExtensionAbility](../reference/apis/js-apis-application-windowExtensionAbility.md): ExtensionAbility component of the window type, which allows a system application to be embedded in and displayed over another application. +- [WindowExtensionAbility (for system applications only)](../reference/apis/js-apis-application-windowExtensionAbility.md): ExtensionAbility component of the window type, which allows a system application to be embedded in and displayed over another application. - [EnterpriseAdminExtensionAbility](../reference/apis/js-apis-EnterpriseAdminExtensionAbility.md): ExtensionAbility component of the enterprise_admin type, which provides APIs for processing enterprise management events, such as application installation events on devices and events indicating too many incorrect screen-lock password attempts. -> **NOTE**
-> 1. Third-party applications cannot implement ServiceExtensionAbility, DataShareExtensionAbility, StaticSubscriberExtensionAbility, or WindowExtensionAbility. -> -> 2. To implement transaction processing in the background for a third-party application, use background tasks rather than ServiceExtensionAbility. For details, see [Background Task](../task-management/background-task-overview.md). -> -> 3. Third-party applications can use other types of ExtensionAbility components that have been defined. +> **NOTE** +> +>- Third-party applications cannot implement ServiceExtensionAbility, DataShareExtensionAbility, StaticSubscriberExtensionAbility, or WindowExtensionAbility. They can use other types of ExtensionAbility components that have been defined. +> +>- To implement transaction processing in the background for a third-party application, use background tasks rather than ServiceExtensionAbility. For details, see [Background Task](../task-management/background-task-overview.md). + ## Using ExtensionAbility of the Specified Type -All types of ExtensionAbility components are started by the corresponding system management service, rather than applications, so that their lifecycles are under control by the system. The caller of the ExtensionAbility component does not need to care about its lifecycle. +Each type of ExtensionAbility component is started by the corresponding system management service, rather than applications, so that its lifecycle is under system control. The caller of the ExtensionAbility component does not need to care about its lifecycle. The following uses [InputMethodExtensionAbility](../reference/apis/js-apis-inputmethod.md) as an example. As shown in the figure below, when an application calls the InputMethodExtensionAbility component, the input method management service is called first. The input method management service starts the InputMethodExtensionAbility component, returns the component to the application, and starts to manage its lifecycle. @@ -45,21 +45,21 @@ The following uses [InputMethodExtensionAbility](../reference/apis/js-apis-input ## Implementing ExtensionAbility of the Specified Type -The following uses [FormExtensionAbility](../reference/apis/js-apis-app-form-formExtensionAbility.md) as an example. The widget framework provides the base class [FormExtensionAbility](../reference/apis/js-apis-app-form-formExtensionAbility.md). You derive this base class to create your own class (such as **MyFormExtensionAbility**), implement the callbacks, such as **onCreate()** and **onUpdateForm()**, to provide specific widget functionalities. For details, see [FormExtensionAbility](Widget-development-stage.md). +The following uses [FormExtensionAbility](../reference/apis/js-apis-app-form-formExtensionAbility.md) as an example. The widget framework provides the base class [FormExtensionAbility](../reference/apis/js-apis-app-form-formExtensionAbility.md). You can derive this base class to create your own class (for example, **MyFormExtensionAbility**) and implement the callbacks, such as **onCreate()** and **onUpdateForm()**, to provide specific widget features. For details, see [FormExtensionAbility](service-widget-overview.md). -You do not need to care when to add or delete a widget. The lifecycle of the FormExtensionAbility instance and the lifecycle of the ExtensionAbility process where the FormExtensionAbility instance is located are scheduled and managed by FormManagerService. +You do not need to care when to add or delete a widget. The lifecycle of the FormExtensionAbility instance and the lifecycle of the ExtensionAbility process where the FormExtensionAbility instance is located are managed by FormManagerService. ![form_extension](figures/form_extension.png) > **NOTE** > -> For an application, all ExtensionAbility components of the same type run in an independent process, whereas UIAbility, ServiceExtensionAbility, and DataShareExtensionAbility run in another independent process. For details, see [Process Model (Stage Model)](process-model-stage.md). -> -> For example, an application has one UIAbility component, one ServiceExtensionAbility, one DataShareExtensionAbility, two FormExtensionAbility, and one ImeExtensionAbility. When the application is running, there are three processes: -> +> For an application, all ExtensionAbility components of the same type run in an independent process, whereas the UIAbility, ServiceExtensionAbility, and DataShareExtensionAbility components run in another independent process. For details, see [Process Model (Stage Model)](process-model-stage.md). +> +> For example, if an application has one UIAbility component, one ServiceExtensionAbility component, one DataShareExtensionAbility component, two FormExtensionAbility components, and one ImeExtensionAbility component, there will be three processes when the application is running. +> > - UIAbility, ServiceExtensionAbility, and DataShareExtensionAbility run in an independent process. -> +> > - The two FormExtensionAbility components run in an independent process. -> +> > - The two ImeExtensionAbility components run in an independent process. diff --git a/en/application-dev/application-models/fa-model-development-overview.md b/en/application-dev/application-models/fa-model-development-overview.md index 07e7ef8a0bdaea927762c15e4123ae728c026cb7..295e1863556cd37c7bc7e8cb588eaabbb9decb14 100644 --- a/en/application-dev/application-models/fa-model-development-overview.md +++ b/en/application-dev/application-models/fa-model-development-overview.md @@ -8,8 +8,8 @@ During application development based on the Feature Ability (FA) model, the foll | Task| Introduction| Guide| | -------- | -------- | -------- | -| Application component development| Use the PageAbility, ServiceAbility, DataAbility, and widgets of the FA model to develop applications.| - [Application- or Component-Level Configuration](application-component-configuration-fa.md)
- [PageAbility Component](pageability-overview.md)
- [ServiceAbility Component](serviceability-overview.md)
- [DataAbility Component](dataability-overview.md)
- [Widget Development](Widget-development-fa.md)
- [Context](application-context-fa.md)
- [Want](want-fa.md) | -| Inter-process communication (IPC)| Learn the process model and common IPC modes of the FA model.| [Common Events](common-event-fa.md)
[Background Services](rpc.md) | -| Inter-thread communication| Learn the thread model and common inter-thread communication modes of the FA model.| [Inter-Thread Communication](itc-fa-overview.md)| +| Application component development| Use the PageAbility, ServiceAbility, DataAbility, and widgets of the FA model to develop applications.| - [Application- or Component-Level Configuration](application-component-configuration-fa.md)
- [PageAbility Component](pageability-overview.md)
- [ServiceAbility Component](serviceability-overview.md)
- [DataAbility Component](dataability-overview.md)
- [Widget Development](widget-development-fa.md)
- [Context](application-context-fa.md)
- [Want](want-fa.md)| +| Process model| Learn the process model and common IPC modes of the FA model.| [Common Events](common-event-fa.md)
[Background Services](rpc.md)| +| Thread model| Learn the thread model and common inter-thread communication modes of the FA model.| [Inter-Thread Communication](itc-fa-overview.md)| | Mission management| Learn the basic concepts and typical scenarios of mission management in the FA model.| [Mission Management](mission-management-fa.md)| -| Application configuration file| Learn the requirements for developing application configuration files in the FA model.| [Application Configuration File](config-file-fa.md) | +| Application configuration file| Learn the requirements for developing application configuration files in the FA model.| [Application Configuration File](config-file-fa.md)| diff --git a/en/application-dev/application-models/fa-stage-interaction-overview.md b/en/application-dev/application-models/fa-stage-interaction-overview.md index 0d1ed27f0df2d4964b0d69faf48afcb42e32bf91..d9f71ea983fd65a4e02174478eaf09de2256be42 100644 --- a/en/application-dev/application-models/fa-stage-interaction-overview.md +++ b/en/application-dev/application-models/fa-stage-interaction-overview.md @@ -4,22 +4,23 @@ The FA model is supported by API version 8 and earlier versions, and the stage model is recommended since API version 9. The FA model and stage model have their respective components. The FA model provides three types of application components: PageAbility, ServiceAbility, and DataAbility. The stage model provides two types of application components: UIAbility and ExtensionAbility. -You cannot use both models for the development of an application (see the figure below). However, a device (system) can contain applications developed on both models (scenario 3 in the figure below). In this case, their components may interact with each other. +You cannot use both models for the development of an application (see the figure below). However, a device (system) can contain applications developed on different models (scenario 3 in the figure below). In this case, their components may interact with each other. + +**Figure 1** Coexistent application components of the FA model and stage model -Figure 1 Coexistent application components of the FA model and stage model ![coexistence-of-FAandStage](figures/coexistence-of-FAandStage.png) -The following table lists the possible interaction scenarios. You must pay attention to the concerns listed below during your application development. +The following table lists the possible interaction scenarios and the concerns of each scenario. -Table 1 Application component interaction scenarios +**Table 1** Application component interaction scenarios | Interaction Scenario| Concerns| | -------- | -------- | -| [Starting a UIAbility from the FA Model](start-uiability-from-fa.md) | Set **bundleName** and **abilityName** in the **want** parameter to the bundle name and ability name of the UIAbility in the stage model.| -| [Connecting to a ServiceExtensionAbility from the FA Model](bind-serviceextensionability-from-fa.md) | Set **bundleName** and **abilityName** in the **want** parameter to the bundle name and ability name of the ServiceExtensionAbility in the stage model.| -| [Accessing a DataShareExtensionAbility from the FA Model](access-datashareextensionability-from-fa.md) | No code modification is required. However, you need to understand the API compatibility of **DataShareHelper** and **DataAbilityHelper**.| -| [Starting a PageAbility from the Stage Model](start-pageability-from-stage.md) | Set **bundleName** and **abilityName** in the **want** parameter to the bundle name and ability name of the PageAbility in the FA model.| -| [Connecting to a ServiceAbility from the Stage Model](bind-serviceability-from-stage.md) | Set **bundleName** and **abilityName** in the **want** parameter to the bundle name and ability name of the ServiceAbility in the FA model.| -| Accessing a DataAbility from the Stage Model | This type of access is not supported.| +| [Starting a UIAbility from the FA Model](start-uiability-from-fa.md)| Set **bundleName** and **abilityName** in the **want** parameter to the bundle name and ability name of the UIAbility in the stage model.| +| [Connecting to a ServiceExtensionAbility from the FA Model](bind-serviceextensionability-from-fa.md)| Set **bundleName** and **abilityName** in the **want** parameter to the bundle name and ability name of the ServiceExtensionAbility in the stage model.| +| [Accessing a DataShareExtensionAbility from the FA Model](access-datashareextensionability-from-fa.md)| No code modification is required. However, you need to understand the API compatibility of **DataShareHelper** and **DataAbilityHelper**.| +| [Starting a PageAbility from the Stage Model](start-pageability-from-stage.md)| Set **bundleName** and **abilityName** in the **want** parameter to the bundle name and ability name of the PageAbility in the FA model.| +| [Connecting to a ServiceAbility from the Stage Model](bind-serviceability-from-stage.md)| Set **bundleName** and **abilityName** in the **want** parameter to the bundle name and ability name of the ServiceAbility in the FA model.| +| Accessing a DataAbility from the Stage Model| This type of access is not supported.| diff --git a/en/application-dev/application-models/featureability-switch.md b/en/application-dev/application-models/featureability-switch.md index f7db8056ea156650e11b55a78137de194ce9d43f..b4c0254a320b85e9b87c8907505a3e3a91cbf582 100644 --- a/en/application-dev/application-models/featureability-switch.md +++ b/en/application-dev/application-models/featureability-switch.md @@ -1,9 +1,9 @@ # featureAbility Switching -| API in the FA Model| Corresponding d.ts File in the Stage Model| Corresponding API in the Stage Model| + | API in the FA Model| Corresponding .d.ts File in the Stage Model| Corresponding API in the Stage Model| | -------- | -------- | -------- | -| [getWant(callback: AsyncCallback<Want>): void;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitygetwant)
[getWant(): Promise<Want>;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitygetwant-1) | \@ohos.app.ability.UIAbility.d.ts | [launchWant: Want;](../reference/apis/js-apis-app-ability-uiAbility.md#attributes)| +| [getWant(callback: AsyncCallback<Want>): void;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitygetwant)
[getWant(): Promise<Want>;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitygetwant-1) | \@ohos.app.ability.UIAbility.d.ts | [launchWant: Want;](../reference/apis/js-apis-app-ability-uiAbility.md#attributes)| | [startAbility(parameter: StartAbilityParameter, callback: AsyncCallback<number>): void;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitystartability)
[startAbility(parameter: StartAbilityParameter): Promise<number>;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitystartability-1) | application\UIAbilityContext.d.ts | [startAbility(want: Want, callback: AsyncCallback<void>): void;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartability)
[startAbility(want: Want, options: StartOptions, callback: AsyncCallback<void>): void;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartability-1)
[startAbility(want: Want, options?: StartOptions): Promise<void>;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartability-2) | | [getContext(): Context;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitygetcontext) | \@ohos.app.ability.UIAbility.d.ts | [context: UIAbilityContext;](../reference/apis/js-apis-app-ability-uiAbility.md#attributes)| | [startAbilityForResult(parameter: StartAbilityParameter, callback: AsyncCallback<AbilityResult>): void;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitystartabilityforresult7)
[startAbilityForResult(parameter: StartAbilityParameter): Promise<AbilityResult>;](../reference/apis/js-apis-ability-featureAbility.md#featureabilitystartabilityforresult7-1) | application\UIAbilityContext.d.ts | [startAbilityForResult(want: Want, callback: AsyncCallback<AbilityResult>): void;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartabilityforresult)
[startAbilityForResult(want: Want, options: StartOptions, callback: AsyncCallback<AbilityResult>): void;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartabilityforresult-1)
[startAbilityForResult(want: Want, options?: StartOptions): Promise<AbilityResult>;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartabilityforresult-2) | diff --git a/en/application-dev/application-models/figures/AccessibilityFramework.png b/en/application-dev/application-models/figures/AccessibilityFramework.png new file mode 100644 index 0000000000000000000000000000000000000000..786233e6ac160972f62b9786397eb077f7ee767c Binary files /dev/null and b/en/application-dev/application-models/figures/AccessibilityFramework.png differ diff --git a/en/application-dev/application-models/figures/JSCardPrinciple.png b/en/application-dev/application-models/figures/JSCardPrinciple.png new file mode 100644 index 0000000000000000000000000000000000000000..558c2c2a679737eed2bf3b129f632e6300d0d2da Binary files /dev/null and b/en/application-dev/application-models/figures/JSCardPrinciple.png differ diff --git a/en/application-dev/application-models/figures/WidgerCameraCard.png b/en/application-dev/application-models/figures/WidgerCameraCard.png new file mode 100644 index 0000000000000000000000000000000000000000..55e62cdb8791ca6bbc95b7ea4c054e93270ce7a6 Binary files /dev/null and b/en/application-dev/application-models/figures/WidgerCameraCard.png differ diff --git a/en/application-dev/application-models/figures/WidgetAnimation.gif b/en/application-dev/application-models/figures/WidgetAnimation.gif new file mode 100644 index 0000000000000000000000000000000000000000..eaddfb4cf4d0bf9613b3a108c26ea1617d68d3c1 Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetAnimation.gif differ diff --git a/en/application-dev/application-models/figures/WidgetArchitecture.png b/en/application-dev/application-models/figures/WidgetArchitecture.png new file mode 100644 index 0000000000000000000000000000000000000000..b97ddda74fb89f32ed248c1d4c6d3e8e6e100a05 Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetArchitecture.png differ diff --git a/en/application-dev/application-models/figures/WidgetCanvasDemo.jpeg b/en/application-dev/application-models/figures/WidgetCanvasDemo.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..3961eba1947c74229e43af53d1ad525af414028f Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetCanvasDemo.jpeg differ diff --git a/en/application-dev/application-models/figures/WidgetCardPage.png b/en/application-dev/application-models/figures/WidgetCardPage.png new file mode 100644 index 0000000000000000000000000000000000000000..795e96171e6d890e72a09382906302dd0fa45fab Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetCardPage.png differ diff --git a/en/application-dev/application-models/figures/WidgetLocalStorageProp.png b/en/application-dev/application-models/figures/WidgetLocalStorageProp.png new file mode 100644 index 0000000000000000000000000000000000000000..1a45723865ff9f990c3a4197338e9cbc9eb3b6f4 Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetLocalStorageProp.png differ diff --git a/en/application-dev/application-models/figures/WidgetModules.png b/en/application-dev/application-models/figures/WidgetModules.png new file mode 100644 index 0000000000000000000000000000000000000000..6eaac0b6ca404eb9575587add72935e9ce580030 Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetModules.png differ diff --git a/en/application-dev/application-models/figures/WidgetPostCardAction.png b/en/application-dev/application-models/figures/WidgetPostCardAction.png new file mode 100644 index 0000000000000000000000000000000000000000..42a07e13036d6252309ca4e4bc857043486269c8 Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetPostCardAction.png differ diff --git a/en/application-dev/application-models/figures/WidgetPreviewPage.png b/en/application-dev/application-models/figures/WidgetPreviewPage.png new file mode 100644 index 0000000000000000000000000000000000000000..5f614e3db780f8d83f3c2f0865a9521aacd2b0de Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetPreviewPage.png differ diff --git a/en/application-dev/application-models/figures/WidgetPrinciple.png b/en/application-dev/application-models/figures/WidgetPrinciple.png new file mode 100644 index 0000000000000000000000000000000000000000..68ca315394fe2cb5bd2580ca6df38b9940ac1349 Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetPrinciple.png differ diff --git a/en/application-dev/application-models/figures/WidgetProject.png b/en/application-dev/application-models/figures/WidgetProject.png new file mode 100644 index 0000000000000000000000000000000000000000..299eed75fc1edfd9557e0fe743facb0e9c8d94b2 Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetProject.png differ diff --git a/en/application-dev/application-models/figures/WidgetProjectCreate1.png b/en/application-dev/application-models/figures/WidgetProjectCreate1.png new file mode 100644 index 0000000000000000000000000000000000000000..5369f48edcee476ae8317b9f0e1fb98b06607e93 Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetProjectCreate1.png differ diff --git a/en/application-dev/application-models/figures/WidgetProjectCreate2.png b/en/application-dev/application-models/figures/WidgetProjectCreate2.png new file mode 100644 index 0000000000000000000000000000000000000000..7bf742e04e2f30febb05f2d8638193dc10532863 Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetProjectCreate2.png differ diff --git a/en/application-dev/application-models/figures/WidgetProjectCreate3.png b/en/application-dev/application-models/figures/WidgetProjectCreate3.png new file mode 100644 index 0000000000000000000000000000000000000000..98429567ad24b1a83c67118173bf6cb504bea25d Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetProjectCreate3.png differ diff --git a/en/application-dev/application-models/figures/WidgetProjectView.png b/en/application-dev/application-models/figures/WidgetProjectView.png new file mode 100644 index 0000000000000000000000000000000000000000..9d1c06e47502131983b0b7cd56e66269b5be6d88 Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetProjectView.png differ diff --git a/en/application-dev/application-models/figures/WidgetRender.png b/en/application-dev/application-models/figures/WidgetRender.png new file mode 100644 index 0000000000000000000000000000000000000000..0f46bd74b0e48ac0c9f947d96d5e147786f547c0 Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetRender.png differ diff --git a/en/application-dev/application-models/figures/WidgetSupportApi.png b/en/application-dev/application-models/figures/WidgetSupportApi.png new file mode 100644 index 0000000000000000000000000000000000000000..1ac3d68c19683c69a16f5ebc305f3b79cb8c6566 Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetSupportApi.png differ diff --git a/en/application-dev/application-models/figures/WidgetUpdatePage.png b/en/application-dev/application-models/figures/WidgetUpdatePage.png new file mode 100644 index 0000000000000000000000000000000000000000..075c8e97c85386c062a651f3b4f876e6c049171f Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetUpdatePage.png differ diff --git a/en/application-dev/application-models/figures/WidgetUse.png b/en/application-dev/application-models/figures/WidgetUse.png new file mode 100644 index 0000000000000000000000000000000000000000..9bcc46d9044b04633692171f6a553bf43ce147c3 Binary files /dev/null and b/en/application-dev/application-models/figures/WidgetUse.png differ diff --git a/en/application-dev/application-models/figures/application_details.jpg b/en/application-dev/application-models/figures/application_details.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e849a47b3d10faefafbf76a7b6309da305a2e9b0 Binary files /dev/null and b/en/application-dev/application-models/figures/application_details.jpg differ diff --git a/en/application-dev/application-models/figures/globalThis1.png b/en/application-dev/application-models/figures/globalThis1.png index 128f79d3437304845ac822d32377dab4cf0c9e05..eebbd55560ec8ab84cea439d8cf17d6ea8294ccb 100644 Binary files a/en/application-dev/application-models/figures/globalThis1.png and b/en/application-dev/application-models/figures/globalThis1.png differ diff --git a/en/application-dev/application-models/figures/hop-cross-device-migration.png b/en/application-dev/application-models/figures/hop-cross-device-migration.png index 1623bc94af414539f6634aea6d583e205eccf409..82a819977da9ff408223ce6ae1fdb09573c15b5b 100644 Binary files a/en/application-dev/application-models/figures/hop-cross-device-migration.png and b/en/application-dev/application-models/figures/hop-cross-device-migration.png differ diff --git a/en/application-dev/application-models/figures/hop-multi-device-collaboration.png b/en/application-dev/application-models/figures/hop-multi-device-collaboration.png index 28fa0a6e269a4266236898e19ce7bca4e670027d..a6a3ccbd0efe7a942f22ab99eb369c37b3d981ac 100644 Binary files a/en/application-dev/application-models/figures/hop-multi-device-collaboration.png and b/en/application-dev/application-models/figures/hop-multi-device-collaboration.png differ diff --git a/en/application-dev/application-models/figures/hop-structure.png b/en/application-dev/application-models/figures/hop-structure.png index 96b82de856fcbc7db6d7668791a668ec152141fc..76b9d3c483dab44dd4eea2d65324bfc2d385cabe 100644 Binary files a/en/application-dev/application-models/figures/hop-structure.png and b/en/application-dev/application-models/figures/hop-structure.png differ diff --git a/en/application-dev/application-models/figures/mission-and-multiton.png b/en/application-dev/application-models/figures/mission-and-multiton.png new file mode 100644 index 0000000000000000000000000000000000000000..e50f9d44d475711c17bfe56394fddd8a6c7b784c Binary files /dev/null and b/en/application-dev/application-models/figures/mission-and-multiton.png differ diff --git a/en/application-dev/application-models/figures/stage-concepts.png b/en/application-dev/application-models/figures/stage-concepts.png index 42e99447a780b167adaf6ddd196bea4437dfa1a7..9d753f27fca4d507da20b5d5060f9b3d28e616b0 100644 Binary files a/en/application-dev/application-models/figures/stage-concepts.png and b/en/application-dev/application-models/figures/stage-concepts.png differ diff --git a/en/application-dev/application-models/figures/uiability-launch-type1.gif b/en/application-dev/application-models/figures/uiability-launch-type1.gif new file mode 100644 index 0000000000000000000000000000000000000000..d31a51a1aa97d32ee0ee7df4803378c1b7124119 Binary files /dev/null and b/en/application-dev/application-models/figures/uiability-launch-type1.gif differ diff --git a/en/application-dev/application-models/figures/uiability-launch-type1.png b/en/application-dev/application-models/figures/uiability-launch-type1.png deleted file mode 100644 index c4f5aa4b9a988d8e7148b504c4dcc163961cb103..0000000000000000000000000000000000000000 Binary files a/en/application-dev/application-models/figures/uiability-launch-type1.png and /dev/null differ diff --git a/en/application-dev/application-models/figures/uiability-launch-type2.gif b/en/application-dev/application-models/figures/uiability-launch-type2.gif new file mode 100644 index 0000000000000000000000000000000000000000..ecb3c413e3af2f92ef6834024d0d413e30c2419f Binary files /dev/null and b/en/application-dev/application-models/figures/uiability-launch-type2.gif differ diff --git a/en/application-dev/application-models/figures/uiability-launch-type2.png b/en/application-dev/application-models/figures/uiability-launch-type2.png deleted file mode 100644 index 6f0e43d24f745aee41601cc48f4bc138572fbeb5..0000000000000000000000000000000000000000 Binary files a/en/application-dev/application-models/figures/uiability-launch-type2.png and /dev/null differ diff --git a/en/application-dev/application-models/figures/uiability-launch-type3.gif b/en/application-dev/application-models/figures/uiability-launch-type3.gif new file mode 100644 index 0000000000000000000000000000000000000000..029e8ba7e90eb836f8466c604d4fcf8171ffec6e Binary files /dev/null and b/en/application-dev/application-models/figures/uiability-launch-type3.gif differ diff --git a/en/application-dev/application-models/figures/want-action.png b/en/application-dev/application-models/figures/want-action.png index 0d8e18ce5870bea777c26b832d3f29674c2fa261..b907e8158bd9fd183ceabb181a13aa813f01e77e 100644 Binary files a/en/application-dev/application-models/figures/want-action.png and b/en/application-dev/application-models/figures/want-action.png differ diff --git a/en/application-dev/application-models/hop-cross-device-migration.md b/en/application-dev/application-models/hop-cross-device-migration.md index c51e82e15f4e14f4b42b25e656543a01d84406fb..d26f4b452febf4e7683e319e703ac350f0525857 100644 --- a/en/application-dev/application-models/hop-cross-device-migration.md +++ b/en/application-dev/application-models/hop-cross-device-migration.md @@ -3,7 +3,7 @@ ## When to Use -The main task of cross-device migration is to migrate the current task (including the page control status) of an application to the target device so that the task can continue on it. Cross-device migration supports the following functionalities: +The main task of cross-device migration is to migrate the current task (including the page control status) of an application to the target device so that the task can continue on it. Cross-device migration supports the following features: - Storage and restoration of custom data @@ -16,7 +16,8 @@ The main task of cross-device migration is to migrate the current task (includin The following figure shows the cross-device migration process. -**Figure 1** Cross-device migration process +**Figure 1** Cross-device migration process + ![hop-cross-device-migration](figures/hop-cross-device-migration.png) @@ -49,27 +50,27 @@ The table below describes the main APIs used for cross-device migration. For det 1. Request the **ohos.permission.DISTRIBUTED_DATASYNC** permission. For details, see [Declaring Permissions in the Configuration File](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file). -2. Display a dialog box to ask authorization from the user when the application is started for the first time. For details, see [Requesting User Authorization](../security/accesstoken-guidelines.md#requesting-user-authorization). +2. Display a dialog box to ask for authorization from the user when the application is started for the first time. For details, see [Requesting User Authorization](../security/accesstoken-guidelines.md#requesting-user-authorization). 3. Configure the fields related to cross-device migration in the configuration file. Configure the application to support migration. Set the **continuable** field in the **module.json5** file to **true**. The default value is **false**. If this parameter is set to **false**, the application cannot be continued on the target device. - - - ```json - { - "module": { - // ... - "abilities": [ - { - // ... - "continuable": true, - } - ] - } - } - ``` + + + ```json + { + "module": { + ... + "abilities": [ + { + ... + "continuable": true, + } + ] + } + } + ``` Configure the application launch type. For details, see [UIAbility Component Launch Type](uiability-launch-type.md). @@ -79,23 +80,23 @@ The table below describes the main APIs used for cross-device migration. For det - Checking application compatibility: You can obtain the version number of the target application from **wantParam** and check the compatibility between the target application and the current application. - - Making a migration decision: You can determine whether to support the migration based on the return value of **onContinue()**. For details about the return value, see [Available APIs](#available-apis). + - Making a migration decision: You can determine whether to support the migration based on the return value of **onContinue()**. For details about the return values, see [Available APIs](#available-apis). The sample code is as follows: - ```ts - import UIAbility from '@ohos.app.ability.UIAbility'; - import AbilityConstant from '@ohos.app.ability.AbilityConstant'; - - onContinue(wantParam : {[key: string]: any}) { - console.info(`onContinue version = ${wantParam.version}, targetDevice: ${wantParam.targetDevice}`) - let workInput = AppStorage.Get('ContinueWork'); - // Set the user input data into wantParam. - wantParam["work"] = workInput // set user input data into want params - console.info(`onContinue input = ${wantParam["input"]}`); - return AbilityConstant.OnContinueResult.AGREE - } - ``` + ```ts + import UIAbility from '@ohos.app.ability.UIAbility'; + import AbilityConstant from '@ohos.app.ability.AbilityConstant'; + + onContinue(wantParam : {[key: string]: any}) { + console.info(`onContinue version = ${wantParam.version}, targetDevice: ${wantParam.targetDevice}`) + let workInput = AppStorage.Get('ContinueWork'); + // Set the user input data into wantParam. + wantParam["work"] = workInput // set user input data into want params + console.info(`onContinue input = ${wantParam["input"]}`); + return AbilityConstant.OnContinueResult.AGREE + } + ``` 5. Implement **onCreate()** and **onNewWant()** in the UIAbility of the target application to implement data restoration. - Implementation example of **onCreate** in the multi-instance scenario diff --git a/en/application-dev/application-models/hop-multi-device-collaboration.md b/en/application-dev/application-models/hop-multi-device-collaboration.md index adbaef7a927f61bc04b7b9066264f8367ef90d76..06c091b68c3fbe71737205fdcdcd79b15d6f4dde 100644 --- a/en/application-dev/application-models/hop-multi-device-collaboration.md +++ b/en/application-dev/application-models/hop-multi-device-collaboration.md @@ -3,9 +3,9 @@ ## When to Use -Multi-device coordination involves the following scenarios: +Multi-device collaboration involves the following scenarios: -- [Starting UIAbility and ServiceExtensionAbility Across Devices (No Data Returned)](#starting-uiability-and-serviceextensionability-across-devices-no-data-returned) +- [Starting UIAbility or ServiceExtensionAbility Across Devices (No Data Returned)](#starting-uiability-or-serviceextensionability-across-devices-no-data-returned) - [Starting UIAbility Across Devices (Data Returned)](#starting-uiability-across-devices-data-returned) @@ -18,22 +18,23 @@ Multi-device coordination involves the following scenarios: The figure below shows the multi-device collaboration process. -**Figure 1** Multi-device collaboration process +**Figure 1** Multi-device collaboration process + ![hop-multi-device-collaboration](figures/hop-multi-device-collaboration.png) ## Constraints -- Since multi-device collaboration task management is not available, you can obtain the device list by developing system applications. Access to third-party applications is not supported. +- Since multi-device collaboration task management is not available, you can obtain the device list by developing system applications. Third-party applications cannot access the device list. - Multi-device collaboration must comply with [Inter-Device Component Startup Rules](component-startup-rules.md#inter-device-component-startup-rules). - For better user experience, you are advised to use the **want** parameter to transmit data smaller than 100 KB. -## Starting UIAbility and ServiceExtensionAbility Across Devices (No Data Returned) +## Starting UIAbility or ServiceExtensionAbility Across Devices (No Data Returned) -On device A, touch the **Start** button provided by the initiator application to start a specified UIAbility on device B. +On device A, touch the **Start** button provided by the initiator application to start a specified UIAbility or ServiceExtensionAbility on device B. ### Available APIs @@ -42,14 +43,16 @@ On device A, touch the **Start** button provided by the initiator application to | **API**| **Description**| | -------- | -------- | -| startAbility(want: Want, callback: AsyncCallback<void>): void; | Starts UIAbility and ServiceExtensionAbility. This API uses an asynchronous callback to return the result.| +| startAbility(want: Want, callback: AsyncCallback<void>): void; | Starts a UIAbility or ServiceExtensionAbility. This API uses an asynchronous callback to return the result.| +| stopServiceExtensionAbility(want: Want, callback: AsyncCallback<void>): void; | Stops a ServiceExtensionAbility. This API uses an asynchronous callback to return the result.| +| stopServiceExtensionAbility(want: Want): Promise<void>; | Stops a ServiceExtensionAbility. This API uses a promise to return the result.| ### How to Develop 1. Request the **ohos.permission.DISTRIBUTED_DATASYNC** permission. For details, see [Declaring Permissions in the Configuration File](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file). -2. Display a dialog box to ask authorization from the user when the application is started for the first time. For details, see [Requesting User Authorization](../security/accesstoken-guidelines.md#requesting-user-authorization). +2. Display a dialog box to ask for authorization from the user when the application is started for the first time. For details, see [Requesting User Authorization](../security/accesstoken-guidelines.md#requesting-user-authorization). 3. Obtain the device ID of the target device. @@ -61,7 +64,7 @@ On device A, touch the **Start** button provided by the initiator application to // createDeviceManager is a system API. deviceManager.createDeviceManager('ohos.samples.demo', (err, dm) => { if (err) { - // ... + ... return } dmClass = dm @@ -81,7 +84,7 @@ On device A, touch the **Start** button provided by the initiator application to } ``` -4. Set the target component parameters, and call [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) to start UIAbility or ServiceExtensionAbility. +4. Set the target component parameters, and call [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) to start a UIAbility or ServiceExtensionAbility. ```ts let want = { @@ -92,16 +95,32 @@ On device A, touch the **Start** button provided by the initiator application to } // context is the AbilityContext of the initiator UIAbility. this.context.startAbility(want).then(() => { - // ... + ... }).catch((err) => { - // ... + ... }) ``` +5. Call [stopServiceExtensionAbility](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstopserviceextensionability) to stop the ServiceExtensionAbility when it is no longer required on device B. (This API cannot be used to stop a UIAbility. Users must manually stop a UIAbility through task management.) + + ```ts + let want = { + deviceId: getRemoteDeviceId(), + bundleName: 'com.example.myapplication', + abilityName: 'FuncAbility', + moduleName: 'module1', // moduleName is optional. + } + // Stop the ServiceExtensionAbility started by calling startAbility(). + this.context.stopServiceExtensionAbility(want).then(() => { + console.info("stop service extension ability success") + }).catch((err) => { + console.info("stop service extension ability err is " + JSON.stringify(err)) + }) + ``` ## Starting UIAbility Across Devices (Data Returned) -On device A, touch the **Start** button provided by the initiator application to start a specified UIAbility on device B. When the UIAbility on device B exits, a value is sent back to the initiator application. +On device A, touch the **Start** button provided by the initiator application to start a specified UIAbility on device B. When the UIAbility on device B exits, a value is returned to the initiator application. ### Available APIs @@ -119,9 +138,9 @@ On device A, touch the **Start** button provided by the initiator application to 1. Request the **ohos.permission.DISTRIBUTED_DATASYNC** permission. For details, see [Declaring Permissions in the Configuration File](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file). -2. Display a dialog box to ask authorization from the user when the application is started for the first time. For details, see [Requesting User Authorization](../security/accesstoken-guidelines.md#requesting-user-authorization). +2. Display a dialog box to ask for authorization from the user when the application is started for the first time. For details, see [Requesting User Authorization](../security/accesstoken-guidelines.md#requesting-user-authorization). -3. Set the target component parameters on the initiator, and call **startAbilityForResult()** to start the target UIAbility. **data** in the asynchronous callback is used to receive the information returned by the target UIAbility to the initiator UIAbility after the target UIAbility terminates itself. For details about how to implement **getRemoteDeviceId()**, see [Starting UIAbility and ServiceExtensionAbility Across Devices (No Data Returned)](#starting-uiability-and-serviceextensionability-across-devices-no-data-returned). +3. Set the target component parameters on the initiator, and call **startAbilityForResult()** to start the target UIAbility. **data** in the asynchronous callback is used to receive the information returned by the target UIAbility to the initiator UIAbility after the target UIAbility terminates itself. For details about how to implement **getRemoteDeviceId()**, see [Starting UIAbility or ServiceExtensionAbility Across Devices (No Data Returned)](#starting-uiability-or-serviceextensionability-across-devices-no-data-returned). ```ts let want = { @@ -132,13 +151,13 @@ On device A, touch the **Start** button provided by the initiator application to } // context is the AbilityContext of the initiator UIAbility. this.context.startAbilityForResult(want).then((data) => { - // ... + ... }).catch((err) => { - // ... + ... }) ``` -4. After the UIAbility task at the target device is complete, call **terminateSelfWithResult()** to return the data to the initiator UIAbility. +4. After the UIAbility task on the target device is complete, call **terminateSelfWithResult()** to return the data to the initiator UIAbility. ```ts const RESULT_CODE: number = 1001; @@ -152,7 +171,7 @@ On device A, touch the **Start** button provided by the initiator application to } // context is the AbilityContext of the target UIAbility. this.context.terminateSelfWithResult(abilityResult, (err) => { - // ... + ... }); ``` @@ -161,17 +180,17 @@ On device A, touch the **Start** button provided by the initiator application to ```ts const RESULT_CODE: number = 1001; - // ... + ... // context is the UIAbilityContext of the initiator UIAbility. this.context.startAbilityForResult(want).then((data) => { if (data?.resultCode === RESULT_CODE) { // Parse the information returned by the target UIAbility. let info = data.want?.parameters?.info - // ... + ... } }).catch((err) => { - // ... + ... }) ``` @@ -196,7 +215,7 @@ A system application can connect to a service on another device by calling [conn 1. Request the **ohos.permission.DISTRIBUTED_DATASYNC** permission. For details, see [Declaring Permissions in the Configuration File](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file). -2. Display a dialog box to ask authorization from the user when the application is started for the first time. For details, see [Requesting User Authorization](../security/accesstoken-guidelines.md#requesting-user-authorization). +2. Display a dialog box to ask for authorization from the user when the application is started for the first time. For details, see [Requesting User Authorization](../security/accesstoken-guidelines.md#requesting-user-authorization). 3. (Optional) [Implement a background service](serviceextensionability.md#implementing-a-background-service). Perform this operation only if no background service is available. @@ -205,7 +224,7 @@ A system application can connect to a service on another device by calling [conn - Set the target component parameters, including the target device ID, bundle name, and ability name. - Call **connectServiceExtensionAbility** to initiate a connection. - Receive the service handle returned by the target device when the connection is successful. - - Perform cross-device invoking and obtain the result returned by the target service. + - Perform cross-device call and obtain the result returned by the target service. ```ts import rpc from '@ohos.rpc'; @@ -253,7 +272,7 @@ A system application can connect to a service on another device by calling [conn let connectionId = this.context.connectServiceExtensionAbility(want, options); ``` - For details about how to implement **getRemoteDeviceId()**, see [Starting UIAbility and ServiceExtensionAbility Across Devices (No Data Returned)](#starting-uiability-and-serviceextensionability-across-devices-no-data-returned). + For details about how to implement **getRemoteDeviceId()**, see [Starting UIAbility or ServiceExtensionAbility Across Devices (No Data Returned)](#starting-uiability-or-serviceextensionability-across-devices-no-data-returned). 5. Disconnect the connection. Use **disconnectServiceExtensionAbility()** to disconnect from the background service. @@ -293,7 +312,7 @@ The following describes how to implement multi-device collaboration through cros 1. Request the **ohos.permission.DISTRIBUTED_DATASYNC** permission. For details, see [Declaring Permissions in the Configuration File](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file). -2. Display a dialog box to ask authorization from the user when the application is started for the first time. For details, see [Requesting User Authorization](../security/accesstoken-guidelines.md#requesting-user-authorization). +2. Display a dialog box to ask for authorization from the user when the application is started for the first time. For details, see [Requesting User Authorization](../security/accesstoken-guidelines.md#requesting-user-authorization). 3. Create the CalleeAbility. @@ -313,12 +332,12 @@ The following describes how to implement multi-device collaboration through cros ```json "abilities":[{ "name": ".CalleeAbility", - "srcEntrance": "./ets/CalleeAbility/CalleeAbility.ts", + "srcEntry": "./ets/CalleeAbility/CalleeAbility.ts", "launchType": "singleton", "description": "$string:CalleeAbility_desc", "icon": "$media:icon", "label": "$string:CalleeAbility_label", - "visible": true + "exported": true }] ``` 2. Import the **UIAbility** module. @@ -426,10 +445,10 @@ The following describes how to implement multi-device collaboration through cros // Register the onRemoteStateChange listener of the CallerAbility. try { caller.onRemoteStateChange((str) => { - console.log('Remote state changed ' + str); + console.info('Remote state changed ' + str); }); } catch (error) { - console.log('Caller.onRemoteStateChange catch error, error.code: ${JSON.stringify(error.code)}, error.message: ${JSON.stringify(error.message)}'); + console.info('Caller.onRemoteStateChange catch error, error.code: ${JSON.stringify(error.code)}, error.message: ${JSON.stringify(error.message)}'); } } }).catch((error) => { @@ -438,7 +457,7 @@ The following describes how to implement multi-device collaboration through cros } ``` - For details about how to implement **getRemoteDeviceId()**, see [Starting UIAbility and ServiceExtensionAbility Across Devices (No Data Returned)](#starting-uiability-and-serviceextensionability-across-devices-no-data-returned). + For details about how to implement **getRemoteDeviceId()**, see [Starting UIAbility or ServiceExtensionAbility Across Devices (No Data Returned)](#starting-uiability-or-serviceextensionability-across-devices-no-data-returned). 5. Sends agreed parcelable data to the CalleeAbility. 1. The parcelable data can be sent to the CalleeAbility with or without a return value. The method and parcelable data must be consistent with those of the CalleeAbility. The following example describes how to send data to the CalleeAbility. diff --git a/en/application-dev/application-models/inputmethodextentionability.md b/en/application-dev/application-models/inputmethodextentionability.md index 8a7856f402bf30b1610521e3cf05dda7145c3509..49686c5d5c087d8a484123f0f6d58a12f6283976 100644 --- a/en/application-dev/application-models/inputmethodextentionability.md +++ b/en/application-dev/application-models/inputmethodextentionability.md @@ -1,11 +1,11 @@ -# InputMethodExtensionAbility Development +# InputMethodExtensionAbility -[InputMethodExtensionAbility](../reference/apis/js-apis-inputmethod-extension-ability.md) is an ExtensionAbility component of the inputMethod type that provides extension capabilities for the input method framework. +## When to Use +[InputMethodExtensionAbility](../reference/apis/js-apis-inputmethod-extension-ability.md), inherited from [ExtensionAbility](extensionability-overview.md), is used for developing input method applications. -InputMethodExtensionAbility can be started or connected by other application components to process transactions in the background based on the request of the caller. +The entire lifecycle of the [InputMethodExtensionAbility](../reference/apis/js-apis-inputmethod-extension-ability.md) instance and the owning ExtensionAbility process is scheduled and managed by the input method framework. The input method framework provides the [InputMethodExtensionAbility](../reference/apis/js-apis-inputmethod-extension-ability.md) base class. Derive this base class to implement initialization and resource clearing. - -InputMethodExtensionAbility provides related capabilities through the [InputMethodExtensionContext](../reference/apis/js-apis-inputmethod-extension-context.md). +[InputMethodExtensionAbility](../reference/apis/js-apis-inputmethod-extension-ability.md) provides related capabilities through [InputMethodExtensionContext](../reference/apis/js-apis-inputmethod-extension-context.md). ## Implementing an Input Method Application @@ -13,15 +13,13 @@ InputMethodExtensionAbility provides related capabilities through the [InputMeth InputMethodExtensionAbility provides the **onCreate()** and **onDestory()** callbacks, as described below. Override them as required. - **onCreate** - This callback is triggered when a service is created for the first time. You can perform initialization operations, for example, registering a common event listener. - + > **NOTE** > > If a service has been created, starting it again does not trigger the **onCreate()** callback. - + - **onDestroy** - This callback is triggered when the service is no longer used and the instance is ready for destruction. You can clear resources in this callback, for example, deregister the listener. @@ -29,7 +27,7 @@ InputMethodExtensionAbility provides the **onCreate()** and **onDestory()** call To implement an input method application, manually create an InputMethodExtensionAbility component in DevEco Studio. The procedure is as follows: -In the **ets** directory of the target module, right-click and choose **New** > **Extention Ability** > **InputMethod** to a minimum template of InputMethodExtensionAbility. +In the **ets** directory of the target module, right-click and choose **New** > **Extension Ability** > **InputMethod** to a minimum template of InputMethodExtensionAbility. > **NOTE** > @@ -54,7 +52,7 @@ The minimum template contains four files: **KeyboardController.ts**, **InputMeth 1. **InputMethodService.ts** file: - In this file, add the dependency package for importing InputMethodExtensionAbility. Customize a class that inherits from InputMethodExtensionAbility and add the required lifecycle callbacks. + In the **InputMethodService.ts** file, add the dependency package for importing InputMethodExtensionAbility. Customize a class that inherits from InputMethodExtensionAbility and add the required lifecycle callbacks. ```ts import InputMethodExtensionAbility from '@ohos.InputMethodExtensionAbility'; @@ -70,7 +68,7 @@ The minimum template contains four files: **KeyboardController.ts**, **InputMeth onDestroy() { console.log("onDestroy."); - this.context.destroy(); + this.keyboardController.onDestroy(); // Destroy the window and deregister the event listener. } } ``` @@ -109,7 +107,6 @@ The minimum template contains four files: **KeyboardController.ts**, **InputMeth this.unRegisterListener(); // Deregister the event listener. let win = windowManager.findWindow(this.windowName); win.destroyWindow(); // Destroy the window. - this.mContext.terminateSelf(); // Terminate the InputMethodExtensionAbility service. } private initWindow(): void // Initialize the window. @@ -159,7 +156,7 @@ The minimum template contains four files: **KeyboardController.ts**, **InputMeth }) globalThis.inputAbility.on('inputStop', (imeId) => { if (imeId == "Bundle name/Ability name") { - this.onDestroy(); + this.mContext.destroy(); // Destroy the InputMethodExtensionAbility service. } }); } @@ -342,20 +339,20 @@ The minimum template contains four files: **KeyboardController.ts**, **InputMeth } ``` - Register the InputMethodExtensionAbility in the [module.json5 file](../quick-start/module-configuration-file.md) corresponding to the target module. Set **type** to **"inputMethod"** and **srcEntrance** to the code path of the InputMethodExtensionAbility component. +5. Register the InputMethodExtensionAbility in the [module.json5 file](../quick-start/module-configuration-file.md) corresponding to the **Module** project. Set **type** to **"inputMethod"** and **srcEntry** to the code path of the InputMethodExtensionAbility component. ```ts { "module": { - // ... + ... "extensionAbilities": [ { "description": "inputMethod", "icon": "$media:icon", "name": "InputMethodExtAbility", - "srcEntrance": "./ets/inputmethodextability/InputMethodService.ts", + "srcEntry": "./ets/inputmethodextability/InputMethodService.ts", "type": "inputMethod", - "visible": true, + "exported": true, } ] } @@ -364,3 +361,47 @@ The minimum template contains four files: **KeyboardController.ts**, **InputMeth +## Restrictions + +To reduce the risk of abuse of the InputMethodExtensionAbility by third-party applications, the invoking of APIs in the following modules is restricted in the InputMethodExtensionAbility: + +> **NOTE** +> +> - If a restricted module is imported, no error is reported during compilation, but an incorrect value (**undefined**) is returned during running. As a result, the module does not take effect. +> - Currently, access to the [@ohos.multimedia.audio (Audio Management)](../reference/apis/js-apis-audio.md) module is allowed, with compliance with the following rules: +> - Users who deny the recording permission should still be allowed to use the non-voice-input features of the input method application. +> - Recording-related services are allowed only when the InputMethodExtensionAbility is in the foreground. For example, perform recording only when the soft keyboard is in the foreground and the user is proactively using the voice input method; stop recording when the application is switched to the background. +> - Applications will see increasingly stringent measures against violations with the preceding rules, and any violation may result in function exceptions. + +**Restricted modules:** + +- [@ohos.ability.featureAbility (FeatureAbility)](../reference/apis/js-apis-ability-featureAbility.md) +- [@ohos.ability.particleAbility (ParticleAbility)](../reference/apis/js-apis-ability-particleAbility.md) +- [@ohos.account.distributedAccount (Distributed Account Management)](../reference/apis/js-apis-distributed-account.md) +- [@ohos.backgroundTaskManager (Background Task Management)](../reference/apis/js-apis-backgroundTaskManager.md) +- [@ohos.bluetooth (Bluetooth)](../reference/apis/js-apis-bluetooth.md) +- [@ohos.bluetoothManager (Bluetooth)](../reference/apis/js-apis-bluetoothManager.md) +- [@ohos.connectedTag (Active Tags)](../reference/apis/js-apis-connectedTag.md) +- [@ohos.geolocation (Geolocation)](../reference/apis/js-apis-geolocation.md) +- [@ohos.geoLocationManager (Geolocation Manager)](../reference/apis/js-apis-geoLocationManager.md) +- [@ohos.nfc.cardEmulation (Standard NFC Card Emulation)](../reference/apis/js-apis-cardEmulation.md) +- [@ohos.nfc.controller (Standard NFC)](../reference/apis/js-apis-nfcController.md) +- [@ohos.nfc.tag (Standard NFC Tags)](../reference/apis/js-apis-nfcTag.md) +- [@ohos.reminderAgent (Reminder Agent)](../reference/apis/js-apis-reminderAgent.md) +- [@ohos.reminderAgentManager (reminderAgentManager)](../reference/apis/js-apis-reminderAgentManager.md) +- [@ohos.sensor (Sensor)](../reference/apis/js-apis-sensor.md) +- [@ohos.telephony.call (Call)](../reference/apis/js-apis-call.md) +- [@ohos.telephony.data (Cellular Data)](../reference/apis/js-apis-telephony-data.md) +- [@ohos.telephony.observer (observer)](../reference/apis/js-apis-observer.md) +- [@ohos.telephony.radio (Network Search)](../reference/apis/js-apis-radio.md) +- [@ohos.telephony.sim (SIM Management)](../reference/apis/js-apis-sim.md) +- [@ohos.telephony.sms (SMS)](../reference/apis/js-apis-sms.md) +- [@ohos.wallpaper (Wallpaper)](../reference/apis/js-apis-wallpaper.md) +- [@ohos.wifiext (WLAN Extension)](../reference/apis/js-apis-wifiext.md) +- [@ohos.wifiManager (WLAN)](../reference/apis/js-apis-wifiManager.md) +- [@ohos.wifiManagerExt (WLAN Extension Interface)](../reference/apis/js-apis-wifiManagerExt.md) +- [@system.geolocation (Geolocation)](../reference/apis/js-apis-system-location.md) +- [nfctech (Standard NFC Technologies)](../reference/apis/js-apis-nfctech.md) +- [tagSession (Standard NFC Tag Session)](../reference/apis/js-apis-tagSession.md) + + diff --git a/en/application-dev/application-models/inter-device-interaction-hop-overview.md b/en/application-dev/application-models/inter-device-interaction-hop-overview.md index 8a6cb49f86ff60655037955aaba1b00a5ff40a17..ee69e4928db174f4b51f481fdf5bafd1427a0314 100644 --- a/en/application-dev/application-models/inter-device-interaction-hop-overview.md +++ b/en/application-dev/application-models/inter-device-interaction-hop-overview.md @@ -3,7 +3,7 @@ ## When to Use -As the all-scenario, multi-device lifestyle becomes popular, users have an increasing number of devices. Each device provides users with what they need in a certain scenario. For example, watches allow users to view information in a timely manner, and smart TVs bring them an immersive watching experience. However, each device has its limitation, for example, typing text on a smart TV is frustrating as it is much more difficult than on a mobile device. If multiple devices can sense each other through a distributed OS and together form a super device, the strengths of each device can be fully exerted to provide a more natural and smoother distributed experience for users. +As the all-scenario, multi-device lifestyle becomes popular, users have an increasing number of devices. Each device provides users with what they need in a certain scenario. For example, watches allow users to view information in a timely manner, and smart TVs bring them an immersive watching experience. However, each device has its limitations, for example, typing text on a smart TV is frustrating as it is much more difficult than on a mobile device. If multiple devices can sense each other through a distributed OS and together form a super device, the strengths of each device can be fully exerted to provide a more natural and smoother distributed experience for users. In OpenHarmony, distributed operations across devices are called continuation (previously named hopping), which is further classified into [cross-device migration](hop-cross-device-migration.md) and [multi-device collaboration](hop-multi-device-collaboration.md). To implement continuation, cross-device interaction capabilities of application components are required. Currently, these capabilities are open only to system applications. @@ -20,7 +20,7 @@ In OpenHarmony, distributed operations across devices are called continuation (p - **Multi-device collaboration** - Multi-device collaboration enables collaboration between multiple devices, providing users with more efficient and immersive experience than with a single device. A typical multi-device collaboration scenario is as follows: Application A on the tablet is used as the answer board, and application B on the smart TV is used for live broadcast, delivering a better online class experience. From the perspective of application development, multi-device collaboration enables different UIAbility or ServiceExtensionAbility components to run simultaneously or alternately on multiple devices to provide a complete service, or enables the same UIAbility and ServiceExtensionAbility component to run simultaneously on multiple devices to provide a complete service. + Multi-device collaboration provides users with more efficient and immersive experience than with a single device. A typical multi-device collaboration scenario is as follows: Application A on the tablet is used as the answer board, and application B on the smart TV is used for live broadcast, delivering a better online class experience. From the perspective of application development, multi-device collaboration enables different UIAbility or ServiceExtensionAbility components to run simultaneously or alternately on multiple devices to provide a complete service, or enables the same UIAbility and ServiceExtensionAbility component to run simultaneously on multiple devices to provide a complete service. ## Continuation Architecture @@ -35,9 +35,9 @@ OpenHarmony provides a set of APIs for you to implement continuation in your app The following figure shows the continuation architecture. - **Figure 1** Continuation architecture +**Figure 1** Continuation architecture - ![hop-structure](figures/hop-structure.png) + ![hop-structure](figures/hop-structure.png) - Cross-device migration task management: The initiator accepts a migration request from the user, provides a migration entry, and displays the migration result. (This capability is unavailable yet.) @@ -47,4 +47,4 @@ The following figure shows the continuation architecture. - Distributed security authentication: provides an E2E encrypted channel for cross-device transmission between applications to ensure that the right person uses the right data through the right device. -- DSoftBus: functions as a unified communication base for a wide range of devices such as tablets, wearables, and smart TVs, and enables unified distributed communication between these devices. +- DSoftBus: functions as a unified communication base for a wide range of devices, such as tablets, wearables, and smart TVs, and enables unified distributed communication between these devices. diff --git a/en/application-dev/application-models/itc-with-emitter.md b/en/application-dev/application-models/itc-with-emitter.md index 2966bd8eea41e04893814f20a3c5b2f9e4e456c9..43a5dc67be7349bb1d51a7e4141920b8739f7beb 100644 --- a/en/application-dev/application-models/itc-with-emitter.md +++ b/en/application-dev/application-models/itc-with-emitter.md @@ -13,12 +13,12 @@ To develop the Emitter mode, perform the following steps: // Define an event with eventId 1. let event = { - eventId: 1 + eventId: 1 }; // Trigger the callback after the event with eventId 1 is received. let callback = (eventData) => { - console.info('event callback'); + console.info('event callback'); }; // Subscribe to the event with eventId 1. @@ -29,21 +29,21 @@ To develop the Emitter mode, perform the following steps: ```ts import emitter from "@ohos.events.emitter"; - + // Define an event with eventId 1 and priority Low. let event = { - eventId: 1, - priority: emitter.EventPriority.LOW + eventId: 1, + priority: emitter.EventPriority.LOW }; - + let eventData = { - data: { - "content": "c", - "id": 1, - "isEmpty": false, - } + data: { + "content": "c", + "id": 1, + "isEmpty": false, + } }; - + // Emit the event with eventId 1 and event content eventData. emitter.emit(event, eventData); ``` diff --git a/en/application-dev/application-models/itc-with-worker.md b/en/application-dev/application-models/itc-with-worker.md index 996ab941b0244571dff6116a45ab5e2165cf1184..1f105d4f0ce31acdf135ab254e7bdb66e30d1ecf 100644 --- a/en/application-dev/application-models/itc-with-worker.md +++ b/en/application-dev/application-models/itc-with-worker.md @@ -9,13 +9,13 @@ To develop the Worker mode, perform the following steps: 1. Configure the **buildOption** field in the [module-level build-profile.json5](https://developer.harmonyos.com/en/docs/documentation/doc-guides/ohos-building-configuration-0000001218440654#section6887184182020) file of the project. ```ts - "buildOption": { - "sourceOption": { - "workers": [ - "./src/main/ets/workers/worker.ts" - ] - } + "buildOption": { + "sourceOption": { + "workers": [ + "./src/main/ets/workers/worker.ts" + ] } + } ``` 2. Create the **worker.ts** file based on the configuration in **build-profile.json5**. @@ -27,9 +27,9 @@ To develop the Worker mode, perform the following steps: // Process messages from the main thread. parent.onmessage = function(message) { - console.info("onmessage: " + message) - // Send a message to the main thread. - parent.postMessage("message from worker thread.") + console.info("onmessage: " + message) + // Send a message to the main thread. + parent.postMessage("message from worker thread.") } ``` @@ -46,10 +46,10 @@ To develop the Worker mode, perform the following steps: // Process messages from the worker thread. wk.onmessage = function(message) { - console.info("message from worker: " + message) + console.info("message from worker: " + message) - // Stop the worker thread based on service requirements. - wk.terminate() + // Stop the worker thread based on service requirements. + wk.terminate(); } ``` @@ -57,23 +57,22 @@ To develop the Worker mode, perform the following steps: ```ts import worker from '@ohos.worker'; - + let wk = new worker.ThreadWorker("../workers/worker.ts"); - + // Send a message to the worker thread. wk.postMessage("message from main thread.") - + // Process messages from the worker thread. wk.onmessage = function(message) { - console.info("message from worker: " + message) - - // Stop the worker thread based on service requirements. - wk.terminate() + console.info("message from worker: " + message) + + // Stop the worker thread based on service requirements. + wk.terminate(); } ``` > **NOTE** -> +> > - If the relative path of **worker.ts** configured in **build-profile.json5** is **./src/main/ets/workers/worker.ts**, pass in the path **entry/ets/workers/worker.ts** when creating a worker thread in the stage model, and pass in the path **../workers/worker.ts** when creating a worker thread in the FA model. -> > - For details about the data types supported between the main thread and worker thread, see [Sequenceable Data Types](../reference/apis/js-apis-worker.md#sequenceable-data-types). diff --git a/en/application-dev/application-models/widget-development-stage.md b/en/application-dev/application-models/js-ui-widget-development.md similarity index 70% rename from en/application-dev/application-models/widget-development-stage.md rename to en/application-dev/application-models/js-ui-widget-development.md index 73635fbc05c5e11cc0cc72857ccbcc7648bfa451..178aa903a36b6a4742645cfab82a390364db0b37 100644 --- a/en/application-dev/application-models/widget-development-stage.md +++ b/en/application-dev/application-models/js-ui-widget-development.md @@ -1,39 +1,28 @@ -# FormExtensionAbility (Widget) +# Developing a JS Widget -## Widget Overview - -FormExtensionAbility provides a service widget (also called widget), which is a set of UI components that display important information or operations specific to an application. It provides users with direct access to a desired application service, without the need to open the application first. - -A widget usually appears as a part of the UI of another application (which currently can only be a system application) and provides basic interactive features such as opening a UI page or sending a message. - -Before you get started, it would be helpful if you have a basic understanding of the following concepts: - -- Widget host: an application that displays the widget content and controls the widget location. - -- Widget Manager: a resident agent that provides widget management features such as periodic widget updates. - -- Widget provider: an atomic service that provides the widget content to display and controls how widget components are laid out and how they interact with users. +The following describes how to develop JS widgets based on the web-like development paradigm. ## Working Principles -Figure 1 shows the working principles of the widget framework. +Below shows the working principles of the widget framework. -**Figure 1** Widget framework working principles in the stage model -![form-extension](figures/form-extension.png) +**Figure 1** Widget framework working principles in the stage model + +![JSCardPrinciple](figures/JSCardPrinciple.png) The widget host consists of the following modules: - Widget usage: provides operations such as creating, deleting, or updating a widget. -- Communication adapter: provided by the OpenHarmony SDK for communication with the Widget Manager. It sends widget-related operations to the Widget Manager. +- Communication adapter: provided by the SDK for communication with the Widget Manager. It sends widget-related operations to the Widget Manager. The Widget Manager consists of the following modules: - Periodic updater: starts a scheduled task based on the update policy to periodically update a widget after it is added to the Widget Manager. -- Cache manager: caches view information of a widget after it is added to the Widget Manager to directly return the cached data when the widget is obtained next time. This reduces the latency greatly. +- Cache manager: caches view information of a widget after it is added to the Widget Manager. This enables the cached data to be directly returned when the widget is obtained next time, greatly reducing the latency. - Lifecycle manager: suspends update when a widget is switched to the background or is blocked, and updates and/or clears widget data during upgrade and deletion. @@ -47,7 +36,7 @@ The widget provider consists of the following modules: - Instance manager: implemented by the widget provider developer for persistent management of widget instances allocated by the Widget Manager. -- Communication adapter: provided by the OpenHarmony SDK for communication with the Widget Manager. It pushes update data to the Widget Manager. +- Communication adapter: provided by the SDK for communication with the Widget Manager. It pushes update data to the Widget Manager. > **NOTE** > @@ -58,38 +47,31 @@ The widget provider consists of the following modules: The **FormExtensionAbility** class has the following APIs. For details, see [FormExtensionAbility](../reference/apis/js-apis-app-form-formExtensionAbility.md). -| API| Description| -| -------- | -------- | -| onAddForm(want: Want): formBindingData.FormBindingData | Called to notify the widget provider that a widget has been created.| -| onCastToNormalForm(formId: string): void | Called to notify the widget provider that a temporary widget has been converted to a normal one.| -| onUpdateForm(formId: string): void | Called to notify the widget provider that a widget has been updated.| -| onChangeFormVisibility(newStatus: { [key: string]: number }): void | Called to notify the widget provider of the change in widget visibility.| -| onFormEvent(formId: string, message: string): void | Called to instruct the widget provider to receive and process a widget event.| -| onRemoveForm(formId: string): void| Called to notify the widget provider that a widget has been destroyed.| -| onConfigurationUpdate(config: Configuration): void | Called when the configuration of the environment where the widget is running is updated.| -| onShareForm?(formId: string): { [key: string]: any }| Called by the widget provider to receive shared widget data.| - -The **FormExtensionAbility** class also has a member context, that is, the FormExtensionContext class. For details, see [FormExtensionContext](../reference/apis/js-apis-inner-application-formExtensionContext.md). - -| API| Description| +| Name| Description| | -------- | -------- | -| startAbility(want: Want, callback: AsyncCallback<void>): void | Starts UIAbility of the application to which a widget belongs. This API uses an asynchronous callback to return the result. (This is a system API and cannot be called by third-party applications. You must apply for the permission to use the API.)| -| startAbility(want: Want): Promise<void> | Starts UIAbility of the application to which a widget belongs. This API uses a promise to return the result. (This is a system API and cannot be called by third-party applications. You must apply for the permission to use the API.)| +| onAddForm(want: Want): formBindingData.FormBindingData | Called to notify the widget provider that a widget is being created.| +| onCastToNormalForm(formId: string): void | Called to notify the widget provider that a temporary widget is being converted to a normal one.| +| onUpdateForm(formId: string): void | Called to notify the widget provider that a widget is being updated.| +| onChangeFormVisibility(newStatus: { [key: string]: number }): void | Called to notify the widget provider that the widget visibility status is being changed.| +| onFormEvent(formId: string, message: string): void | Called to instruct the widget provider to process a widget event.| +| onRemoveForm(formId: string): void | Called to notify the widget provider that a widget is being destroyed.| +| onConfigurationUpdate(config: Configuration): void | Called when the configuration of the environment where the widget is running is being updated.| +| onShareForm?(formId: string): { [key: string]: any } | Called to notify the widget provider that the widget host is sharing the widget data.| The **FormProvider** class has the following APIs. For details, see [FormProvider](../reference/apis/js-apis-app-form-formProvider.md). -| API| Description| +| Name| Description| | -------- | -------- | | setFormNextRefreshTime(formId: string, minute: number, callback: AsyncCallback<void>): void; | Sets the next refresh time for a widget. This API uses an asynchronous callback to return the result.| | setFormNextRefreshTime(formId: string, minute: number): Promise<void>; | Sets the next refresh time for a widget. This API uses a promise to return the result.| | updateForm(formId: string, formBindingData: FormBindingData, callback: AsyncCallback<void>): void; | Updates a widget. This API uses an asynchronous callback to return the result.| -| updateForm(formId: string, formBindingData: FormBindingData): Promise<void>;| Updates a widget. This API uses a promise to return the result.| +| updateForm(formId: string, formBindingData: FormBindingData): Promise<void>; | Updates a widget. This API uses a promise to return the result.| The **FormBindingData** class has the following APIs. For details, see [FormBindingData](../reference/apis/js-apis-app-form-formBindingData.md). -| API| Description| +| Name| Description| | -------- | -------- | -| createFormBindingData(obj?: Object \ string): FormBindingData| | Creates a **FormBindingData** object.| +| createFormBindingData(obj?: Object \| string): FormBindingData | Creates a **FormBindingData** object.| ## How to Develop @@ -98,11 +80,11 @@ The widget provider development based on the [stage model](stage-model-developme - [Creating a FormExtensionAbility Instance](#creating-a-formextensionability-instance): Develop the lifecycle callback functions of FormExtensionAbility. -- [Configuring the Widget Configuration File](#configuring-the-widget-configuration-file): Configure the application configuration file **module.json5** and profile configuration file. +- [Configuring the Widget Configuration Files](#configuring-the-widget-configuration-files): Configure the application configuration file **module.json5** and profile configuration file. -- [Persistently Storing Widget Data](#persistently-storing-widget-data): This operation is a form of widget data exchange. +- [Persistently Storing Widget Data](#persistently-storing-widget-data): Manage widget data persistence. -- [Updating Widget Data](#updating-widget-data): Call **updateForm()** to update the information displayed on a widget. +- [Updating Widget Data](#updating-widget-data): Call **updateForm()** to update the information displayed in a widget. - [Developing the Widget UI Page](#developing-the-widget-ui-page): Use HML+CSS+JSON to develop a JS widget UI page. @@ -111,22 +93,24 @@ The widget provider development based on the [stage model](stage-model-developme ### Creating a FormExtensionAbility Instance -To create a widget in the stage model, implement the lifecycle callbacks of **FormExtensionAbility**. Generate a widget template by referring to [Developing a Service Widget](https://developer.harmonyos.com/en/docs/documentation/doc-guides/ohos-development-service-widget-0000001263280425). +To create a widget in the stage model, you need to implement the lifecycle callbacks of FormExtensionAbility. Generate a widget template and then perform the following: 1. Import related modules to **EntryFormAbility.ts**. + ```ts - import FormExtension from '@ohos.app.form.FormExtensionAbility'; + import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility'; import formBindingData from '@ohos.app.form.formBindingData'; import formInfo from '@ohos.app.form.formInfo'; import formProvider from '@ohos.app.form.formProvider'; - import dataStorage from '@ohos.data.storage'; + import dataPreferences from '@ohos.data.preferences'; ``` 2. Implement the FormExtension lifecycle callbacks in **EntryFormAbility.ts**. + ```ts - export default class EntryFormAbility extends FormExtension { + export default class EntryFormAbility extends FormExtensionAbility { onAddForm(want) { console.info('[EntryFormAbility] onAddForm'); // Called when the widget is created. The widget provider should return the widget data binding class. @@ -138,7 +122,7 @@ To create a widget in the stage model, implement the lifecycle callbacks of **Fo return formData; } onCastToNormalForm(formId) { - // Called when the widget host converts the temporary widget into a normal one. The widget provider should do something to respond to the conversion. + // Called when a temporary widget is being converted into a normal one. The widget provider should respond to the conversion. console.info('[EntryFormAbility] onCastToNormalForm'); } onUpdateForm(formId) { @@ -178,7 +162,8 @@ To create a widget in the stage model, implement the lifecycle callbacks of **Fo > > FormExtensionAbility cannot reside in the background. Therefore, continuous tasks cannot be processed in the widget lifecycle callbacks. -### Configuring the Widget Configuration File + +### Configuring the Widget Configuration Files 1. Configure ExtensionAbility information under **extensionAbilities** in the [module.json5 file](../quick-start/module-configuration-file.md). For a FormExtensionAbility, you must specify **metadata**. Specifically, set **name** to **ohos.extension.form** (fixed), and set **resource** to the index of the widget configuration information. Example configuration: @@ -187,11 +172,11 @@ To create a widget in the stage model, implement the lifecycle callbacks of **Fo ```json { "module": { - // ... + ... "extensionAbilities": [ { "name": "EntryFormAbility", - "srcEntrance": "./ets/entryformability/EntryFormAbility.ts", + "srcEntry": "./ets/entryformability/EntryFormAbility.ts", "label": "$string:EntryFormAbility_label", "description": "$string:EntryFormAbility_desc", "type": "form", @@ -207,20 +192,21 @@ To create a widget in the stage model, implement the lifecycle callbacks of **Fo } ``` -2. Configure the widget configuration information. In the **metadata** configuration item of FormExtensionAbility, you can specify the resource index of specific configuration information of the widget. For example, if resource is set to **$profile:form_config**, **form_config.json** in the **resources/base/profile/** directory of the development view is used as the profile configuration file of the widget. The following table describes the internal field structure. - **Table 1** Widget profile configuration file - - | Field| Description| Data Type| Initial Value Allowed| +2. Configure the widget configuration information. In the **metadata** configuration item of FormExtensionAbility, you can specify the resource index of specific configuration information of the widget. For example, if **resource** is set to **$profile:form_config**, **form_config.json** in the **resources/base/profile/** directory of the development view is used as the profile configuration file of the widget. The following table describes the internal structure of the profile configuration file. + + **Table 1** Widget profile configuration file + + | Field| Description| Data Type| Default Value Allowed| | -------- | -------- | -------- | -------- | - | name | Class name of a widget. The value is a string with a maximum of 127 bytes.| String| No| + | name | Class name of the widget. The value is a string with a maximum of 127 bytes.| String| No| | description | Description of the widget. The value can be a string or a resource index to descriptions in multiple languages. The value is a string with a maximum of 255 bytes.| String| Yes (initial value: left empty)| | src | Full path of the UI code corresponding to the widget.| String| No| | window | Window-related configurations.| Object| Yes| - | isDefault | Whether the widget is a default one. Each ability has only one default widget.
**true**: The widget is the default one.
**false**: The widget is not the default one.| Boolean| No| - | colorMode | Color mode of the widget.
**auto**: The widget adopts the auto-adaptive color mode.
**dark**: The widget adopts the dark color mode.
**light**: The widget adopts the light color mode.| String| Yes (initial value: **auto**)| - | supportDimensions | Grid styles supported by the widget.
**1 * 2**: indicates a grid with one row and two columns.
**2 * 2**: indicates a grid with two rows and two columns.
**2 * 4**: indicates a grid with two rows and four columns.
**4 * 4**: indicates a grid with four rows and four columns.| String array| No| + | isDefault | Whether the widget is a default one. Each UIAbility has only one default widget.
- **true**: The widget is the default one.
- **false**: The widget is not the default one.| Boolean| No| + | colorMode | Color mode of the widget.
- **auto**: auto-adaptive color mode
- **dark**: dark color mode
- **light**: light color mode| String| Yes (initial value: **auto**)| + | supportDimensions | Grid styles supported by the widget.
- **1 * 2**: indicates a grid with one row and two columns.
- **2 * 2**: indicates a grid with two rows and two columns.
- **2 * 4**: indicates a grid with two rows and four columns.
- **4 * 4**: indicates a grid with four rows and four columns.| String array| No| | defaultDimension | Default grid style of the widget. The value must be available in the **supportDimensions** array of the widget.| String| No| - | updateEnabled | Whether the widget can be updated periodically.
**true**: The widget can be updated at a specified interval (**updateDuration**) or at the scheduled time (**scheduledUpdateTime**). **updateDuration** takes precedence over **scheduledUpdateTime**.
**false**: The widget cannot be updated periodically.| Boolean| No| + | updateEnabled | Whether the widget can be updated periodically.
- **true**: The widget can be updated at a specified interval (**updateDuration**) or at the scheduled time (**scheduledUpdateTime**). **updateDuration** takes precedence over **scheduledUpdateTime**. If both are specified, the value specified by **updateDuration** is used.
- **false**: The widget cannot be updated periodically.| Boolean| No| | scheduledUpdateTime | Scheduled time to update the widget. The value is in 24-hour format and accurate to minute.
**updateDuration** takes precedence over **scheduledUpdateTime**. If both are specified, the value specified by **updateDuration** is used.| String| Yes (initial value: **0:0**)| | updateDuration | Interval to update the widget. The value is a natural number, in the unit of 30 minutes.
If the value is **0**, this field does not take effect.
If the value is a positive integer *N*, the interval is calculated by multiplying *N* and 30 minutes.
**updateDuration** takes precedence over **scheduledUpdateTime**. If both are specified, the value specified by **updateDuration** is used.| Number| Yes (initial value: **0**)| | formConfigAbility | Link to a specific page of the application. The value is a URI.| String| Yes (initial value: left empty)| @@ -228,13 +214,14 @@ To create a widget in the stage model, implement the lifecycle callbacks of **Fo | metaData | Metadata of the widget. This field contains the array of the **customizeData** field.| Object| Yes (initial value: left empty)| Example configuration: + ```json { "forms": [ { "name": "widget", - "description": "This is a widget.", + "description": "This is a service widget.", "src": "./js/widget/pages/index/index", "window": { "designWidth": 720, @@ -270,8 +257,8 @@ async function storeFormInfo(formId: string, formName: string, tempFlag: boolean "updateCount": 0 }; try { - const storage = await dataStorage.getStorage(DATA_STORAGE_PATH); - // Put the widget information. + const storage = await dataPreferences.getPreferences(this.context, DATA_STORAGE_PATH); + // put form info await storage.put(formId, JSON.stringify(formInfo)); console.info(`[EntryFormAbility] storeFormInfo, put form info successfully, formId: ${formId}`); await storage.flush(); @@ -281,7 +268,7 @@ async function storeFormInfo(formId: string, formName: string, tempFlag: boolean } export default class EntryFormAbility extends FormExtension { - // ... + ... onAddForm(want) { console.info('[EntryFormAbility] onAddForm'); @@ -309,7 +296,7 @@ You should override **onRemoveForm** to implement widget data deletion. const DATA_STORAGE_PATH = "/data/storage/el2/base/haps/form_store"; async function deleteFormInfo(formId: string) { try { - const storage = await dataStorage.getStorage(DATA_STORAGE_PATH); + const storage = await dataPreferences.getPreferences(this.context, DATA_STORAGE_PATH); // Delete the widget information. await storage.delete(formId); console.info(`[EntryFormAbility] deleteFormInfo, del form info successfully, formId: ${formId}`); @@ -319,10 +306,10 @@ async function deleteFormInfo(formId: string) { } } -// ... +... export default class EntryFormAbility extends FormExtension { - // ... + ... onRemoveForm(formId) { console.info('[EntryFormAbility] onRemoveForm'); // Delete the persistent widget instance data. @@ -332,7 +319,7 @@ export default class EntryFormAbility extends FormExtension { } ``` -For details about how to implement persistent data storage, see [Lightweight Data Store Development](../database/database-preference-guidelines.md). +For details about how to implement persistent data storage, see [Application Data Persistence](../database/app-data-persistence-overview.md). The **Want** object passed in by the widget host to the widget provider contains a flag that specifies whether the requested widget is normal or temporary. @@ -369,13 +356,10 @@ onUpdateForm(formId) { You can use the web-like paradigm (HML+CSS+JSON) to develop JS widget pages. This section describes how to develop a page shown below. -![widget-development-stage](figures/widget-development-stage.png) - -> **NOTE** -> -> Only the JavaScript-based web-like development paradigm is supported when developing the widget UI. +![WidgetCardPage](figures/WidgetCardPage.png) - HML: uses web-like paradigm components to describe the widget page information. + ```html
@@ -392,6 +376,7 @@ You can use the web-like paradigm (HML+CSS+JSON) to develop JS widget pages. Thi ``` - CSS: defines style information about the web-like paradigm components in HML. + ```css .container { @@ -433,6 +418,7 @@ You can use the web-like paradigm (HML+CSS+JSON) to develop JS widget pages. Thi ``` - JSON: defines data and event interaction on the widget UI page. + ```json { @@ -455,24 +441,27 @@ You can use the web-like paradigm (HML+CSS+JSON) to develop JS widget pages. Thi ### Developing Widget Events -You can set router and message events for components on a widget. The router event applies to ability redirection, and the message event applies to custom click events. +You can set router and message events for components on a widget. The router event applies to UIAbility redirection, and the message event applies to custom click events. The key steps are as follows: 1. Set the **onclick** field in the HML file to **routerEvent** or **messageEvent**, depending on the **actions** settings in the JSON file. 2. Set the router event. + - **action**: **"router"**, which indicates a router event. - - **abilityName**: name of the ability to redirect to (PageAbility component in the FA model and UIAbility component in the stage model). For example, the default UIAbility name of the stage model created by DevEco Studio is EntryAbility. - - **params**: custom parameters passed to the target ability. Set them as required. The value can be obtained from **parameters** in **want** used for starting the target ability. For example, in the lifecycle function **onCreate** of the main ability in the stage model, you can obtain **want** and its **parameters** field. + - **abilityName**: name of the UIAbility to redirect to (PageAbility component in the FA model and UIAbility component in the stage model). For example, the default UIAbility name of the stage model created by DevEco Studio is EntryAbility. + - **params**: custom parameters passed to the target UIAbility. Set them as required. The value can be obtained from **parameters** in **want** used for starting the target UIAbility. For example, in the lifecycle function **onCreate** of the MainAbility in the stage model, you can obtain **want** and its **parameters** field. 3. Set the message event. + - **action**: **"message"**, which indicates a message event. - **params**: custom parameters of the message event. Set them as required. The value can be obtained from **message** in the widget lifecycle function **onFormEvent()**. -The following is an example: +The following are examples: - HML file: + ```html
@@ -489,6 +478,7 @@ The following is an example: ``` - CSS file: + ```css .container { @@ -530,6 +520,7 @@ The following is an example: ``` - JSON file: + ```json { @@ -556,54 +547,46 @@ The following is an example: } ``` -- Receive the router event and obtain parameters in UIAbility. +- Receive the router event in UIAbility and obtain parameters. + ```ts import UIAbility from '@ohos.app.ability.UIAbility' export default class EntryAbility extends UIAbility { onCreate(want, launchParam) { + let params = JSON.parse(want.parameters.params); // Obtain the info parameter passed in the router event. - if (want.parameters.info === "router info") { - // Do something. - // console.log("router info:" + want.parameters.info) + if (params.info === "router info") { + // do something + // console.info("router info:" + params.info) } // Obtain the message parameter passed in the router event. - if (want.parameters.message === "router message") { - // Do something. - // console.log("router message:" + want.parameters.message) + if (params.message === "router message") { + // do something + // console.info("router message:" + params.message) } } - // ... + ... }; ``` - Receive the message event in FormExtensionAbility and obtain parameters. + ```ts import FormExtension from '@ohos.app.form.FormExtensionAbility'; export default class FormAbility extends FormExtension { - // ... + ... onFormEvent(formId, message) { // Obtain the detail parameter passed in the message event. let msg = JSON.parse(message) - if (msg.params.detail === "message detail") { - // Do something. - // console.log("message info:" + msg.params.detail) + if (msg.detail === "message detail") { + // do something + // console.info("message info:" + msg.detail) } } - // ... + ... }; ``` - -## Restrictions - -To minimize the abuse of **FormExtensionAbility** by third-party applications, the following APIs cannot be invoked in **FormExtensionAbility**: - -- @ohos.ability.particleAbility.d.ts -- @ohos.backgroundTaskManager.d.ts -- @ohos.resourceschedule.backgroundTaskManager.d.ts -- @ohos.multimedia.camera.d.ts -- @ohos.multimedia.audio.d.ts -- @ohos.multimedia.media.d.ts diff --git a/en/application-dev/application-models/lifecycleapp-switch.md b/en/application-dev/application-models/lifecycleapp-switch.md index 892a8915bfed9927c2707364bdaffa1547f71bf6..e2fa51264d4d41f52cef0a91e119a9e9d8e75d78 100644 --- a/en/application-dev/application-models/lifecycleapp-switch.md +++ b/en/application-dev/application-models/lifecycleapp-switch.md @@ -1,20 +1,20 @@ # LifecycleApp Switching - | API in the FA Model| Corresponding d.ts File in the Stage Model| Corresponding API in the Stage Model| +| API in the FA Model| Corresponding .d.ts File in the Stage Model| Corresponding API in the Stage Model| | -------- | -------- | -------- | | onShow?(): void; | \@ohos.window.d.ts | [on(eventType: 'windowStageEvent', callback: Callback<WindowStageEventType>): void;](../reference/apis/js-apis-window.md#onwindowstageevent9)
Listens for the switching to the [foreground](../reference/apis/js-apis-window.md#windowstageeventtype9).| | onHide?(): void; | \@ohos.window.d.ts | [on(eventType: 'windowStageEvent', callback: Callback<WindowStageEventType>): void;](../reference/apis/js-apis-window.md#onwindowstageevent9)
Listens for the switching to the [background](../reference/apis/js-apis-window.md#windowstageeventtype9).| -| onDestroy?(): void; | \@ohos.app.ability.UIAbility.d.ts | [onDestroy(): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityondestroy) | +| onDestroy?(): void; | \@ohos.app.ability.UIAbility.d.ts | [onDestroy(): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityondestroy) | | onCreate?(): void; | \@ohos.app.ability.UIAbility.d.ts | [onCreate(want: Want, param: AbilityConstant.LaunchParam): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityoncreate) | | onWindowDisplayModeChanged?(isShownInMultiWindow: boolean, newConfig: resourceManager.Configuration): void; | There is no corresponding API in the stage model.| No corresponding API is provided.| | onStartContinuation?(): boolean; | There is no corresponding API in the stage model.| In the stage model, an application does not need to detect whether the continuation is successful (detected when the application initiates the continuation request). Therefore, the **onStartContinuation()** callback is deprecated.| | onSaveData?(data: Object): boolean; | \@ohos.app.ability.UIAbility.d.ts | [onContinue(wantParam : {[key: string]: any}): AbilityConstant.OnContinueResult;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityoncontinue) | | onCompleteContinuation?(result: number): void; | application\ContinueCallback.d.ts | [onContinueDone(result: number): void;](../reference/apis/js-apis-distributedMissionManager.md#continuecallback) | -| onRestoreData?(data: Object): void; | \@ohos.app.ability.UIAbility.d.ts | [onCreate(want: Want, param: AbilityConstant.LaunchParam): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityoncreate)
[onNewWant(want: Want, launchParams: AbilityConstant.LaunchParam): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonnewwant)
In standard or singleton mode, the target ability completes data restoration in the **onCreate()** callback. In the callback, **launchParam.launchReason** is used to determine whether it is a continuation-based launch scenario. If it is, the data saved before continuation can be obtained from the **want** parameter.| +| onRestoreData?(data: Object): void; | \@ohos.app.ability.UIAbility.d.ts | [onCreate(want: Want, param: AbilityConstant.LaunchParam): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityoncreate)
[onNewWant(want: Want, launchParams: AbilityConstant.LaunchParam): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonnewwant)
In multiton or singleton mode, the target ability completes data restoration in the **onCreate()** callback. In the callback, **launchParam.launchReason** is used to determine whether it is a continuation-based launch scenario. If it is, the data saved before continuation can be obtained from the **want** parameter.| | onRemoteTerminated?(): void; | application\ContinueCallback.d.ts | [onContinueDone(result: number): void;](../reference/apis/js-apis-distributedMissionManager.md#continuecallback) | | onSaveAbilityState?(outState: PacMap): void; | \@ohos.app.ability.UIAbility.d.ts | [onSaveState(reason: AbilityConstant.StateType, wantParam : {[key: string]: any}): AbilityConstant.OnSaveResult;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonsavestate) | -| onRestoreAbilityState?(inState: PacMap): void; | \@ohos.app.ability.UIAbility.d.ts | [onCreate(want: Want, param: AbilityConstant.LaunchParam): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityoncreate)
After the application is restarted, the **onCreate()** callback is triggered. In the callback, **launchParam.launchReason** is used to determine whether it is a self-recovery scenario. If it is, the data saved before the restart can be obtained from the **want** parameter.| +| onRestoreAbilityState?(inState: PacMap): void; | \@ohos.app.ability.UIAbility.d.ts | [onCreate(want: Want, param: AbilityConstant.LaunchParam): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityoncreate)
After an application is restarted, the **onCreate()** callback is triggered. In the callback, **launchParam.launchReason** is used to determine whether it is a self-recovery scenario. If it is, the data saved before the restart can be obtained from the **want** parameter.| | onInactive?(): void; | \@ohos.app.ability.UIAbility.d.ts | [onBackground(): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonbackground) | | onActive?(): void; | \@ohos.app.ability.UIAbility.d.ts | [onForeground(): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonforeground) | | onNewWant?(want: Want): void; | \@ohos.app.ability.UIAbility.d.ts | [onNewWant(want: Want, launchParams: AbilityConstant.LaunchParam): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonnewwant) | diff --git a/en/application-dev/application-models/lifecycledata-switch.md b/en/application-dev/application-models/lifecycledata-switch.md index be96421a92161deeb26c9e99af9ec5de332d9e25..6e66481e866ef300453f8fcd94fcbe06b7fc7b13 100644 --- a/en/application-dev/application-models/lifecycledata-switch.md +++ b/en/application-dev/application-models/lifecycledata-switch.md @@ -1,7 +1,7 @@ # LifecycleData Switching - | API in the FA Model| Corresponding d.ts File in the Stage Model| Corresponding API in the Stage Model| + | API in the FA Model| Corresponding .d.ts File in the Stage Model| Corresponding API in the Stage Model| | -------- | -------- | -------- | | update?(uri: string, valueBucket: rdb.ValuesBucket, predicates: dataAbility.DataAbilityPredicates, callback: AsyncCallback<number>): void; | \@ohos.application.DataShareExtensionAbility.d.ts | [update?(uri: string, predicates: dataSharePredicates.DataSharePredicates, valueBucket: ValuesBucket, callback: AsyncCallback<number>): void;](../reference/apis/js-apis-application-dataShareExtensionAbility.md#update) | | query?(uri: string, columns: Array<string>, predicates: dataAbility.DataAbilityPredicates, callback: AsyncCallback<ResultSet>): void; | \@ohos.application.DataShareExtensionAbility.d.ts | [query?(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array<string>, callback: AsyncCallback<Object>): void;](../reference/apis/js-apis-application-dataShareExtensionAbility.md#query) | diff --git a/en/application-dev/application-models/lifecycleform-switch.md b/en/application-dev/application-models/lifecycleform-switch.md index 80e577eeac759f589cb53c6b367ae17ba8b98e8c..6356d632e2dc20d5217bb32f2088061d9ab8fe8f 100644 --- a/en/application-dev/application-models/lifecycleform-switch.md +++ b/en/application-dev/application-models/lifecycleform-switch.md @@ -1,7 +1,7 @@ # LifecycleForm Switching - | API in the FA Model| Corresponding d.ts File in the Stage Model| Corresponding API in the Stage Model| + | API in the FA Model| Corresponding .d.ts File in the Stage Model| Corresponding API in the Stage Model| | -------- | -------- | -------- | | onCreate?(want: Want): formBindingData.FormBindingData; | \@ohos.app.form.FormExtensionAbility.d.ts | [onAddForm(want: Want): formBindingData.FormBindingData;](../reference/apis/js-apis-app-form-formExtensionAbility.md#onaddform) | | onCastToNormal?(formId: string): void; | \@ohos.app.form.FormExtensionAbility.d.ts | [onCastToNormalForm(formId: string): void;](../reference/apis/js-apis-app-form-formExtensionAbility.md#oncasttonormalform) | diff --git a/en/application-dev/application-models/lifecycleservice-switch.md b/en/application-dev/application-models/lifecycleservice-switch.md index d1fcdc7a30efb0114e092ac5a6233566270312fa..96d1e132f7abc1b59f13fd7dc81540f1653f3510 100644 --- a/en/application-dev/application-models/lifecycleservice-switch.md +++ b/en/application-dev/application-models/lifecycleservice-switch.md @@ -1,7 +1,7 @@ # LifecycleService Switching - | API in the FA Model| Corresponding d.ts File in the Stage Model| Corresponding API in the Stage Model| + | API in the FA Model| Corresponding .d.ts File in the Stage Model| Corresponding API in the Stage Model| | -------- | -------- | -------- | | onStart?(): void; | \@ohos.app.ability.ServiceExtensionAbility.d.ts | [onCreate(want: Want): void;](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md#serviceextensionabilityoncreate) | | onCommand?(want: Want, startId: number): void; | \@ohos.app.ability.ServiceExtensionAbility.d.ts | [onRequest(want: Want, startId: number): void;](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md#serviceextensionabilityonrequest) | | diff --git a/en/application-dev/application-models/medialibrary-switch.md b/en/application-dev/application-models/medialibrary-switch.md index 29e9b10964d2b9c967960f6c2ad802a942aa0ac3..dc671d1b61b467f98d7d01f43703b165df4c1e52 100644 --- a/en/application-dev/application-models/medialibrary-switch.md +++ b/en/application-dev/application-models/medialibrary-switch.md @@ -1,6 +1,6 @@ # mediaLibrary Switching - | API in the FA Model| Corresponding d.ts File in the Stage Model| Corresponding API in the Stage Model| + | API in the FA Model| Corresponding .d.ts File in the Stage Model| Corresponding API in the Stage Model| | -------- | -------- | -------- | | [getMediaLibrary(): MediaLibrary;](../reference/apis/js-apis-medialibrary.md#medialibrarygetmedialibrary) | \@ohos.multimedia.mediaLibrary.d.ts | [getMediaLibrary(context: Context): MediaLibrary;](../reference/apis/js-apis-medialibrary.md#medialibrarygetmedialibrary8) | diff --git a/en/application-dev/application-models/mission-management-launch-type.md b/en/application-dev/application-models/mission-management-launch-type.md index 267ed5011fe28cdc576e6caca85a526450110867..56a389cc52e093008491f75e01144bd7635b94eb 100644 --- a/en/application-dev/application-models/mission-management-launch-type.md +++ b/en/application-dev/application-models/mission-management-launch-type.md @@ -1,4 +1,4 @@ -# Mission Management and Launch Type +# Mission and Launch Type One UIAbility instance corresponds to one mission. The number of UIAbility instances is related to the UIAbility launch type, specified by **launchType**, which is configured in the **config.json** file in the FA model and the [module.json5](../quick-start/module-configuration-file.md) file in the stage model. @@ -8,16 +8,19 @@ The following describes how the mission list manager manages the UIAbility insta - **singleton**: Only one UIAbility instance exists for an application. **Figure 1** Missions and singleton mode + ![mission-and-singleton](figures/mission-and-singleton.png) -- **standard**: Each time [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) is called, a **UIAbility** instance is created in the application process. +- **multiton**: Each time [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) is called, a UIAbility instance is created in the application process. + + **Figure 2** Missions and multiton mode - **Figure 2** Missions and standard mode - ![mission-and-standard](figures/mission-and-standard.png) + ![mission-and-multiton](figures/mission-and-multiton.png) -- **specified**: The ([onAcceptWant](../reference/apis/js-apis-app-ability-abilityStage.md#abilitystageonacceptwant)) method of [AbilityStage](abilitystage.md) determines whether to create an instance. +- **specified**: The ([onAcceptWant()](../reference/apis/js-apis-app-ability-abilityStage.md#abilitystageonacceptwant)) method of [AbilityStage](abilitystage.md) determines whether to create a UIAbility instance. **Figure 3** Missions and specified mode + ![mission-and-specified](figures/mission-and-specified.png) diff --git a/en/application-dev/application-models/mission-management-overview.md b/en/application-dev/application-models/mission-management-overview.md index ba55ebb136ebffca0294bf69013f2f2ab4392e7f..785a9f8291ea43e756ebed07843ceef23570160d 100644 --- a/en/application-dev/application-models/mission-management-overview.md +++ b/en/application-dev/application-models/mission-management-overview.md @@ -4,7 +4,7 @@ Before getting started with the development of mission management, be familiar with the following concepts related to mission management: -- AbilityRecord: minimum unit for the system service to manage a UIAbility instance. It corresponds to a UIAbility component instance of an application. +- AbilityRecord: minimum unit for the system service to manage a UIAbility instance. It corresponds to a UIAbility component instance of an application. A maximum of 512 UIAbility instances can be managed on the system service side. - MissionRecord: minimum unit for mission management. One MissionRecord has only one AbilityRecord. In other words, a UIAbility component instance corresponds to a mission. @@ -30,42 +30,42 @@ Missions are managed by system applications (such as home screen), rather than t A UIAbility instance corresponds to an independent mission. Therefore, when an application calls [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) to start a UIAbility, a mission is created. -To call [missionManager](../reference/apis/js-apis-application-missionManager.md) to manage missions, the home screen application must request the **ohos.permission.MANAGE_MISSIONS** permission. For details about the configuration, see [Declaring Permissions in the Configuration File](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file). +1. To call [missionManager](../reference/apis/js-apis-application-missionManager.md) to manage missions, the home screen application must request the **ohos.permission.MANAGE_MISSIONS** permission. For details about the configuration, see [Declaring Permissions in the Configuration File](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file). -You can use **missionManager** to manage missions, for example, listening for mission changes, obtaining mission information or snapshots, and clearing, locking, or unlocking missions. +2. You can use **missionManager** to manage missions, for example, listening for mission changes, obtaining mission information or snapshots, and clearing, locking, or unlocking missions. ```ts import missionManager from '@ohos.app.ability.missionManager' let listener = { - // Listen for mission creation. - onMissionCreated: function (mission) { - console.info("--------onMissionCreated-------") - }, - // Listen for mission destruction. - onMissionDestroyed: function (mission) { - console.info("--------onMissionDestroyed-------") - }, - // Listen for mission snapshot changes. - onMissionSnapshotChanged: function (mission) { - console.info("--------onMissionSnapshotChanged-------") - }, - // Listen for switching the mission to the foreground. - onMissionMovedToFront: function (mission) { - console.info("--------onMissionMovedToFront-------") - }, - // Listen for mission icon changes. - onMissionIconUpdated: function (mission, icon) { - console.info("--------onMissionIconUpdated-------") - }, - // Listen for mission name changes. - onMissionLabelUpdated: function (mission) { - console.info("--------onMissionLabelUpdated-------") - }, - // Listen for mission closure events. - onMissionClosed: function (mission) { - console.info("--------onMissionClosed-------") - } + // Listen for mission creation. + onMissionCreated: function (mission) { + console.info("--------onMissionCreated-------") + }, + // Listen for mission destruction. + onMissionDestroyed: function (mission) { + console.info("--------onMissionDestroyed-------") + }, + // Listen for mission snapshot changes. + onMissionSnapshotChanged: function (mission) { + console.info("--------onMissionSnapshotChanged-------") + }, + // Listen for switching the mission to the foreground. + onMissionMovedToFront: function (mission) { + console.info("--------onMissionMovedToFront-------") + }, + // Listen for mission icon changes. + onMissionIconUpdated: function (mission, icon) { + console.info("--------onMissionIconUpdated-------") + }, + // Listen for mission name changes. + onMissionLabelUpdated: function (mission) { + console.info("--------onMissionLabelUpdated-------") + }, + // Listen for mission closure events. + onMissionClosed: function (mission) { + console.info("--------onMissionClosed-------") + } }; // 1. Register a mission change listener. @@ -73,56 +73,56 @@ You can use **missionManager** to manage missions, for example, listening for mi // 2. Obtain the latest 20 missions in the system. missionManager.getMissionInfos("", 20, (error, missions) => { - console.info("getMissionInfos is called, error.code = " + error.code); - console.info("size = " + missions.length); - console.info("missions = " + JSON.stringify(missions)); + console.info("getMissionInfos is called, error.code = " + error.code); + console.info("size = " + missions.length); + console.info("missions = " + JSON.stringify(missions)); }); // 3. Obtain the detailed information about a mission. let missionId = 11; // The mission ID 11 is only an example. let mission = missionManager.getMissionInfo("", missionId).catch(function (err) { - console.info(err); + console.info(err); }); // 4. Obtain the mission snapshot. missionManager.getMissionSnapShot("", missionId, (error, snapshot) => { - console.info("getMissionSnapShot is called, error.code = " + error.code); - console.info("bundleName = " + snapshot.ability.bundleName); + console.info("getMissionSnapShot is called, error.code = " + error.code); + console.info("bundleName = " + snapshot.ability.bundleName); }) // 5. Obtain the low-resolution mission snapshot. missionManager.getLowResolutionMissionSnapShot("", missionId, (error, snapshot) => { - console.info("getLowResolutionMissionSnapShot is called, error.code = " + error.code); - console.info("bundleName = " + snapshot.ability.bundleName); + console.info("getLowResolutionMissionSnapShot is called, error.code = " + error.code); + console.info("bundleName = " + snapshot.ability.bundleName); }) // 6. Lock or unlock the mission. missionManager.lockMission(missionId).then(() => { - console.info("lockMission is called "); + console.info("lockMission is called "); }); missionManager.unlockMission(missionId).then(() => { - console.info("unlockMission is called "); + console.info("unlockMission is called "); }); // 7. Switch the mission to the foreground. missionManager.moveMissionToFront(missionId).then(() => { - console.info("moveMissionToFront is called "); + console.info("moveMissionToFront is called "); }); // 8. Clear a single mission. missionManager.clearMission(missionId).then(() => { - console.info("clearMission is called "); + console.info("clearMission is called "); }); // 9. Clear all missions. missionManager.clearAllMissions().catch(function (err) { - console.info(err); + console.info(err); }); // 10. Deregister the mission change listener. missionManager.off('mission', listenerId, (error) => { - console.info("unregisterMissionListener"); + console.info("unregisterMissionListener"); }) ``` diff --git a/en/application-dev/application-models/mission-set-icon-name-for-task-snapshot.md b/en/application-dev/application-models/mission-set-icon-name-for-task-snapshot.md index 9fdc03477c0552f523a0ee9c40c6fa5b8d7c4363..d758de4763e2933d09b7bcb8750f502d0c593800 100644 --- a/en/application-dev/application-models/mission-set-icon-name-for-task-snapshot.md +++ b/en/application-dev/application-models/mission-set-icon-name-for-task-snapshot.md @@ -8,7 +8,7 @@ Figure 1 Mission snapshot of a UIAbility ![](figures/mission-list-recent.png) -You can also use [UIAbilityContext.setMissionIcon()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextsetmissionicon) and [UIAbilityContext.setMissionLabel()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextsetmissionlabel) to customize the icon and name for a mission snapshot. For example, for a UIAbility instance with the launch type set to **standard**, you can configure the icon and name for each mission snapshot based on different functions. +You can also use [UIAbilityContext.setMissionIcon()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextsetmissionicon) and [UIAbilityContext.setMissionLabel()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextsetmissionlabel) to customize the icon and name for a mission snapshot. For example, for a UIAbility instance in multiton mode, you can configure the icon and name for each mission snapshot based on different functions. This document describes the following operations: @@ -17,19 +17,22 @@ This document describes the following operations: ## Setting a Mission Snapshot Icon (for System Applications Only) -Call [UIAbilityContext.setMissionIcon()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextsetmissionicon) to set the icon of a mission snapshot. The icon is an object of the [PixelMap](../reference/apis/js-apis-image.md#pixelmap7) type. For details about how to obtain the context, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability). +Call [UIAbilityContext.setMissionIcon()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextsetmissionicon) to set the icon of a mission snapshot. For details about how to obtain the context, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability). For details about how to obtain the PixelMap information in the example, see [Image Decoding](../media/image-decoding.md). + ```ts -let imagePixelMap: PixelMap = undefined; // Obtain the PixelMap information. +let context = ...; // UIAbilityContext +let pixelMap: PixelMap =...; // PixelMap information of the image. -this.context.setMissionIcon(imagePixelMap, (err) => { - console.error(`setMissionLabel failed, code is ${err.code}, message is ${err.message}`); +context.setMissionIcon(pixelMap, (err) => { + if (err.code) { + console.error(`Failed to set mission icon. Code is ${err.code}, message is ${err.message}`); + } }) ``` The display effect is shown below. Figure 2 Mission snapshot icon - ![](figures/mission-set-task-snapshot-icon.png) ## Setting a Mission Snapshot Name @@ -37,15 +40,16 @@ Figure 2 Mission snapshot icon Call [UIAbilityContext.setMissionLabel()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextsetmissionlabel) to set the name of a mission snapshot. ```ts -this.context.setMissionLabel('test').then(() => { - console.info('setMissionLabel succeeded.'); +let context = ...; // UIAbilityContext + +context.setMissionLabel('test').then(() => { + console.info('Succeeded in seting mission label.'); }).catch((err) => { - console.error(`setMissionLabel failed, code is ${err.code}, message is ${err.message}`); + console.error(`Failed to set mission label. Code is ${err.code}, message is ${err.message}`); }); ``` The display effect is shown below. Figure 3 Mission snapshot name - -![](figures/mission-set-task-snapshot-label.png) \ No newline at end of file +![](figures/mission-set-task-snapshot-label.png) diff --git a/en/application-dev/application-models/model-switch-overview.md b/en/application-dev/application-models/model-switch-overview.md index e42882ca59b33c65fe6591510954d95e2c49453b..9a8a2101ed2a2f9f402404cc68eea49d92f84121 100644 --- a/en/application-dev/application-models/model-switch-overview.md +++ b/en/application-dev/application-models/model-switch-overview.md @@ -5,19 +5,23 @@ Perform the following operations to switch a declarative paradigm-based applicat - Project switch: Create an application project of the stage model. + ![model-switch-overview1](figures/model-switch-overview1.png) - [Configuration file switch](configuration-file-diff.md): Switch **config.json** to **app.json5** and **module.json5**. + ![model-switch-overview2](figures/model-switch-overview2.png) - [Component switch](pageability-switch.md): Switch the PageAbility, ServiceAbility, and DataAbility components of the FA model to the UIAbility and ExtensionAbility components of the stage model. The figure below shows only the switching from PageAbility to UIAbility. The left part is the FA model, and **app.ets** is the PageAbility component. The right part is the stage model, and **EntryAbility.ts** is the UIAbility component. -![model-switch-overview3](figures/model-switch-overview3.png) + ![model-switch-overview3](figures/model-switch-overview3.png) - [Widget switch](widget-switch.md): Switch the FormAbility component of the FA model to the FormExtensionAbility component of the stage model. In the figure below, **Service Widget** is FormAbility in the FA model and FormExtensionAbility in the stage model. + ![model-switch-overview4](figures/model-switch-overview4.png) ![model-switch-overview5](figures/model-switch-overview5.png) - [API switch](api-switch-overview.md): Switch the APIs with the **FAModelOnly** tag used in the FA model to the recommended APIs in the stage model. + ![model-switch-overview6](figures/model-switch-overview6.png) diff --git a/en/application-dev/application-models/module-switch.md b/en/application-dev/application-models/module-switch.md index a6e532e94827198880cb772c174725b2a89c469b..4ca41a83e7282fe155c43d01b0cbfd11939cb5c8 100644 --- a/en/application-dev/application-models/module-switch.md +++ b/en/application-dev/application-models/module-switch.md @@ -1,9 +1,9 @@ # Switching of module -When switching an application from the FA model to the stage model, you must migrate the configurations under the **module** tag in the **config.json** file to the **module** tag in the **module.json5** file. +When switching an application from the FA model to the stage model, migrate the configurations under **module** in the **config.json** file to **module** in the **module.json5** file. -### **Table 1** module comparison +**Table 1** module comparison | Field Name in the FA Model| Field Description| Field Name in the Stage Model| Difference| | -------- | -------- | -------- | -------- | @@ -15,52 +15,52 @@ When switching an application from the FA model to the stage model, you must mig | moduleType in the distro object| Type of the HAP file. The value can be **entry** or **feature**. For the HAR type, set this field to **har**.| type | The field name is changed.| | installationFree in the distro object| Whether the HAP file supports the installation-free feature.| installationFree | The field name is changed.| | deliveryWithInstall in the distro object| Whether the HAP file is installed with the application.| deliveryWithInstall | The field name is changed.| -| metaData | Metadata of the HAP file.| metadata | See [Table 2](#table-2-metadata-comparison).| -| abilities | All abilities in the current module.| abilities | See [Table 5](#table-5-abilities-comparison).| +| metaData | Metadata of the HAP file.| metadata | For details, see Table 2.| +| abilities | All abilities in the current module.| abilities | For details, see Table 5.| | js | A set of JS modules developed using ArkUI. Each element in the set represents the information about a JS module.| pages | The stage model retains **pages** under the **module** tag. The window configuration is the lower level of **pages**.| | shortcuts | Shortcuts of the application.| shortcut_config.json| In the stage model, the **shortcut_config.json** file is defined in **resources/base/profile** in the development view.| | reqPermissions | Permissions that the application requests from the system when it is running.| requestPermissions | The field name is changed.| | colorMode | Color mode of the application.| / | This configuration is not supported in the stage model.| -| distroFilter | Distribution rules of the application.| distroFilter_config.json| In the stage model, the **distroFilter_config.json** file is defined in **resources/base/profile** in the development view.| +| distributionFilter | Distribution rules of the application.| distroFilter_config.json| In the stage model, the **distroFilter_config.json** file is defined in **resources/base/profile** in the development view.| | reqCapabilities | Device capabilities required for running the application.| / | This configuration is not supported in the stage model.| | commonEvents | Common events.| common_event_config.json| In the stage model, the **common_event_config.json** file is defined in **resources/base/profile** in the development view.| | entryTheme | Keyword of an OpenHarmony internal theme.| / | This configuration is not supported in the stage model.| -### Table 2 metaData comparison +**Table 2** metaData comparison -| Field Name Under metaData in the FA Model| Field Description| Field Name Under metaData in the Stage Model| Difference| +| Field Name in the FA Model| Field Description| Field Name in the Stage Model| Difference| | -------- | -------- | -------- | -------- | | parameters | Metadata of the parameters to be passed for calling the ability.| / | This configuration is not supported in the stage model.| | results | Metadata of the ability return value.| / | This configuration is not supported in the stage model.| -| customizeData | Custom metadata of the parent component. **parameters** and **results** cannot be configured in **application**.| metadata | See [Table 3](#table-3-comparison-between-customizedata-under-metadata-in-the-fa-model-and-metadata-in-the-stage-model).| +| customizeData | Custom metadata of the parent component. **parameters** and **results** cannot be configured in **application**.| metadata | **For details**, see Table 3.| -### Table 3 Comparison between customizeData under metaData in the FA model and metadata in the stage model +**Table 3** Comparison between customizeData under metaData in the FA model and metadata in the stage Model -| Field Name Under customizeData in metaData in the FA Model| Field Description| Field Name Under metaData in the Stage Model| Difference| +| Field Name in the FA Model| Field Description| Field Name in the Stage Model| Difference| | -------- | -------- | -------- | -------- | | name | Key name that identifies a data item. The value is a string with a maximum of 255 bytes.| name | None.| | value | Value of the data item. The value is a string with a maximum of 255 bytes.| value | None.| -| extra | Format of the current custom data. The value is the resource value of **extra**.| resource | The field name is changed. For details, see [Table 4](#table 4-metadata-examples).| +| extra | Format of the current custom data. The value is the resource value of **extra**.| resource | The field name is changed. For details, see Table 4.| -### Table 4 metaData examples +**Table 4** metaData examples | Example in the FA Model| Example in the Stage Model| | -------- | -------- | | "meteData": {
"customizeDate": [{
"name": "label",
"value": "string",
"extra": "$string:label",
}]
} | "meteData": [{
"name": "label",
"value": "string",
"resource": "$string:label",
}] | -### Table 5 abilities comparison +**Table 5** abilities comparison | Field Name Under abilities in the FA Model| Field Description| Field Name Under abilities in the Stage Model| Difference| | -------- | -------- | -------- | -------- | | process | Name of the process running the application or ability.| / | The stage model does not support configuration of **process** under **abilities**. The configuration of **process** is available under the **module** tag.| | uri | URI of the ability.| / | This configuration is not supported in the stage model.| | deviceCapability | Device capabilities required to run the ability.| / | This configuration is not supported in the stage model.| -| metaData | Metadata of the ability.| metadata | See [Table 2](#table-2-metadata-comparison).| +| metaData | Metadata of the ability.| metadata | For details, see Table 2.| | type | Ability type.| / | This configuration is not supported in the stage model.| -| grantPermission | Whether permissions can be granted for any data in the ability.| / | The stage model does not support such a configuration under **abilities**.| +| grantPermission | Whether permissions can be granted to any data in the ability.| / | The stage model does not support such a configuration under **abilities**.| | readPermission | Permission required for reading data in the ability. This field applies only to the ability using the Data template.| / | In the stage model, this configuration is available under **extensionAbilities**, but not **abilities**.| | writePermission | Permission required for writing data to the ability.| / | In the stage model, this configuration is available under **extensionAbilities**, but not **abilities**.| | configChanges | System configurations that the ability concerns.| / | This configuration is not supported in the stage model.| @@ -71,5 +71,5 @@ When switching an application from the FA model to the stage model, you must mig | formsEnabled | Whether the ability can provide widgets.| / | This configuration is not supported in the stage model.| | forms | Information about the widgets used by the ability. This field is valid only when **formsEnabled** is set to **true**.| form_config.json| In the stage model, the **form_config.json** file is defined in **resources/base/profile** in the development view.| | srcLanguage | Programming language used to develop the ability.| / | This configuration is not supported in the stage model.| -| srcPath | Path of the JS component code corresponding to the ability.| srcEntrance | Path of the JS code corresponding to the ability.| +| srcPath | Path of the JS component code corresponding to the ability.| srcEntry | Path of the JS code corresponding to the ability.| | uriPermission | Application data that the ability can access.| / | This configuration is not supported in the stage model.| diff --git a/en/application-dev/application-models/page-mission-stack.md b/en/application-dev/application-models/page-mission-stack.md index 702cb9ba928d5266ce6720d10538df6109b0cbeb..cdb7ce724f2a29c711d4d056bcda5716f265ba48 100644 --- a/en/application-dev/application-models/page-mission-stack.md +++ b/en/application-dev/application-models/page-mission-stack.md @@ -5,7 +5,8 @@ A single UIAbility component can implement multiple pages and redirection between these pages. The redirection relationship inside the UIAbility component is called page stack, which is managed by the ArkUI framework. For example, Page1 -> Page2 -> Page3 of UIAbility1 and PageA -> PageB -> PageC of UIAbility2 in the figure below are two page stacks. - **Figure 1** Page stack +**Figure 1** Page stack + ![mission-record](figures/mission-record.png) - A page stack is formed as follows (Steps 2, 3, 5, and 6 are page redirection and managed by ArkUI): diff --git a/en/application-dev/application-models/pageability-launch-type.md b/en/application-dev/application-models/pageability-launch-type.md index 5241a7cabefbf3e68e6a3f413b8892ef5f6ff8d3..1e5d14c3037261e66fb2decdede6779c079651bc 100644 --- a/en/application-dev/application-models/pageability-launch-type.md +++ b/en/application-dev/application-models/pageability-launch-type.md @@ -5,10 +5,10 @@ Depending on the launch type, the action performed when the PageAbility starts d **Table 1** PageAbility launch types -| Launch Type| Description| -| -------- | -------- | -| singleton | Each time **startAbility()** is called, if an ability instance of this type already exists in the application process, the instance is reused. There is only one ability instance of this type in **Recents**.
A typical scenario is as follows: When a user opens a video playback application and watches a video, returns to the home screen, and opens the video playback application again, the video that the user watched before returning to the home screen is still played.| -| standard | Default type. Each time **startAbility()** is called, a new ability instance is created in the application process. Multiple ability instances of this type are displayed in **Recents**.
A typical scenario is as follows: When a user opens a document application and touches **New**, a new document task is created. Multiple new document missions are displayed in **Recents**.| +| Launch Type| Meaning| Description | +| -------- | -------- | -------- | +| singleton | Singleton mode| Each time **startAbility()** is called, if an ability instance of this type already exists in the application process, the instance is reused. There is only one ability instance of this type in **Recents**.
A typical scenario is as follows: When a user opens a video playback application and watches a video, returns to the home screen, and opens the video playback application again, the video that the user watched before returning to the home screen is still played.| +| standard | Multiton mode| Default type. Each time **startAbility()** is called, a new ability instance is created in the application process. Multiple ability instances of this type are displayed in **Recents**.
A typical scenario is as follows: When a user opens a document application and touches **New**, a new document task is created. Multiple new document missions are displayed in **Recents**.| You can set **launchType** in the **config.json** file to configure the launch type. The sample code is as follows: @@ -16,13 +16,13 @@ You can set **launchType** in the **config.json** file to configure the launch t ```json { "module": { - // ... + ... "abilities": [ { - // singleton mode. - // standard mode. + // singleton means the singleton mode. + // standard means the multiton mode. "launchType": "standard", - // ... + ... } ] } @@ -30,7 +30,8 @@ You can set **launchType** in the **config.json** file to configure the launch t ``` -When the PageAbility is started for the first time (either in standard or singleton mode), the [PageAbility lifecycle callbacks](pageability-lifecycle.md#table13118194914476) are triggered. When it is not started for the first time in singleton mode, the **onNewWant()** callback (as described in the table below) is triggered, but the **onCreate()** callback is not. +When the PageAbility is started in multiton mode or it is started in singleton mode for the first time, the [PageAbility lifecycle callbacks](pageability-lifecycle.md#table13118194914476) are triggered. When it is not started for the first time in singleton mode, the **onNewWant()** callback (as described in the table below) is triggered, but the **onCreate()** callback is not. + **Table 2** Callbacks specific to the singleton mode diff --git a/en/application-dev/application-models/pageability-switch.md b/en/application-dev/application-models/pageability-switch.md index 1953c02c8067a38d1633ae9eb9f768dc60a87e0f..23c663ca14a25bba25aef5c1693a519a1a0bff6c 100644 --- a/en/application-dev/application-models/pageability-switch.md +++ b/en/application-dev/application-models/pageability-switch.md @@ -27,7 +27,7 @@ The PageAbility lifecycle is basically the same as the UIAbility lifecycle. The 3. Adjust the migrated code, since the methods of loading pages are different. - In the FA model, you can configure the page to be loaded by setting page information in **config.json**. - - In the stage model, you must call **windowStage.loadContent** in the **onWindowStageCreate** callback to load a page. + - In the stage model, call **windowStage.loadContent** in the **onWindowStageCreate** callback to load a page. For example, to load the **pages/Index** page after the ability is started, use the following code in the **config.json** file in the FA model: diff --git a/en/application-dev/application-models/particleability-switch.md b/en/application-dev/application-models/particleability-switch.md index 21ecd96c9a24f1328c20da14abf5cc8f8d079b95..7686ab281f8b6dd8b17e13fa0cbebd8cd6382d09 100644 --- a/en/application-dev/application-models/particleability-switch.md +++ b/en/application-dev/application-models/particleability-switch.md @@ -1,7 +1,7 @@ # particleAbility Switching - | API in the FA Model| Corresponding d.ts File in the Stage Model| Corresponding API in the Stage Model| + | API in the FA Model| Corresponding .d.ts File in the Stage Model| Corresponding API in the Stage Model| | -------- | -------- | -------- | | [startAbility(parameter: StartAbilityParameter, callback: AsyncCallback<number>): void;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitystartability)
[startAbility(parameter: StartAbilityParameter): Promise<number>;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitystartability-1) | application\ServiceExtensionContext.d.ts | [startAbility(want: Want, callback: AsyncCallback<void>): void;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextstartability)
[startAbility(want: Want, options: StartOptions, callback: AsyncCallback<void>): void;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextstartability-2)
[startAbility(want: Want, options?: StartOptions): Promise<void>;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextstartability-1)
[startServiceExtensionAbility(want: Want, callback: AsyncCallback<void>): void;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextstartserviceextensionability)
[startServiceExtensionAbility(want: Want): Promise<void>;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextstartserviceextensionability-1) | | [terminateSelf(callback: AsyncCallback<void>): void;](../reference/apis/js-apis-ability-particleAbility.md#particleabilityterminateself)
[terminateSelf(): Promise<void>;](../reference/apis/js-apis-ability-particleAbility.md#particleabilityterminateself-1) | application\ServiceExtensionContext.d.ts | [terminateSelf(callback: AsyncCallback<void>): void;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextterminateself)
[terminateSelf(): Promise<void>;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextterminateself-1) | @@ -10,3 +10,5 @@ | [acquireDataAbilityHelper(uri: string): DataAbilityHelper;](../reference/apis/js-apis-ability-particleAbility.md#particleabilityacquiredataabilityhelper) | \@ohos.data.dataShare.d.ts
[\@ohos.data.fileAccess.d.ts | [createDataShareHelper(context: Context, uri: string, callback: AsyncCallback<DataShareHelper>): void;](../reference/apis/js-apis-data-dataShare.md#datasharecreatedatasharehelper)
[createDataShareHelper(context: Context, uri: string): Promise<DataShareHelper>;](../reference/apis/js-apis-data-dataShare.md#datasharecreatedatasharehelper-1)
[createFileAccessHelper(context: Context): FileAccessHelper;](../reference/apis/js-apis-fileAccess.md#fileaccesscreatefileaccesshelper-1)
[createFileAccessHelper(context: Context, wants: Array<Want>): FileAccessHelper;](../reference/apis/js-apis-fileAccess.md#fileaccesscreatefileaccesshelper) | | [startBackgroundRunning(id: number, request: NotificationRequest, callback: AsyncCallback<void>): void;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitystartbackgroundrunning)
[startBackgroundRunning(id: number, request: NotificationRequest): Promise<void>;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitystartbackgroundrunning-1) | \@ohos.resourceschedule.backgroundTaskManager.d.ts | [startBackgroundRunning(context: Context, bgMode: BackgroundMode, wantAgent: WantAgent, callback: AsyncCallback): void;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstartbackgroundrunningcallback)
[startBackgroundRunning(context: Context, bgMode: BackgroundMode, wantAgent: WantAgent): Promise<void>;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstartbackgroundrunningpromise) | | [cancelBackgroundRunning(callback: AsyncCallback<void>): void;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitycancelbackgroundrunning)
[cancelBackgroundRunning(): Promise<void>;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitycancelbackgroundrunning-1) | \@ohos.resourceschedule.backgroundTaskManager.d.ts | [stopBackgroundRunning(context: Context, callback: AsyncCallback): void;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstopbackgroundrunningcallback)
[stopBackgroundRunning(context: Context): Promise<void>;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstopbackgroundrunningpromise) | + + \ No newline at end of file diff --git a/en/application-dev/application-models/process-model-fa.md b/en/application-dev/application-models/process-model-fa.md index 699643031121521fbf95d26a949df906fa175a18..2294d65ee957456acdf6cccd8483b8cf0a728bb3 100644 --- a/en/application-dev/application-models/process-model-fa.md +++ b/en/application-dev/application-models/process-model-fa.md @@ -1,4 +1,4 @@ -# Process Model (FA Model) +# Process Model Overview (FA Model) The OpenHarmony process model is shown below. @@ -8,9 +8,9 @@ The OpenHarmony process model is shown below. - WebView has an independent rendering process, which is **Render process** in yellow in the figure. - **Figure 1** Process model +**Figure 1** Process model - ![process-model-fa](figures/process-model-fa.png) +![process-model-fa](figures/process-model-fa.png) OpenHarmony provides two inter-process communication (IPC) mechanisms. @@ -19,4 +19,3 @@ OpenHarmony provides two inter-process communication (IPC) mechanisms. - [Common Events](common-event-fa.md): This mechanism is used in one-to-many communication scenarios. Multiple subscribers may receive events at the same time. - [Background Services](rpc.md): This mechanism is implemented through [ServiceAbility](serviceability-overview.md). - diff --git a/en/application-dev/application-models/process-model-stage.md b/en/application-dev/application-models/process-model-stage.md index bbfa0602aecb127c5e484f0ebbdcb166f81310f7..f8e78ed82a707c61603e73fc08b7287aac6abff0 100644 --- a/en/application-dev/application-models/process-model-stage.md +++ b/en/application-dev/application-models/process-model-stage.md @@ -1,25 +1,26 @@ -# Process Model (Stage Model) +# Process Model Overview (Stage Model) The OpenHarmony process model is shown below. - All UIAbility, ServiceExtensionAbility, and DataShareExtensionAbility components of an application (with the same bundle name) run in an independent process, which is **Main process** in green in the figure. - -- The ExtensionAbility components of the same type (except ServiceExtensionAbility and DataShareExtensionAbility) of an application (with the same bundle name) run in an independent process, which is **FormExtensionAbility process**, **InputMethodExtensionAbility process**, and other **ExtensionAbility process** in blue in the figure. - +- All ExtensionAbility components of the same type (except ServiceExtensionAbility and DataShareExtensionAbility) of an application (with the same bundle name) run in an independent process, which is **FormExtensionAbility process**, **InputMethodExtensionAbility process**, and other **ExtensionAbility process** in blue in the figure. - WebView has an independent rendering process, which is **Render process** in yellow in the figure. - **Figure 1** Process model +**Figure 1** Process model + ![process-model](figures/process-model.png) > NOTE > -> You can create ServiceExtensionAbility and DataShareExtensionAbility only for system applications. +> - You can create ServiceExtensionAbility and DataShareExtensionAbility only for system applications. +> - To view information about all running processes, run the **hdc shell** command to enter the shell CLI of the device, and run the **ps -ef** command. A system application can apply for multi-process permissions (as shown in the following figure) and configure a custom process for an HAP. UIAbility, DataShareExtensionAbility, and ServiceExtensionAbility in the HAP run in the custom process. Different HAPs run in different processes by configuring different process names. -**Figure 2** Multi-process +**Figure 2** Multi-process + ![multi-process](figures/multi-process.png) diff --git a/en/application-dev/application-models/redirection-rules.md b/en/application-dev/application-models/redirection-rules.md index d7456653640942bca333a28f7f6d5262ec4d63f3..19c74c605cd7ca1451cef6809f6ec5238cec36df 100644 --- a/en/application-dev/application-models/redirection-rules.md +++ b/en/application-dev/application-models/redirection-rules.md @@ -21,11 +21,11 @@ To enable an ability to be called by any application, configure the **config.jso ```ts { "module": { - // ... + ... "abilities": [ { "visible": "true", - // ... + ... } ] } @@ -33,4 +33,4 @@ To enable an ability to be called by any application, configure the **config.jso ``` -If the ability contains **skills**, you are advised to set **visible** to **true** so that the ability can be [implicitly started](explicit-implicit-want-mappings.md#matching-rules-of-implicit-want) by other applications. If this attribute is set to **false**, the system returns **PERMISSION_DENIED** when other applications attempt to start the ability. In this case, a system application can request the [START_INVISIBLE_ABILITY](../security/permission-list.md) permission to start the ability. Example abilities with **visible** set to **false** are home screen, voice assistant, or search assistant. +If the ability contains **skills**, you are advised to set **visible** to **true** so that the ability can be [implicitly started](explicit-implicit-want-mappings.md) by other applications. If this attribute is set to **false**, the system returns **PERMISSION_DENIED** when other applications attempt to start the ability. In this case, a system application can request the [START_INVISIBLE_ABILITY](../security/permission-list.md) permission to start the ability. Example abilities with **visible** set to **false** are home screen, voice assistant, or search assistant. diff --git a/en/application-dev/application-models/request-switch.md b/en/application-dev/application-models/request-switch.md index 5c9e2f49d48aaba203a6207de37992823ab5ae97..3ab01246598b8321c51f6e8ec06c201010797c28 100644 --- a/en/application-dev/application-models/request-switch.md +++ b/en/application-dev/application-models/request-switch.md @@ -1,7 +1,7 @@ # request Switching - | API in the FA Model| Corresponding d.ts File in the Stage Model| Corresponding API in the Stage Model| + | API in the FA Model| Corresponding .d.ts File in the Stage Model| Corresponding API in the Stage Model| | -------- | -------- | -------- | | [download(config: DownloadConfig, callback: AsyncCallback<DownloadTask>): void;](../reference/apis//js-apis-request.md#requestdownload-1)
[download(config: DownloadConfig): Promise<DownloadTask>;](../reference/apis/js-apis-request.md#requestdownload) | \@ohos.request.d.ts | [downloadFile(context: BaseContext, config: DownloadConfig, callback: AsyncCallback<DownloadTask>): void;](../reference/apis/js-apis-request.md#requestdownloadfile9-1)
[downloadFile(context: BaseContext, config: DownloadConfig): Promise<DownloadTask>;](../reference/apis/js-apis-request.md#requestdownloadfile9) | | [upload(config: UploadConfig, callback: AsyncCallback<UploadTask>): void;](../reference/apis/js-apis-request.md#requestupload-1)
[upload(config: UploadConfig): Promise<UploadTask>;](../reference/apis/js-apis-request.md#requestupload) | \@ohos.request.d.ts | [uploadFile(context: BaseContext, config: UploadConfig, callback: AsyncCallback<UploadTask>): void;](../reference/apis/js-apis-request.md#requestuploadfile9-1)
[uploadFile(context: BaseContext, config: UploadConfig): Promise<UploadTask>;](../reference/apis/js-apis-request.md#requestuploadfile9) | diff --git a/en/application-dev/application-models/resourcemanager-switch.md b/en/application-dev/application-models/resourcemanager-switch.md index 34eedb16597e30c76ccaed2c01a3b4c7206c0dfd..9f791d98ed2c0c0998ebd4ffcb5c141613196ec9 100644 --- a/en/application-dev/application-models/resourcemanager-switch.md +++ b/en/application-dev/application-models/resourcemanager-switch.md @@ -1,6 +1,6 @@ # resourceManager Switching - | API in the FA Model| Corresponding d.ts File in the Stage Model| Corresponding Field in the Stage Model| + | API in the FA Model| Corresponding .d.ts File in the Stage Model| Corresponding Field in the Stage Model| | -------- | -------- | -------- | | [getResourceManager(callback: AsyncCallback<ResourceManager>): void;](../reference/apis/js-apis-resource-manager.md#resourcemanagergetresourcemanager)
[getResourceManager(bundleName: string, callback: AsyncCallback<ResourceManager>): void;](../reference/apis/js-apis-resource-manager.md#resourcemanagergetresourcemanager-1)
[getResourceManager(): Promise<ResourceManager>;](../reference/apis/js-apis-resource-manager.md#resourcemanagergetresourcemanager-2)
[getResourceManager(bundleName: string): Promise<ResourceManager>;](../reference/apis/js-apis-resource-manager.md#resourcemanagergetresourcemanager-3) | application\Context.d.ts | [resourceManager: resmgr.ResourceManager;](../reference/apis/js-apis-inner-application-context.md#attributes)| diff --git a/en/application-dev/application-models/service-widget-overview.md b/en/application-dev/application-models/service-widget-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..528d9d4c134107c30de75f7f9e84ab42be514224 --- /dev/null +++ b/en/application-dev/application-models/service-widget-overview.md @@ -0,0 +1,58 @@ +# Service Widget Overview + + +A service widget (also called widget) is a set of UI components that display important information or operations specific to an application. It provides users with direct access to a desired application service, without the need to open the application first. A widget usually appears as a part of the UI of another application (which currently can only be a system application, such as the home screen) and provides basic interactive features such as opening a UI page or sending a message. + + +## Service Widget Architecture + +**Figure 1** Service widget architecture + +![WidgetArchitecture](figures/WidgetArchitecture.png) + +Before you get started, it would be helpful if you have a basic understanding of the following concepts: + +- Widget host: an application that displays the widget content and controls the widget location. An example is the home screen in the preceding figure. + + - Application icon: an application entry icon, clicking which starts the application process. The icon content does not support interactions. + - Widget: an interactive UI in various sizes. It may provide buttons to implement different functions, such as the button to [update the widget content](arkts-ui-widget-event-formextensionability.md) or [switch to an application](arkts-ui-widget-event-router.md). + +- Card provider: an application that provides service widget content to be displayed. It controls the display content, display logic, and component click events triggered on a service widget. + + - FormExtensionAbility: widget service logic module, which provides lifecycle callbacks invoked when a widget is created, destroyed, or updated. + - Widget page: widget UI module, which contains display and interaction information such as components, layouts, and events. + +Below is the typical procedure of using the widget: + +**Figure 2** Typical procedure of using the widget + +![WidgetUse](figures/WidgetUse.png) + +1. Touch and hold an application icon on the home screen to display the shortcut menu. + +2. Touch **Service widget** to access the preview screen. + +3. Touch the **Add to home** button. The widget is then added to the home screen. + + +## Widget UI Development Mode + +In the stage model, the UI of a widget can be developed in [ArkTS](arkts-ui-widget-working-principles.md) or [JS](js-ui-widget-development.md). + +- A widget developed in the ArkTS-based declarative development paradigm is called ArkTS widget. + +- A widget developed in the JS-compatible web-like development paradigm is called JS widget. + +ArkTS widgets and JS widgets have different implementation principles and features. The following table lists the differences in capabilities. + +| Category| JS widget| ArkTS widget| +| -------- | -------- | -------- | +| Development paradigm| Web-like paradigm| Declarative paradigm| +| Component capability| Supported| Supported| +| Layout capability| Supported| Supported| +| Event capability| Supported| Supported| +| Custom animation| Not supported| Supported| +| Custom drawing| Not supported| Supported| +| Logic code execution (excluding the import capability)| Not supported| Supported| + +As can be seen above, ArkTS widgets provide more capabilities and use cases than JS widgets. Therefore, ArkTS widgets are always recommended, except for the case where the widget consists of only static pages. diff --git a/en/application-dev/application-models/serviceability-switch.md b/en/application-dev/application-models/serviceability-switch.md index 9752a4a11be4982ab65b4fc17262a39b6190b00b..569fc39110e3b0c3c84bfc38e8014b33fb99b461 100644 --- a/en/application-dev/application-models/serviceability-switch.md +++ b/en/application-dev/application-models/serviceability-switch.md @@ -4,9 +4,9 @@ The ServiceAbility component in the FA model corresponds to the ServiceExtensionAbility component in the stage model. The ServiceExtensionAbility class provides system APIs. Only system applications can create ServiceExtensionAbility instances. Therefore, ServiceAbility switching adopts different policies for system applications and third-party applications. -## Switching a ServiceAbility of a System Application +## Switching a ServiceAbility for a System Application -The procedure for switching a ServiceAbility of a system application is similar to the procedure of PageAbility switching. +The procedure for switching a ServiceAbility for a system application is similar to the procedure of PageAbility switching. 1. [Create a ServiceExtensionAbility](serviceextensionability.md) in the stage model. @@ -24,7 +24,7 @@ The table below describes the lifecycle comparison of the ServiceAbility and Ser | onStop(): void | onDestroy(): void | The two methods have the same meaning, invoking time, and parameters.| -## Switching a ServiceAbility of a Third-Party Application +## Switching a ServiceAbility for a Third-Party Application In the stage model, third-party applications cannot provide services for other third-party applications. You can select a switching solution based on your service requirements. diff --git a/en/application-dev/application-models/serviceextensionability.md b/en/application-dev/application-models/serviceextensionability.md index 9ff7a0ae5d6df7574da19565c81411236dba3dda..0c3725a3761806124682550d26ba836448a613c1 100644 --- a/en/application-dev/application-models/serviceextensionability.md +++ b/en/application-dev/application-models/serviceextensionability.md @@ -1,125 +1,152 @@ # ServiceExtensionAbility +## Overview -[ServiceExtensionAbility](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md) is an ExtensionAbility component of the service type that provides extension capabilities related to background services. +[ServiceExtensionAbility](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md) is an ExtensionAbility component of the service type that provides capabilities related to background services. It holds an internal [ServiceExtensionContext](../reference/apis/js-apis-inner-application-serviceExtensionContext.md), through which a variety of APIs are provided for external systems. +In this document, the started ServiceExtensionAbility component is called the server, and the component that starts ServiceExtensionAbility is called the client. -ServiceExtensionAbility can be started or connected by other application components to process transactions in the background based on the request of the caller. System applications can call the [startServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartserviceextensionability) method to start background services or call the [connectServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextconnectserviceextensionability) method to connect to background services. Third-party applications can call only **connectServiceExtensionAbility()** to connect to background services. The differences between starting and connecting to background services are as follows: +A ServiceExtensionAbility can be started or connected by other components to process transactions in the background based on the request of the caller. System applications can call the [startServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartserviceextensionability) method to start background services or call the [connectServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextconnectserviceextensionability) method to connect to background services. Third-party applications can call only [connectServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextconnectserviceextensionability) to connect to background services. The differences between starting and connecting to background services are as follows: +- **Starting**: In the case that AbilityA starts ServiceB, they are weakly associated. After AbilityA exits, ServiceB remains running. -- In the case that AbilityA starts ServiceB, they are weakly associated. After AbilityA exits, ServiceB can still exist. +- **Connecting**: In the case that AbilityA connects to ServiceB, they are strongly associated. After AbilityA exits, ServiceB also exits. -- In the case that AbilityA connects to ServiceB, they are strongly associated. After AbilityA exits, ServiceB also exits. +Note the following: +- If a ServiceExtensionAbility is started only by means of connecting, its lifecycle is controlled by the client. A new connection is set up each time the client calls the [connectServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextconnectserviceextensionability) method. When the client exits or calls the [disconnectServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextdisconnectserviceextensionability) method, the connection is interrupted. After all connections are interrupted, the ServiceExtensionAbility automatically exits. -Each type of ExtensionAbility has its own context. ServiceExtensionAbility has [ServiceExtensionContext](../reference/apis/js-apis-inner-application-serviceExtensionContext.md). In this document, the started ServiceExtensionAbility component is called the server, and the component that starts ServiceExtensionAbility is called the client. - - -This topic describes how to use ServiceExtensionAbility in the following scenarios: - - -- [Implementing a Background Service (for System Applications Only)](#implementing-a-background-service-for-system-applications-only) - -- [Starting a Background Service (for System Applications Only)](#starting-a-background-service-for-system-applications-only) - -- [Connecting to a Background Service](#connecting-to-a-background-service) - +- Once a ServiceExtensionAbility is started by means of starting, it will not exit automatically. System applications can call the [stopServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstopserviceextensionability) method to stop it. > **NOTE** -> - OpenHarmony does not support third-party applications in implementing ServiceExtensionAbility. If you want to implement transaction processing in the background, use background tasks. For details, see [Background Task](../task-management/background-task-overview.md). -> +> +> - Currently, third-party applications cannot implement ServiceExtensionAbility. Alternatively, they can use background tasks to implement transaction processing in the background. For details, see [Background Task](../task-management/background-task-overview.md). > - UIAbility of a third-party application can connect to ServiceExtensionAbility provided by the system through the context. -> > - Third-party applications can connect to ServiceExtensionAbility provided by the system only when they gain focus in the foreground. +## Lifecycle -## Implementing a Background Service (for System Applications Only) +[ServiceExtensionAbility](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md) provides the lifecycle callbacks **onCreate()**, **onRequest()**, **onConnect()**, **onDisconnect()**, and **onDestory()**. Override them as required. The following figure shows the lifecycle of ServiceExtensionAbility. -[ServiceExtensionAbility](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md) provides the callbacks **onCreate()**, **onRequest()**, **onConnect()**, **onDisconnect()**, and **onDestory()**. Override them as required. The following figure shows the lifecycle of ServiceExtensionAbility. +**Figure 1** ServiceExtensionAbility lifecycle - **Figure 1** ServiceExtensionAbility lifecycle ![ServiceExtensionAbility-lifecycle](figures/ServiceExtensionAbility-lifecycle.png) - **onCreate** - - This callback is triggered when a service is created for the first time. You can perform initialization operations, for example, registering a common event listener. + + This callback is triggered when a ServiceExtensionAbility is created for the first time. You can perform initialization operations, for example, registering a common event listener. > **NOTE** > - > If a service has been created, starting it again does not trigger the **onCreate()** callback. + > If a ServiceExtensionAbility has been created, starting it again does not trigger the **onCreate()** callback. - **onRequest** - - This callback is triggered when another component calls the **startServiceExtensionAbility()** method to start the service. After being started, the service runs in the background. + + This callback is triggered when another component calls the [startServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartserviceextensionability) method to start a ServiceExtensionAbility. After being started, the ServiceExtensionAbility runs in the background. This callback is triggered each time the [startServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartserviceextensionability) method is called. - **onConnect** - - This callback is triggered when another component calls the **connectServiceExtensionAbility()** method to connect to the service. In this method, a remote proxy object (IRemoteObject) is returned, through which the client communicates with the server by means of RPC. + + This callback is triggered when another component calls the [connectServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextconnectserviceextensionability) method to connect to a ServiceExtensionAbility. In this method, a remote proxy object, namely, IRemoteObject, is returned, through which the client communicates with the server by means of RPC. At the same time, the system stores the IRemoteObject. If another component calls the [connectServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextconnectserviceextensionability) method to connect to this ServiceExtensionAbility, the system directly returns the saved IRemoteObject and does not trigger the callback. - **onDisconnect** - - This callback is triggered when a component calls the **disconnectServiceExtensionAbility()** method to disconnect from the service. + + This callback is triggered when the last connection is interrupted. A connection is interrupted when the client exits or the [disconnectServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextdisconnectserviceextensionability) method is called. - **onDestroy** - This callback is triggered when the service is no longer used and the instance is ready for destruction. You can clear resources in this callback, for example, deregister the listener. + This callback is triggered when ServiceExtensionAbility is no longer used and the instance is ready for destruction. You can clear resources in this callback, for example, deregister the listener. +## Implementing a Background Service (for System Applications Only) -## How to Develop +### Preparations -To implement a background service, manually create a ServiceExtensionAbility component in DevEco Studio. The procedure is as follows: +Only system applications can implement ServiceExtensionAbility. You must make the following preparations before development: -1. In the **ets** directory of the **Module** project, right-click and choose **New > Directory** to create a directory named **serviceextability**. +- **Switching to the full SDK**: All APIs related to ServiceExtensionAbility are marked as system APIs and hidden by default. Therefore, you must manually obtain the full SDK from the mirror and switch to it in DevEco Studio. For details, see [Guide to Switching to Full SDK](../faqs/full-sdk-switch-guide.md). -2. In the **serviceextability** directory, right-click and choose **New > TypeScript File** to create a file named **ServiceExtAbility.ts**. +- **Requesting the AllowAppUsePrivilegeExtension privilege**: Only applications with the **AllowAppUsePrivilegeExtension** privilege can implement ServiceExtensionAbility. For details about how to request the privilege, see [Application Privilege Configuration Guide](../../device-dev/subsystems/subsys-app-privilege-config-guide.md). -3. Open the **ServiceExtAbility.ts** file, import the [RPC module](../reference/apis/js-apis-rpc.md), and reload the **onRemoteMessageRequest()** method to receive messages from the client and return the processing result to the client. **REQUEST_VALUE** is used to verify the service request code sent by the client. - - ```ts - import rpc from '@ohos.rpc'; - - const REQUEST_CODE = 99; - - class StubTest extends rpc.RemoteObject { - constructor(des) { - super(des); - } - - // Receive a message from the client and return the processing result to the client. - onRemoteMessageRequest(code, data, reply, option) { - if (code === REQUEST_CODE) { - // Receive data from the client. - // If the client calls data.writeInt() multiple times to write multiple pieces of data, the server can call data.readInt() multiple times to receive all the data. - let optFir = data.readInt(); - let optSec = data.readInt(); - // The server returns the data processing result to the client. - // In the example, the server receives two pieces of data and returns the sum of the two pieces of data to the client. - reply.writeInt(optFir + optSec); - } - return true; - } - - // Send messages to the client in synchronous or asynchronous mode. - sendRequest(code, data, reply, options) { - return null; - } - } - ``` +### Defining IDL APIs + +As a background service, ServiceExtensionAbility needs to provide APIs that can be called by external systems. You can define the APIs in IDL files and use the [IDL tool](../IDL/idl-guidelines.md) to generate proxy and stub files. The following demonstrates how to define a file named **IIdlServiceExt.idl**: + +```cpp +interface OHOS.IIdlServiceExt { + int ProcessData([in] int data); + void InsertDataToMap([in] String key, [in] int val); +} +``` + +Create the **IdlServiceExt** directory in the **ets** directory corresponding to the module of the DevEco Studio project, and copy the files generated by the [IDL tool](../IDL/idl-guidelines.md) to this directory. Then create a file named **idl_service_ext_impl.ts** to implement the IDL APIs. + +``` +├── ets +│ ├── IdlServiceExt +│ │ ├── i_idl_service_ext.ts # File generated by the IDL tool. +│ │ ├── idl_service_ext_proxy.ts # File generated by the IDL tool. +│ │ ├── idl_service_ext_stub.ts # File generated by the IDL tool. +│ │ ├── idl_service_ext_impl.ts # Customize this file to implement IDL APIs. +│ └ +└ +``` + +An example of **idl_service_ext_impl.ts** is as follows: + +```ts +import {processDataCallback} from './i_idl_service_ext'; +import {insertDataToMapCallback} from './i_idl_service_ext'; +import IdlServiceExtStub from './idl_service_ext_stub'; + +const ERR_OK = 0; +const TAG: string = "[IdlServiceExtImpl]"; + +// You need to implement APIs in this type. +export default class ServiceExtImpl extends IdlServiceExtStub { + processData(data: number, callback: processDataCallback): void { + // Implement service logic. + console.info(TAG, `processData: ${data}`); + callback(ERR_OK, data + 1); + } + + insertDataToMap(key: string, val: number, callback: insertDataToMapCallback): void { + // Implement service logic. + console.info(TAG, `insertDataToMap, key: ${key} val: ${val}`); + callback(ERR_OK); + } +} +``` + +### Creating a ServiceExtensionAbility + +To manually create a ServiceExtensionAbility in the DevEco Studio project, perform the following steps: + +1. In the **ets** directory of the **Module** project, right-click and choose **New > Directory** to create a directory named **ServiceExtAbility**. + +2. In the **ServiceExtAbility** directory, right-click and choose **New > TypeScript File** to create a file named **ServiceExtAbility.ts**. + + ``` + ├── ets + │ ├── IdlServiceExt + │ │ ├── i_idl_service_ext.ts # File generated by the IDL tool. + │ │ ├── idl_service_ext_proxy.ts # File generated by the IDL tool. + │ │ ├── idl_service_ext_stub.ts # File generated by the IDL tool. + │ │ ├── idl_service_ext_impl.ts # Customize this file to implement IDL APIs. + │ ├── ServiceExtAbility + │ │ ├── ServiceExtAbility.ts + └ + ``` + +3. In the **ServiceExtAbility.ts** file, add the dependency package for importing ServiceExtensionAbility. Customize a class that inherits from ServiceExtensionAbility and implement the lifecycle callbacks. Return the previously defined **ServiceExtImpl** object in the **onConnect** lifecycle callback. -4. In the **ServiceExtAbility.ts** file, add the dependency package for importing ServiceExtensionAbility. Customize a class that inherits from ServiceExtensionAbility and add the required lifecycle callbacks. - ```ts import ServiceExtensionAbility from '@ohos.app.ability.ServiceExtensionAbility'; - import rpc from '@ohos.rpc'; + import ServiceExtImpl from '../IdlServiceExt/idl_service_ext_impl'; - const TAG: string = "[Example].[Entry].[ServiceExtAbility]"; - const REQUEST_CODE = 99; - - class StubTest extends rpc.RemoteObject { - // ... - } + const TAG: string = "[ServiceExtAbility]"; export default class ServiceExtAbility extends ServiceExtensionAbility { + serviceExtImpl = new ServiceExtImpl("ExtImpl"); + onCreate(want) { console.info(TAG, `onCreate, want: ${want.abilityName}`); } @@ -130,7 +157,8 @@ To implement a background service, manually create a ServiceExtensionAbility com onConnect(want) { console.info(TAG, `onConnect, want: ${want.abilityName}`); - return new StubTest("test"); + // Return the ServiceExtImpl object, through which the client can communicate with the ServiceExtensionAbility. + return this.serviceExtImpl; } onDisconnect(want) { @@ -143,137 +171,116 @@ To implement a background service, manually create a ServiceExtensionAbility com } ``` -5. Register ServiceExtensionAbility in the [module.json5 file](../quick-start/module-configuration-file.md) corresponding to the **Module** project. Set **type** to **"service"** and **srcEntrance** to the code path of the ExtensionAbility component. - +4. Register ServiceExtensionAbility in the [module.json5 file](../quick-start/module-configuration-file.md) corresponding to the **Module** project. Set **type** to **"service"** and **srcEntry** to the code path of the ServiceExtensionAbility component. + ```json { "module": { - // ... + ... "extensionAbilities": [ { "name": "ServiceExtAbility", "icon": "$media:icon", "description": "service", "type": "service", - "visible": true, - "srcEntrance": "./ets/serviceextability/ServiceExtAbility.ts" + "exported": true, + "srcEntry": "./ets/ServiceExtAbility/ServiceExtAbility.ts" } ] } } ``` - ## Starting a Background Service (for System Applications Only) -A system application uses the [startServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartserviceextensionability) method to start a background service. The [onRequest()](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md#serviceextensionabilityonrequest) callback is invoked, and the **Want** object passed by the caller is received through the callback. After the background service is started, its lifecycle is independent of that of the client. In other words, even if the client is destroyed, the background service can still run. Therefore, the background service must be stopped by calling [terminateSelf()](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextterminateself) when its work is complete. Alternatively, another component can call [stopServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstopserviceextensionability) to stop the background service. +A system application uses the [startServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartserviceextensionability) method to start a background service. The [onRequest()](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md#serviceextensionabilityonrequest) callback is invoked, through which the background service receives the **Want** object passed by the caller. After the background service is started, its lifecycle is independent of that of the client. In other words, even if the client is destroyed, the background service remains alive. Therefore, the background service must be stopped by calling [terminateSelf()](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextterminateself) when its work is complete. Alternatively, another component can call [stopServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstopserviceextensionability) to stop the background service. > **NOTE** > > [startServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartserviceextensionability), [stopServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstopserviceextensionability), and [terminateSelf()](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextterminateself) of ServiceExtensionContext are system APIs and cannot be called by third-party applications. 1. Start a new ServiceExtensionAbility in a system application. For details about how to obtain the context, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability). - + ```ts + let context = ...; // UIAbilityContext let want = { - "deviceId": "", - "bundleName": "com.example.myapplication", - "abilityName": "ServiceExtAbility" + "deviceId": "", + "bundleName": "com.example.myapplication", + "abilityName": "ServiceExtAbility" }; - this.context.startServiceExtensionAbility(want).then(() => { - console.info('startServiceExtensionAbility success'); - }).catch((error) => { - console.info('startServiceExtensionAbility failed'); + context.startServiceExtensionAbility(want).then(() => { + console.info('Succeeded in starting ServiceExtensionAbility.'); + }).catch((err) => { + console.error(`Failed to start ServiceExtensionAbility. Code is ${err.code}, message is ${err.message}`); }) ``` 2. Stop ServiceExtensionAbility in the system application. - + ```ts + let context = ...; // UIAbilityContext let want = { - "deviceId": "", - "bundleName": "com.example.myapplication", - "abilityName": "ServiceExtAbility" + "deviceId": "", + "bundleName": "com.example.myapplication", + "abilityName": "ServiceExtAbility" }; - this.context.stopServiceExtensionAbility(want).then(() => { - console.info('stopServiceExtensionAbility success'); - }).catch((error) => { - console.info('stopServiceExtensionAbility failed'); + context.stopServiceExtensionAbility(want).then(() => { + console.info('Succeeded in stoping ServiceExtensionAbility.'); + }).catch((err) => { + console.error(`Failed to stop ServiceExtensionAbility. Code is ${err.code}, message is ${err.message}`); }) ``` -3. ServiceExtensionAbility stops itself. - +3. Have ServiceExtensionAbility stop itself. + ```ts - // this is the current ServiceExtensionAbility component. - this.context.terminateSelf().then(() => { - console.info('terminateSelf success'); - }).catch((error) => { - console.info('terminateSelf failed'); + let context = ...; // ServiceExtensionContext + context.terminateSelf().then(() => { + console.info('Succeeded in terminating self.'); + }).catch((err) => { + console.error(`Failed to terminate self. Code is ${err.code}, message is ${err.message}`); }) ``` - > **NOTE** > -> Background services can run in the background for a long time. To minimize resource usage, destroy it in time when a background service finishes the task of the requester. A background service can be stopped in either of the following ways: +> Background services can run in the background for a long time. To minimize resource usage, destroy a background service in time when it finishes the task of the requester. A background service can be destroyed in either of the following ways: > > - The background service calls the [terminateSelf()](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextterminateself) method to automatically stop itself. -> > - Another component calls the [stopServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextstopserviceextensionability) method to stop the background service. -> -> After either method is called, the system destroys the background service. - +> ## Connecting to a Background Service -Either a system application or a third-party application can connect to a service (service specified in the **Want** object) through [connectServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextconnectserviceextensionability). The [onConnect()](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md#serviceextensionabilityonconnect) callback is invoked, and the **Want** object passed by the caller is received through the callback. In this way, a persistent connection is established. +Either a system application or a third-party application can connect to a background service (specified in the **Want** object) through [connectServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextconnectserviceextensionability). The [onConnect()](../reference/apis/js-apis-app-ability-serviceExtensionAbility.md#serviceextensionabilityonconnect) callback is invoked, through which the background service receives the **Want** object passed by the caller. In this way, a persistent connection is established. The ServiceExtensionAbility component returns an IRemoteObject in the **onConnect()** callback. Through this IRemoteObject, you can define communication interfaces for RPC interaction between the client and server. Multiple clients can connect to the same background service at the same time. After a client finishes the interaction, it must call [disconnectServiceExtensionAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#abilitycontextdisconnectserviceextensionability) to disconnect from the service. If all clients connected to a background service are disconnected, the system destroys the service. - Call **connectServiceExtensionAbility()** to establish a connection to a background service. For details about how to obtain the context, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability). ```ts - import rpc from '@ohos.rpc'; - - const REQUEST_CODE = 99; let want = { - "deviceId": "", - "bundleName": "com.example.myapplication", - "abilityName": "ServiceExtAbility" + "deviceId": "", + "bundleName": "com.example.myapplication", + "abilityName": "ServiceExtAbility" }; let options = { - onConnect(elementName, remote) { - console.info('onConnect callback'); - if (remote === null) { - console.info(`onConnect remote is null`); - return; - } - let option = new rpc.MessageOption(); - let data = new rpc.MessageParcel(); - let reply = new rpc.MessageParcel(); - data.writeInt(100); - data.writeInt(200); - - // @param code Indicates the service request code sent by the client. - // @param data Indicates the {@link MessageParcel} object sent by the client. - // @param reply Indicates the response message object sent by the remote service. - // @param options Specifies whether the operation is synchronous or asynchronous. - // - // @return Returns {@code true} if the operation is successful; returns {@code false} otherwise. - remote.sendRequest(REQUEST_CODE, data, reply, option).then((ret) => { - let msg = reply.readInt(); - console.info(`sendRequest ret:${ret} msg:${msg}`); - }).catch((error) => { - console.info('sendRequest failed'); - }); - }, - onDisconnect(elementName) { - console.info('onDisconnect callback') - }, - onFailed(code) { - console.info('onFailed callback') + onConnect(elementName, remote) { + /* The input parameter remote is the object returned by ServiceExtensionAbility in the onConnect lifecycle callback. + * This object is used for communication with ServiceExtensionAbility. For details, see the section below. + */ + console.info('onConnect callback'); + if (remote === null) { + console.info(`onConnect remote is null`); + return; } + }, + onDisconnect(elementName) { + console.info('onDisconnect callback') + }, + onFailed(code) { + console.info('onFailed callback') + } } // The ID returned after the connection is set up must be saved. The ID will be passed for service disconnection. let connectionId = this.context.connectServiceExtensionAbility(want, options); @@ -282,11 +289,172 @@ The ServiceExtensionAbility component returns an IRemoteObject in the **onConnec - Use **disconnectServiceExtensionAbility()** to disconnect from the background service. ```ts - let connectionId = 1 // ID returned when the service is connected through connectServiceExtensionAbility. + // connectionId is returned when connectServiceExtensionAbility is called and needs to be manually maintained. this.context.disconnectServiceExtensionAbility(connectionId).then((data) => { - console.info('disconnectServiceExtensionAbility success'); + console.info('disconnectServiceExtensionAbility success'); }).catch((error) => { - console.error('disconnectServiceExtensionAbility failed'); + console.error('disconnectServiceExtensionAbility failed'); }) ``` +## Communication Between the Client and Server + +After obtaining the [rpc.RemoteObject](../reference/apis/js-apis-rpc.md#iremoteobject) from the **onConnect()** callback, the client can communicate with ServiceExtensionAbility in either of the following ways: + +- Using the IDL API provided by the server for communication (recommended) + + ```ts + // The client needs to import idl_service_ext_proxy.ts provided by the server for external systems to the local project. + import IdlServiceExtProxy from '../IdlServiceExt/idl_service_ext_proxy'; + + let options = { + onConnect(elementName, remote) { + console.info('onConnect callback'); + if (remote === null) { + console.info(`onConnect remote is null`); + return; + } + let serviceExtProxy = new IdlServiceExtProxy(remote); + // Communication is carried out by API call, without exposing RPC details. + serviceExtProxy.processData(1, (errorCode, retVal) => { + console.info(`processData, errorCode: ${errorCode}, retVal: ${retVal}`); + }); + serviceExtProxy.insertDataToMap('theKey', 1, (errorCode) => { + console.info(`insertDataToMap, errorCode: ${errorCode}`); + }) + }, + onDisconnect(elementName) { + console.info('onDisconnect callback') + }, + onFailed(code) { + console.info('onFailed callback') + } + } + ``` + +- Calling [sendMessageRequest](../reference/apis/js-apis-rpc.md#sendmessagerequest9) to send messages to the server (not recommended) + + ```ts + import rpc from '@ohos.rpc'; + + const REQUEST_CODE = 1; + let options = { + onConnect(elementName, remote) { + console.info('onConnect callback'); + if (remote === null) { + console.info(`onConnect remote is null`); + return; + } + // Directly call the RPC interface to send messages to the server. The client needs to serialize the input parameters and deserialize the return values. The process is complex. + let option = new rpc.MessageOption(); + let data = new rpc.MessageSequence(); + let reply = new rpc.MessageSequence(); + data.writeInt(100); + + // @param code Indicates the service request code sent by the client. + // @param data Indicates the {@link MessageSequence} object sent by the client. + // @param reply Indicates the response message object sent by the remote service. + // @param options Specifies whether the operation is synchronous or asynchronous. + // + // @return Returns {@code true} if the operation is successful; returns {@code false} otherwise. + remote.sendMessageRequest(REQUEST_CODE, data, reply, option).then((ret) => { + let msg = reply.readInt(); + console.info(`sendMessageRequest ret:${ret} msg:${msg}`); + }).catch((error) => { + console.info('sendMessageRequest failed'); + }); + }, + onDisconnect(elementName) { + console.info('onDisconnect callback') + }, + onFailed(code) { + console.info('onFailed callback') + } + } + ``` + +## Client Identity Verification by the Server + +When ServiceExtensionAbility is used to provide sensitive services, the client identity must be verified. You can implement the verification on the IDL stub. For details about the IDL API implementation, see [Defining IDL APIs](#defining-idl-apis). Two verification modes are recommended: + +- **Verifying the client identity based on callerUid** + + Call the [getCallingUid()](../reference/apis/js-apis-rpc.md#getcallinguid) method to obtain the UID of the client, and then call the [getBundleNameByUid()](../reference/apis/js-apis-bundleManager.md#bundlemanagergetbundlenamebyuid) method to obtain the corresponding bundle name. In this way, the client identify is verified. Note that [getBundleNameByUid()](../reference/apis/js-apis-bundleManager.md#bundlemanagergetbundlenamebyuid) is asynchronous, and therefore the server cannot return the verification result to the client. This verification mode applies when the client sends an asynchronous task execution request to the server. The sample code is as follows: + + ```ts + import rpc from '@ohos.rpc'; + import bundleManager from '@ohos.bundle.bundleManager'; + import { processDataCallback } from './i_idl_service_ext'; + import { insertDataToMapCallback } from './i_idl_service_ext'; + import IdlServiceExtStub from './idl_service_ext_stub'; + + const ERR_OK = 0; + const ERR_DENY = -1; + const TAG: string = "[IdlServiceExtImpl]"; + + export default class ServiceExtImpl extends IdlServiceExtStub { + processData(data: number, callback: processDataCallback): void { + console.info(TAG, `processData: ${data}`); + + let callerUid = rpc.IPCSkeleton.getCallingUid(); + bundleManager.getBundleNameByUid(callerUid).then((callerBundleName) => { + console.info(TAG, 'getBundleNameByUid: ' + callerBundleName); + // Identify the bundle name of the client. + if (callerBundleName != 'com.example.connectextapp') { // The verification fails. + console.info(TAG, 'The caller bundle is not in trustlist, reject'); + return; + } + // The verification is successful, and service logic is executed normally. + }).catch(err => { + console.info(TAG, 'getBundleNameByUid failed: ' + err.message); + }); + } + + insertDataToMap(key: string, val: number, callback: insertDataToMapCallback): void { + // Implement service logic. + console.info(TAG, `insertDataToMap, key: ${key} val: ${val}`); + callback(ERR_OK); + } + } + ``` + +- **Verifying the client identity based on callerTokenId** + + Call the [getCallingTokenId()](../reference/apis/js-apis-rpc.md#getcallingtokenid) method to obtain the token ID of the client, and then call the [verifyAccessTokenSync()](../reference/apis/js-apis-abilityAccessCtrl.md#verifyaccesstokensync) method to check whether the client has the required permission. Currently, OpenHarmony does not support permission customization. Therefore, only [system-defined permissions](../security/permission-list.md) can be verified. The sample code is as follows: + + ```ts + import rpc from '@ohos.rpc'; + import abilityAccessCtrl from '@ohos.abilityAccessCtrl'; + import {processDataCallback} from './i_idl_service_ext'; + import {insertDataToMapCallback} from './i_idl_service_ext'; + import IdlServiceExtStub from './idl_service_ext_stub'; + + const ERR_OK = 0; + const ERR_DENY = -1; + const TAG: string = "[IdlServiceExtImpl]"; + + export default class ServiceExtImpl extends IdlServiceExtStub { + processData(data: number, callback: processDataCallback): void { + console.info(TAG, `processData: ${data}`); + + let callerTokenId = rpc.IPCSkeleton.getCallingTokenId(); + let accessManger = abilityAccessCtrl.createAtManager(); + // The permission to be verified varies depending on the service requirements. ohos.permission.SET_WALLPAPER is only an example. + let grantStatus = + accessManger.verifyAccessTokenSync(callerTokenId, "ohos.permission.SET_WALLPAPER"); + if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) { + console.info(TAG, `PERMISSION_DENIED`); + callback(ERR_DENY, data); // The verification fails and an error is returned. + return; + } + callback(ERR_OK, data + 1); // The verification is successful, and service logic is executed normally. + } + + insertDataToMap(key: string, val: number, callback: insertDataToMapCallback): void { + // Implement service logic. + console.info(TAG, `insertDataToMap, key: ${key} val: ${val}`); + callback(ERR_OK); + } + } + ``` + diff --git a/en/application-dev/application-models/stage-model-development-overview.md b/en/application-dev/application-models/stage-model-development-overview.md index 451649bdb1a63147b79f8c7e2d4523d6c651c548..d4ad1d87c602c169e13b9ff99b8b491a33babd0a 100644 --- a/en/application-dev/application-models/stage-model-development-overview.md +++ b/en/application-dev/application-models/stage-model-development-overview.md @@ -12,7 +12,7 @@ The following figure shows the basic concepts used in the stage model. The stage model provides two types of application components: UIAbility and ExtensionAbility. Both have specific classes and support object-oriented development. - - UIAbility has the UI and is mainly used for user interaction. For example, with UIAbility, the Gallery application can display images in the liquid layout. After a user selects an image, it uses a new UI to display the image details. The user can touch the **Back** button to return to the liquid layout. The lifecycle of the UIAbility component contains the creation, destruction, foreground, and background states. Display-related states are exposed through WindowStage events. + - UIAbility is a type of application component that provides the UI for user interaction. For example, with UIAbility, the Gallery application can display images in the liquid layout. After a user selects an image, it uses a new UI to display the image details. The user can touch the **Back** button to return to the liquid layout. The lifecycle of the UIAbility component contains the creation, destruction, foreground, and background states. Display-related states are exposed through WindowStage events. - ExtensionAbility is oriented to specific scenarios. You cannot derive directly from ExtensionAbility. Instead, use the derived classes of ExtensionAbility for your scenarios, such as FormExtensionAbility for widget scenarios, InputMethodExtensionAbility for input method scenarios, and WorkSchedulerExtensionAbility for Work Scheduled task scenarios. For example, to enable a user to create an application widget on the home screen, you must derive FormExtensionAbility, implement the callback functions, and configure the capability in the configuration file. The derived class instances are created by developers and their lifecycles are managed by the system. In the stage model, you must use the derived classes of ExtensionAbility to develop custom services based on your service scenarios. - [WindowStage](../windowmanager/application-window-stage.md) @@ -37,7 +37,7 @@ During application development based on the stage model, the following tasks are | Task| Introduction| Guide| | -------- | -------- | -------- | | Application component development| Use the UIAbility and ExtensionAbility components of the stage model to develop applications.| - [Application- or Component-Level Configuration](application-component-configuration-stage.md)
- [UIAbility Component](uiability-overview.md)
- [ExtensionAbility Component](extensionability-overview.md)
- [AbilityStage Container Component](abilitystage.md)
- [Context](application-context-stage.md)
- [Component Startup Rules](component-startup-rules.md)| -| Inter-process communication (IPC)| Learn the process model and common IPC modes of the stage model.| - [Common Events](common-event-overview.md)
- [Background Services](background-services.md)| -| Inter-thread communication| Learn the thread model and common inter-thread communication modes of the stage model.| - [Emitter](itc-with-emitter.md)
- [Worker](itc-with-worker.md)| +| Process model| Learn the process model and common IPC modes of the stage model.| - [Common Events](common-event-overview.md)
- [Background Services](background-services.md)| +| Thread model| Learn the thread model and common inter-thread communication modes of the stage model.| - [Emitter](itc-with-emitter.md)
- [Worker](itc-with-worker.md)| | Mission management| Learn the basic concepts and typical scenarios of mission management in the stage model.| - [Mission Management Scenarios](mission-management-overview.md)
- [Mission Management and Launch Type](mission-management-launch-type.md)
- [Page Stack and Mission List](page-mission-stack.md)| | Application configuration file| Learn the requirements for developing application configuration files in the stage model.| [Application Configuration File](config-file-stage.md)| diff --git a/en/application-dev/application-models/start-page.md b/en/application-dev/application-models/start-page.md index 58966d93cba037eaad141caaed0feaaaa672cde1..1def472cd5fa2567fda123fc272542787b1f985c 100644 --- a/en/application-dev/application-models/start-page.md +++ b/en/application-dev/application-models/start-page.md @@ -70,7 +70,7 @@ struct Index { ``` -When the launch type of a PageAbility is set to **standard** or when the PageAbility with the launch type set to **singleton** is started for the first time, you can use the **parameters** parameter in **want** to transfer the pages information and use the **startAbility()** method to start the PageAbility. For details about the launch type, see [PageAbility Launch Type](pageability-launch-type.md). The target PageAbility can use the **featureAbility.getWant()** method in **onCreate** to obtain the **want** parameter, and then call **router.push** to start a specified page. +When a PageAbility in multiton mode is started or when the PageAbility in singleton mode is started for the first time, you can use the **parameters** parameter in **want** to transfer the pages information and use the **startAbility()** method to start the PageAbility. For details about the launch type, see [PageAbility Launch Type](pageability-launch-type.md). The target PageAbility can use the **featureAbility.getWant()** method in **onCreate** to obtain the **want** parameter, and then call **router.push** to start a specified page. When a user touches the button on the page of the caller PageAbility, the **startAbility()** method is called to start the target PageAbility. The **want** parameter in **startAbility()** carries the specified page information. @@ -83,7 +83,7 @@ struct Index { @State message: string = 'Hello World' build() { - // ... + ... Button("startAbility") .onClick(() => { featureAbility.startAbility({ @@ -98,7 +98,7 @@ struct Index { console.info("startAbility failed errcode:" + err.code) }) }) - // ... + ... Button("page2") .onClick(() => { featureAbility.startAbility({ @@ -113,7 +113,7 @@ struct Index { console.info("startAbility failed errcode:" + err.code) }) }) - // ... + ... } } ``` @@ -136,7 +136,7 @@ export default { }) }, onDestroy() { - // ... + ... }, } ``` diff --git a/en/application-dev/application-models/start-pageability-from-stage.md b/en/application-dev/application-models/start-pageability-from-stage.md index 9d1b7ed27f6780ce56d1e90b3be5d196cf3b1187..bd6a11187fdfbc81c63bcc6601f8a8e82b0dbe4c 100644 --- a/en/application-dev/application-models/start-pageability-from-stage.md +++ b/en/application-dev/application-models/start-pageability-from-stage.md @@ -21,7 +21,7 @@ export default class EntryAbility extends UIAbility { onWindowStageCreate(windowStage) { console.info("EntryAbility onWindowStageCreate") windowStage.loadContent('pages/Index', (err, data) => { - // ... + ... }); let want = { bundleName: "com.ohos.fa", @@ -66,7 +66,7 @@ export default class EntryAbility extends UIAbility { onWindowStageCreate(windowStage) { console.info("EntryAbility onWindowStageCreate") windowStage.loadContent('pages/Index', (err, data) => { - // ... + ... }); let want = { bundleName: "com.ohos.fa", diff --git a/en/application-dev/application-models/start-remote-pageability.md b/en/application-dev/application-models/start-remote-pageability.md index 36ee305b49698c1f6e6cf216174f77212f1d53e4..a52378af306c9719b086b23f0909f87d7bf376b3 100644 --- a/en/application-dev/application-models/start-remote-pageability.md +++ b/en/application-dev/application-models/start-remote-pageability.md @@ -83,28 +83,31 @@ After obtaining the data synchronization permission, obtain the trusted device l The following sample code shows how to use **getTrustedDeviceListSync()** to obtain the trusted device list. ```ts -import deviceManager from '@ohos.distributedHardware.deviceManager'; -let dmClass; +import deviceManager from '@ohos.distributedHardware.deviceManager'; + +let dmClass; + function getDeviceManager() { - deviceManager.createDeviceManager('ohos.example.distributedService', (error, dm) => { - if (error) { - console.info('create device manager failed with ' + error) - } - dmClass = dm; - }) + deviceManager.createDeviceManager('ohos.example.distributedService', (error, dm) => { + if (error) { + console.info('create device manager failed with ' + error) + } + dmClass = dm; + }) } -function getRemoteDeviceId() { - if (typeof dmClass === 'object' && dmClass != null) { - let list = dmClass.getTrustedDeviceListSync(); - if (typeof (list) == 'undefined' || typeof (list.length) == 'undefined') { - console.info("EntryAbility onButtonClick getRemoteDeviceId err: list is null"); - return; - } - console.info("EntryAbility onButtonClick getRemoteDeviceId success:" + list[0].deviceId); - return list[0].deviceId; - } else { - console.info("EntryAbility onButtonClick getRemoteDeviceId err: dmClass is null"); - } + +function getRemoteDeviceId() { + if (typeof dmClass === 'object' && dmClass != null) { + let list = dmClass.getTrustedDeviceListSync(); + if (typeof (list) == 'undefined' || typeof (list.length) == 'undefined') { + console.info("EntryAbility onButtonClick getRemoteDeviceId err: list is null"); + return; + } + console.info("EntryAbility onButtonClick getRemoteDeviceId success:" + list[0].deviceId); + return list[0].deviceId; + } else { + console.info("EntryAbility onButtonClick getRemoteDeviceId err: dmClass is null"); + } } ``` @@ -116,21 +119,22 @@ The following sample code shows how to explicitly start a remote PageAbility thr ```ts import featureAbility from '@ohos.ability.featureAbility'; -function onStartRemoteAbility() { - console.info('onStartRemoteAbility begin'); - let params; - let wantValue = { - bundleName: 'ohos.samples.etsDemo', - abilityName: 'ohos.samples.etsDemo.RemoteAbility', - deviceId: getRemoteDeviceId(), // getRemoteDeviceId is defined in the preceding sample code. - parameters: params - }; - console.info('onStartRemoteAbility want=' + JSON.stringify(wantValue)); - featureAbility.startAbility({ - want: wantValue - }).then((data) => { - console.info('onStartRemoteAbility finished, ' + JSON.stringify(data)); - }); - console.info('onStartRemoteAbility end'); + +function onStartRemoteAbility() { + console.info('onStartRemoteAbility begin'); + let params; + let wantValue = { + bundleName: 'ohos.samples.etsDemo', + abilityName: 'ohos.samples.etsDemo.RemoteAbility', + deviceId: getRemoteDeviceId(), // getRemoteDeviceId is defined in the preceding sample code. + parameters: params + }; + console.info('onStartRemoteAbility want=' + JSON.stringify(wantValue)); + featureAbility.startAbility({ + want: wantValue + }).then((data) => { + console.info('onStartRemoteAbility finished, ' + JSON.stringify(data)); + }); + console.info('onStartRemoteAbility end'); } ``` diff --git a/en/application-dev/application-models/storage-switch.md b/en/application-dev/application-models/storage-switch.md index 63486fe56fdf3605121711bee423066d9ac6e116..bbd550ebc3a01253a6d94652022c3ec5e2bcd92d 100644 --- a/en/application-dev/application-models/storage-switch.md +++ b/en/application-dev/application-models/storage-switch.md @@ -1,7 +1,7 @@ # Storage Switching - | API in the FA Model| Corresponding d.ts File in the Stage Model| Corresponding API in the Stage Model| + | API in the FA Model| Corresponding .d.ts File in the Stage Model| Corresponding API in the Stage Model| | -------- | -------- | -------- | | GetStorageOptions | There is no corresponding API in the stage model.| The stage model uses **Prefereces** to replace **Storage** and has redesigned the input parameters.| | SetStorageOptions | There is no corresponding API in the stage model.| The stage model uses **Prefereces** to replace **Storage** and has redesigned the input parameters.| diff --git a/en/application-dev/application-models/subscribe-system-environment-variable-changes.md b/en/application-dev/application-models/subscribe-system-environment-variable-changes.md index c231f483e9bcd8f83faf49d40007730d0f854de5..69b30ed47e3ef145f09aa626afb809ee4bdab83d 100644 --- a/en/application-dev/application-models/subscribe-system-environment-variable-changes.md +++ b/en/application-dev/application-models/subscribe-system-environment-variable-changes.md @@ -1,6 +1,6 @@ # Subscribing to System Environment Variable Changes -System environment variables are system settings (for example, the system language or screen direction) of a device that may change during the running of an application. +System environment variables are system settings (for example, the system language or screen orientation) of a device that may change during the running of an application. By subscribing to the changes of system environment variables, the application can detect the changes in a timely manner and process the changes accordingly, providing better user experience. For example, when the system language changes, the application can display the UI in the new language; when the user rotates the device to landscape or portrait mode, the application can re-arrange the UI to adapt to the new screen orientation and size. @@ -54,7 +54,7 @@ In OpenHarmony, you can subscribe to system environment variable changes in the // Page display. build() { - // ... + ... } } ``` @@ -77,7 +77,7 @@ In OpenHarmony, you can subscribe to system environment variable changes in the // Page display. build() { - // ... + ... } } ``` @@ -99,19 +99,19 @@ import AbilityStage from '@ohos.app.ability.AbilityStage'; let systemLanguage: string; // System language in use. export default class MyAbilityStage extends AbilityStage { - onCreate() { - systemLanguage = this.context.config.language; // Obtain the system language in use when the AbilityStage instance is loaded for the first time. - console.info(`systemLanguage is ${systemLanguage} `); - } + onCreate() { + systemLanguage = this.context.config.language; // Obtain the system language in use when the AbilityStage instance is loaded for the first time. + console.info(`systemLanguage is ${systemLanguage} `); + } - onConfigurationUpdate(newConfig) { - console.info(`onConfigurationUpdated systemLanguage is ${systemLanguage}, newConfig: ${JSON.stringify(newConfig)}`); + onConfigurationUpdate(newConfig) { + console.info(`onConfigurationUpdated systemLanguage is ${systemLanguage}, newConfig: ${JSON.stringify(newConfig)}`); - if (systemLanguage !== newConfig.language) { - console.info(`systemLanguage from ${systemLanguage} changed to ${newConfig.language}`); - systemLanguage = newConfig.language; // Save the new system language as the system language in use, which will be used for comparison. - } + if (systemLanguage !== newConfig.language) { + console.info(`systemLanguage from ${systemLanguage} changed to ${newConfig.language}`); + systemLanguage = newConfig.language; // Save the new system language as the system language in use, which will be used for comparison. } + } } ``` @@ -131,21 +131,21 @@ import UIAbility from '@ohos.app.ability.UIAbility'; let systemLanguage: string; // System language in use. export default class EntryAbility extends UIAbility { - onCreate(want, launchParam) { - systemLanguage = this.context.config.language; // Obtain the system language in use when the UIAbility instance is loaded for the first time. - console.info(`systemLanguage is ${systemLanguage} `); - } + onCreate(want, launchParam) { + systemLanguage = this.context.config.language; // Obtain the system language in use when the UIAbility instance is loaded for the first time. + console.info(`systemLanguage is ${systemLanguage} `); + } - onConfigurationUpdate(newConfig) { - console.info(`onConfigurationUpdated systemLanguage is ${systemLanguage}, newConfig: ${JSON.stringify(newConfig)}`); + onConfigurationUpdate(newConfig) { + console.info(`onConfigurationUpdated systemLanguage is ${systemLanguage}, newConfig: ${JSON.stringify(newConfig)}`); - if (systemLanguage !== newConfig.language) { - console.info(`systemLanguage from ${systemLanguage} changed to ${newConfig.language}`); - systemLanguage = newConfig.language; // Save the new system language as the system language in use, which will be used for comparison. - } + if (systemLanguage !== newConfig.language) { + console.info(`systemLanguage from ${systemLanguage} changed to ${newConfig.language}`); + systemLanguage = newConfig.language; // Save the new system language as the system language in use, which will be used for comparison. } + } - // ... + ... } ``` @@ -163,10 +163,10 @@ The code snippet below uses FormExtensionAbility as an example to describe how t import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility'; export default class EntryFormAbility extends FormExtensionAbility { - onConfigurationUpdate(newConfig) { - console.info(`newConfig is ${JSON.stringify(newConfig)}`); - } + onConfigurationUpdate(newConfig) { + console.info(`newConfig is ${JSON.stringify(newConfig)}`); + } - // ... + ... } ``` diff --git a/en/application-dev/application-models/thread-model-fa.md b/en/application-dev/application-models/thread-model-fa.md index 75401be69cba994ac631b6da997fb6ce2ea35a2f..b8b877432f0d80f45bc96ae2e5cad56fa1972beb 100644 --- a/en/application-dev/application-models/thread-model-fa.md +++ b/en/application-dev/application-models/thread-model-fa.md @@ -1,13 +1,13 @@ -# Thread Model (FA Model) +# Thread Model Overview (FA Model) There are three types of threads in the FA model: - Main thread - -Manages other threads. - + + Manages other threads. + - Ability thread - One ability thread for each ability. - Distributes input events. @@ -16,13 +16,11 @@ Manages other threads. - Receives messages sent by the worker thread. - Worker thread - - Performs time-consuming operations + Performs time-consuming operations. Based on the OpenHarmony thread model, different services run on different threads. Service interaction requires inter-thread communication. Threads can communicate with each other in Emitter or Worker mode. Emitter is mainly used for event synchronization between threads, and Worker is mainly used to execute time-consuming tasks. - > **NOTE** > > The FA model provides an independent thread for each ability. Emitter is mainly used for event synchronization within the ability thread, between a pair of ability threads, or between the ability thread and worker thread. diff --git a/en/application-dev/application-models/thread-model-stage.md b/en/application-dev/application-models/thread-model-stage.md index deaab60b7bd7549dcb96bc00d7896d5c67e5c5d2..c56dacb810747aafe47dea8e73889fdeabb31dbb 100644 --- a/en/application-dev/application-models/thread-model-stage.md +++ b/en/application-dev/application-models/thread-model-stage.md @@ -1,25 +1,21 @@ -# Thread Model (Stage Model) +# Thread Model Overview (Stage Model) For an OpenHarmony application, each process has a main thread to provide the following functionalities: -- Manage other threads. - -- Enable multiple UIAbility components of the same application to share the same main thread. - -- Distribute input events. - - Draw the UI. - -- Invoke application code callbacks (event processing and lifecycle callbacks). - +- Manage the ArkTS engine instance of the main thread so that multiple UIAbility components can run on it. +- Manage ArkTS engine instances of other threads, for example, starting and terminating other threads. +- Distribute interaction events. +- Process application code callbacks (event processing and lifecycle management). - Receive messages sent by the worker thread. -In addition to the main thread, there is an independent thread, named worker. The worker thread is mainly used to perform time-consuming operations. It cannot directly operate the UI. The worker thread is created in the main thread and is independent of the main thread. A maximum of seven worker threads can be created. - +In addition to the main thread, there is an independent thread, named worker. The worker thread is mainly used to perform time-consuming operations. The worker thread is created in the main thread and is independent from the main thread. It cannot directly operate the UI. A maximum of eight worker threads can be created. ![thread-model-stage](figures/thread-model-stage.png) Based on the OpenHarmony thread model, different services run on different threads. Service interaction requires inter-thread communication. In the same process, threads can communicate with each other in Emitter or Worker mode. Emitter is mainly used for event synchronization between threads, and Worker is mainly used to execute time-consuming tasks. > **NOTE** -> -> The stage model provides only the main thread and worker thread. Emitter is mainly used for event synchronization within the main thread or between the main thread and worker thread. +> +> - The stage model provides only the main thread and worker thread. Emitter is mainly used for event synchronization within the worker thread or between the main thread and worker thread. +> - The UIAbility and UI are in the main thread. For details about data synchronization between them, see [Data Synchronization Between UIAbility and UI](uiability-data-sync-with-ui.md). +> - To view thread information about an application process, run the **hdc shell** command to enter the shell CLI of the device, and then run the **ps -p ** -T command**, where ** indicates the [process ID](process-model-stage.md) of the application. diff --git a/en/application-dev/application-models/uiability-data-sync-with-ui.md b/en/application-dev/application-models/uiability-data-sync-with-ui.md index e5e5b7b54f2ad8e98048a08599360806e3ea578d..cb3cf3e17ff9f4ec7941ecb54ef26c1dd428d91d 100644 --- a/en/application-dev/application-models/uiability-data-sync-with-ui.md +++ b/en/application-dev/application-models/uiability-data-sync-with-ui.md @@ -1,18 +1,18 @@ -# Data Synchronization Between UIAbility and UI +# Data Synchronization Between UIAbility and UI Page -Based on the OpenHarmony application model, you can use any of the following ways to implement data synchronization between the UIAbility component and UI: +Based on the OpenHarmony application model, you can use any of the following ways to implement data synchronization between UIAbility components and UI pages: -- [Using EventHub for Data Synchronization](#using-eventhub-for-data-synchronization): The **EventHub** object is provided by the base class **Context**. Events are transferred using the publish/subscribe (pub/sub) pattern. Specifically, after subscribing to an event, your application will receive the event and process it accordingly when the event is published. -- [Using globalThis for Data Synchronization](#using-globalthis-for-data-synchronization): **globalThis** is a global object inside the ArkTS engine instance and can be accessed by components such as UIAbility, ExtensionAbility, and Page. +- [Using EventHub for Data Synchronization](#using-eventhub-for-data-synchronization): The **EventHub** object is provided by the base class **Context**. It allows events to be transferred using the publish/subscribe (pub/sub) pattern. Specifically, after subscribing to an event, your application will receive the event and process it accordingly when the event is published. +- [Using globalThis for Data Synchronization](#using-globalthis-for-data-synchronization): **globalThis** is a global object inside the ArkTS engine instance and can be accessed by the UIAbility components, ExtensionAbility components, and ArkUI pages inside the instance. - [Using AppStorage or LocalStorage for Data Synchronization](#using-appstorage-or-localstorage-for-data-synchronization): ArkUI provides two application-level state management solutions: AppStorage and LocalStorage, which implement application- and UIAbility-level data synchronization, respectively. ## Using EventHub for Data Synchronization -[EventHub](../reference/apis/js-apis-inner-application-eventHub.md) provides an event mechanism for the UIAbility or ExtensionAbility component so that they can subscribe to, unsubscribe from, and trigger events. +[EventHub](../reference/apis/js-apis-inner-application-eventHub.md) provides an event mechanism for the UIAbility component so that they can subscribe to, unsubscribe from, and trigger events. -Before using the APIs provided by **EventHub**, you must obtain an **EventHub** object, which is provided by the [base class Context](application-context-stage.md). This section uses EventHub as an example to describe how to implement data synchronization between the UIAbility component and the UI. +Before using the APIs provided by **EventHub**, you must obtain an **EventHub** object, which is provided by the [base class Context](application-context-stage.md). 1. Call [eventHub.on()](../reference/apis/js-apis-inner-application-eventHub.md#eventhubon) in the UIAbility in either of the following ways to register a custom event **event1**. @@ -22,25 +22,25 @@ Before using the APIs provided by **EventHub**, you must obtain an **EventHub** const TAG: string = '[Example].[Entry].[EntryAbility]'; export default class EntryAbility extends UIAbility { - func1(...data) { - // Trigger the event to complete the service operation. - console.info(TAG, '1. ' + JSON.stringify(data)); - } - - onCreate(want, launch) { - // Obtain an eventHub object. - let eventhub = this.context.eventHub; - // Subscribe to the event. - eventhub.on('event1', this.func1); - eventhub.on('event1', (...data) => { - // Trigger the event to complete the service operation. - console.info(TAG, '2. ' + JSON.stringify(data)); - }); - } + func1(...data) { + // Trigger the event to complete the service operation. + console.info(TAG, '1. ' + JSON.stringify(data)); + } + + onCreate(want, launch) { + // Obtain an eventHub object. + let eventhub = this.context.eventHub; + // Subscribe to the event. + eventhub.on('event1', this.func1); + eventhub.on('event1', (...data) => { + // Trigger the event to complete the service operation. + console.info(TAG, '2. ' + JSON.stringify(data)); + }); + } } ``` -2. Call [eventHub.emit()](../reference/apis/js-apis-inner-application-eventHub.md#eventhubemit) on the UI to trigger the event, and pass the parameters as required. +2. Call [eventHub.emit()](../reference/apis/js-apis-inner-application-eventHub.md#eventhubemit) on the UI page to trigger the event, and pass in the parameters as required. ```ts import common from '@ohos.app.ability.common'; @@ -60,14 +60,14 @@ Before using the APIs provided by **EventHub**, you must obtain an **EventHub** // You can design the parameters based on your service requirements. } - // Page display. + // UI page display. build() { - // ... + ... } } ``` -3. Obtain the event trigger result from the subscription callback of UIAbility. The run log result is as follows: +3. Obtain the event trigger result from the subscription callback of the UIAbility. The run log result is as follows: ```ts [] @@ -77,7 +77,7 @@ Before using the APIs provided by **EventHub**, you must obtain an **EventHub** [2,'test'] ``` -4. After **event1** is used, you can call [eventHub.off()](../reference/apis/js-apis-inner-application-eventHub.md#eventhuboff) to unsubscribe from the event. +4. When **event1** is not needed, call [eventHub.off()](../reference/apis/js-apis-inner-application-eventHub.md#eventhuboff) to unsubscribe from the event. ```ts // context is the AbilityContext of the UIAbility instance. @@ -87,54 +87,54 @@ Before using the APIs provided by **EventHub**, you must obtain an **EventHub** ## Using globalThis for Data Synchronization -**globalThis** is a global object inside the [ArkTS engine instance](thread-model-stage.md) and can be used by UIAbility, ExtensionAbility, and Page inside the engine. Therefore, you can use **globalThis** for data synchronization. +**globalThis** is a global object inside the [ArkTS engine instance](thread-model-stage.md) and can be used by UIAbility, ExtensionAbility, and UI page inside the engine. Therefore, you can use **globalThis** for data synchronization. **Figure 1** Using globalThis for data synchronization - ![globalThis1](figures/globalThis1.png) +![globalThis1](figures/globalThis1.png) The following describes how to use **globalThis** in three scenarios. Precautions are provided as well. -- [Using globalThis Between UIAbility and Page](#using-globalthis-between-uiability-and-page) +- [Using globalThis Between UIAbility and UI Page](#using-globalthis-between-uiability-and-ui-page) - [Using globalThis Between UIAbility and UIAbility](#using-globalthis-between-uiability-and-uiability) -- [Use globalThis Between UIAbility and ExtensionAbility](#using-globalthis-between-uiability-and-extensionability) +- [Using globalThis Between UIAbility and ExtensionAbility](#using-globalthis-between-uiability-and-extensionability) - [Precautions for Using globalThis](#precautions-for-using-globalthis) -### Using globalThis Between UIAbility and Page +### Using globalThis Between UIAbility and UI Page -By binding attributes or methods to **globalThis**, you can implement data synchronization between the UIAbility component and UI. For example, if you bind the **want** parameter in the UIAbility component, you can use the **want** parameter information on the UI corresponding to the UIAbility component. +To implement data synchronization between the UIAbility component and UI page, you can bind attributes or methods to **globalThis**. For example, if you bind the **want** parameter in the UIAbility component, you can use the **want** parameter information on the UI page corresponding to the UIAbility component. -1. When [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) is called to start a UIAbility instance, the **onCreate()** callback is invoked, and the **want** parameter can be passed in the callback. Therefore, you can bind the **want** parameter to **globalThis**. +1. When [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) is called to start a UIAbility instance, the [onCreate()](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityoncreate) callback is invoked, and the **want** parameter can be passed in the callback. Bind the **want** parameter to **globalThis**. ```ts import UIAbility from '@ohos.app.ability.UIAbility'; export default class EntryAbility extends UIAbility { - onCreate(want, launch) { - globalThis.entryAbilityWant = want; - // ... - } + onCreate(want, launch) { + globalThis.entryAbilityWant = want; + ... + } - // ... + ... } ``` -2. Use **globalThis** on the UI to obtain the **want** parameter information. +2. Use **globalThis** on the UI page to obtain the **want** parameter information. ```ts let entryAbilityWant; - + @Entry @Component struct Index { aboutToAppear() { entryAbilityWant = globalThis.entryAbilityWant; } - - // Page display. + + // UI page display. build() { - // ... + ... } } ``` @@ -144,16 +144,16 @@ By binding attributes or methods to **globalThis**, you can implement data synch To implement data synchronization between two UIAbility components in the same application, you can bind data to **globalThis**. For example, you can save data in **globalThis** in UIAbilityA and obtain the data from UIAbilityB. -1. UIAbilityA stores a string and binds it to globalThis. +1. Save data in UIAbilityA and bind it to **globalThis**. ```ts import UIAbility from '@ohos.app.ability.UIAbility' export default class UIAbilityA extends UIAbility { - onCreate(want, launch) { - globalThis.entryAbilityStr = 'UIAbilityA'; // UIAbilityA stores the string "UIAbilityA" to globalThis. - // ... - } + onCreate(want, launch) { + globalThis.entryAbilityStr = 'UIAbilityA'; // UIAbilityA stores the string "UIAbilityA" to globalThis. + ... + } } ``` @@ -161,13 +161,13 @@ To implement data synchronization between two UIAbility components in the same a ```ts import UIAbility from '@ohos.app.ability.UIAbility' - + export default class UIAbilityB extends UIAbility { - onCreate(want, launch) { - // UIAbilityB reads name from globalThis and outputs it. - console.info('name from entryAbilityStr: ' + globalThis.entryAbilityStr); - // ... - } + onCreate(want, launch) { + // UIAbilityB reads name from globalThis and outputs it. + console.info('name from entryAbilityStr: ' + globalThis.entryAbilityStr); + ... + } } ``` @@ -176,17 +176,17 @@ To implement data synchronization between two UIAbility components in the same a To implement data synchronization between the UIAbility and ExtensionAbility components in the same application, you can bind data to **globalThis**. For example, you can save data in **globalThis** in UIAbilityA and obtain the data from ServiceExtensionAbility. -1. UIAbilityA stores a string and binds it to globalThis. +1. Save data in UIAbilityA and bind it to **globalThis**. ```ts import UIAbility from '@ohos.app.ability.UIAbility' export default class UIAbilityA extends UIAbility { - onCreate(want, launch) { - // UIAbilityA stores the string "UIAbilityA" to globalThis. - globalThis.entryAbilityStr = 'UIAbilityA'; - // ... - } + onCreate(want, launch) { + // UIAbilityA stores the string "UIAbilityA" to globalThis. + globalThis.entryAbilityStr = 'UIAbilityA'; + ... + } } ``` @@ -194,45 +194,47 @@ To implement data synchronization between the UIAbility and ExtensionAbility com ```ts import Extension from '@ohos.app.ability.ServiceExtensionAbility' - + export default class ServiceExtAbility extends Extension { - onCreate(want) { - / / ServiceExtAbility reads name from globalThis and outputs it. - console.info('name from entryAbilityStr: ' + globalThis.entryAbilityStr); - // ... - } + onCreate(want) { + / / ServiceExtAbility reads name from globalThis and outputs it. + console.info('name from entryAbilityStr: ' + globalThis.entryAbilityStr); + ... + } } ``` ### Precautions for Using globalThis -**Figure 2** Precautions for globalThis +**Figure 2** Precautions for using globalThis ![globalThis2](figures/globalThis2.png) - In the stage model, all the UIAbility components in a process share one ArkTS engine instance. When using **globalThis**, do not store objects with the same name. For example, if UIAbilityA and UIAbilityB use **globalThis** to store two objects with the same name, the object stored earlier will be overwritten. +- **globalThis** cannot be used across processes. The UIAbility and ExtensionAbility components of different processes cannot use **globalThis** to share data. For details about the process model and inter-process communication, see [Process Model Overview](./process-model-stage.md#process-model-overview). + - This problem does not occur in the FA model because each UIAbility component uses an independent engine. -- The lifecycle of an object bound to **globalThis** is the same as that of the ArkTS engine instance. You are advised to assign the value **null** after using the object to minimize memory usage. +- The lifecycle of an object bound to **globalThis** is the same as that of the ArkTS engine instance. To minimize memory usage, you are advised to assign the value **null** to the object when it is not in use. The following provides an example to describe the object overwritten problem in the stage model. -1. In the UIAbilityA file, [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) is stored in **globalThis**. +1. In the UIAbilityA file, use **globalThis** to store [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md). ```ts import UIAbility from '@ohos.app.ability.UIAbility' export default class UIAbilityA extends UIAbility { - onCreate(want, launch) { - globalThis.context = this.context; // UIAbilityA stores the context in globalThis. - // ... - } + onCreate(want, launch) { + globalThis.context = this.context; // UIAbilityA stores the context in globalThis. + ... + } } ``` -2. Obtain and use [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) on the page of UIAbilityA. After the UIAbilityA instance is used, switch it to the background. +2. Obtain and use [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) on the UI page of UIAbilityA. When the UIAbilityA instance is not in use, switch it to the background. ```ts @Entry @@ -241,28 +243,28 @@ The following provides an example to describe the object overwritten problem in onPageShow() { let ctx = globalThis.context; // Obtain the context from globalThis and use it. } - // Page display. + // UI page display. build() { - // ... + ... } } ``` - -3. In the UIAbilityB file, [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) is stored in **globalThis** and has the same name as that in the UIAbilityA file. + +3. In the UIAbilityB file, use **globalThis** to store [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md), which is named the same as that in the UIAbilityA file. ```ts import UIAbility from '@ohos.app.ability.UIAbility' export default class UIAbilityB extends UIAbility { - onCreate(want, launch) { - // UIAbilityB overwrites the context stored by UIAbilityA in globalThis. - globalThis.context = this.context; - // ... - } + onCreate(want, launch) { + // UIAbilityB overwrites the context stored by UIAbilityA in globalThis. + globalThis.context = this.context; + ... + } } ``` -4. Obtain and use [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) on the page of UIAbilityB. The obtained **globalThis.context** is the value of [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) in UIAbilityB. +4. Obtain [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) from the UI page of UIAbilityB and use it. The obtained **globalThis.context** is the value of [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) in UIAbilityB. ```ts @Entry @@ -271,27 +273,27 @@ The following provides an example to describe the object overwritten problem in onPageShow() { let ctx = globalThis.context; // Obtain the context from globalThis and use it. } - // Page display. + // UI page display. build() { - // ... + ... } } ``` - + 5. Switch the UIAbilityB instance to the background and switch the UIAbilityA instance to the foreground. In this case, UIAbilityA will not enter the **onCreate()** lifecycle again. ```ts import UIAbility from '@ohos.app.ability.UIAbility' export default class UIAbilityA extends UIAbility { - onCreate(want, launch) { // UIAbilityA will not enter this lifecycle. - globalThis.context = this.context; - // ... - } + onCreate(want, launch) { // UIAbilityA will not enter this lifecycle. + globalThis.context = this.context; + ... + } } ``` -6. When the page of UIAbilityA is displayed, the obtained **globalThis.context** is [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) of UIAbilityB instead of UIAbilityA. An error occurs. +6. When the UI page of UIAbilityA is displayed, the obtained **globalThis.context** is the value of [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) of UIAbilityB instead of UIAbilityA. An error occurs. ```ts @Entry @@ -300,13 +302,13 @@ The following provides an example to describe the object overwritten problem in onPageShow() { let ctx = globalThis.context; // The context in globalThis is the context of UIAbilityB. } - // Page display. + // UI page display. build() { - // ... + ... } } ``` ## Using AppStorage or LocalStorage for Data Synchronization -ArkUI provides AppStorage and LocalStorage to implement application- and UIAbility-level data synchronization, respectively. Both solutions can be used to manage the application state, enhance application performance, and improve user experience. The AppStorage is a global state manager and is applicable when multiple UIAbilities share the same state data. The LocalStorage is a local state manager that manages state data used inside a single UIAbility. They help you control the application state more flexibly and improve the maintainability and scalability of applications. For details, see [State Management of Application-Level Variables](../quick-start/arkts-state-mgmt-application-level.md). +ArkUI provides AppStorage and LocalStorage to implement application- and UIAbility-level data synchronization, respectively. Both solutions can be used to manage the application state, enhance application performance, and improve user experience. The AppStorage is a global state manager that manages state data shared among multiple UIAbilities. The LocalStorage is a local state manager that manages state data used inside a single UIAbility. They help you control the application state more flexibly and improve the maintainability and scalability of applications. For details, see [State Management of Application-Level Variables](../quick-start/arkts-application-state-management-overview.md). diff --git a/en/application-dev/application-models/uiability-intra-device-interaction.md b/en/application-dev/application-models/uiability-intra-device-interaction.md index c8ba4ec50fa9b67805685468f0b3ab5cdada2377..2ed36f466408f4280ef516f405bc0e6837fb31f6 100644 --- a/en/application-dev/application-models/uiability-intra-device-interaction.md +++ b/en/application-dev/application-models/uiability-intra-device-interaction.md @@ -1,7 +1,7 @@ # Intra-Device Interaction Between UIAbility Components -UIAbility is the minimum unit that can be scheduled by the system. Jumping between functional modules in a device involves starting of specific UIAbility components, which belong to the same or a different application (for example, starting UIAbility of a third-party payment application). +UIAbility is the minimum unit that can be scheduled by the system. Redirection between functional modules in a device involves starting of specific UIAbility components, which belong to the same or a different application (for example, starting UIAbility of a third-party payment application). This topic describes the UIAbility interaction modes in the following scenarios. For details about cross-device application component interaction, see [Inter-Device Application Component Interaction (Continuation)](inter-device-interaction-hop-overview.md). @@ -26,26 +26,26 @@ This topic describes the UIAbility interaction modes in the following scenarios. This scenario is possible when an application contains multiple UIAbility components. For example, in a payment application, you may need to start the payment UIAbility from the entry UIAbility. -Assume that your application has two UIAbility components: EntryAbility and FuncAbility, either in the same module or different modules. You are required to start FuncAbility from EntryAbility. +Assume that your application has two UIAbility components: EntryAbility and FuncAbility, either in the same module or different modules. To start FuncAbility from EntryAbility, proceed as follows: -1. In EntryAbility, call [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) to start UIAbility. The [want](../reference/apis/js-apis-app-ability-want.md) parameter is the entry parameter for starting the UIAbility instance. In the **want** parameter, **bundleName** indicates the bundle name of the application to start; **abilityName** indicates the name of the UIAbility to start; **moduleName** is required only when the target UIAbility belongs to a different module; **parameters** is used to carry custom information. For details about how to obtain the context, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability). +1. In EntryAbility, call [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) and pass the [want](../reference/apis/js-apis-app-ability-want.md) parameter to start the UIAbility instance. In the **want** parameter, **bundleName** indicates the bundle name of the application to start; **abilityName** indicates the name of the UIAbility to start; **moduleName** is required only when the target UIAbility belongs to a different module from EntryAbility; **parameters** is used to carry custom information. For details about how to obtain the context in the example, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability). ```ts let context = ...; // UIAbilityContext - let wantInfo = { + let want = { deviceId: '', // An empty deviceId indicates the local device. bundleName: 'com.example.myapplication', abilityName: 'FuncAbility', - moduleName: 'module1', // moduleName is optional. - parameters: {// Custom information. + moduleName: 'func', // moduleName is optional. + parameters: { // Custom information. info: 'From the Index page of EntryAbility', }, } // context is the UIAbilityContext of the initiator UIAbility. - context.startAbility(wantInfo).then(() => { - // ... + context.startAbility(want).then(() => { + console.info('Succeeded in starting ability.'); }).catch((err) => { - // ... + console.error(`Failed to start ability. Code is ${err.code}, message is ${err.message}`); }) ``` @@ -53,30 +53,32 @@ Assume that your application has two UIAbility components: EntryAbility and Func ```ts import UIAbility from '@ohos.app.ability.UIAbility'; - import window from '@ohos.window'; export default class FuncAbility extends UIAbility { onCreate(want, launchParam) { // Receive the parameters passed by the initiator UIAbility. let funcAbilityWant = want; let info = funcAbilityWant?.parameters?.info; - // ... + ... } } ``` - - > **NOTE**
+ + > **NOTE** > > In FuncAbility started, you can obtain the PID and bundle name of the UIAbility through **parameters** in the passed **want** parameter. -3. To stop the **UIAbility** instance after the FuncAbility service is complete, call [terminateSelf()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextterminateself) in FuncAbility. +3. To stop the **UIAbility** instance after the FuncAbility service is not needed, call [terminateSelf()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextterminateself) in FuncAbility. ```ts let context = ...; // UIAbilityContext // context is the UIAbilityContext of the UIAbility instance to stop. context.terminateSelf((err) => { - // ... + if (err.code) { + console.error(`Failed to terminate Self. Code is ${err.code}, message is ${err.message}`); + return; + } }); ``` @@ -84,31 +86,31 @@ Assume that your application has two UIAbility components: EntryAbility and Func > > When [terminateSelf()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextterminateself) is called to stop the **UIAbility** instance, the snapshot of the instance is retained by default. That is, the mission corresponding to the instance is still displayed in Recents. If you do not want to retain the snapshot, set **removeMissionAfterTerminate** under the [abilities](../quick-start/module-configuration-file.md#abilities) tag to **true** in the [module.json5 file](../quick-start/module-configuration-file.md) of the corresponding UIAbility. -4. To stop all UIAbility instances of the application, call [killProcessBySelf()](../reference/apis/js-apis-inner-application-applicationContext.md#applicationcontextkillallprocesses9) of [ApplicationContext](../reference/apis/js-apis-inner-application-applicationContext.md) to stop all processes of the application. +4. To stop all UIAbility instances of the application, call [killProcessBySelf()](../reference/apis/js-apis-inner-application-applicationContext.md#applicationcontextkillallprocesses9) of [ApplicationContext](../reference/apis/js-apis-inner-application-applicationContext.md). ## Starting UIAbility in the Same Application and Obtaining the Return Result -When starting FuncAbility from EntryAbility, you want the result to be returned after the FuncAbility service is finished. For example, your application uses two independent UIAbility components to carry the entry and sign-in functionalities. After the sign-in operation is finished in the sign-in UIAbility, the sign-in result needs to be returned to the entry UIAbility. +When starting FuncAbility from EntryAbility, you may want the result to be returned after the FuncAbility service is finished. For example, after the sign-in operation is finished in the sign-in UIAbility of your application, you want the sign-in result to be returned to the entry UIAbility. -1. In EntryAbility, call [startAbilityForResult()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextterminateselfwithresult) to start FuncAbility. Use **data** in the asynchronous callback to receive information returned after FuncAbility stops itself. For details about how to obtain the context, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability). +1. In EntryAbility, call [startAbilityForResult()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextterminateselfwithresult) to start FuncAbility. Use **data** in the asynchronous callback to receive information returned after FuncAbility stops itself. For details about how to obtain the context in the example, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability). ```ts let context = ...; // UIAbilityContext - let wantInfo = { + let want = { deviceId: '', // An empty deviceId indicates the local device. bundleName: 'com.example.myapplication', abilityName: 'FuncAbility', - moduleName: 'module1', // moduleName is optional. - parameters: {// Custom information. + moduleName: 'func', // moduleName is optional. + parameters: { // Custom information. info: 'From the Index page of EntryAbility', }, } // context is the UIAbilityContext of the initiator UIAbility. - context.startAbilityForResult(wantInfo).then((data) => { - // ... + context.startAbilityForResult(want).then((data) => { + ... }).catch((err) => { - // ... + console.error(`Failed to start ability for result. Code is ${err.code}, message is ${err.message}`); }) ``` @@ -122,7 +124,7 @@ When starting FuncAbility from EntryAbility, you want the result to be returned want: { bundleName: 'com.example.myapplication', abilityName: 'FuncAbility', - moduleName: 'module1', + moduleName: 'func', parameters: { info: 'From the Index page of FuncAbility', }, @@ -130,42 +132,45 @@ When starting FuncAbility from EntryAbility, you want the result to be returned } // context is the AbilityContext of the target UIAbility. context.terminateSelfWithResult(abilityResult, (err) => { - // ... + if (err.code) { + console.error(`Failed to terminate self with result. Code is ${err.code}, message is ${err.message}`); + return; + } }); ``` -3. After FuncAbility stops itself, EntryAbility uses [startAbilityForResult()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextterminateselfwithresult) to receive the information returned by FuncAbility. The value of **RESULT_CODE** must be the same as the preceding value. +3. After FuncAbility stops itself, EntryAbility uses [startAbilityForResult()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextterminateselfwithresult) to receive the information returned by FuncAbility. The value of **RESULT_CODE** must be the same as that specified in the preceding step. ```ts let context = ...; // UIAbilityContext const RESULT_CODE: number = 1001; - // ... + ... // context is the UIAbilityContext of the initiator UIAbility. - context.startAbilityForResult(wantInfo).then((data) => { + context.startAbilityForResult(want).then((data) => { if (data?.resultCode === RESULT_CODE) { // Parse the information returned by the target UIAbility. let info = data.want?.parameters?.info; - // ... + ... } }).catch((err) => { - // ... + console.error(`Failed to start ability for result. Code is ${err.code}, message is ${err.message}`); }) ``` ## Starting UIAbility of Another Application -Generally, the user only needs to do a common operation (for example, selecting a document application to view the document content) to start the UIAbility of another application. The [implicit Want launch mode](want-overview.md#types-of-want) is recommended. The system identifies a matched UIAbility and starts it based on the **want** parameter of the initiator UIAbility. +Generally, the user only needs to perform a general operation (for example, selecting a document application to view the document content) to start the UIAbility of another application. In this case, the [implicit Want launch mode](want-overview.md#types-of-want) is recommended. In this mode, the system identifies a matched UIAbility and starts it based on the **want** parameter of the initiator UIAbility. There are two ways to start **UIAbility**: [explicit and implicit](want-overview.md). -- Explicit Want launch: This mode is used to start a determined UIAbility component of an application. You need to set **bundleName** and **abilityName** of the target application in the **want** parameter. +- Explicit Want launch is used to start a determined UIAbility component of an application. You need to set **bundleName** and **abilityName** of the target application in the **want** parameter. -- Implicit Want launch: The user selects a UIAbility to start based on the matching conditions. That is, the UIAbility to start is not determined (the **abilityName** parameter is not specified). When [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) is called, the want parameter specifies a series of parameters such as **entities** and **actions**. **entities** provides category information of the target UIAbility, such as the browser or video player. **actions** specifies the common operations to perform, such as viewing, sharing, and application details. Then the system analyzes the **want** parameter to find the right UIAbility to start. You usually do not know whether the target application is installed and what **bundleName** and **abilityName** of the target application are. Therefore, implicit Want launch is usually used to start the UIAbility of another application. +- Implicit Want launch is used to start a UIAbility based on the matching conditions. That is, the UIAbility to start is not determined (the **abilityName** parameter is not specified). When [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) is called, the **want** parameter specifies a series of parameters such as **entities** and **actions**. **entities** provides category information of the target UIAbility, such as the browser or video player. **actions** specifies the common operations to perform, such as viewing and sharing. Then the system analyzes the **want** parameter to find the right UIAbility to start. If you are not sure about whether the target application is installed and what **bundleName** and **abilityName** of the target application are, consider using implicit Want launch. -This section describes how to start the UIAbility of another application through implicit Want. +The following example describes how to start the UIAbility of another application through implicit Want. 1. Install multiple document applications on your device. In the [module.json5 file](../quick-start/module-configuration-file.md) of each UIAbility component, configure **entities** and **actions** under **skills**. @@ -174,15 +179,15 @@ This section describes how to start the UIAbility of another application through "module": { "abilities": [ { - // ... + ... "skills": [ { "entities": [ - // ... + ... "entity.system.default" ], "actions": [ - // ... + ... "ohos.want.action.viewData" ] } @@ -193,11 +198,11 @@ This section describes how to start the UIAbility of another application through } ``` -2. Include **entities** and **actions** of the initiator UIAbility's **want** parameter into **entities** and **actions** under **skills** of the target UIAbility. After the system matches the UIAbility that meets the **entities** and **actions** information, a dialog box is displayed, showing the list of matched UIAbility instances for users to select. For details about how to obtain the context, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability). +2. Include **entities** and **actions** of the initiator UIAbility's **want** parameter into **entities** and **actions** under **skills** of the target UIAbility. After the system identifies the UIAbility instances that match the **entities** and **actions** information, a dialog box is displayed, showing the list of matching UIAbility instances for users to select. For details about how to obtain the context in the example, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability). ```ts let context = ...; // UIAbilityContext - let wantInfo = { + let want = { deviceId: '', // An empty deviceId indicates the local device. // Uncomment the line below if you want to implicitly query data only in the specific bundle. // bundleName: 'com.example.myapplication', @@ -207,31 +212,34 @@ This section describes how to start the UIAbility of another application through } // context is the UIAbilityContext of the initiator UIAbility. - context.startAbility(wantInfo).then(() => { - // ... + context.startAbility(want).then(() => { + console.info('Succeeded in starting ability.'); }).catch((err) => { - // ... + console.error(`Failed to start ability. Code is ${err.code}, message is ${err.message}`); }) ``` - The following figure shows the effect. When you click **Open PDF**, a dialog box is displayed for you to select. + The following figure shows the effect. When you click **Open PDF**, a dialog box is displayed for you to select the application to use. ![](figures/uiability-intra-device-interaction.png) -3. To stop the **UIAbility** instance after the document application is used, call [terminateSelf()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextterminateself). +3. To stop the **UIAbility** instance when the document application is not in use, call [terminateSelf()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextterminateself). ```ts let context = ...; // UIAbilityContext - // context is the AbilityContext of the UIAbility instance to stop. + // context is the UIAbilityContext of the UIAbility instance to stop. context.terminateSelf((err) => { - // ... + if (err.code) { + console.error(`Failed to terminate self. Code is ${err.code}, message is ${err.message}`); + return; + } }); ``` ## Starting UIAbility of Another Application and Obtaining the Return Result -If you want to obtain the return result when using implicit Want to start the UIAbility of another application, use [startAbilityForResult()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextterminateselfwithresult). An example scenario is that the main application needs to start a third-party payment application and obtain the payment result. +If you want to obtain the return result when using implicit Want to start the UIAbility of another application, use [startAbilityForResult()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextterminateselfwithresult). An example scenario is that your application needs to start a third-party payment application and obtain the payment result. 1. In the [module.json5 file](../quick-start/module-configuration-file.md) of the UIAbility corresponding to the payment application, set **entities** and **actions** under **skills**. @@ -240,15 +248,15 @@ If you want to obtain the return result when using implicit Want to start the UI "module": { "abilities": [ { - // ... + ... "skills": [ { "entities": [ - // ... + ... "entity.system.default" ], "actions": [ - // ... + ... "ohos.want.action.editData" ] } @@ -259,24 +267,24 @@ If you want to obtain the return result when using implicit Want to start the UI } ``` -2. Call [startAbilityForResult()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextterminateselfwithresult) to start the UIAbility of the payment application. Include **entities** and **actions** of the initiator UIAbility's **want** parameter into **entities** and **actions** under **skills** of the target UIAbility. Use **data** in the asynchronous callback to receive the information returned to the initiator UIAbility after the payment UIAbility stops itself. After the system matches the UIAbility that meets the **entities** and **actions** information, a dialog box is displayed, showing the list of matched UIAbility instances for users to select. +2. Call [startAbilityForResult()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextterminateselfwithresult) to start the UIAbility of the payment application. Include **entities** and **actions** of the initiator UIAbility's **want** parameter into **entities** and **actions** under **skills** of the target UIAbility. Use **data** in the asynchronous callback to receive the information returned to the initiator UIAbility after the payment UIAbility stops itself. After the system identifies the UIAbility instances that match the **entities** and **actions** information, a dialog box is displayed, showing the list of matching UIAbility instances for users to select. ```ts let context = ...; // UIAbilityContext - let wantInfo = { + let want = { deviceId: '', // An empty deviceId indicates the local device. // Uncomment the line below if you want to implicitly query data only in the specific bundle. // bundleName: 'com.example.myapplication', action: 'ohos.want.action.editData', // entities can be omitted. - entities: ['entity.system.default'], + entities: ['entity.system.default'] } // context is the UIAbilityContext of the initiator UIAbility. - context.startAbilityForResult(wantInfo).then((data) => { - // ... + context.startAbilityForResult(want).then((data) => { + ... }).catch((err) => { - // ... + console.error(`Failed to start ability for result. Code is ${err.code}, message is ${err.message}`); }) ``` @@ -298,7 +306,10 @@ If you want to obtain the return result when using implicit Want to start the UI } // context is the AbilityContext of the target UIAbility. context.terminateSelfWithResult(abilityResult, (err) => { - // ... + if (err.code) { + console.error(`Failed to terminate self with result. Code is ${err.code}, message is ${err.message}`); + return; + } }); ``` @@ -317,90 +328,91 @@ If you want to obtain the return result when using implicit Want to start the UI if (data?.resultCode === RESULT_CODE) { // Parse the information returned by the target UIAbility. let payResult = data.want?.parameters?.payResult; - // ... + ... } }).catch((err) => { - // ... + console.error(`Failed to start ability for result. Code is ${err.code}, message is ${err.message}`); }) ``` ## Starting UIAbility with Window Mode Specified (for System Applications Only) -By specifying the window mode when starting the UIAbility of an application, the application can be displayed in different window modes, which can be full-screen, floating window, or split-screen. +By specifying the window mode when starting the UIAbility of an application, you can have the application displayed in the specified window mode, which can be full-screen, floating window, or split-screen. In full-screen mode, an application occupies the entire screen after being started. Users cannot view other windows or applications. This mode is suitable for an application that requires users to focus on a specific task or UI. -In floating window mode, an application is displayed on the screen as a floating window after being started. Users can easily switch to other windows or applications. The mode is suitable for an application that requires users to process multiple tasks at the same time. +In floating window mode, an application is displayed on the screen as a floating window after being started. Users can easily switch to other windows or applications. This mode is suitable for an application that allows users to process multiple tasks at the same time. -In split-screen mode, two applications occupy the entire screen, with one on the left or in the upper part of the screen and the other on the right or in the lower part. This mode helps users improve multi-task processing efficiency. +In split-screen mode, two applications occupy the entire screen, side by side, horizontally or vertically. This mode helps users improve multi-task processing efficiency. The window mode is specified by the **windowMode** field in the [StartOptions](../reference/apis/js-apis-app-ability-startOptions.md) parameter of [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability). > **NOTE** > > 1. If the **windowMode** field is not specified, the UIAbility is started in the default window mode. -> 2. To ensure that the application can be displayed in the required window mode, check the **supportWindowMode** field in the [abilities](../quick-start/module-configuration-file.md#abilities) tag in the [module.json5 file](../quick-start/module-configuration-file.md) of the UIAbility and make sure the specified window mode is supported. +> 2. To ensure that the application can be displayed in the required window mode, check the **supportWindowMode** field under [abilities](../quick-start/module-configuration-file.md#abilities) in the [module.json5 file](../quick-start/module-configuration-file.md) of the UIAbility and make sure the specified window mode is supported. -The following uses the floating window mode as an example to describe how to start the FuncAbility from the EntryAbility page. +The following describes how to start the FuncAbility from the EntryAbility page and display it in floating window mode. 1. Add the [StartOptions](../reference/apis/js-apis-app-ability-startOptions.md) parameter in [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability). -2. Set the **windowMode** field in the [StartOptions](../reference/apis/js-apis-app-ability-startOptions.md) parameter to **WINDOW_MODE_FLOATING**, indicating that the UIAbility will be displayed in a floating window. +2. Set the **windowMode** field in the [StartOptions](../reference/apis/js-apis-app-ability-startOptions.md) parameter to **WINDOW_MODE_FLOATING**. -For details about how to obtain the context, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability). +For details about how to obtain the context in the example, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability). ```ts import AbilityConstant from '@ohos.app.ability.AbilityConstant'; let context = ...; // UIAbilityContext -let wantInfo = { +let want = { deviceId: '', // An empty deviceId indicates the local device. bundleName: 'com.example.myapplication', abilityName: 'FuncAbility', - moduleName: 'module1', // moduleName is optional. - parameters: {// Custom information. + moduleName: 'func', // moduleName is optional. + parameters: { // Custom information. info: 'From the Index page of EntryAbility', }, } let options = { windowMode: AbilityConstant.WindowMode.WINDOW_MODE_FLOATING -} +}; // context is the UIAbilityContext of the initiator UIAbility. -context.startAbility(wantInfo, options).then(() => { - // ... +context.startAbility(want, options).then(() => { + console.info('Succeeded in starting ability.'); }).catch((err) => { - // ... + console.error(`Failed to start ability. Code is ${err.code}, message is ${err.message}`); }) ``` -The display effect is shown below. +The display effect is shown below. + ![](figures/start-uiability-floating-window.png) ## Starting a Specified Page of UIAbility -A UIAbility component can have multiple pages. When it is started in different scenarios, different pages can be displayed. For example, when a user jumps from a page of a UIAbility component to another UIAbility, you want to start a specified page of the target UIAbility. This section describes how to specify a startup page and start the specified page when the target UIAbility is started for the first time or when the target UIAbility is not started for the first time. +A UIAbility component can have multiple pages that each display in specific scenarios. This section describes how to specify a startup page and start the specified page when the target UIAbility is started for the first time or when the target UIAbility is not started for the first time. ### Specifying a Startup Page -When the initiator UIAbility starts another UIAbility, it usually needs to redirect to a specified page. For example, FuncAbility contains two pages: Index (corresponding to the home page) and Second (corresponding to function A page). You can configure the specified page URL in the **want** parameter by adding a custom parameter to **parameters** in **want**. For details about how to obtain the context, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability). +When the initiator UIAbility starts another UIAbility, it usually needs to redirect to a specified page of the target UIAbility. For example, with FuncAbility, which contains two pages, starting FuncAbility means to redirect to either of the pages: Index (corresponding to the home page) and Second (corresponding to feature A page). You can configure the specified page URL in the **want** parameter by adding a custom parameter to **parameters** in **want**. For details about how to obtain the context in the example, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability). ```ts let context = ...; // UIAbilityContext -let wantInfo = { +let want = { deviceId: '', // An empty deviceId indicates the local device. bundleName: 'com.example.myapplication', abilityName: 'FuncAbility', - moduleName: 'module1', // moduleName is optional. - parameters: {// Custom parameter used to pass the page information. + moduleName: 'func', // moduleName is optional. + parameters: { // Custom parameter used to pass the page information. router: 'funcA', }, } // context is the UIAbilityContext of the initiator UIAbility. -context.startAbility(wantInfo).then(() => { - // ... +context.startAbility(want).then(() => { + console.info('Succeeded in starting ability.'); }).catch((err) => { - // ... + console.error(`Failed to start ability. Code is ${err.code}, message is ${err.message}`); }) ``` @@ -431,7 +443,7 @@ export default class FuncAbility extends UIAbility { } } windowStage.loadContent(url, (err, data) => { - // ... + ... }); } } @@ -440,11 +452,11 @@ export default class FuncAbility extends UIAbility { ### Starting a Page When the Target UIAbility Is Not Started for the First Time -You start application A, and its home page is displayed. Then you return to the home screen and start application B. Now you need to start application A again from application B and have a specified page of application A displayed. An example scenario is as follows: When you open the home page of the SMS application and return to the home screen, the SMS application is in the opened state and its home page is displayed. Then you open the home page of the Contacts application, access user A's details page, and touch the SMS icon to send an SMS message to user A. The SMS application is started again and the sending page is displayed. +You start application A, and its home page is displayed. Then you return to the home screen and start application B. Now you need to start application A again from application B and access a specified page of application A. An example scenario is as follows: When you open the home page of the SMS application and return to the home screen, the SMS application is in the opened state with its home page. Then you open the home page of the Contacts application, access user A's details page, and touch the SMS icon to send an SMS message to user A. The SMS application is started again and the sending page is displayed. ![uiability_not_first_started](figures/uiability_not_first_started.png) -In summary, when a UIAbility instance of application A has been created and the main page of the UIAbility instance is displayed, you need to start the UIAbility of application A from application B and have a different page displayed. +In summary, when a UIAbility instance of application A has been created and the main page of the UIAbility instance is displayed, you need to start the UIAbility of application A from application B and access a different page. 1. In the target UIAbility, the **Index** page is loaded by default. The UIAbility instance has been created, and the **onNewWant()** callback rather than **onCreate()** and **onWindowStageCreate()** will be invoked. In the **onNewWant()** callback, parse the **want** parameter and bind it to the global variable **globalThis**. @@ -455,7 +467,7 @@ In summary, when a UIAbility instance of application A has been created and the onNewWant(want, launchParam) { // Receive the parameters passed by the initiator UIAbility. globalThis.funcAbilityWant = want; - // ... + ... } } ``` @@ -480,25 +492,25 @@ In summary, when a UIAbility instance of application A has been created and the // Page display. build() { - // ... + ... } } ``` > **NOTE** > -> When the [launch type of the target UIAbility](uiability-launch-type.md) is set to **standard**, a new instance is created each time the target UIAbility is started. In this case, the [onNewWant()](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonnewwant) callback will not be invoked. +> When the [launch type of the target UIAbility](uiability-launch-type.md) is set to **multiton**, a new instance is created each time the target UIAbility is started. In this case, the [onNewWant()](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonnewwant) callback will not be invoked. ## Using Call to Implement UIAbility Interaction (for System Applications Only) Call is an extension of the UIAbility capability. It enables the UIAbility to be invoked by and communicate with external systems. The UIAbility invoked can be either started in the foreground or created and run in the background. You can use the call to implement data sharing between two UIAbility instances (CallerAbility and CalleeAbility) through IPC. -The core API used for the call is **startAbilityByCall**, which differs from **startAbility** in the following ways: +The core API used for the call is **startAbilityByCall()**, which differs from **startAbility()** in the following ways: -- **startAbilityByCall** supports UIAbility launch in the foreground and background, whereas **startAbility** supports UIAbility launch in the foreground only. +- **startAbilityByCall()** supports UIAbility launch in the foreground and background, whereas **startAbility()** supports UIAbility launch in the foreground only. -- The CallerAbility can use the caller object returned by **startAbilityByCall** to communicate with the CalleeAbility, but **startAbility** does not provide the communication capability. +- The CallerAbility can use the caller object returned by **startAbilityByCall()** to communicate with the CalleeAbility, but **startAbility()** does not provide the communication capability. Call is usually used in the following scenarios: @@ -506,6 +518,7 @@ Call is usually used in the following scenarios: - Starting the CalleeAbility in the background + **Table 1** Terms used in the call | **Term**| Description| @@ -517,27 +530,27 @@ Call is usually used in the following scenarios: The following figure shows the call process. - Figure 1 Call process +**Figure 1** Call process - ![call](figures/call.png) +![call](figures/call.png) - The CallerAbility uses **startAbilityByCall** to obtain a caller object and uses **call()** of the caller object to send data to the CalleeAbility. -- The CalleeAbility, which holds a **Callee** object, uses **on()** of the **Callee** object to register a callback. This callback is invoked when the CalleeAbility receives data from the CallerAbility. +- The CalleeAbility, which holds a callee object, uses **on()** of the callee object to register a callback. This callback is invoked when the CalleeAbility receives data from the CallerAbility. > **NOTE** -> 1. Currently, only system applications can use the call. +> - Currently, only system applications can use the call. > -> 2. The launch type of the CalleeAbility must be **singleton**. +> - The launch type of the CalleeAbility must be **singleton**. > -> 3. Both local (intra-device) and cross-device calls are supported. The following describes how to initiate a local call. For details about how to initiate a cross-device call, see [Using Cross-Device Call](hop-multi-device-collaboration.md#using-cross-device-call). +> - Both local (intra-device) and cross-device calls are supported. The following describes how to initiate a local call. For details about how to initiate a cross-device call, see [Using Cross-Device Call](hop-multi-device-collaboration.md#using-cross-device-call). ### Available APIs The following table describes the main APIs used for the call. For details, see [AbilityContext](../reference/apis/js-apis-app-ability-uiAbility.md#caller). - **Table 2** Call APIs +**Table 2** Call APIs | API| Description| | -------- | -------- | @@ -549,7 +562,7 @@ The following table describes the main APIs used for the call. For details, see | release(): void | Releases the caller object.| | on(type: "release", callback: OnReleaseCallback): void | Callback invoked when the caller object is released.| -The implementation of using the call for UIAbility interaction involves two parts. +The implementation of using the call for UIAbility interaction involves two parts: - [Creating a CalleeAbility](#creating-a-calleeability) @@ -560,7 +573,7 @@ The implementation of using the call for UIAbility interaction involves two part For the CalleeAbility, 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 launch type of the UIAbility. +1. Configure the launch type of the CalleeAbility. For example, set the launch type of the CalleeAbility to **singleton**. For details, see [UIAbility Component Launch Type](uiability-launch-type.md). @@ -571,7 +584,6 @@ For the CalleeAbility, implement the callback to receive data and the methods to ``` 3. Define the agreed parcelable data. - The data formats sent and received by the CallerAbility and CalleeAbility must be consistent. In the following example, the data formats are number and string. @@ -588,7 +600,7 @@ For the CalleeAbility, implement the callback to receive data and the methods to marshalling(messageSequence) { messageSequence.writeInt(this.num); messageSequence.writeString(this.str); - return true + return true; } unmarshalling(messageSequence) { @@ -600,9 +612,9 @@ For the CalleeAbility, implement the callback to receive data and the methods to ``` 4. Implement **Callee.on** and **Callee.off**. - + The time to register a listener for the CalleeAbility 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 UIAbility and deregistered in **onDestroy**. After receiving parcelable data, the application processes the data and returns the data result. You need to implement processing based on service requirements. The sample code is as follows: - + ```ts const TAG: string = '[CalleeAbility]'; @@ -625,16 +637,16 @@ For the CalleeAbility, implement the callback to receive data and the methods to onCreate(want, launchParam) { try { this.callee.on(MSG_SEND_METHOD, sendMsgCallback); - } catch (error) { - console.info(`${MSG_SEND_METHOD} register failed with error ${JSON.stringify(error)}`); + } catch (err) { + console.error(`Failed to register. Code is ${err.code}, message is ${err.message}`); } } onDestroy() { try { this.callee.off(MSG_SEND_METHOD); - } catch (error) { - console.error(TAG, `${MSG_SEND_METHOD} unregister failed with error ${JSON.stringify(error)}`); + } catch (err) { + console.error(`Failed to unregister. Code is ${err.code}, message is ${err.message}`); } } } @@ -661,9 +673,9 @@ For the CalleeAbility, implement the callback to receive data and the methods to caller.on('release', (msg) => { console.info(`caller onRelease is called ${msg}`); }) - console.info('caller register OnRelease succeed'); - } catch (error) { - console.info(`caller register OnRelease failed with ${error}`); + console.info('Succeeded in registering on release.'); + } catch (err) { + console.err(`Failed to caller register on release. Code is ${err.code}, message is ${err.message}`); } } @@ -672,15 +684,15 @@ For the CalleeAbility, implement the callback to receive data and the methods to this.caller = await context.startAbilityByCall({ bundleName: 'com.samples.CallApplication', abilityName: 'CalleeAbility' - }) + }); if (this.caller === undefined) { console.info('get caller failed') - return + return; } console.info('get caller success') this.regOnRelease(this.caller) - } catch (error) { - console.info(`get caller failed with ${error}`) + } (err) { + console.err(`Failed to get caller. Code is ${err.code}, message is ${err.message}`); } } ``` diff --git a/en/application-dev/application-models/uiability-launch-type.md b/en/application-dev/application-models/uiability-launch-type.md index 6442ffc4359254bbed7d7da85ec4b753f0f3eea4..3b91469c1db08e2cbed59c7fceb4563547b54a72 100644 --- a/en/application-dev/application-models/uiability-launch-type.md +++ b/en/application-dev/application-models/uiability-launch-type.md @@ -1,12 +1,12 @@ -# UIAbility Component Launch Type +# UIAbility Launch Type -The launch type of the UIAbility component refers to the state of the UIAbility instance at startup. The system provides three launch types: +The launch type of the UIAbility component refers to the state of the UIAbility instance at startup. Three launch types are available: - [Singleton](#singleton) -- [Standard](#standard) +- [Multiton](#multiton) - [Specified](#specified) @@ -15,27 +15,27 @@ The launch type of the UIAbility component refers to the state of the UIAbility **singleton** is the default launch type. -Each time [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) is called, if a UIAbility instance of this type already exists in the application process, the instance is reused. Therefore, only one UIAbility instance of this type exists in the system, that is, displayed in **Recents**. +Each time [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) is called, if a UIAbility instance of this type already exists in the application process, the instance is reused. In other words, UIAbility of this type can have only one instance in the system, meaning that only one mission is displayed in the system application Recents. -**Figure 1** Demonstration effect in singleton mode +**Figure 1** Demonstration effect in singleton mode -![uiability-launch-type1](figures/uiability-launch-type1.png) +![uiability-launch-type1](figures/uiability-launch-type1.gif) > **NOTE** > -> Assume that the application already has a UIAbility instance created, and the launch type of the UIAbility instance is set to **singleton**. If [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) is called again to start the UIAbility instance, the original UIAbility instance is started, and no new UIAbility instance is created. In this case, the [onNewWant()](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonnewwant) callback is invoked, but the [onCreate()](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityoncreate) and [onWindowStageCreate()](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityonwindowstagecreate) callbacks are not. +> If [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) is called to start an existing UIAbility instance in singleton mode, that instance is started, and no new UIAbility instance is created. In this case, the [onNewWant()](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonnewwant) callback is invoked, but the [onCreate()](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityoncreate) and [onWindowStageCreate()](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityonwindowstagecreate) callbacks are not. -To use the singleton mode, set **launchType** in the [module.json5 configuration file](../quick-start/module-configuration-file.md) to **singleton**. +To use the singleton mode, set **launchType** in the [module.json5 file](../quick-start/module-configuration-file.md) to **singleton**. ```json { "module": { - // ... + ... "abilities": [ { "launchType": "singleton", - // ... + ... } ] } @@ -43,25 +43,25 @@ To use the singleton mode, set **launchType** in the [module.json5 configuration ``` -## Standard +## Multiton -In standard mode, each time [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) is called, a new UIAbility instance of this type is created in the application process. Multiple UIAbility instances of this type are displayed in **Recents**. +In multiton mode, each time [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) is called, a new UIAbility instance is created in the application process. Multiple missions are displayed for UIAbility of this type in Recents. -**Figure 2** Demonstration effect in standard mode +**Figure 2** Demonstration effect in multiton mode -![standard-mode](figures/standard-mode.png) +![uiability-launch-type2](figures/uiability-launch-type2.gif) -To use the standard mode, set **launchType** in the [module.json5 configuration file](../quick-start/module-configuration-file.md) to **standard**. +To use the multiton mode, set **launchType** in the [module.json5 file](../quick-start/module-configuration-file.md) to **multiton**. ```json { "module": { - // ... + ... "abilities": [ { - "launchType": "standard", - // ... + "launchType": "multiton", + ... } ] } @@ -71,87 +71,90 @@ To use the standard mode, set **launchType** in the [module.json5 configuration ## Specified -The **specified** mode is used in some special scenarios. For example, in a document application, you want a document instance to be created each time you create a document, but you want to use the same document instance when you repeatedly open an existing document. +The **specified** mode is used in some special scenarios. For example, in a document application, you may want a document instance to be created each time you create a document, and you may also want to use the same document instance when you open an existing document. -**Figure 3** Demonstration effect in specified mode +**Figure 3** Demonstration effect in specified mode -![uiability-launch-type2](figures/uiability-launch-type2.png) +![uiability-launch-type3](figures/uiability-launch-type3.gif) -For example, there are two UIAbility components: EntryAbility and SpecifiedAbility (with the launch type **specified**). You are required to start SpecifiedAbility from EntryAbility. +In the following example, there are two UIAbility components: EntryAbility and SpecifiedAbility (with the launch type **specified**). To start SpecifiedAbility from EntryAbility, proceed as follows: -1. In SpecifiedAbility, set the **launchType** field in the [module.json5 file](../quick-start/module-configuration-file.md) to **specified**. +1. In SpecifiedAbility, set **launchType** in the [module.json5 file](../quick-start/module-configuration-file.md) to **specified**. ```json { "module": { - // ... + ... "abilities": [ { "launchType": "specified", - // ... + ... } ] } } ``` -2. Create a unique string key for the instance. Each time [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) is called, the application, based on the key, identifies the UIAbility instance used to respond to the request. In EntryAbility, add a custom parameter, for example, **instanceKey**, to the **want** parameter in [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) to distinguish the UIAbility instance. +2. Create a unique string key for the SpecifiedAbility instance. Each time [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) is called, the application, based on the key, identifies the UIAbility instance used to respond to the request. In EntryAbility, add a custom parameter, for example, **instanceKey**, to the **want** parameter in [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) to distinguish the UIAbility instances. ```ts - // Configure an independent key for each UIAbility instance. + // Configure a unique key for each UIAbility instance. // For example, in the document usage scenario, use the document path as the key. function getInstance() { - // ... + ... } + let context =...; // context is the UIAbilityContext of the initiator UIAbility. let want = { - deviceId: '', // An empty deviceId indicates the local device. - bundleName: 'com.example.myapplication', - abilityName: 'SpecifiedAbility', - moduleName: 'module1', // moduleName is optional. - parameters: {// Custom information. - instanceKey: getInstance(), - }, + deviceId: '', // An empty deviceId indicates the local device. + bundleName: 'com.example.myapplication', + abilityName: 'SpecifiedAbility', + moduleName: 'specified', // moduleName is optional. + parameters: {// Custom information. + instanceKey: getInstance(), + }, } - // context is the UIAbilityContext of the initiator UIAbility. - this.context.startAbility(want).then(() => { - // ... + + context.startAbility(want).then(() => { + console.info('Succeeded in starting ability.'); }).catch((err) => { - // ... + console.error(`Failed to start ability. Code is ${err.code}, message is ${err.message}`); }) ``` -3. Before SpecifiedAbility is started, the [onAcceptWant()](../reference/apis/js-apis-app-ability-abilityStage.md#abilitystageonacceptwant) callback of the corresponding AbilityStage instance is invoked to obtain the key of the UIAbility, because the launch type of SpecifiedAbility is set to **specified**. If a UIAbility instance matching the key exists, the system starts the UIAbility instance and invokes its [onNewWant()](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonnewwant) callback. Otherwise, the system creates a new UIAbility instance and invokes its [onCreate()](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityoncreate) and [onWindowStageCreate()](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityonwindowstagecreate) callbacks. +3. Before SpecifiedAbility is started, the [onAcceptWant()](../reference/apis/js-apis-app-ability-abilityStage.md#abilitystageonacceptwant) callback of the corresponding AbilityStage instance is invoked to obtain the key of the target UIAbility. If a UIAbility instance matching the key exists, the system starts the UIAbility instance and invokes its [onNewWant()](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonnewwant) callback. Otherwise, the system creates a new UIAbility instance and invokes its [onCreate()](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityoncreate) and [onWindowStageCreate()](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityonwindowstagecreate) callbacks. - In the sample code, the [onAcceptWant()](../reference/apis/js-apis-app-ability-abilityStage.md#abilitystageonacceptwant) callback parses the **want** parameter to obtain the custom parameter **instanceKey**. The service logic returns a key string based on **instanceKey** parameter to identify the UIAbility instance. If the returned key maps to a started UIAbility instance, the system pulls the UIAbility instance back to the foreground and obtains the focus. If the returned key does not map to a started UIAbility instance, the system creates a new UIAbility instance and starts it. + In the sample code, the [onAcceptWant()](../reference/apis/js-apis-app-ability-abilityStage.md#abilitystageonacceptwant) callback uses the passed **want** parameter to obtain the custom parameter **instanceKey**. The service logic returns a key string based on the **instanceKey** parameter to identify the UIAbility instance. If the returned key maps to a started UIAbility instance, the system pulls the UIAbility instance back to the foreground and gives it the focus. If the returned key does not map to a started UIAbility instance, the system creates a new UIAbility instance and starts it. ```ts import AbilityStage from '@ohos.app.ability.AbilityStage'; export default class MyAbilityStage extends AbilityStage { - onAcceptWant(want): string { - // In the AbilityStage instance of the callee, a key value corresponding to a UIAbility instance is returned for UIAbility whose launch type is specified. - // In this example, SpecifiedAbility of module1 is returned. - if (want.abilityName === 'SpecifiedAbility') { - // The returned key string is a custom string. - return `SpecifiedAbilityInstance_${want.parameters.instanceKey}`; - } - - return ''; + onAcceptWant(want): string { + // In the AbilityStage instance of the callee, a key string corresponding to a UIAbility instance is returned for UIAbility whose launch type is specified. + // In this example, SpecifiedAbility of module1 is returned. + if (want.abilityName === 'SpecifiedAbility') { + // The returned key string is a custom string. + return `SpecifiedAbilityInstance_${want.parameters.instanceKey}`; } + + return ''; + } } ``` > **NOTE** > - > 1. Assume that the application already has a UIAbility instance created, and the launch type of the UIAbility instance is set to **specified**. If [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) is called again to start the UIAbility instance, and the [onAcceptWant()](../reference/apis/js-apis-app-ability-abilityStage.md#abilitystageonacceptwant) callback of [AbilityStage](../reference/apis/js-apis-app-ability-abilityStage.md) matches a created UIAbility instance, the original UIAbility instance is started, and no new UIAbility instance is created. In this case, the [onNewWant()](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonnewwant) callback is invoked, but the [onCreate()](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityoncreate) and [onWindowStageCreate()](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityonwindowstagecreate) callbacks are not. - > 2. AbilityStage is not automatically generated in the default project of DevEco Studio. For details about how to create an AbilityStage file, see [AbilityStage Component Container](abilitystage.md). + > - If [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) is called to start an existing UIAbility instance in specified mode, and the [onAcceptWant()](../reference/apis/js-apis-app-ability-abilityStage.md#abilitystageonacceptwant) callback of [AbilityStage](../reference/apis/js-apis-app-ability-abilityStage.md) matches that UIAbility instance, that instance is started, and no new UIAbility instance is created. In this case, the [onNewWant()](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonnewwant) callback is invoked, but the [onCreate()](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityoncreate) and [onWindowStageCreate()](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityonwindowstagecreate) callbacks are not. + > + > - AbilityStage is not automatically generated by default in the project of DevEco Studio. For details about how to create an AbilityStage file, see [AbilityStage Component Container](abilitystage.md). + - For example, in the document application, different keys are bound to different document instances. Each time a document is created, a new key (for example, file path) is passed, and a new UIAbility instance is created when UIAbility is started in AbilityStage. However, when you open an existing document, the same UIAbility instance is started again in AbilityStage. +For example, in the document application, different keys are bound to different document instances. Each time a document is created, a new key (for example, file path) is passed in, and a new UIAbility instance is created when UIAbility is started in AbilityStage. However, when an existing document is opened, the same UIAbility instance is started again in AbilityStage. - The following steps are used as an example. +The following steps are used as an example. - 1. Open file A. A UIAbility instance, for example, UIAbility instance 1, is started. - 2. Close the process of file A in **Recents**. UIAbility instance 1 is destroyed. Return to the home screen and open file A again. A new UIAbility instance is started, for example, UIAbility instance 2. - 3. Return to the home screen and open file B. A new UIAbility instance is started, for example, UIAbility instance 3. - 4. Return to the home screen and open file A again. UIAbility instance 2 is started. This is because the system automatically matches the key of the UIAbility instance and starts the UIAbility instance that has a matching key. In this example, UIAbility instance 2 has the same key as file A. Therefore, the system pulls back UIAbility instance 2 and focuses it without creating a new instance. + 1. Open file A. A UIAbility instance, UIAbility instance 1, is started. + 2. Close the process of file A in Recents. UIAbility instance 1 is destroyed. Return to the home screen and open file A again. A new UIAbility instance, UIAbility instance 2, is started. + 3. Return to the home screen and open file B. A new UIAbility instance, UIAbility instance 3, is started. + 4. Return to the home screen and open file A again. UIAbility instance 2 is started. This is because the system automatically matches the key with the UIAbility instance and starts the UIAbility instance that has a matching key. In this example, UIAbility instance 2 has the same key as file A. Therefore, the system pulls back UIAbility instance 2 and focuses it without creating a new instance.hao diff --git a/en/application-dev/application-models/uiability-lifecycle.md b/en/application-dev/application-models/uiability-lifecycle.md index 57200abb8fbfb625e2e6c8999da5ad817e2e85b4..78a49c5be6ae12ff879e12cc509e2fbc15ece2af 100644 --- a/en/application-dev/application-models/uiability-lifecycle.md +++ b/en/application-dev/application-models/uiability-lifecycle.md @@ -1,15 +1,15 @@ -# UIAbility Component Lifecycle +# UIAbility Lifecycle ## Overview -When a user opens, switches, and returns to an application, the UIAbility instances in the application transit in their different states. The UIAbility class provides a series of callbacks. Through these callbacks, you can know the state changes of the UIAbility instance, for example, being created or destroyed, or running in the foreground or background. +When a user opens or switches to and from an application, the UIAbility instances in the application transit in their different states. The UIAbility class provides a series of callbacks. Through these callbacks, you can know the state changes of the UIAbility instance. The lifecycle of UIAbility has four states: **Create**, **Foreground**, **Background**, and **Destroy**, as shown in the figure below. **Figure 1** UIAbility lifecycle states -![Ability-Life-Cycle](figures/Ability-Life-Cycle.png) +![Ability-Life-Cycle](figures/Ability-Life-Cycle.png) ## Description of Lifecycle States @@ -17,21 +17,23 @@ The lifecycle of UIAbility has four states: **Create**, **Foreground**, **Backgr ### Create -The **Create** state is triggered when the UIAbility instance is created during application loading. The system invokes the **onCreate()** callback. In this callback, you can perform application initialization operations, for example, defining variables or loading resources. +The **Create** state is triggered when the UIAbility instance is created during application loading. It corresponds to the **onCreate()** callback. In this callback, you can perform application initialization operations, for example, defining variables or loading resources. ```ts import UIAbility from '@ohos.app.ability.UIAbility'; -import window from '@ohos.window'; export default class EntryAbility extends UIAbility { - onCreate(want, launchParam) { - // Initialize the application. - } - // ... + onCreate(want, launchParam) { + // Initialize the application. + } + ... } ``` +> **NOTE** +> +> The [want](../reference/apis/js-apis-app-ability-want.md) parameter in the **onCreate()** callback is used as the carrier to transfer information between application components. For details, see [Want](want-overview.md). ### WindowStageCreate and WindowStageDestory @@ -39,7 +41,7 @@ After the UIAbility instance is created but before it enters the **Foreground** **Figure 2** WindowStageCreate and WindowStageDestory -![Ability-Life-Cycle-WindowStage](figures/Ability-Life-Cycle-WindowStage.png) +![Ability-Life-Cycle-WindowStage](figures/Ability-Life-Cycle-WindowStage.png) In the **onWindowStageCreate()** callback, use [loadContent()](../reference/apis/js-apis-window.md#loadcontent9-2) to set the page to be loaded, and call [on('windowStageEvent')](../reference/apis/js-apis-window.md#onwindowstageevent9) to subscribe to [WindowStage events](../reference/apis/js-apis-window.md#windowstageeventtype9), for example, having or losing focus, or becoming visible or invisible. @@ -48,25 +50,40 @@ import UIAbility from '@ohos.app.ability.UIAbility'; import window from '@ohos.window'; export default class EntryAbility extends UIAbility { - // ... - - onWindowStageCreate(windowStage: Window.WindowStage) { - // Subscribe to the WindowStage events (having or losing focus, or becoming visible or invisible). - try { - windowStage.on('windowStageEvent', (data) => { - console.info('Succeeded in enabling the listener for window stage event changes. Data: ' + - JSON.stringify(data)); - }); - } catch (exception) { - console.error('Failed to enable the listener for window stage event changes. Cause:' + - JSON.stringify(exception)); - }; - - // Set the UI loading. - windowStage.loadContent('pages/Index', (err, data) => { - // ... - }); + ... + + onWindowStageCreate(windowStage: window.WindowStage) { + // Subscribe to the WindowStage events (having or losing focus, or becoming visible or invisible). + try { + windowStage.on('windowStageEvent', (data) => { + let stageEventType: window.WindowStageEventType = data; + switch (stageEventType) { + case window.WindowStageEventType.SHOWN: // Switch to the foreground. + console.info('windowStage foreground.'); + break; + case window.WindowStageEventType.ACTIVE: // Gain focus. + console.info('windowStage active.'); + break; + case window.WindowStageEventType.INACTIVE: // Lose focus. + console.info('windowStage inactive.'); + break; + case window.WindowStageEventType.HIDDEN: // Switch to the background. + console.info('windowStage background.'); + break; + default: + break; + } + }); + } catch (exception) { + console.error('Failed to enable the listener for window stage event changes. Cause:' + + JSON.stringify(exception)); } + + // Set the page to be loaded. + windowStage.loadContent('pages/Index', (err, data) => { + ... + }); + } } ``` @@ -82,49 +99,54 @@ import UIAbility from '@ohos.app.ability.UIAbility'; import window from '@ohos.window'; export default class EntryAbility extends UIAbility { - // ... - - onWindowStageDestroy() { - // Release UI resources. - // Unsubscribe from the WindowStage events such as having or losing focus in the onWindowStageDestroy() callback. - try { - windowStage.off('windowStageEvent'); - } catch (exception) { - console.error('Failed to disable the listener for window stage event changes. Cause:' + - JSON.stringify(exception)); - }; - } + windowStage: window.WindowStage; + ... + + onWindowStageCreate(windowStage: window.WindowStage) { + this.windowStage = windowStage; + ... + } + + onWindowStageDestroy() { + // Release UIresources. + // Unsubscribe from the WindowStage events such as having or losing focus in the onWindowStageDestroy() callback. + try { + this.windowStage.off('windowStageEvent'); + } catch (err) { + console.error(`Failed to disable the listener for window stage event changes. Code is ${err.code}, message is ${err.message}`); + }; + } } ``` ### Foreground and Background -The **Foreground** and **Background** states are triggered when the UIAbility instance is switched to the foreground and background respectively. They correspond to the **onForeground()** and **onBackground()** callbacks. +The **Foreground** and **Background** states are triggered when the UIAbility instance is switched to the foreground and background, respectively. They correspond to the **onForeground()** and **onBackground()** callbacks. -The **onForeground()** callback is triggered before the UI of the UIAbility instance becomes visible, for example, when the UIAbility instance is switched to the foreground. In this callback, you can apply for resources required by the system or re-apply for resources that have been released in the **onBackground()** callback. +The **onForeground()** callback is triggered when the UI of the UIAbility instance is about to become visible, for example, when the UIAbility instance is about to enter the foreground. In this callback, you can apply for resources required by the system or re-apply for resources that have been released in the **onBackground()** callback. -The **onBackground()** callback is triggered after the UI of the UIAbility component is completely invisible, for example, when the UIAbility instance is switched to the background. In this callback, you can release useless resources or perform time-consuming operations such as saving the status. +The **onBackground()** callback is triggered when the UI of the UIAbility instance is about to become invisible, for example, when the UIAbility instance is about to enter the background. In this callback, you can release unused resources or perform time-consuming operations such as saving the status. -For example, an application needs to use positioning, and the application has requested the positioning permission from the user. Before the UI is displayed, you can enable positioning in the **onForeground()** callback to obtain the location information. +For example, there is an application that requires location access and has obtained the location permission from the user. Before the UI is displayed, you can enable location in the **onForeground()** callback to obtain the location information. -When the application is switched to the background, you can disable positioning in the **onBackground()** callback to reduce system resource consumption. +When the application is switched to the background, you can disable location in the **onBackground()** callback to reduce system resource consumption. ```ts import UIAbility from '@ohos.app.ability.UIAbility'; export default class EntryAbility extends UIAbility { - // ... + ... - onForeground() { - // Apply for the resources required by the system or re-apply for the resources released in onBackground(). - } + onForeground() { + // Apply for the resources required by the system or re-apply for the resources released in onBackground(). + } - onBackground() { - // Release useless resources when the UI is invisible, or perform time-consuming operations in this callback, - // for example, saving the status. - } + onBackground() { + // Release unused resources when the UI is invisible, or perform time-consuming operations in this callback, + // for example, saving the status. + } } ``` @@ -133,17 +155,16 @@ export default class EntryAbility extends UIAbility { The **Destroy** state is triggered when the UIAbility instance is destroyed. You can perform operations such as releasing system resources and saving data in the **onDestroy()** callback. -The UIAbility instance is destroyed when **terminateSelf()** is called or the user closes the instance in **Recents**. +The UIAbility instance is destroyed when **terminateSelf()** is called or the user closes the instance in the system application Recents. ```ts import UIAbility from '@ohos.app.ability.UIAbility'; -import window from '@ohos.window'; export default class EntryAbility extends UIAbility { - // ... + ... - onDestroy() { - // Release system resources and save data. - } + onDestroy() { + // Release system resources and save data. + } } ``` diff --git a/en/application-dev/application-models/uiability-overview.md b/en/application-dev/application-models/uiability-overview.md index cd059b9555bfd80c02c9bce66f4c50cd58fff568..6c94e42dd688793620f0acfd9c8079f693b6651e 100644 --- a/en/application-dev/application-models/uiability-overview.md +++ b/en/application-dev/application-models/uiability-overview.md @@ -1,49 +1,49 @@ -# UIAbility Component Overview +# UIAbility Overview ## Overview -UIAbility is a type of application component that provides the UI for user interaction. +UIAbility is a type of application component that provides the UI for user interactions. The following design philosophy is behind UIAbility: 1. Native support for [cross-device migration](hop-cross-device-migration.md) and [multi-device collaboration](hop-multi-device-collaboration.md) at the application component level -2. Support for multiple device types and window forms +2. Support for multiple device types and window modes -For details, see [Interpretation of the Application Model](application-model-description.md). +> **NOTE** +> +> For details, see [Interpretation of the Application Model](application-model-description.md). -The UIAbility division principles and suggestions are as follows: +UIAbility is the basic unit of scheduling in OpenHarmony and provides a window for applications to draw the UI. An application can contain one or more UIAbility components. For example, for a payment application, you can use separate UIAbility components to carry the entry and payment functionalities. -UIAbility is the basic unit scheduled by the system and provides a window for applications to draw UIs. An application can contain one or more UIAbility components. For example, for a payment application, you can use two UIAbility components to carry the entry and payment functionalities. - -Each UIAbility component instance is displayed as a mission in Recents. +Each UIAbility component instance is displayed as a mission in the system application Recents. You can develop a single UIAbility or multiple UIAbilities for your application based on service requirements. -- If you want only one mission to be displayed in Recents, use one UIAbility and multiple pages. +- If you want your application to be displayed as one mission in Recents, use one UIAbility and multiple pages. -- If you want multiple missions to be displayed in Recents or multiple windows to be opened simultaneously, use multiple UIAbilities. +- If you want your application to be displayed as multiple missions in Recents or multiple windows to be opened simultaneously, use multiple UIAbilities. -## Privacy Statement Configuration +## Declaration Configuration -To enable an application to properly use a UIAbility component, declare the UIAbility name, entry, and tags under [abilities](../quick-start/module-configuration-file.md#abilities) in the [module.json5 configuration file](../quick-start/module-configuration-file.md). +To enable an application to properly use a UIAbility component, declare the UIAbility name, entry, and label under [abilities](../quick-start/module-configuration-file.md#abilities) in the [module.json5 file](../quick-start/module-configuration-file.md). ```json { "module": { - // ... + ... "abilities": [ { "name": "EntryAbility", // Name of the UIAbility component. - "srcEntrance": "./ets/entryability/EntryAbility.ts", // Code path of the UIAbility component. + "srcEntry": "./ets/entryability/EntryAbility.ts", // Code path of the UIAbility component. "description": "$string:EntryAbility_desc", // Description of the UIAbility component. "icon": "$media:icon", // Icon of the UIAbility component. "label": "$string:EntryAbility_label", // Label of the UIAbility component. "startWindowIcon": "$media:icon", // Index of the icon resource file. "startWindowBackground": "$color:start_window_background", // Index of the background color resource file. - // ... + ... } ] } diff --git a/en/application-dev/application-models/uiability-usage.md b/en/application-dev/application-models/uiability-usage.md index fa8badc6d48c7e550922cb60a15d02eab9cc80b6..d734312a01f527741371461791958059976619aa 100644 --- a/en/application-dev/application-models/uiability-usage.md +++ b/en/application-dev/application-models/uiability-usage.md @@ -1,4 +1,4 @@ -# UIAbility Component Usage +# UIAbility Usage When using the UIAbility component, you must specify a startup page and obtain the context, [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md). @@ -6,7 +6,7 @@ When using the UIAbility component, you must specify a startup page and obtain t ## Specifying the Startup Page of UIAbility -If no startup page is specified, a white screen occurs after the application is started. You can use **loadContent()** of [WindowStage](../reference/apis/js-apis-window.md#windowstage9) to set the startup page in the **onWindowStageCreate()** callback of the UIAbility instance. +You can use **loadContent()** of [WindowStage](../reference/apis/js-apis-window.md#windowstage9) to set the startup page in the **onWindowStageCreate()** callback of the UIAbility instance. If no startup page is specified, a white screen occurs after the application is started. ```ts @@ -14,20 +14,20 @@ import UIAbility from '@ohos.app.ability.UIAbility'; import window from '@ohos.window'; export default class EntryAbility extends UIAbility { - onWindowStageCreate(windowStage: window.WindowStage) { - // Main window is created. Set a main page for this ability. - windowStage.loadContent('pages/Index', (err, data) => { - // ... - }); - } + onWindowStageCreate(windowStage: window.WindowStage) { + // Main window is created. Set a main page for this ability. + windowStage.loadContent('pages/Index', (err, data) => { + ... + }); + } - // ... + ... } ``` > **NOTE** > -> When you create UIAbility in DevEco Studio, the UIAbility instance loads the **Index** page by default. Therefore, you only need to replace the **Index** page path with the required startup page path. +> When you create UIAbility in DevEco Studio, the UIAbility instance loads the **Index** page as its startup page. Therefore, you only need to replace the **Index** page path with the required startup page path. ## Obtaining the Context of UIAbility @@ -40,15 +40,14 @@ The UIAbility class has its own context, which is an instance of the [UIAbilityC import UIAbility from '@ohos.app.ability.UIAbility'; export default class EntryAbility extends UIAbility { - onCreate(want, launchParam) { - // Obtain the context of the UIAbility instance. - let context = this.context; - - // ... - } + onCreate(want, launchParam) { + // Obtain the context of the UIAbility instance. + let context = this.context; + ... + } } ``` - + - Import the context module and define the **context** variable in the component. ```ts @@ -68,7 +67,7 @@ The UIAbility class has its own context, which is an instance of the [UIAbilityC // Page display. build() { - // ... + ... } } ``` @@ -93,7 +92,7 @@ The UIAbility class has its own context, which is an instance of the [UIAbilityC // Page display. build() { - // ... + ... } } ``` diff --git a/en/application-dev/application-models/want-overview.md b/en/application-dev/application-models/want-overview.md index 1ce771daf195a09250a5fde05e0ce5a7acc60355..cf5cac43999a5efbe59659252b6b3db325cacd8a 100644 --- a/en/application-dev/application-models/want-overview.md +++ b/en/application-dev/application-models/want-overview.md @@ -6,43 +6,46 @@ [Want](../reference/apis/js-apis-app-ability-want.md) is an object that transfers information between application components. It is often used as a parameter of [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability). For example, when UIAbilityA needs to start UIAbilityB and transfer some data to UIAbilityB, it can use the **want** parameter in **startAbility()** to transfer the data. **Figure 1** Want usage + ![usage-of-want](figures/usage-of-want.png) ## Types of Want -- **Explicit Want**: If **abilityName** and **bundleName** are specified when starting an ability, explicit Want is used. - Explicit Want is usually used to start a known target ability in the same application. The target ability is started by specifying **bundleName** of the application where the target ability is located and **abilityName** in the **Want** object. When there is an explicit object to process the request, explicit Want is a simple and effective way to start the target ability. - +- **Explicit Want**: If **abilityName** and **bundleName** are specified in the **want** parameter when starting an an application component, explicit Want is used. + + Explicit Want is usually used to start a known target application component in the same application. The target application component is started by specifying **bundleName** of the application where the target application component is located and **abilityName** in the **Want** object. When there is an explicit object to process the request, explicit Want is a simple and effective way to start the target application component. + ```ts let wantInfo = { - deviceId: '', // An empty deviceId indicates the local device. - bundleName: 'com.example.myapplication', - abilityName: 'FuncAbility', + deviceId: '', // An empty deviceId indicates the local device. + bundleName: 'com.example.myapplication', + abilityName: 'FuncAbility', } ``` - -- **Implicit Want**: If **abilityName** is not specified when starting the ability, implicit Want is used. + +- **Implicit Want**: If **abilityName** is not specified in the **want** parameter when starting the an application component, implicit Want is used. + Implicit Want can be used when the object used to process the request is unclear and the current application wants to use a capability (defined by the [skills tag](../quick-start/module-configuration-file.md#skills)) provided by another application. The system matches all applications that declare to support the capability. For example, for a link open request, the system matches all applications that support the request and provides the available ones for users to select. - + ```ts let wantInfo = { - // Uncomment the line below if you want to implicitly query data only in the specific bundle. - // bundleName: 'com.example.myapplication', - action: 'ohos.want.action.search', - // entities can be omitted. - entities: [ 'entity.system.browsable' ], - uri: 'https://www.test.com:8080/query/student', - type: 'text/plain', + // Uncomment the line below if you want to implicitly query data only in the specific bundle. + // bundleName: 'com.example.myapplication', + action: 'ohos.want.action.search', + // entities can be omitted. + entities: [ 'entity.system.browsable' ], + uri: 'https://www.test.com:8080/query/student', + type: 'text/plain', }; ``` - + > **NOTE** - > - Depending on the ability matching result, the following cases may be possible when you attempt to use implicit Want to start the ability. - > - No ability is matched. The startup fails. - > - An ability that meets the conditions is matched. That ability is started. - > - Multiple abilities that meet the conditions are matched. A dialog box is displayed for users to select one of them. + > - Depending on the application component matching result, the following cases may be possible when you attempt to use implicit Want to start the application component. + > - No application component is matched. The startup fails. + > - An application component that meets the conditions is matched. That application component is started. + > - Multiple application components that meet the conditions are matched. A dialog box is displayed for users to select one of them. > > - If the **want** parameter passed does not contain **abilityName** or **bundleName**, the ServiceExtensionAbility components of all applications cannot be started through implicit Want. > diff --git a/en/application-dev/application-models/widget-development-fa.md b/en/application-dev/application-models/widget-development-fa.md index 17f9ee7234865b5d01e2a5f68e52cf7928739db7..5405cf30050269a97039bc2e9d898da7b5ee1dc8 100644 --- a/en/application-dev/application-models/widget-development-fa.md +++ b/en/application-dev/application-models/widget-development-fa.md @@ -20,7 +20,7 @@ Before you get started, it would be helpful if you have a basic understanding of Figure 1 shows the working principles of the widget framework. -**Figure 1** Widget framework working principles in the FA model +**Figure 1** Widget framework working principles in the FA model ![form-extension](figures/form-extension.png) The widget host consists of the following modules: @@ -115,55 +115,55 @@ To create a widget in the FA model, implement the widget lifecycle callbacks. Ge import formBindingData from '@ohos.app.form.formBindingData'; import formInfo from '@ohos.app.form.formInfo'; import formProvider from '@ohos.app.form.formProvider'; - import dataStorage from '@ohos.data.storage'; + import dataPreferences from '@ohos.data.preferences'; ``` 2. Implement the widget lifecycle callbacks in **form.ts**. ```ts export default { - onCreate(want) { - console.info('FormAbility onCreate'); - // Called when the widget is created. The widget provider should return the widget data binding class. - let obj = { - "title": "titleOnCreate", - "detail": "detailOnCreate" - }; - let formData = formBindingData.createFormBindingData(obj); - return formData; - }, - onCastToNormal(formId) { - // Called when the widget host converts the temporary widget into a normal one. The widget provider should do something to respond to the conversion. - console.info('FormAbility onCastToNormal'); - }, - onUpdate(formId) { - // Override this method to support scheduled updates, periodic updates, or updates requested by the widget host. - console.info('FormAbility onUpdate'); - let obj = { - "title": "titleOnUpdate", - "detail": "detailOnUpdate" - }; - let formData = formBindingData.createFormBindingData(obj); - formProvider.updateForm(formId, formData).catch((error) => { - console.info('FormAbility updateForm, error:' + JSON.stringify(error)); - }); - }, - onVisibilityChange(newStatus) { - // Called when the widget host initiates an event about visibility changes. The widget provider should do something to respond to the notification. This callback takes effect only for system applications. - console.info('FormAbility onVisibilityChange'); - }, - onEvent(formId, message) { - // If the widget supports event triggering, override this method and implement the trigger. - console.info('FormAbility onEvent'); - }, - onDestroy(formId) { - // Delete widget data. - console.info('FormAbility onDestroy'); - }, - onAcquireFormState(want) { - console.info('FormAbility onAcquireFormState'); - return formInfo.FormState.READY; - }, + onCreate(want) { + console.info('FormAbility onCreate'); + // Called when the widget is created. The widget provider should return the widget data binding class. + let obj = { + "title": "titleOnCreate", + "detail": "detailOnCreate" + }; + let formData = formBindingData.createFormBindingData(obj); + return formData; + }, + onCastToNormal(formId) { + // Called when the widget host converts the temporary widget into a normal one. The widget provider should do something to respond to the conversion. + console.info('FormAbility onCastToNormal'); + }, + onUpdate(formId) { + // Override this method to support scheduled updates, periodic updates, or updates requested by the widget host. + console.info('FormAbility onUpdate'); + let obj = { + "title": "titleOnUpdate", + "detail": "detailOnUpdate" + }; + let formData = formBindingData.createFormBindingData(obj); + formProvider.updateForm(formId, formData).catch((error) => { + console.info('FormAbility updateForm, error:' + JSON.stringify(error)); + }); + }, + onVisibilityChange(newStatus) { + // Called when the widget host initiates an event about visibility changes. The widget provider should do something to respond to the notification. This callback takes effect only for system applications. + console.info('FormAbility onVisibilityChange'); + }, + onEvent(formId, message) { + // If the widget supports event triggering, override this method and implement the trigger. + console.info('FormAbility onEvent'); + }, + onDestroy(formId) { + // Delete widget data. + console.info('FormAbility onDestroy'); + }, + onAcquireFormState(want) { + console.info('FormAbility onAcquireFormState'); + return formInfo.FormState.READY; + }, } ``` @@ -188,15 +188,15 @@ The widget configuration file is named **config.json**. Find the **config.json** ```json - "js": [{ - "name": "widget", - "pages": ["pages/index/index"], - "window": { - "designWidth": 720, - "autoDesignWidth": true - }, - "type": "form" - }] + "js": [{ + "name": "widget", + "pages": ["pages/index/index"], + "window": { + "designWidth": 720, + "autoDesignWidth": true + }, + "type": "form" + }] ``` - The **abilities** module in the **config.json** file corresponds to **FormAbility** of the widget. The internal structure is described as follows: @@ -265,7 +265,7 @@ async function storeFormInfo(formId: string, formName: string, tempFlag: boolean "updateCount": 0 }; try { - const storage = await dataStorage.getStorage(DATA_STORAGE_PATH); + const storage = await dataPreferences.getPreferences(this.context, DATA_STORAGE_PATH); // Put the widget information. await storage.put(formId, JSON.stringify(formInfo)); console.info(`storeFormInfo, put form info successfully, formId: ${formId}`); @@ -275,7 +275,7 @@ async function storeFormInfo(formId: string, formName: string, tempFlag: boolean } } -// ... +... onCreate(want) { console.info('FormAbility onCreate'); @@ -293,7 +293,7 @@ async function storeFormInfo(formId: string, formName: string, tempFlag: boolean let formData = formBindingData.createFormBindingData(obj); return formData; } -// ... +... ``` You should override **onDestroy** to implement widget data deletion. @@ -303,7 +303,7 @@ You should override **onDestroy** to implement widget data deletion. const DATA_STORAGE_PATH = "/data/storage/el2/base/haps/form_store"; async function deleteFormInfo(formId: string) { try { - const storage = await dataStorage.getStorage(DATA_STORAGE_PATH); + const storage = await dataPreferences.getPreferences(this.context, DATA_STORAGE_PATH); // Delete the widget information. await storage.delete(formId); console.info(`deleteFormInfo, del form info successfully, formId: ${formId}`); @@ -313,17 +313,17 @@ async function deleteFormInfo(formId: string) { } } -// ... +... onDestroy(formId) { console.info('FormAbility onDestroy'); // Delete the persistent widget instance data. // Implement this API based on project requirements. deleteFormInfo(formId); } -// ... +... ``` -For details about how to implement persistent data storage, see [Lightweight Data Store Development](../database/database-preference-guidelines.md). +For details about how to implement persistent data storage, see [Application Data Persistence Overview](../database/app-data-persistence-overview.md). The **Want** object passed in by the widget host to the widget provider contains a flag that specifies whether the requested widget is normal or temporary. @@ -364,7 +364,7 @@ You can use the web-like paradigm (HML+CSS+JSON) to develop JS widget pages. Thi > **NOTE** > -> Only the JavaScript-based web-like development paradigm is supported when developing the widget UI. +> In the FA model, only the JavaScript-based web-like development paradigm is supported when developing the widget UI. - HML: uses web-like paradigm components to describe the widget page information. @@ -543,4 +543,3 @@ The following is an example: } } ``` - diff --git a/en/application-dev/application-models/widget-switch.md b/en/application-dev/application-models/widget-switch.md index 8d9823385a8a05f71c742327dc966054427a6718..bec5f69afa3b058471075847c41dc131da32c977 100644 --- a/en/application-dev/application-models/widget-switch.md +++ b/en/application-dev/application-models/widget-switch.md @@ -11,9 +11,9 @@ Widget switching involves the following parts: | Configuration Item | FA Model | Stage Model | | ---------------- | ------------------------------------------- | ------------------------------------------------------------ | | Configuration item location | **formAbility** and **forms** are in the **config.json** file.| **extensionAbilities** (configuration for **formExtensionAbility**) is in the **module.json5** file in the level-1 directory, and **forms** (configuration for **forms** contained in **formExtensionAbility**) is in the **form_config.json** file in the level-2 directory.| -| Widget code path | Specified by **srcPath**, without the file name. | Specified by **srcEntrance**, with the file name. | +| Widget code path | Specified by **srcPath**, without the file name. | Specified by **srcEntry**, with the file name. | | Programming language | **srcLanguage** can be set to **js** or **ets**. | This configuration item is unavailable. Only ets is supported. | -| Whether to enable widgets | formsEnabled | This configuration item is unavailable. The setting of **type** set to **form** means that the widgets are enabled. | +| Whether to enable widgets | formsEnabled | This configuration item is unavailable. When **type** is set to **form**, widgets are enabled. | | Ability type | type: service | type: form | | Level-2 directory configuration tag| This configuration item is unavailable. | **metadata**, which consists of **name**, **value**, and **resource**, where **resource** points to the location of the **form_config.json** file in the level-2 directory.| @@ -32,7 +32,7 @@ Figure 2 Widget configuration differences | Item| FA Model| Stage Model| | -------- | -------- | -------- | -| Entry file| **form.ts** in the directory pointed to by **srcPath**| File pointed to by **srcEntrance**| +| Entry file| **form.ts** in the directory pointed to by **srcPath**| File pointed to by **srcEntry**| | Lifecycle| export default| import FormExtension from '\@ohos.app.form.FormExtensionAbility';
export default class FormAbility extends FormExtension| diff --git a/en/application-dev/application-models/window-switch.md b/en/application-dev/application-models/window-switch.md index 379f0282b1e50e856d0010a9087622e2e1363d89..50983da9dba7f2a044e5e045abf4874a4e920961 100644 --- a/en/application-dev/application-models/window-switch.md +++ b/en/application-dev/application-models/window-switch.md @@ -1,8 +1,7 @@ # window Switching -| API in the FA Model| Corresponding d.ts File in the Stage Model| Corresponding API in the Stage Model| + | API in the FA Model| Corresponding .d.ts File in the Stage Model| Corresponding API in the Stage Model| | -------- | -------- | -------- | | [create(id: string, type: WindowType, callback: AsyncCallback<Window>): void;](../reference/apis/js-apis-window.md#windowcreatedeprecated)
[create(id: string, type: WindowType): Promise<Window>;](../reference/apis/js-apis-window.md#windowcreatedeprecated-1) | \@ohos.window.d.ts | [createSubWindow(name: string, callback: AsyncCallback<Window>): void;](../reference/apis/js-apis-window.md#createsubwindow9)
[createSubWindow(name: string): Promise;](../reference/apis/js-apis-window.md#createsubwindow9-1)
An application developed on the FA model uses **window.create(id, WindowType.TYPE_APP)** to create a subwindow, whereas an application developed on the stage model uses **WindowStage.CreateSubWindow()** to create a subwindow.| | [getTopWindow(callback: AsyncCallback<Window>): void;](../reference/apis/js-apis-window.md#windowgettopwindowdeprecated)
[getTopWindow(): Promise<Window>;](../reference/apis/js-apis-window.md#windowgettopwindowdeprecated-1) | \@ohos.window.d.ts | [getLastWindow(ctx: BaseContext, callback: AsyncCallback<Window>): void;](../reference/apis/js-apis-window.md#windowgetlastwindow9)
[getLastWindow(ctx: BaseContext): Promise<Window>;](../reference/apis/js-apis-window.md#windowgetlastwindow9-1) | - diff --git a/en/application-dev/application-models/windowextensionability.md b/en/application-dev/application-models/windowextensionability.md index 069897ad02435070ac470f5d2d3d528c76b417e8..541f7e14bd14bfac4f79cf04fdef234c0eb1b83b 100644 --- a/en/application-dev/application-models/windowextensionability.md +++ b/en/application-dev/application-models/windowextensionability.md @@ -1,4 +1,5 @@ -# WindowExtensionAbility +# WindowExtensionAbility (for System Applications Only) + [WindowExtensionAbility](../reference/apis/js-apis-application-windowExtensionAbility.md) is a type of ExtensionAbility component that allows a system application to be embedded in and displayed over another application. @@ -6,23 +7,23 @@ The WindowExtensionAbility component must be used together with the [AbilityComponent](../reference/arkui-ts/ts-container-ability-component.md) to process services of the started application. WindowExtensionAbility is run in connection mode. A system application must use the AbilityComponent to start the WindowExtensionAbility component. Each ExtensionAbility has its own context. For WindowExtensionAbility, -the context is [WindowExtensionContext](../reference/apis/js-apis-inner-application-windowExtensionContext.md). +the context is [WindowExtensionContext](../reference/apis/js-apis-inner-application-windowExtensionContext.md). > **NOTE** > -> **WindowExtensionAbility** is a system API. To embed a third-party application in another application and display it over the application, switch to the full SDK by following the instructions provided in [Guide to Switching to Full SDK](../../application-dev/quick-start/full-sdk-switch-guide.md). +> **WindowExtensionAbility** is a system API. To use it, switch to the full SDK by following the instructions provided in [Guide to Switching to Full SDK](../faqs/full-sdk-switch-guide.md). > -## Setting an Embedded Ability (for System Applications Only) +## Setting an Embedded UIAbility The **WindowExtensionAbility** class provides **onConnect()**, **onDisconnect()**, and **onWindowReady()** lifecycle callbacks, which can be overridden. -- The **onWindowReady()** callback is invoked when a window is created for the ability. +- The **onWindowReady()** callback is invoked when a window is created for the UIAbility. -- The **onConnect()** callback is invoked when the AbilityComponent corresponding to the window connects to the ability. +- The **onConnect()** callback is invoked when the AbilityComponent corresponding to the window connects to the UIAbility. -- The **onDisconnect()** callback is invoked when the AbilityComponent disconnects from the ability. +- The **onDisconnect()** callback is invoked when the AbilityComponent disconnects from the UIAbility. **How to Develop** @@ -42,7 +43,7 @@ To implement an embedded application, manually create a WindowExtensionAbility i onWindowReady(window) { window.loadContent('WindowExtAbility/pages/index1').then(() => { window.getProperties().then((pro) => { - console.log("WindowExtension " + JSON.stringify(pro)); + console.info("WindowExtension " + JSON.stringify(pro)); }) window.show(); }) @@ -58,7 +59,7 @@ To implement an embedded application, manually create a WindowExtensionAbility i } ``` -4. Register the WindowExtensionAbility in the [module.json5 file](../quick-start/module-configuration-file.md) corresponding to the **Module** project. Set **type** to **"window"** and **srcEntrance** to the code path of the ExtensionAbility component. +4. Register the WindowExtensionAbility in the [module.json5 file](../quick-start/module-configuration-file.md) corresponding to the **Module** project. Set **type** to **"window"** and **srcEntry** to the code path of the ExtensionAbility component. ```json { @@ -66,11 +67,11 @@ To implement an embedded application, manually create a WindowExtensionAbility i "extensionAbilities": [ { "name": "WindowExtAbility", - "srcEntrance": "./ets/WindowExtAbility/WindowExtAbility.ts", + "srcEntry": "./ets/WindowExtAbility/WindowExtAbility.ts", "icon": "$media:icon", "description": "WindowExtension", "type": "window", - "visible": true, + "exported": true, } ], } @@ -78,7 +79,7 @@ To implement an embedded application, manually create a WindowExtensionAbility i ``` -## Starting an Embedded Ability (for System Applications Only) +## Starting an Embedded UIAbility System applications can load the created WindowExtensionAbility through the AbilityComponent. @@ -90,23 +91,24 @@ System applications can load the created WindowExtensionAbility through the Abil 3. Set the width and height. The sample code is as follows: -```ts -@Entry -@Component -struct Index { - @State message: string = 'Hello World' - - build() { - Row() { - Column() { - AbilityComponent({ abilityName: "WindowExtAbility", bundleName: "com.example.WindowExtAbility"}) - .width(500) - .height(500) - } - .width('100%') - } - .height('100%') - .backgroundColor(0x64BB5c) - } -} -``` + ```ts + @Entry + @Component + struct Index { + @State message: string = 'Hello World' + + build() { + Row() { + Column() { + AbilityComponent({ abilityName: "WindowExtAbility", bundleName: "com.example.WindowExtAbility"}) + .width(500) + .height(500) + } + .width('100%') + } + .height('100%') + .backgroundColor(0x64BB5c) + } + } + ``` + diff --git a/en/application-dev/application-test/arkxtest-guidelines.md b/en/application-dev/application-test/arkxtest-guidelines.md index 64edba5e9f4d4ebbd6b7bfbff44c4b01c8a67d4d..00c733c7c37676511ccab4d53dc9992b01456ff8 100644 --- a/en/application-dev/application-test/arkxtest-guidelines.md +++ b/en/application-dev/application-test/arkxtest-guidelines.md @@ -3,7 +3,7 @@ ## Overview -To accelerate test automation of OpenHarmony, arkXtest — an automated test framework that supports both the JavaScript (JS) and TypeScript (TS) programming languages — is provided. +To accelerate test automation of OpenHarmony, arkXtest — an automated unit and UI test framework that supports both the JavaScript (JS) and TypeScript (TS) programming languages — is provided. In this document you will learn about the key functions of arkXtest and how to use it to perform unit testing on application or system APIs and to write UI automated test scripts. @@ -13,7 +13,7 @@ In this document you will learn about the key functions of arkXtest and how to u arkXtest is part of the OpenHarmony toolkit and provides basic capabilities of writing and running OpenHarmony automated test scripts. In terms of test script writing, arkXtest offers a wide range of APIs, including basic process APIs, assertion APIs, and APIs related to UI operations. In terms of test script running, arkXtest offers such features as identifying, scheduling, and executing test scripts, as well as summarizing test script execution results. -### Principles +### Implementation arkXtest is divided into two parts: unit test framework and UI test framework. @@ -27,16 +27,16 @@ arkXtest is divided into two parts: unit test framework and UI test framework. ![](figures/TestFlow.PNG) -- UI Testing Framework +- UI Test Framework - The UI test framework provides [UiTest APIs](../reference/apis/js-apis-uitest.md) for you to call in different test scenarios. The test scripts are executed on top of the unit test framework mentioned above. + The UI test framework provides [UiTest APIs](../reference/apis/js-apis-uitest.md) for you to call in different test scenarios. The UI test scripts are executed on top of the aformentioned unit test framework. The figure below shows the main functions of the UI test framework. ![](figures/Uitest.PNG) -### Limitations and Constraints +### Constraints - The features of the UI test framework are available only in OpenHarmony 3.1 and later versions. - The feature availability of the unit test framework varies by version. For details about the mappings between the features and versions, see [arkXtest](https://gitee.com/openharmony/testfwk_arkxtest/blob/master/README_en.md). @@ -46,9 +46,9 @@ arkXtest is divided into two parts: unit test framework and UI test framework. ### Environment Requirements -Software for writing test scripts: DevEco Studio 3.0 or later +Software: DevEco Studio 3.0 or later -Hardware for running test scripts: PC connected to an OpenHarmony device, such as the RK3568 development board +Hardware: PC connected to an OpenHarmony device, such as the RK3568 development board ### Setting Up the Environment @@ -57,7 +57,7 @@ Hardware for running test scripts: PC connected to an OpenHarmony device, such a ## Creating a Test Script -1. Open DevEco Studio and create a project, where the **ohos** directory is where the test script is located. +1. Open DevEco Studio and create a project, in which the **ohos** directory is where the test script is located. 2. Open the .ets file of the module to be tested in the project directory. Move the cursor to any position in the code, and then right-click and choose **Show Context Actions** > **Create Ohos Test** or press **Alt+Enter** and choose **Create Ohos Test** to create a test class. ## Writing a Unit Test Script @@ -95,7 +95,7 @@ export default function abilityTest() { The unit test script must contain the following basic elements: -1. Import of the dependency package so that the dependent test APIs can be used. +1. Import of the dependencies so that the dependent test APIs can be used. 2. Test code, mainly about the related logic, such as API invoking. @@ -105,7 +105,7 @@ The unit test script must contain the following basic elements: You write a UI test script based on the unit test framework, adding the invoking of APIs provided by the UI test framework to implement the corresponding test logic. -In this example, the UI test script is written based on the preceding unit test script. First, add the dependency package, as shown below: +In this example, the UI test script is written based on the preceding unit test script. First, import the dependency, as shown below: ```js import {Driver,ON,Component,MatchPattern} from '@ohos.uitest' @@ -158,11 +158,9 @@ export default function abilityTest() { You can run a test script in DevEco Studio in any of the following modes: -1. Test package level: All test cases in the test package are executed. - -2. Test suite level: All test cases defined in the **describe** method are executed. - -3. Test method level: The specified **it** method, that is, a single test case, is executed. +- Test package level: All test cases in the test package are executed. +- Test suite level: All test cases defined in the **describe** method are executed. +- Test method level: The specified **it** method, that is, a single test case, is executed. ![](figures/Execute.PNG) @@ -176,7 +174,7 @@ After the test is complete, you can view the test result in DevEco Studio, as sh To run a test script in the CLI, execute **aa** commands with different execution control keywords. -Parameters in aa test commands +The table below lists the keywords in **aa** test commands. | Keyword | Abbreviation| Description | Example | | ------------- | ------------ | -------------------------------------- | ---------------------------------- | @@ -187,18 +185,18 @@ Parameters in aa test commands The framework supports multiple test case execution modes, which are triggered by the key-value pair following the **-s** keyword. The table below lists the available keys and values. -| Key | Description | Value | Parameter | +| Key | Description | Value | Example | | ------------ | ----------------------------------------------------------------------------- | ------------------------------------------------------------ | ----------------------------------------- | -| unittest | OpenHarmonyTestRunner object used for test case execution. | **OpenHarmonyTestRunner** or custom runner name. | - s unittest OpenHarmonyTestRunner | +| unittest | **OpenHarmonyTestRunner** object used for test case execution. | **OpenHarmonyTestRunner** or custom runner name. | - s unittest OpenHarmonyTestRunner | | class | Test suite or test case to be executed. | {describeName}#{itName}, {describeName} | -s class attributeTest#testAttributeIt | | notClass | Test suite or test case that does not need to be executed. | {describeName}#{itName}, {describeName} | -s notClass attributeTest#testAttributeIt | | itName | Test case to be executed. | {itName} | -s itName testAttributeIt | | timeout | Timeout interval for executing a test case. | Positive integer (unit: ms). If no value is set, the default value 5000 is used. | -s timeout 15000 | -| breakOnError | Whether to enable break-on-error mode. When this mode is enabled, the test execution process exits if a test assertion error or any other error occurs.| **true**/**false** (default value) | -s breakOnError true | +| breakOnError | Whether to enable break-on-error mode. When this mode is enabled, the test execution process exits if a test assertion failure or error occurs.| **true**/**false** (default value) | -s breakOnError true | | random | Whether to execute test cases in random sequence.| **true**/**false** (default value) | -s random true | | testType | Type of the test case to be executed. | function, performance, power, reliability, security, global, compatibility, user, standard, safety, resilience| -s testType function | | level | Level of the test case to be executed. | 0, 1, 2, 3, 4 | -s level 0 | -| size | Size of the test case to be executed. | small, medium, large | -s size small | +| size | Size of the test case to be executed. | small, medium, large | -s size small | stress | Number of times that the test case is executed. | Positive integer | -s stress 1000 | **Running Commands** @@ -306,7 +304,7 @@ OHOS_REPORT_STATUS: consuming=4 | OHOS_REPORT_STATUS: stream | Error information of the current test case.| | OHOS_REPORT_STATUS: test| Name of the current test case.| | OHOS_REPORT_STATUS_CODE | Execution result of the current test case. The options are as follows:
**0**: pass
**1**: error
**2**: fail| -| OHOS_REPORT_STATUS: consuming | Execution duration of the current test case.| +| OHOS_REPORT_STATUS: consuming | Time spent in executing the current test case.| - After the commands are executed, the log information similar to the following is displayed: @@ -324,7 +322,7 @@ OHOS_REPORT_STATUS: taskconsuming=16029 | Failure | Number of failed test cases.| | Error | Number of test cases whose execution encounters errors. | | Pass | Number of passed test cases.| -| Ignore | Number of test cases not executed.| +| Ignore | Number of test cases not yet executed.| | taskconsuming| Total time spent in executing the current test case.| > When an error occurs in break-on-error mode, check the **Ignore** and interrupt information. @@ -341,11 +339,11 @@ The logs added to the test case are displayed after the test case execution, rat **Possible Causes** -More than one asynchronous interface is called in the test case.
In principle, logs in the test case are printed before the test case execution is complete. +More than one asynchronous API is called in the test case.
In principle, logs in the test case are printed before the test case execution is complete. **Solution** -If more than one asynchronous interface is called, you are advised to encapsulate the interface invoking into the promise mode +If more than one asynchronous API is called, you are advised to encapsulate the API invoking into the promise mode. #### Error "fail to start ability" is reported during test case execution @@ -373,7 +371,7 @@ After the test case execution is complete, the console displays the error messag 2. The time taken for API invocation is longer than the timeout interval set for test case execution. -3. Test assertion fails, and a failure exception is thrown. As a result, the test case execution does not end until the timeout expires. +3. Test assertion fails, and a failure exception is thrown. As a result, the test case execution does not end until it times out. **Solution** @@ -388,11 +386,11 @@ After the test case execution is complete, the console displays the error messag **Problem** -The UI test case fails to be executed. The HiLog file contains the error message "Get windows failed/GetRootByWindow failed". +The UI test case fails to be executed. The HiLog file contains the error message "Get windows failed/GetRootByWindow failed." **Possible Causes** -The ArkUI feature is disabled. As a result, the control tree information on the test page is not generated. +The ArkUI feature is disabled. As a result, the component tree information is not generated on the test page. **Solution** @@ -410,13 +408,13 @@ The UI test case fails to be executed. The HiLog file contains the error message **Possible Causes** -1. In the test case, the **await** operator is not added to the asynchronous interface provided by the UI test framework. +1. In the test case, the **await** operator is not added to the asynchronous API provided by the UI test framework. 2. The UI test case is executed in multiple processes. As a result, multiple UI test processes are started. The framework does not support multi-process invoking. **Solution** -1. Check the case implementation and add the **await** operator to the asynchronous interface invoking. +1. Check the case implementation and add the **await** operator to the asynchronous API. 2. Do not execute UI test cases in multiple processes. @@ -424,11 +422,11 @@ The UI test case fails to be executed. The HiLog file contains the error message **Problem** -The UI test case fails to be executed. The HiLog file contains the error message "does not exist on current UI! Check if the UI has changed after you got the widget object". +The UI test case fails to be executed. The HiLog file contains the error message "does not exist on current UI! Check if the UI has changed after you got the widget object." **Possible Causes** -After the target component is found in the code of the test case, the device UI changes. As a result, the found component is lost and the emulation operation cannot be performed. +After the target component is found in the code of the test case, the device UI changes, resulting in loss of the found component and inability to perform emulation. **Solution** diff --git a/en/application-dev/connectivity/Readme-EN.md b/en/application-dev/connectivity/Readme-EN.md index 7176cb8fb438cbe8beec5b36bdd290c0b01bbd1f..c09ca21b6d0814bd1cd2cecb95b0d2896fada8c4 100755 --- a/en/application-dev/connectivity/Readme-EN.md +++ b/en/application-dev/connectivity/Readme-EN.md @@ -5,10 +5,10 @@ - [HTTP Data Request](http-request.md) - [WebSocket Connection](websocket-connection.md) - [Socket Connection](socket-connection.md) - - [Network Policy Management](net-policy-management.md) - [Network Sharing](net-sharing.md) - [Ethernet Connection](net-ethernet.md) - [Network Connection Management](net-connection-manager.md) + - [mDNS Management](net-mdns.md) - IPC & RPC - [IPC & RPC Overview](ipc-rpc-overview.md) - [IPC & RPC Development](ipc-rpc-development-guideline.md) diff --git a/en/application-dev/connectivity/http-request.md b/en/application-dev/connectivity/http-request.md index 223e40a97ecddcfa6b1613106d94ba942ee22006..1bb784cf96fb1d74dcbafed54498435f505814b6 100644 --- a/en/application-dev/connectivity/http-request.md +++ b/en/application-dev/connectivity/http-request.md @@ -78,6 +78,8 @@ httpRequest.request( // data.header carries the HTTP response header. Parse the content based on service requirements. console.info('header:' + JSON.stringify(data.header)); console.info('cookies:' + JSON.stringify(data.cookies)); // 8+ + // Call the destroy() method to release resources after HttpRequest is complete. + httpRequest.destroy(); } else { console.info('error:' + JSON.stringify(err)); // Unsubscribe from HTTP Response Header events. @@ -158,5 +160,11 @@ httpRequest.request2( httpRequest.destroy(); } ); +``` + +## Samples + +The following sample is provided to help you better understand how to develop the HTTP data request feature: -``` \ No newline at end of file +- [`Http`: Data Request (ArkTS) (API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Connectivity/Http) +- [HTTP Communication (ArkTS) (API9)](https://gitee.com/openharmony/codelabs/tree/master/NetworkManagement/SmartChatEtsOH) diff --git a/en/application-dev/connectivity/ipc-rpc-overview.md b/en/application-dev/connectivity/ipc-rpc-overview.md index 29fdec791c9a6b96d2ae2138b47a9b8dc48c050b..0ca829403e00a833f787b4f4de5b5997dbd4afe7 100755 --- a/en/application-dev/connectivity/ipc-rpc-overview.md +++ b/en/application-dev/connectivity/ipc-rpc-overview.md @@ -3,42 +3,25 @@ ## Basic Concepts -The inter-process communication (IPC) and remote procedure call (RPC) mechanisms are used to implement cross-process communication. The difference between them lies in that IPC uses the Binder driver to implement cross-process communication within a device, whereas RPC uses the DSoftBus driver to implement cross-process communication across devices. +Inter-process communication (IPC) and remote procedure call (RPC) are used to implement cross-process communication. IPC uses the Binder driver to implement cross-process communication within a device, whereas RPC uses the DSoftBus driver to implement cross-process communication across devices. Cross-process communication is required because each process has its own independent resources and memory space and one process is not allowed to access the resources and memory space of other processes. -The reason why cross-process communication is needed is that each process has its own independent resources and memory space and one process is not allowed to access the resources and memory space of other processes. IPC and RPC usually use the client-server model, where the client (service requester, that is, the process that requests a service) obtains the proxy of the server (service provider, that is, the process that provides the service) and uses the proxy to read and write data to implement data communication across processes. More specifically, the client constructs a proxy object of the server. The proxy object has the same functions as the server. To access a certain API of the server, you only need to access the corresponding API in the proxy object. The proxy object sends the request to the server, and the server processes the received request and returns the processing result to the proxy object through the driver. Then, the proxy object forwards the processing result to the client. The server registers system abilities (SAs) with the system ability manager (SAMgr), which manages the SAs and provides APIs for clients. To communicate with a specific SA, the client must obtain the proxy of the SA from SAMgr. +> **NOTE** +> The applications in the stage model cannot use IPC or RPC directly, and must use the following capabilities to implement related service scenarios: +>- [Background services](../application-models/background-services.md): use IPC to implement service invocation across processes. +>- [Multi-device collaboration](../application-models/hop-multi-device-collaboration.md): uses RPC to call remote interfaces and transfer data. -In the following sections, proxy represents the service requester, and stub represents the service provider. -![IPC&RPC communication mechanisms](figures/IPC_RPC_communication.PNG) +## Implementation Principles +IPC and RPC usually use the client-server model, where the client (service requester, that is, the process that requests a service) obtains the proxy of the server (service provider, that is, the process that provides the service) and uses the proxy to read and write data to implement data communication across processes. More specifically, the client constructs a proxy object of the server. The proxy object has the same functions as the server. To access a certain API of the server, you only need to access the corresponding API in the proxy object. The proxy object sends the request to the server, and the server processes the received request and returns the processing result to the proxy object through the driver. Then, the proxy object forwards the processing result to the client. The server registers system abilities (SAs) with the system ability manager (SAMgr), which manages the SAs and provides APIs for clients. To communicate with a specific SA, the client must obtain the proxy of the SA from SAMgr. In the following sections, proxy represents the service requester, and stub represents the service provider. -## Constraints - -- During cross-process communication within a single device, the maximum amount of data to be transmitted is about 1 MB. If the amount of data to be transmitted exceeds this limit, use the [anonymous shared memory](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-rpc.md#ashmem8). -- Subscription to death notifications of anonymous stub objects (not registered with SAMgr) is prohibited in RPC. -- During cross-process communication across processes, a proxy object cannot be passed back to the device that hosts the stub object pointed by the proxy object. That is, the proxy object pointing to the stub object of the remote device cannot be passed across processes twice on the local device. - -## **Recommendations** - -First, compile an API class and define message codes in the API class for both communication parties to identify operations. Unimplemented APIs are allowed in the API class because it must be inherited by both communication parties and its inheritance classes cannot be abstract classes. When inheriting the API class, both communication parties must implement the unimplemented APIs, so as to make sure that the inheritance classes are not abstract classes. - -Then, implement the API class specific to the stub, and override the **AsObject** and **OnRemoteRequest** APIs. In addition, compile the proxy to implement the APIs in the API class and override the **AsObject** API. You can also encapsulate an additional API for calling **SendRequest** to send data to the peer. - -After the preceding operations are done, register a system ability (SA) with SAMgr. Note that the registration should be completed in the process that hosts the stub. Then, obtain the proxy from SAMgr as needed to implement cross-process communication with the stub. +![IPC & RPC communication mechanisms] (figures/IPC_RPC_communication.PNG) -Related steps are as follows: -- Implementing the API class: Inherit **IRemoteBroker**, define message codes, and declare APIs that are not implemented in the API class. - -- Implementing the service provider (stub): Inherit **IRemoteStub** or **RemoteObject**, and override the **AsObject** and **OnRemoteRequest** APIs. - -- Implementing the service requester (proxy): Inherit **IRemoteProxy** or **RemoteProxy**, override the **AsObject** API, and encapsulate the required API to call **SendRequest**. - -- Registering the SA: Apply for a unique ID for the SA, and register the SA with SAMgr. - -- Obtaining the SA: Obtain the proxy based on the SA ID and device ID, and use the proxy to communicate with the remote end. +## Constraints +- A maximum of 1 MB data can be transferred in cross-process communication on a single device. If the amount of data to be transmitted is larger than 1 MB, use [anonymous shared memory](../reference/apis/js-apis-rpc.md#ashmem8). -## Related Modules +- Subscription to death notifications of anonymous stub objects (not registered with SAMgr) is prohibited in RPC. -[Distributed Ability Manager Service Framework](https://gitee.com/openharmony/ability_dmsfwk) +- During cross-process communication across processes, a proxy object cannot be passed back to the device that hosts the stub object pointed by the proxy object. That is, the proxy object pointing to the stub object of the remote device cannot be passed across processes twice on the local device. diff --git a/en/application-dev/connectivity/net-connection-manager.md b/en/application-dev/connectivity/net-connection-manager.md index 69ce20a372c60c2bf0443db2697c5a65352bf34c..c443c93759caddbc5203b65022426882c0bb960b 100644 --- a/en/application-dev/connectivity/net-connection-manager.md +++ b/en/application-dev/connectivity/net-connection-manager.md @@ -39,7 +39,7 @@ For the complete list of APIs and example code, see [Network Connection Manageme | ---- | ---- | ---- | | ohos.net.connection | function getDefaultNet(callback: AsyncCallback\): void; |Creates a **NetHandle** object that contains the **netId** of the default network. This API uses an asynchronous callback to return the result.| | ohos.net.connection | function getGlobalHttpProxy10+(callback: AsyncCallback\): void;| Obtains the global HTTP proxy for the network. This API uses an asynchronous callback to return the result.| -| ohos.net.connection | function setGlobalHttpProxy10+(httpProxy: HttpProxy, callback: AsyncCallback): void;| Sets the global HTTP proxy for the network. This API uses an asynchronous callback to return the result.| +| ohos.net.connection | function setGlobalHttpProxy10+(httpProxy: HttpProxy, callback: AsyncCallback\): void;| Sets the global HTTP proxy for the network. This API uses an asynchronous callback to return the result.| | ohos.net.connection | function getAppNet9+(callback: AsyncCallback\): void;| Obtains a **NetHandle** object that contains the **netId** of the network bound to the application. This API uses an asynchronous callback to return the result.| | ohos.net.connection | function setAppNet9+(netHandle: NetHandle, callback: AsyncCallback\): void;| Binds an application to the specified network. The application can access the external network only through this network. This API uses an asynchronous callback to return the result.| | ohos.net.connection | function getDefaultNetSync9+(): NetHandle; |Obtains the default active data network in synchronous mode. You can use **getNetCapabilities** to obtain information such as the network type and capabilities.| @@ -47,7 +47,7 @@ For the complete list of APIs and example code, see [Network Connection Manageme | ohos.net.connection | function getAllNets(callback: AsyncCallback\>): void;| Obtains the list of **NetHandle** objects of the connected network. This API uses an asynchronous callback to return the result.| | ohos.net.connection | function getConnectionProperties(netHandle: NetHandle, callback: AsyncCallback\): void; |Obtains link information of the default network. This API uses an asynchronous callback to return the result.| | ohos.net.connection | function getNetCapabilities(netHandle: NetHandle, callback: AsyncCallback\): void; |Obtains the capability set of the default network. This API uses an asynchronous callback to return the result.| -| ohos.net.connection | function isDefaultNetMetered9+(callback: AsyncCallback): void; |Checks whether the data traffic usage on the current network is metered. This API uses an asynchronous callback to return the result.| +| ohos.net.connection | function isDefaultNetMetered9+(callback: AsyncCallback\): void; |Checks whether the data traffic usage on the current network is metered. This API uses an asynchronous callback to return the result.| | ohos.net.connection | function reportNetConnected(netHandle: NetHandle, callback: AsyncCallback\): void;| Reports a **netAavailable** event to NetManager. If this API is called, the application considers that its network status (ohos.net.connection.NetCap.NET_CAPABILITY_VAILDATED) is inconsistent with that of NetManager. This API uses an asynchronous callback to return the result.| | ohos.net.connection | function reportNetDisconnected(netHandle: NetHandle, callback: AsyncCallback\): void;| Reports a **netAavailable** event to NetManager. If this API is called, the application considers that its network status (ohos.net.connection.NetCap.NET_CAPABILITY_VAILDATED) is inconsistent with that of NetManager. This API uses an asynchronous callback to return the result.| | ohos.net.connection | function getAddressesByName(host: string, callback: AsyncCallback\>): void; |Obtains all IP addresses of the specified network by resolving the domain name. This API uses an asynchronous callback to return the result.| @@ -81,7 +81,7 @@ For the complete list of APIs and example code, see [Network Connection Manageme 6. Call **conn.unregister()** to unsubscribe from the network status changes if required. ```js - // Import the connection namespace. +// Import the connection namespace. import connection from '@ohos.net.connection' let netCap = { @@ -128,7 +128,7 @@ conn.unregister((err, data) => { 2. Call **getAllNets** to obtain the list of all connected networks. ```js - // Import the connection namespace. +// Import the connection namespace. import connection from '@ohos.net.connection' // Obtain the list of all connected networks. @@ -154,7 +154,7 @@ connection.getAllNets((err, data) => { 4. Call **getConnectionProperties** to obtain the connection information of the data network specified by **NetHandle**. ```js - // Import the connection namespace. +// Import the connection namespace. import connection from '@ohos.net.connection' // Call getDefaultNet to obtain the default data network specified by **NetHandle**. diff --git a/en/application-dev/connectivity/net-ethernet.md b/en/application-dev/connectivity/net-ethernet.md index f1891594166c9ecf3688b93d78cdece890796d35..18f20a7fd7e1a4c9516386c543c9521522df5f66 100644 --- a/en/application-dev/connectivity/net-ethernet.md +++ b/en/application-dev/connectivity/net-ethernet.md @@ -44,7 +44,7 @@ For the complete list of APIs and example code, see [Ethernet Connection](../ref 5. Call **getIfaceConfig** in user mode to obtain the static network attributes of the **eth0** port. By default, an unconfigured Ethernet network uses the DHCP mode, in which the Ethernet network obtains the automatically assigned network attributes. ```js - // Import the ethernet namespace from @ohos.net.ethernet. +// Import the ethernet namespace from @ohos.net.ethernet. import ethernet from '@ohos.net.ethernet' // Call getAllActiveIfaces to obtain the list of all active network ports. @@ -96,7 +96,7 @@ ethernet.getIfaceConfig("eth0", (error, data) => { 6. Call **getIfaceConfig** in user mode to obtain the static network attributes of the **eth0** port. ```js - // Import the ethernet namespace from @ohos.net.ethernet. +// Import the ethernet namespace from @ohos.net.ethernet. import ethernet from '@ohos.net.ethernet' // Call getAllActiveIfaces to obtain the list of all active network ports. @@ -158,13 +158,13 @@ ethernet.getIfaceConfig("eth0", (error, data) => { 4. Call the **off()** method to unsubscribe from **interfaceStateChange** events. ```js - // Import the ethernet namespace from @ohos.net.ethernet. +// Import the ethernet namespace from @ohos.net.ethernet. import ethernet from '@ohos.net.ethernet' // Subscribe to interfaceStateChange events. -ethernet.on('interfaceStateChange', ((data) => { +ethernet.on('interfaceStateChange', (data) => { console.log(JSON.stringify(data)); -})); +}); // Unsubscribe from interfaceStateChange events. ethernet.off('interfaceStateChange'); diff --git a/en/application-dev/connectivity/net-mdns.md b/en/application-dev/connectivity/net-mdns.md new file mode 100644 index 0000000000000000000000000000000000000000..16aa29609d0826388b244a7daebbcb1f849ed27e --- /dev/null +++ b/en/application-dev/connectivity/net-mdns.md @@ -0,0 +1,156 @@ +# MDNS Management + +## Introduction + +Multicast DNS (mDNS) provides functions such as adding, removing, discovering, and resolving local services on a LAN. +- Local service: a service provider on a LAN, for example, a printer or scanner. + +Typical MDNS management scenarios include: + +- Managing local services on a LAN, such as adding, removing, and resolving local services. +- Discovering local services and listening to the status changes of local services of the specified type through the **DiscoveryService** object. + +> **NOTE** +> To maximize the application running efficiency, most API calls are called asynchronously in callback or promise mode. The following code examples use the callback mode. For details about the APIs, see [mDNS Management](../reference/apis/js-apis-net-mdns.md). + +The following describes the development procedure specific to each application scenario. + +## Available APIs + +For the complete list of APIs and example code, see [mDNS Management](../reference/apis/js-apis-net-mdns.md). + +| Type| API| Description| +| ---- | ---- | ---- | +| ohos.net.mdns | addLocalService(context: Context, serviceInfo: LocalServiceInfo, callback: AsyncCallback\): void | Adds an mDNS service. This API uses an asynchronous callback to return the result.| +| ohos.net.mdns | removeLocalService(context: Context, serviceInfo: LocalServiceInfo, callback: AsyncCallback\): void | Removes an mDNS service. This API uses an asynchronous callback to return the result.| +| ohos.net.mdns | createDiscoveryService(context: Context, serviceType: string): DiscoveryService | Creates a **DiscoveryService** object, which is used to discover mDNS services of the specified type.| +| ohos.net.mdns | resolveLocalService(context: Context, serviceInfo: LocalServiceInfo, callback: AsyncCallback\): void | Resolves an mDNS service. This API uses an asynchronous callback to return the result.| +| ohos.net.mdns.DiscoveryService | startSearchingMDNS(): void | Searches for mDNS services on the LAN.| +| ohos.net.mdns.DiscoveryService | stopSearchingMDNS(): void | Stops searching for mDNS services on the LAN.| +| ohos.net.mdns.DiscoveryService | on(type: 'discoveryStart', callback: Callback<{serviceInfo: LocalServiceInfo, errorCode?: MdnsError}>): void | Enables listening for **discoveryStart** events.| +| ohos.net.mdns.DiscoveryService | on(type: 'discoveryStop', callback: Callback<{serviceInfo: LocalServiceInfo, errorCode?: MdnsError}>): void | Enables listening for **discoveryStop** events.| +| ohos.net.mdns.DiscoveryService | on(type: 'serviceFound', callback: Callback\): void | Enables listening for **serviceFound** events.| +| ohos.net.mdns.DiscoveryService | on(type: 'serviceLost', callback: Callback\): void | Enables listening for **serviceLost** events.| + +## Managing Local Services + +1. Connect the device to the Wi-Fi network. +2. Import the **mdns** namespace from **@ohos.net.mdns**. +3. Call **addLocalService** to add a local service. +4. (Optional) Call **resolveLocalService** to resolve the local service for the IP address of the local network. +5. Call **removeLocalService** to remove the local service. + +```js +// Import the mdns namespace from @ohos.net.mdns. +import mdns from '@ohos.net.mdns' + +// 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 UIAbility from '@ohos.app.ability.UIAbility'; +class EntryAbility extends UIAbility { + onWindowStageCreate(windowStage){ + globalThis.context = this.context; + } +} +let context = globalThis.context; + +// Create a LocalService object. +let localServiceInfo = { + serviceType: "_print._tcp", + serviceName: "servicename", + port: 5555, + host: { + address: "10.14.**.***", + }, + serviceAttribute: [{ + key: "111", + value: [1] + }] +} + +// Call addLocalService to add a local service. +mdns.addLocalService(context, localServiceInfo, function (error, data) { + console.log(JSON.stringify(error)); + console.log(JSON.stringify(data)); +}); + +// (Optional) Call resolveLocalService to resolve the local service. +mdns.resolveLocalService(context, localServiceInfo, function (error, data) { + console.log(JSON.stringify(error)); + console.log(JSON.stringify(data)); +}); + +// Call removeLocalService to remove the local service. +mdns.removeLocalService(context, localServiceInfo, function (error, data) { + console.log(JSON.stringify(error)); + console.log(JSON.stringify(data)); +}); +``` + +## Discovering Local Services + +1. Connect the device to the Wi-Fi network. +2. Import the **mdns** namespace from **@ohos.net.mdns**. +3. Create a **DiscoveryService** object, which is used to discover mDNS services of the specified type. +4. Subscribe to mDNS service discovery status changes. +5. Enable discovery of mDNS services on the LAN. +6. Stop searching for mDNS services on the LAN. + +```js +// Import the mdns namespace from @ohos.net.mdns. +import mdns from '@ohos.net.mdns' + +// 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 UIAbility from '@ohos.app.ability.UIAbility'; +class EntryAbility extends UIAbility { + onWindowStageCreate(windowStage){ + globalThis.context = this.context; + } +} +let context = globalThis.context; + +// Create a LocalService object. +let localServiceInfo = { + serviceType: "_print._tcp", + serviceName: "servicename", + port: 5555, + host: { + address: "10.14.**.***", + }, + serviceAttribute: [{ + key: "111", + value: [1] + }] +} + +// Create a DiscoveryService object, which is used to discover mDNS services of the specified type. +let serviceType = "_print._tcp"; +let discoveryService = mdns.createDiscoveryService(context, serviceType); + +// Subscribe to mDNS service discovery status changes. +discoveryService.on('discoveryStart', (data) => { + console.log(JSON.stringify(data)); +}); +discoveryService.on('discoveryStop', (data) => { + console.log(JSON.stringify(data)); +}); +discoveryService.on('serviceFound', (data) => { + console.log(JSON.stringify(data)); +}); +discoveryService.on('serviceLost', (data) => { + console.log(JSON.stringify(data)); +}); + +// Enable discovery of mDNS services on the LAN. +discoveryService.startSearchingMDNS(); + +// Stop searching for mDNS services on the LAN. +discoveryService.stopSearchingMDNS(); +``` diff --git a/en/application-dev/connectivity/net-mgmt-overview.md b/en/application-dev/connectivity/net-mgmt-overview.md index 0ad30c35cc9b4d5e90b2c8fe90cac7ca2e413a57..f03d7668edc9fc27ef22c4ef4d69b186f7b4c3d9 100644 --- a/en/application-dev/connectivity/net-mgmt-overview.md +++ b/en/application-dev/connectivity/net-mgmt-overview.md @@ -2,13 +2,13 @@ Network management functions include: -- [HTTP data request](http-request.md): Initiates a data request through HTTP. -- [WebSocket connection](websocket-connection.md): Establishes a bidirectional connection between the server and client through WebSocket. -- [Socket connection](socket-connection.md): Transmits data through Socket. -- [Network policy management](net-policy-management.md): Restricts network capabilities by setting network policies, including cellular network policy, sleep/power-saving mode policy, and background network policy, and resets network policies as needed. -- [Network sharing](net-sharing.md): Shares a device's Internet connection with other connected devices by means of Wi-Fi hotspot, Bluetooth, and USB sharing, and queries the network sharing state and shared mobile data volume. -- [Ethernet connection](net-ethernet.md): Provides wired network capabilities, which allow you to set the IP address, subnet mask, gateway, and Domain Name System (DNS) server of a wired network. -- [Network connection management](net-connection-manager.md): Provides basic network management capabilities, including management of Wi-Fi/cellular/Ethernet connection priorities, network quality evaluation, subscription to network connection status changes, query of network connection information, and DNS resolution. +- [HTTP data request](http-request.md): initiates a data request through HTTP. +- [WebSocket connection](websocket-connection.md): establishes a bidirectional connection between the server and client through WebSocket. +- [Socket connection](socket-connection.md): transmits data through Socket. +- [Network sharing](net-sharing.md): shares a device's Internet connection with other connected devices by means of Wi-Fi hotspot, Bluetooth, and USB sharing, and queries the network sharing state and shared mobile data volume. +- [Ethernet connection](net-ethernet.md): provides wired network capabilities, which allow you to set the IP address, subnet mask, gateway, and Domain Name System (DNS) server of a wired network. +- [Network connection management](net-connection-manager.md): provides basic network management capabilities, including management of Wi-Fi/cellular/Ethernet connection priorities, network quality evaluation, subscription to network connection status changes, query of network connection information, and DNS resolution. +- [mDNS management](net-mdns.md): provides Multicast DNS (mDNS) management capabilities, such as adding, removing, discovering, and resolving local services on a LAN. ## Constraints diff --git a/en/application-dev/connectivity/net-policy-management.md b/en/application-dev/connectivity/net-policy-management.md deleted file mode 100644 index 6450bd671e565fdffafb7eeed499e123893a45a3..0000000000000000000000000000000000000000 --- a/en/application-dev/connectivity/net-policy-management.md +++ /dev/null @@ -1,402 +0,0 @@ -# Network Policy Management - -## Introduction - -The Network Policy Management module allows you to restrict network capabilities by setting network policies, including cellular network policy, sleep/power-saving mode policy, and background network policy, and to reset network policies as needed. - -> **NOTE** -> To maximize the application running efficiency, most API calls are called asynchronously in callback or promise mode. The following code examples use the callback mode. For details about the APIs, see [sms API Reference](../reference/apis/js-apis-net-policy.md). - -## Basic Concepts - -- Sleep mode: A mode in which the system shuts down some idle components and peripherals to enter the low-power mode and restricts some applications from accessing the network. -- Power-saving mode: A mode in which the system disables certain functions and features to save power. When this mode is enabled, the system performance deteriorates and some applications are restricted from accessing the network. -- Traffic-saving mode: A mode in which the system restricts background applications that use the metering network. It is equivalent to the background network policy. -- Cellular network: A mobile communication network. -- Metering network: A mobile network with preconfigured traffic quota, WLAN network, or Ethernet network. - -## **Constraints** - -- Programming language: C++ and JS -- System: Linux kernel -- The initial APIs of this module are supported since API version 9. Newly added APIs will be marked with a superscript to indicate their earliest API version. - -## When to Use - -Typical application scenarios of network policy management are as follows: - -- Managing the metering network policy: Set the metering network quota and obtain the configured metering network policy. -- Managing network access for an application in the background: Set and obtain the status of the background network restriction switch, and check whether the application indicated by the specified UID can access the network in the background. -- Managing the metering network access policy: Set and obtain the policy for the application indicated by the specified UID to access the metering network, and obtain the UIDs of the applications for which the policy is configured. -- Restoring network policies -- Checking whether an application indicated by the specified UID can access a metering or non-metering network -- Adding a UID to or removing a UID from the sleep mode allowlist, and obtaining the sleep mode allowlist -- Adding a UID to or removing a UID from the power-saving mode allowlist, and obtaining the power-saving mode allowlist -- Updating the network notification policy - -The following describes the development procedure specific to each application scenario. - -## Available APIs - -For the complete list of APIs and example code, see [Network Policy Management](../reference/apis/js-apis-net-policy.md). - -| Type| API| Description| -| ---- | ---- | ---- | -| ohos.net.policy | function setBackgroundPolicy(isAllowed: boolean, callback: AsyncCallback\): void |Sets a background network policy. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function isBackgroundAllowed(callback: AsyncCallback\): void; |Obtains the background network policy. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function setPolicyByUid(uid: number, policy: NetUidPolicy, callback: AsyncCallback\): void; |Sets an application-specific network policy by **uid**. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function getPolicyByUid(uid: number, callback: AsyncCallback\): void;| Obtains an application-specific network policy by **uid**. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function getUidsByPolicy(policy: NetUidPolicy, callback: AsyncCallback\>): void; | Obtains the UID array of applications configured with a certain application-specific network policy. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function getNetQuotaPolicies(callback: AsyncCallback\>): void; |Obtains the network quota policies. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function setNetQuotaPolicies(quotaPolicies: Array\, callback: AsyncCallback\): void; |Sets an array of network quota policies. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function restoreAllPolicies(iccid: string, callback: AsyncCallback\): void; | Restores all the policies (cellular network, background network, firewall, and application-specific network policies) for the given SIM card. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function isUidNetAllowed(uid: number, isMetered: boolean, callback: AsyncCallback\): void; | Checks whether an application is allowed to access metering or non-metering networks. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function isUidNetAllowed(uid: number, iface: string, callback: AsyncCallback\): void; | Checks whether an application is allowed to access the given network. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function setDeviceIdleAllowList(uid: number, isAllowed: boolean, callback: AsyncCallback\): void; | Sets whether to add an application to the device idle allowlist. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function getDeviceIdleAllowList(callback: AsyncCallback\>): void; | Obtains the UID array of applications that are on the device idle allowlist. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function getBackgroundPolicyByUid(uid: number, callback: AsyncCallback\): void; | Obtains the background network policies configured for the given application. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function resetPolicies(iccid: string, callback: AsyncCallback\): void; | Restores all the policies (cellular network, background network, firewall, and application-specific network policies) for the given SIM card. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function updateRemindPolicy(netType: NetBearType, iccid: string, remindType: RemindType, callback: AsyncCallback\): void; | Updates a reminder policy. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function setPowerSaveAllowList(uid: number, isAllowed: boolean, callback: AsyncCallback\): void; | Sets whether to add an application to the power-saving allowlist. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function getPowerSaveAllowList(callback: AsyncCallback\>): void; | Obtains the UID array of applications that are on the power-saving allowlist. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function on(type: "netUidPolicyChange", callback: Callback\<{ uid: number, policy: NetUidPolicy }>): void; | Subscribes to policy changes. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function off(type: "netUidPolicyChange", callback: Callback\<{ uid: number, policy: NetUidPolicy }>): void; | Unsubscribes from policy changes. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function on(type: "netUidRuleChange", callback: Callback\<{ uid: number, rule: NetUidRule }>): void; | Subscribes to rule changes. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function off(type: "netUidRuleChange", callback: Callback\<{ uid: number, rule: NetUidRule }>): void; | Unsubscribes from rule changes. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function on(type: "netMeteredIfacesChange", callback: Callback\>): void; | Subscribes to metered **iface** changes. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function off(type: "netMeteredIfacesChange", callback: Callback\>): void; | Unsubscribes from metered **iface** changes. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function on(type: "netQuotaPolicyChange", callback: Callback\>): void; | Subscribes to network quota policy changes. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function off(type: "netQuotaPolicyChange", callback: Callback\>): void; | Unsubscribes from network quota policy changes. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function on(type: "netBackgroundPolicyChange", callback: Callback\): void; | Subscribes to background network policy changes. This API uses an asynchronous callback to return the result.| -| ohos.net.policy | function off(type: "netBackgroundPolicyChange", callback: Callback\): void; | Unsubscribes from background network policy changes. This API uses an asynchronous callback to return the result.| - -## Managing the Metering Network Policy - -1. Import the **policy** namespace from **@ohos.net.policy.d.ts**. - -2. Call **setNetQuotaPolicies** to configure the metering network policy. - -3. Call **getNetQuotaPolicies** to obtain the configured metering network policy. - -```js - // Import the policy namespace. - import policy from '@ohos.net.policy'; - - addNetQuotaPolicy(){ - let param = { - // For details about the value of netType, see [NetBearType](../reference/apis/js-apis-net-connection.md#netbeartype). - netType:Number.parseInt(this.netType), - - // Integrated circuit card identifier (ICCID) of the SIM card on the metering cellular network. It is not available for an Ethernet or Wi-Fi network. - iccid:this.iccid, - - // Used together with ICCID on the metering cellular network. It is used independently on an Ethernet or Wi-Fi network. - ident:this.ident, - - // Metering start time, for example, M1, D1, and Y1. - periodDuration:this.periodDuration, - - // Set the traffic threshold for generating an alarm to an integer greater than 0. - warningBytes:Number.parseInt(this.warningBytes), - - // Set the traffic quota to an integer greater than 0. - limitBytes:Number.parseInt(this.limitBytes), - - // Specify whether the network is a metering network. The value true means a metering network and false means a non-metering network. - metered:Boolean(Number.parseInt(this.metered)),https://gitee.com/openharmony/docs/pulls/14404 - // For details about the action triggered after the traffic limit is reached, see [LimitAction](../reference/apis/js-apis-net-policy.md#limitaction). - limitAction:Number.parseInt(this.limitAction) - }; - this.netQuotaPolicyList.push(param); - }, - - // Subscribe to metered iface changes. - policy.on('netMeteredIfacesChange', (data) => { - this.log('on netMeteredIfacesChange: ' + JSON.stringify(data)); - }); - - // Subscribe to metering network policy changes. - policy.on('netQuotaPolicyChange', (data) => { - this.log('on netQuotaPolicyChange: ' + JSON.stringify(data)); - }); - - // Call setNetQuotaPolicies to configure the metering network policy. - setNetQuotaPolicies(){ - this.dialogType = DialogType.HIDE; - policy.setNetQuotaPolicies(this.netQuotaPolicyList, (err, data) => { - console.log(JSON.stringify(err)); - console.log(JSON.stringify(data)); - }); - }, - - // Call getNetQuotaPolicies to obtain the configured metering network policy. - getNetQuotaPolicies(){ - policy.getNetQuotaPolicies((err, data) => { - this.callBack(err, data); - if(data){ - this.netQuotaPolicyList = data; - } - }); - }, - - // Unsubscribe from metered iface changes. - policy.off('netMeteredIfacesChange', (data) => { - this.log('off netMeteredIfacesChange: ' + JSON.stringify(data)); - }); - - // Unsubscribe from metering network policy changes. - policy.off('netQuotaPolicyChange', (data) => { - this.log('off netQuotaPolicyChange: ' + JSON.stringify(data)); - }); -``` - -## Managing Network Access for an Application in the Background - -### How to Develop - -1. Import the **policy** namespace from **@ohos.net.policy.d.ts**. - -2. Call **setBackgroundAllowed** to enable or disable the background network restriction switch. - -3. Call **isBackgroundAllowed** to check whether the background network restriction switch is enabled or disabled. - -4. Call **getBackgroundPolicyByUid** to check whether the application indicated b the specified UID can access the network in the background. - -```js - // Import the policy namespace. - import policy from '@ohos.net.policy' - - // Subscribe to background network policy changes. - policy.on('netBackgroundPolicyChange', (data) => { - this.log('on netBackgroundPolicyChange: ' + JSON.stringify(data)); - }); - - // Call setBackgroundAllowed to enable or disable the background network restriction switch. - setBackgroundAllowed() { - policy.setBackgroundAllowed(Boolean(Number.parseInt(this.isBoolean)), (err, data) => { - console.log(JSON.stringify(err)); - console.log(JSON.stringify(data)) - }); - }, - - // Call isBackgroundAllowed to check whether the background network restriction switch is enabled or disabled. - isBackgroundAllowed() { - policy.isBackgroundAllowed((err, data) => { - console.log(JSON.stringify(err)); - console.log(JSON.stringify(data)) - }); - }, - - // Call getBackgroundPolicyByUid to check whether the application indicated b the specified UID can access the network in the background. - getBackgroundPolicyByUid() { - policy.getBackgroundPolicyByUid(Number.parseInt(this.firstParam), (err, data) => { - console.log(JSON.stringify(err)); - console.log(JSON.stringify(data)) - }); - }, - - // Unsubscribe from background network policy changes. - policy.off('netBackgroundPolicyChange', (data) => { - this.log('off netBackgroundPolicyChange: ' + JSON.stringify(data)); - }); -``` - -## Managing the Metering Network Access Policy - -### How to Develop - -1. Import the **policy** namespace from **@ohos.net.policy.d.ts**. - -2. Call **setPolicyByUid** to set whether the application indicated by the specified UID can access the network in the background. - -3. Call **getPolicyByUid** to check whether the metering network access policy for the application indicated by the specified UID. - -4. Call **getUidsByPolicy** to obtain the UIDs of the applications for which the metering network access policy is configured. - -```js - // Import the policy namespace. - import policy from '@ohos.net.policy' - - // Subscribe to policy changes of the application indicated by the specified UID. - policy.on('netUidPolicyChange', (data) => { - this.log('on netUidPolicyChange: ' + JSON.stringify(data)); - }); - - // Subscribe to rule changes of the application indicated by the specified UID. - policy.on('netUidRuleChange', (data) => { - this.log('on netUidRuleChange: ' + JSON.stringify(data)); - }); - - // Call setPolicyByUid to set whether the application indicated by the specified UID can access the network in the background. - setPolicyByUid() { - let param = { - uid: Number.parseInt(this.firstParam), policy: Number.parseInt(this.currentNetUidPolicy) - } - policy.setPolicyByUid(Number.parseInt(this.firstParam), Number.parseInt(this.currentNetUidPolicy), (err, data) => { - console.log(JSON.stringify(err)); - console.log(JSON.stringify(data)) - }); - }, - - // Call getPolicyByUid to check whether the metering network access policy for the application indicated by the specified UID. - getPolicyByUid() { - policy.getPolicyByUid(Number.parseInt(this.firstParam), (err, data) => { - console.log(JSON.stringify(err)); - console.log(JSON.stringify(data)) - }); - }, - - // Call getUidsByPolicy to obtain the UIDs of the applications for which the metering network access policy is configured. - getUidsByPolicy(){ - policy.getUidsByPolicy(Number.parseInt(this.currentNetUidPolicy), (err, data) => { - console.log(JSON.stringify(err)); - console.log(JSON.stringify(data)) - }); - }, - - // Unsubscribe from policy changes of the application indicated by the specified UID. - policy.off('netUidPolicyChange', (data) => { - this.log('off netUidPolicyChange: ' + JSON.stringify(data)); - }); - - // Unsubscribe from rule changes of the application indicated by the specified UID. - policy.off('netUidRuleChange', (data) => { - this.log('off netUidRuleChange: ' + JSON.stringify(data)); - }); - -``` - -## Restoring Network Policies - -### How to Develop - -1. Import the **policy** namespace from **@ohos.net.policy.d.ts**. - -2. Call **restoreAllPolicies** to restore all network policies. - -```js - // Import the policy namespace. - import policy from '@ohos.net.policy' - - // Call restoreAllPolicies to restore all network policies. - restoreAllPolicies(){ - policy.restoreAllPolicies(this.firstParam, (err, data) => { - console.log(JSON.stringify(err)); - console.log(JSON.stringify(data)) - }); - }, -``` - -## Checking Access to a Metering or Non-metering Network - -### How to Develop - -1. Import the **policy** namespace from **@ohos.net.policy.d.ts**. - -2. Call **isUidNetAllowed** to check whether the UID can access the metering or non-metering network. - -```js - // Import the policy namespace. - import policy from '@ohos.net.policy' - - // Call isUidNetAllowed to check whether the application indicated by the specified UID can access the metering or non-metering network. - isUidNetAllowedIsMetered(){ - let param = { - uid: Number.parseInt(this.firstParam), isMetered: Boolean(Number.parseInt(this.isBoolean)) - } - policy.isUidNetAllowed(Number.parseInt(this.firstParam), Boolean(Number.parseInt(this.isBoolean)), (err, data) => { - console.log(JSON.stringify(err)); - console.log(JSON.stringify(data)) - }); - }, -``` - -## Managing the Sleep Mode Allowlist - -### How to Develop - -1. Import the **policy** namespace from **@ohos.net.policy.d.ts**. - -2. Call **setDeviceIdleAllowList** to add a UID to or remove a UID from the sleep mode allowlist. - -3. Call **getDeviceIdleAllowList** to obtain the UIDs added to the sleep mode allowlist. - -```js - // Import the policy namespace. - import policy from '@ohos.net.policy' - - // Call setDeviceIdleAllowList to add a UID to or remove a UID from the sleep mode allowlist. - setDeviceIdleAllowList(){ - let param = { - uid: Number.parseInt(this.firstParam), isAllowed: Boolean(Number.parseInt(this.isBoolean)) - } - policy.setDeviceIdleAllowList(Number.parseInt(this.firstParam), Boolean(Number.parseInt(this.isBoolean)), (err, data) => { - console.log(JSON.stringify(err)); - console.log(JSON.stringify(data)) - }); - }, - - // Call getDeviceIdleAllowList to obtain the UIDs added to the sleep mode allowlist. - getDeviceIdleAllowList(){ - policy.getDeviceIdleAllowList((err, data) => { - console.log(JSON.stringify(err)); - console.log(JSON.stringify(data)) - }); - }, -``` - -## Managing the Power-saving Mode Allowlist - -### How to Develop - -1. Import the **policy** namespace from **@ohos.net.policy.d.ts**. -2. Call **setPowerSaveAllowList** to add a UID to or remove a UID from the power-saving mode allowlist. -3. Call **getPowerSaveAllowList** to obtain the UIDs added to the power-saving mode allowlist. - -```js - // Import the policy namespace. - import policy from '@ohos.net.policy' - - // Call setPowerSaveAllowList to add a UID to or remove a UID from the power-saving mode allowlist. - setPowerSaveAllowList(){ - let param = { - uid: Number.parseInt(this.firstParam), isAllowed: Boolean(Number.parseInt(this.isBoolean)) - } - policy.setPowerSaveAllowList(Number.parseInt(this.firstParam), Boolean(Number.parseInt(this.isBoolean)), (err, data) => { - console.log(JSON.stringify(err)); - console.log(JSON.stringify(data)) - }); - }, - - // Call getPowerSaveAllowList to obtain the UIDs added to the power-saving mode allowlist. - getPowerSaveAllowList(){ - policy.getPowerSaveAllowList((err, data) => { - console.log(JSON.stringify(err)); - console.log(JSON.stringify(data)) - }); - }, -``` - -## Updating the Network Notification Policy - -### How to Develop - -1. Import the **policy** namespace from **@ohos.net.policy.d.ts**. - -2. Call **updateRemindPolicy** to update the network notification policy. - -```js - // Import the policy namespace. - import policy from '@ohos.net.policy' - - // Call updateRemindPolicy to update the network notification policy. - updateRemindPolicy() { - let param = { - netType: Number.parseInt(this.netType), iccid: this.firstParam, remindType: this.currentRemindType - } - policy.updateRemindPolicy(Number.parseInt(this.netType), this.firstParam, Number.parseInt(this.currentRemindType), (err, data) => { - console.log(JSON.stringify(err)); - console.log(JSON.stringify(data)) - }); - }, -``` diff --git a/en/application-dev/connectivity/net-sharing.md b/en/application-dev/connectivity/net-sharing.md index 331ffec3b1a1e0047c39e2fe416ad5c05e913b61..4072217d9ced5d99b2052b5db8ccb8333fcb7023 100644 --- a/en/application-dev/connectivity/net-sharing.md +++ b/en/application-dev/connectivity/net-sharing.md @@ -60,7 +60,7 @@ For the complete list of APIs and example code, see [Network Sharing](../referen 4. Return the callback for successfully starting network sharing. ```js - // Import the sharing namespace from @ohos.net.sharing. +// Import the sharing namespace from @ohos.net.sharing. import sharing from '@ohos.net.sharing' // Subscribe to network sharing state changes. @@ -85,7 +85,7 @@ sharing.startSharing(sharing.SharingIfaceType.SHARING_WIFI, (error) => { 4. Return the callback for successfully stopping network sharing. ```js - // Import the sharing namespace from @ohos.net.sharing. +// Import the sharing namespace from @ohos.net.sharing. import sharing from '@ohos.net.sharing' // Subscribe to network sharing state changes. @@ -110,7 +110,7 @@ sharing.stopSharing(sharing.SharingIfaceType.SHARING_WIFI, (error) => { 4. Call **stopSharing** to stop network sharing of the specified type and clear the data volume of network sharing. ```js - // Import the sharing namespace from @ohos.net.sharing. +// Import the sharing namespace from @ohos.net.sharing. import sharing from '@ohos.net.sharing' // Call startSharing to start network sharing of the specified type. diff --git a/en/application-dev/connectivity/socket-connection.md b/en/application-dev/connectivity/socket-connection.md index ea2a3ba6dcfb849ea64971503e246e94b16f34a1..109b63fdb5fdcae98e23882b32018d4a03435f55 100644 --- a/en/application-dev/connectivity/socket-connection.md +++ b/en/application-dev/connectivity/socket-connection.md @@ -87,81 +87,81 @@ The implementation is similar for UDP Socket and TCP Socket connections. The fol 7. Enable the TCP Socket connection to be automatically closed after use. - ```js - import socket from '@ohos.net.socket' - - // Create a TCPSocket object. - let tcp = socket.constructTCPSocketInstance(); - - // Subscribe to TCP Socket connection events. - tcp.on('message', value => { - console.log("on message") - let buffer = value.message - let dataView = new DataView(buffer) - let str = "" - for (let i = 0;i < dataView.byteLength; ++i) { - str += String.fromCharCode(dataView.getUint8(i)) - } - console.log("on connect received:" + str) - }); - tcp.on('connect', () => { - console.log("on connect") - }); - tcp.on('close', () => { - console.log("on close") - }); - - // Bind the local IP address and port number. - let bindAddress = { - address: '192.168.xx.xx', - port: 1234, // Bound port, for example, 1234. - family: 1 - }; - tcp.bind(bindAddress, err => { - if (err) { - console.log('bind fail'); - return; - } - console.log('bind success'); - - // Set up a connection to the specified IP address and port number. - let connectAddress = { - address: '192.168.xx.xx', - port: 5678, // Connection port, for example, 5678. - family: 1 - }; - tcp.connect({ - address: connectAddress, timeout: 6000 - }, err => { - if (err) { - console.log('connect fail'); - return; - } - console.log('connect success'); - - // Send data. - tcp.send({ - data: 'Hello, server!' - }, err => { - if (err) { - console.log('send fail'); - return; - } - console.log('send success'); - }) - }); - }); - - // Enable the TCP Socket connection to be automatically closed after use. Then, disable listening for TCP Socket connection events. - setTimeout(() => { - tcp.close((err) => { - console.log('close socket.') - }); - tcp.off('message'); - tcp.off('connect'); - tcp.off('close'); - }, 30 * 1000); - ``` +```js +import socket from '@ohos.net.socket' + +// Create a TCPSocket object. +let tcp = socket.constructTCPSocketInstance(); + +// Subscribe to TCP Socket connection events. +tcp.on('message', value => { + console.log("on message") + let buffer = value.message + let dataView = new DataView(buffer) + let str = "" + for (let i = 0; i < dataView.byteLength; ++i) { + str += String.fromCharCode(dataView.getUint8(i)) + } + console.log("on connect received:" + str) +}); +tcp.on('connect', () => { + console.log("on connect") +}); +tcp.on('close', () => { + console.log("on close") +}); + +// Bind the local IP address and port number. +let bindAddress = { + address: '192.168.xx.xx', + port: 1234, // Bound port, for example, 1234. + family: 1 +}; +tcp.bind(bindAddress, err => { + if (err) { + console.log('bind fail'); + return; + } + console.log('bind success'); + + // Set up a connection to the specified IP address and port number. + let connectAddress = { + address: '192.168.xx.xx', + port: 5678, // Connection port, for example, 5678. + family: 1 + }; + tcp.connect({ + address: connectAddress, timeout: 6000 + }, err => { + if (err) { + console.log('connect fail'); + return; + } + console.log('connect success'); + + // Send data. + tcp.send({ + data: 'Hello, server!' + }, err => { + if (err) { + console.log('send fail'); + return; + } + console.log('send success'); + }) + }); +}); + +// Enable the TCP Socket connection to be automatically closed after use. Then, disable listening for TCP Socket connection events. +setTimeout(() => { + tcp.close((err) => { + console.log('close socket.') + }); + tcp.off('message'); + tcp.off('connect'); + tcp.off('close'); +}, 30 * 1000); +``` ## Implementing Encrypted Data Transmission over TLS Socket Connections @@ -184,7 +184,7 @@ TLS Socket connection process on the client: 7. Enable the TLS Socket connection to be automatically closed after use. ```js - import socket from '@ohos.net.socket' +import socket from '@ohos.net.socket' // Create a TLS Socket connection (for two-way authentication). let tlsTwoWay = socket.constructTLSSocketInstance(); @@ -208,7 +208,7 @@ tlsTwoWay.on('close', () => { }); // Bind the local IP address and port number. -tlsTwoWay.bind({address: '192.168.xxx.xxx', port: xxxx, family: 1}, err => { +tlsTwoWay.bind({ address: '192.168.xxx.xxx', port: xxxx, family: 1 }, err => { if (err) { console.log('bind fail'); return; @@ -280,7 +280,7 @@ tlsTwoWay.on('close', () => { }); // Bind the local IP address and port number. -tlsOneWay.bind({address: '192.168.xxx.xxx', port: xxxx, family: 1}, err => { +tlsOneWay.bind({ address: '192.168.xxx.xxx', port: xxxx, family: 1 }, err => { if (err) { console.log('bind fail'); return; @@ -318,4 +318,12 @@ tlsTwoWay.close((err) => { tlsTwoWay.off('connect'); tlsTwoWay.off('close'); }); -``` \ No newline at end of file +``` + +## Samples + +The following samples are provided to help you better understand how to develop Socket connection features: + +- [`Socket`: Socket Connection (ArkTS) (API9)] (https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Connectivity/Socket) +- [UDP Socket (ArkTS) (API9)](https://gitee.com/openharmony/codelabs/tree/master/NetworkManagement/UdpDemoOH) +- [TCP Socket (ArkTS) (API9)](https://gitee.com/openharmony/codelabs/tree/master/NetworkManagement/TcpSocketDemo) diff --git a/en/application-dev/connectivity/websocket-connection.md b/en/application-dev/connectivity/websocket-connection.md index dfcc9bd7f877393bf1bf8d868046d5d12e896678..4c373011c45be18183e4c622c3e7e35b97198a24 100644 --- a/en/application-dev/connectivity/websocket-connection.md +++ b/en/application-dev/connectivity/websocket-connection.md @@ -37,46 +37,52 @@ The WebSocket connection function is mainly implemented by the WebSocket module. 5. Close the WebSocket connection if it is no longer needed. - ```js - import webSocket from '@ohos.net.webSocket'; - - var defaultIpAddress = "ws://"; - let ws = webSocket.createWebSocket(); - ws.on('open', (err, value) => { - console.log("on open, status:" + JSON.stringify(value)); - // When receiving the on('open') event, the client can use the send() API to communicate with the server. - ws.send("Hello, server!", (err, value) => { - if (!err) { - console.log("Message sent successfully"); - } else { - console.log("Failed to send the message. Err:" + JSON.stringify(err)); - } - }); - }); - ws.on('message', (err, value) => { - console.log("on message, message:" + value); - // When receiving the `bye` message (the actual message name may differ) from the server, the client proactively disconnects from the server. - if (value === 'bye') { - ws.close((err, value) => { - if (!err) { - console.log("Connection closed successfully"); - } else { - console.log("Failed to close the connection. Err: " + JSON.stringify(err)); - } - }); - } - }); - ws.on('close', (err, value) => { - console.log("on close, code is " + value.code + ", reason is " + value.reason); - }); - ws.on('error', (err) => { - console.log("on error, error:" + JSON.stringify(err)); - }); - ws.connect(defaultIpAddress, (err, value) => { - if (!err) { - console.log("Connected successfully"); - } else { - console.log("Connection failed. Err:" + JSON.stringify(err)); - } - }); - ``` +```js +import webSocket from '@ohos.net.webSocket'; + +var defaultIpAddress = "ws://"; +let ws = webSocket.createWebSocket(); +ws.on('open', (err, value) => { + console.log("on open, status:" + JSON.stringify(value)); + // When receiving the on('open') event, the client can use the send() API to communicate with the server. + ws.send("Hello, server!", (err, value) => { + if (!err) { + console.log("Message sent successfully"); + } else { + console.log("Failed to send the message. Err:" + JSON.stringify(err)); + } + }); +}); +ws.on('message', (err, value) => { + console.log("on message, message:" + value); + // When receiving the `bye` message (the actual message name may differ) from the server, the client proactively disconnects from the server. + if (value === 'bye') { + ws.close((err, value) => { + if (!err) { + console.log("Connection closed successfully"); + } else { + console.log("Failed to close the connection. Err: " + JSON.stringify(err)); + } + }); + } +}); +ws.on('close', (err, value) => { + console.log("on close, code is " + value.code + ", reason is " + value.reason); +}); +ws.on('error', (err) => { + console.log("on error, error:" + JSON.stringify(err)); +}); +ws.connect(defaultIpAddress, (err, value) => { + if (!err) { + console.log("Connected successfully"); + } else { + console.log("Connection failed. Err:" + JSON.stringify(err)); + } +}); +``` + +## Samples + +The following samples are provided to help you better understand how to develop WebSocket connection features: + +- [`WebSocket`: WebSocket (ArkTS) (API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Connectivity/WebSocket) diff --git a/en/application-dev/database/data-persistence-by-kv-store.md b/en/application-dev/database/data-persistence-by-kv-store.md index 358661e83d952349220a45c0d8ac065f422e3f70..2337702fb79b1d2c53154181362b393211f90f50 100644 --- a/en/application-dev/database/data-persistence-by-kv-store.md +++ b/en/application-dev/database/data-persistence-by-kv-store.md @@ -32,8 +32,9 @@ The following table lists the APIs used for KV data persistence. Most of the API ## How to Develop -1. Create a **KvManager** instance to manage database objects. Example: +1. Create a **KvManager** instance to manage database objects. + Example: Stage model: @@ -90,13 +91,14 @@ The following table lists the APIs used for KV data persistence. Most of the API } ``` -2. Create and obtain a KV store. Example: +2. Create and obtain a KV store. + Example: ```js try { const options = { createIfMissing: true, // Whether to create a KV store when the database file does not exist. By default, a KV store is created. - createIfMissing: true, // Whether to encrypt database files. By default, database files are not encrypted. + encrypt: false, // Whether to encrypt the KV store. By default, KV stores are not encrypted. backup: false, // Whether to back up database files. By default, the database files are backed up. autoSync: true, // Whether to automatically synchronize database files. The value **true** means to automatically synchronize database files; the value **false** (default) means the opposite. kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION, // Type of the KV store to create. By default, a device KV store is created. @@ -116,8 +118,9 @@ The following table lists the APIs used for KV data persistence. Most of the API } ``` -3. Use **put()** to add data to the KV store. Example: +3. Use **put()** to add data to the KV store. + Example: ```js const KEY_TEST_STRING_ELEMENT = 'key_test_string'; const VALUE_TEST_STRING_ELEMENT = 'value_test_string'; @@ -138,8 +141,9 @@ The following table lists the APIs used for KV data persistence. Most of the API > > The **put()** method adds a KV pair if the specified key does not exists and changes the value if the the specified key already exists. -4. Use **get()** to obtain the value of a key. Example: +4. Use **get()** to obtain the value of a key. + Example: ```js const KEY_TEST_STRING_ELEMENT = 'key_test_string'; const VALUE_TEST_STRING_ELEMENT = 'value_test_string'; @@ -163,8 +167,9 @@ The following table lists the APIs used for KV data persistence. Most of the API } ``` -5. Use **delete()** to delete the data of the specified key. Example: +5. Use **delete()** to delete the data of the specified key. + Example: ```js const KEY_TEST_STRING_ELEMENT = 'key_test_string'; const VALUE_TEST_STRING_ELEMENT = 'value_test_string'; diff --git a/en/application-dev/database/data-persistence-by-preferences.md b/en/application-dev/database/data-persistence-by-preferences.md index a0c4aafbae9314363b44cd99e3abc563a21d2abe..124ab56bd08cb2971a92b6befd5d772a8274d031 100644 --- a/en/application-dev/database/data-persistence-by-preferences.md +++ b/en/application-dev/database/data-persistence-by-preferences.md @@ -10,7 +10,9 @@ The **Preferences** module provides APIs for processing data in the form of key- User applications call **Preference** through the JS interface to read and write data files. You can load the data of a **Preferences** persistence file to a **Preferences** instance. Each file uniquely corresponds to an instance. The system stores the instance in memory through a static container until the instance is removed from the memory or the file is deleted. The following figure illustrates how **Preference** works. - **Figure 1** Preferences working mechanism +The preference persistent file of an application is stored in the application sandbox. You can use **context** to obtain the file path. For details, see [Obtaining Application File Paths](../application-models/application-context-stage.md#obtaining-application-file-paths). + +**Figure 1** Preferences working mechanism ![preferences](figures/preferences.jpg) @@ -19,14 +21,14 @@ User applications call **Preference** through the JS interface to read and write - The key in a KV pair must be a string and cannot be empty or exceed 80 bytes. -- If the value is of the string type, it can be empty or a string not longer than 8192 bytes. +- If the value is of the string type, use the UTF-8 encoding format. It can be empty or a string not longer than 8192 bytes. - The memory usage increases with the amount of **Preferences** data. The maximum number of data records recommended is 10,000. Otherwise, high memory overheads will be caused. ## Available APIs -The following table lists the APIs used for preferences data persistence. Most of the APIs are executed asynchronously, using a callback or promise to return the result. The following table uses the callback-based APIs as an example. For more information about the APIs, see [User Preferences](../reference/apis/js-apis-data-preferences.md). +The following table lists the APIs used for preferences data persistence. Most of the APIs are executed asynchronously in callback or promise mode. The following table uses the callback-based APIs as an example. For more information about the APIs, see [User Preferences](../reference/apis/js-apis-data-preferences.md). | API| Description| | -------- | -------- | diff --git a/en/application-dev/database/data-persistence-by-rdb-store.md b/en/application-dev/database/data-persistence-by-rdb-store.md index d74e79a53c78d4bc0cc7cb2cb6dd95ea7a9ba1fb..60b3b29f2a27377b8f23414209fc64f92ee9d39f 100644 --- a/en/application-dev/database/data-persistence-by-rdb-store.md +++ b/en/application-dev/database/data-persistence-by-rdb-store.md @@ -18,7 +18,7 @@ A relational database (RDB) store is used to store data in complex relational mo **RelationalStore** provides APIs for applications to perform data operations. With SQLite as the underlying persistent storage engine, **RelationalStore** provides SQLite database features, including transactions, indexes, views, triggers, foreign keys, parameterized queries, prepared SQL statements, and more. **Figure 1** Working mechanism - + ![relationStore_local](figures/relationStore_local.jpg) @@ -37,46 +37,68 @@ A relational database (RDB) store is used to store data in complex relational mo The following table lists the APIs used for RDB data persistence. Most of the APIs are executed asynchronously, using a callback or promise to return the result. The following table uses the callback-based APIs as an example. For more information about the APIs, see [RDB Store](../reference/apis/js-apis-data-relationalStore.md). -| API| Description| +| API| Description| | -------- | -------- | -| getRdbStore(context: Context, config: StoreConfig, callback: AsyncCallback<RdbStore>): void | Obtains a **RdbStore** instance to implement RDB store operations. You can set **RdbStore** parameters based on actual requirements and use **RdbStore** APIs to perform data operations.| -| executeSql(sql: string, bindArgs: Array<ValueType>, callback: AsyncCallback<void>):void | Executes an SQL statement that contains specified arguments but returns no value.| -| insert(table: string, values: ValuesBucket, callback: AsyncCallback<number>):void | Inserts a row of data into a table.| -| update(values: ValuesBucket, predicates: RdbPredicates, callback: AsyncCallback<number>):void | Updates data in the RDB store based on the specified **RdbPredicates** instance.| -| delete(predicates: RdbPredicates, callback: AsyncCallback<number>):void | Deletes data from the RDB store based on the specified **RdbPredicates** instance.| -| query(predicates: RdbPredicates, columns: Array<string>, callback: AsyncCallback<ResultSet>):void | Queries data in the RDB store based on specified conditions.| -| deleteRdbStore(context: Context, name: string, callback: AsyncCallback<void>): void | Deletes an RDB store.| +| getRdbStore(context: Context, config: StoreConfig, callback: AsyncCallback<RdbStore>): void | Obtains a **RdbStore** instance to implement RDB store operations. You can set **RdbStore** parameters based on actual requirements and use **RdbStore** APIs to perform data operations.| +| executeSql(sql: string, bindArgs: Array<ValueType>, callback: AsyncCallback<void>):void | Executes an SQL statement that contains specified arguments but returns no value.| +| insert(table: string, values: ValuesBucket, callback: AsyncCallback<number>):void | Inserts a row of data into a table.| +| update(values: ValuesBucket, predicates: RdbPredicates, callback: AsyncCallback<number>):void | Updates data in the RDB store based on the specified **RdbPredicates** instance.| +| delete(predicates: RdbPredicates, callback: AsyncCallback<number>):void | Deletes data from the RDB store based on the specified **RdbPredicates** instance.| +| query(predicates: RdbPredicates, columns: Array<string>, callback: AsyncCallback<ResultSet>):void | Queries data in the RDB store based on specified conditions.| +| deleteRdbStore(context: Context, name: string, callback: AsyncCallback<void>): void | Deletes an RDB store.| ## How to Develop -1. Obtain an **RdbStore** instance.
Example: +1. Obtain an **RdbStore** instance.
Example: Stage model: - + ```js import relationalStore from '@ohos.data.relationalStore'; // Import the module. import UIAbility from '@ohos.app.ability.UIAbility'; - + class EntryAbility extends UIAbility { onWindowStageCreate(windowStage) { const STORE_CONFIG = { name: 'RdbTest.db', // Database file name. securityLevel: relationalStore.SecurityLevel.S1 // Database security level. }; - + + // The RDB store version is 3, and the table structure is EMPLOYEE (NAME, AGE, SALARY, CODES). const SQL_CREATE_TABLE ='CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, AGE INTEGER, SALARY REAL, CODES BLOB)'; // SQL statement for creating a data table. - + relationalStore.getRdbStore(this.context, STORE_CONFIG, (err, store) => { if (err) { console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`); return; } console.info(`Succeeded in getting RdbStore.`); - store.executeSql(SQL_CREATE_TABLE); // Create a data table. - + + // When the RDB store is created, the default version is 0. + if (store.version == 0) { + store.executeSql(SQL_CREATE_TABLE); // Create a data table. + // Set the RDB store version, which must be an integer greater than 0. + store.version = 3; + } + + // If the RDB store version is not 0 and does not match the current version, upgrade or downgrade the RDB store. + // For example, upgrade the RDB store from version 1 to version 2. + if (store.version != 3 && store.version == 1) { + // Upgrade the RDB store from version 1 to version 2, and change the table structure from EMPLOYEE (NAME, SALARY, CODES, ADDRESS) to EMPLOYEE (NAME, AGE, SALARY, CODES, ADDRESS). + store.executeSql("ALTER TABLE EMPLOYEE ADD COLUMN AGE INTEGER", null); + store.version = 2; + } + + // For example, upgrade the RDB store from version 2 to version 3. + if (store.version != 3 && store.version == 2) { + // Upgrade the RDB store from version 2 to version 3, and change the table structure from EMPLOYEE (NAME, AGE, SALARY, CODES, ADDRESS) to EMPLOYEE (NAME, AGE, SALARY, CODES). + store.executeSql("ALTER TABLE EMPLOYEE DROP COLUMN ADDRESS TEXT", null); + store.version = 3; + } + // Perform operations such as adding, deleting, modifying, and querying data in the RDB store. - + }); } } @@ -84,7 +106,7 @@ The following table lists the APIs used for RDB data persistence. Most of the AP FA model: - + ```js import relationalStore from '@ohos.data.relationalStore'; // Import the module. import featureAbility from '@ohos.ability.featureAbility'; @@ -96,16 +118,38 @@ The following table lists the APIs used for RDB data persistence. Most of the AP name: 'RdbTest.db', // Database file name. securityLevel: relationalStore.SecurityLevel.S1 // Database security level. }; - + + // The RDB store version is 3, and the table structure is EMPLOYEE (NAME, AGE, SALARY, CODES). const SQL_CREATE_TABLE ='CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, AGE INTEGER, SALARY REAL, CODES BLOB)'; // SQL statement for creating a data table. - + relationalStore.getRdbStore(context, STORE_CONFIG, (err, store) => { if (err) { console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`); return; } console.info(`Succeeded in getting RdbStore.`); - store.executeSql(SQL_CREATE_TABLE); // Create a data table. + + // When the RDB store is created, the default version is 0. + if (store.version == 0) { + store.executeSql(SQL_CREATE_TABLE); // Create a data table. + // Set the RDB store version, which must be an integer greater than 0. + store.version = 3; + } + + // If the RDB store version is not 0 and does not match the current version, upgrade or downgrade the RDB store. + // For example, upgrade the RDB store from version 1 to version 2. + if (store.version != 3 && store.version == 1) { + // Upgrade the RDB store from version 1 to version 2, and change the table structure from EMPLOYEE (NAME, SALARY, CODES, ADDRESS) to EMPLOYEE (NAME, AGE, SALARY, CODES, ADDRESS). + store.executeSql("ALTER TABLE EMPLOYEE ADD COLUMN AGE INTEGER", null); + store.version = 2; + } + + // For example, upgrade the RDB store from version 2 to version 3. + if (store.version != 3 && store.version == 2) { + // Upgrade the RDB store from version 2 to version 3, and change the table structure from EMPLOYEE (NAME, AGE, SALARY, CODES, ADDRESS) to EMPLOYEE (NAME, AGE, SALARY, CODES). + store.executeSql("ALTER TABLE EMPLOYEE DROP COLUMN ADDRESS TEXT", null); + store.version = 3; + } // Perform operations such as adding, deleting, modifying, and querying data in the RDB store. @@ -116,10 +160,12 @@ The following table lists the APIs used for RDB data persistence. Most of the AP > > - The RDB store created by an application varies with the context. Multiple RDB stores are created for the same database name with different application contexts. For example, each UIAbility has its own context. > - > - When an application calls **getRdbStore()** to obtain an RDB store instance for the first time, the corresponding database file is generated in the application sandbox. If you want to move the files of an RDB store to another place for view, you must also move the temporary files with finename extensions **-wal** or **-shm** in the same directory. Once an application is uninstalled, the database files and temporary files generated by the application on the device are also removed. + > - When an application calls **getRdbStore()** to obtain an RDB store instance for the first time, the corresponding database file is generated in the application sandbox. When the RDB store is used, temporary files ended with **-wal** and **-shm** may be generated in the same directory as the database file. If you want to move the database files to other places, you must also move these temporary files. After the application is uninstalled, the database files and temporary files generated on the device are also removed. -2. Use **insert()** to insert data to the RDB store. Example: - +2. Use **insert()** to insert data to the RDB store. + + Example: + ```js const valueBucket = { 'NAME': 'Lisa', @@ -133,17 +179,19 @@ The following table lists the APIs used for RDB data persistence. Most of the AP return; } console.info(`Succeeded in inserting data. rowId:${rowId}`); - }) +}) ``` - + > **NOTE** - > +> > **RelationalStore** does not provide explicit flush operations for data persistence. Data inserted by **insert()** is stored in files persistently. - + 3. Modify or delete data based on the specified **Predicates** instance. - Use **update()** to modify data and **delete()** to delete data. Example: - + Use **update()** to modify data and **delete()** to delete data. + + Example: + ```js // Modify data. const valueBucket = { @@ -176,8 +224,10 @@ The following table lists the APIs used for RDB data persistence. Most of the AP 4. Query data based on the conditions specified by **Predicates**. - Use **query()** to query data. The data obtained is returned in a **ResultSet** object. Example: - + Use **query()** to query data. The data obtained is returned in a **ResultSet** object. + + Example: + ```js let predicates = new relationalStore.RdbPredicates('EMPLOYEE'); predicates.equalTo('NAME', 'Rose'); @@ -197,11 +247,13 @@ The following table lists the APIs used for RDB data persistence. Most of the AP 5. Delete the RDB store. - Use **deleteRdbStore()** to delete the RDB store and related database files. Example: + Use **deleteRdbStore()** to delete the RDB store and related database files. + + Example: Stage model: - + ```js import UIAbility from '@ohos.app.ability.UIAbility'; @@ -220,7 +272,7 @@ The following table lists the APIs used for RDB data persistence. Most of the AP FA model: - + ```js import featureAbility from '@ohos.ability.featureAbility'; diff --git a/en/application-dev/database/data-sync-of-kv-store.md b/en/application-dev/database/data-sync-of-kv-store.md index f6b2d2c55dca745843d55d37bc3a96166bc3e4ff..eb8994570f04b0d6690c2b91b1b1745602e980fb 100644 --- a/en/application-dev/database/data-sync-of-kv-store.md +++ b/en/application-dev/database/data-sync-of-kv-store.md @@ -68,7 +68,7 @@ When data is added, deleted, or modified, a notification is sent to the subscrib - The KV stores do not support custom conflict resolution policies for applications. -- A maximum of 16 distributed KV stores can be opened simultaneously for an application. +- A maximum of 16 KV stores can be opened simultaneously for an application. - Each KV store supports a maximum of eight callbacks for subscription of data change notifications. @@ -91,7 +91,7 @@ The following table lists the APIs for cross-device data synchronization of the ## How to Develop -The following uses a single KV store as an example to describe how to implement cross-device data synchronization. The following describes the development process. +The following uses a single KV store as an example to describe how to implement cross-device data synchronization. The development process is as follows. ![kvStore_development_process](figures/kvStore_development_process.png) diff --git a/en/application-dev/database/data-sync-of-rdb-store.md b/en/application-dev/database/data-sync-of-rdb-store.md index c47d95a7969d44a96396e2e6e77dd4c958468748..2d6d5a73e0cf7cfae28d7d6296039e28994477a8 100644 --- a/en/application-dev/database/data-sync-of-rdb-store.md +++ b/en/application-dev/database/data-sync-of-rdb-store.md @@ -3,7 +3,7 @@ ## When to Use -When creating a data table, you can set the table to support cross-device access. You can also use APIs to move the data to be accessed across devices to a distributed data. +You can synchronize the application data in a local RDB store on a device to other divices that form a Super Device. ## Basic Concepts @@ -51,14 +51,14 @@ When data is added, deleted, or modified, a notification is sent to the subscrib The following table lists the APIs for cross-device data synchronization of RDB stores. Most of the APIs are executed asynchronously, using a callback or promise to return the result. The following table uses the callback-based APIs as an example. For more information about the APIs, see [RDB Store](../reference/apis/js-apis-data-relationalStore.md). -| API| Description| +| API| Description| | -------- | -------- | -| setDistributedTables(tables: Array<string>, callback: AsyncCallback<void>): void | Sets the distributed tables to be synchronized.| -| sync(mode: SyncMode, predicates: RdbPredicates, callback: AsyncCallback<Array<[string, number]>>): void | Synchronizes data across devices.| -| on(event: 'dataChange', type: SubscribeType, observer: Callback<Array<string>>): void | Subscribes to changes in the distributed data.| -| off(event:'dataChange', type: SubscribeType, observer: Callback<Array<string>>): void | Unsubscribe from changes in the distributed data.| -| obtainDistributedTableName(device: string, table: string, callback: AsyncCallback<string>): void; | Obtains the table name on the specified device based on the local table name.| -| remoteQuery(device: string, table: string, predicates: RdbPredicates, columns: Array<string> , callback: AsyncCallback<ResultSet>): void | Queries data from the RDB store of a remote device based on specified conditions.| +| setDistributedTables(tables: Array<string>, callback: AsyncCallback<void>): void | Sets the distributed tables to be synchronized.| +| sync(mode: SyncMode, predicates: RdbPredicates, callback: AsyncCallback<Array<[string, number]>>): void | Synchronizes data across devices.| +| on(event: 'dataChange', type: SubscribeType, observer: Callback<Array<string>>): void | Subscribes to changes in the distributed data.| +| off(event:'dataChange', type: SubscribeType, observer: Callback<Array<string>>): void | Unsubscribe from changes in the distributed data.| +| obtainDistributedTableName(device: string, table: string, callback: AsyncCallback<string>): void; | Obtains the table name on the specified device based on the local table name.| +| remoteQuery(device: string, table: string, predicates: RdbPredicates, columns: Array<string> , callback: AsyncCallback<ResultSet>): void | Queries data from the RDB store of a remote device based on specified conditions.| ## How to Develop @@ -68,7 +68,7 @@ The following table lists the APIs for cross-device data synchronization of RDB > The data on a device can be synchronized only to the devices whose data security labels are not higher than the security level of the device. For details, see [Access Control Mechanism in Cross-Device Synchronization](sync-app-data-across-devices-overview.md#access-control-mechanism-in-cross-device-synchronization). 1. Import the module. - + ```js import relationalStore from '@ohos.data.relationalStore'; ``` @@ -79,7 +79,7 @@ The following table lists the APIs for cross-device data synchronization of RDB 2. Display a dialog box to ask authorization from the user when the application is started for the first time. For details, see [Requesting User Authorization](../security/accesstoken-guidelines.md#requesting-user-authorization). 3. Create an RDB store and set a table for distributed synchronization. - + ```js const STORE_CONFIG = { name: 'RdbTest.db', // Database file name. @@ -95,7 +95,7 @@ The following table lists the APIs for cross-device data synchronization of RDB ``` 4. Synchronize data across devices. After **sync()** is called to trigger a synchronization, data is synchronized from the local device to all other devices on the network. - + ```js // Construct the predicate object for synchronizing the distributed table. let predicates = new relationalStore.RdbPredicates('EMPLOYEE'); @@ -114,7 +114,7 @@ The following table lists the APIs for cross-device data synchronization of RDB ``` 5. Subscribe to changes in the distributed data. The data synchronization triggers the **observer** callback registered in **on()**. The input parameter of the callback is the ID of the device whose data changes. - + ```js let observer = function storeObserver(devices) { for (let i = 0; i < devices.length; i++) { @@ -144,7 +144,7 @@ The following table lists the APIs for cross-device data synchronization of RDB > > **deviceIds** is obtained by using [devManager.getTrustedDeviceListSync](../reference/apis/js-apis-device-manager.md#gettrusteddevicelistsync). The APIs of the **deviceManager** module are all system interfaces and available only to system applications. - + ```js // Obtain device IDs. import deviceManager from '@ohos.distributedHardware.deviceManager'; diff --git a/en/application-dev/database/share-data-by-datashareextensionability.md b/en/application-dev/database/share-data-by-datashareextensionability.md index 923cac5257b040d5c3c425f26505648135b5f14f..7f70ab30d4c04c421c1e18032a0da13e590f80a7 100644 --- a/en/application-dev/database/share-data-by-datashareextensionability.md +++ b/en/application-dev/database/share-data-by-datashareextensionability.md @@ -16,7 +16,8 @@ There are two roles in **DataShare**: - Data consumer: accesses the data provided by the provider using [createDataShareHelper()](../reference/apis/js-apis-data-dataShare.md#datasharecreatedatasharehelper). -**Figure 1** Data sharing mechanism +**Figure 1** Data sharing mechanism + ![dataShare](figures/dataShare.jpg) - The **DataShareExtensionAbility** module, as the data provider, implements services related to data sharing between applications. @@ -125,15 +126,15 @@ override the service implementation as required. For example, if the data provid **Table 1** Fields in module.json5 - | Field| Description| Mandatory| + | Field| Description| Mandatory| | -------- | -------- | -------- | - | name | Ability name, corresponding to the **ExtensionAbility** class name derived from **Ability**.| Yes| - | type | Ability type. The value is **dataShare**, indicating the development is based on the **datashare** template.| Yes| - | uri | URI used for communication. It is the unique identifier for the data consumer to connect to the provider.| Yes| - | exported | Whether it is visible to other applications. Data sharing is allowed only when the value is **true**.| Yes| - | readPermission | Permission required for accessing data. If this parameter is not set, the read permission is not verified by default.| No| - | writePermission | Permission required for modifying data. If this parameter is not set, write permission verification is not performed by default.| No| - | metadata | Configuration for silent access, including the **name** and **resource** fields.
The **name** field identifies the configuration, which has a fixed value of **ohos.extension.dataShare**.
The **resource** field has a fixed value of **$profile:data_share_config**, which indicates that the profile name is **data_share_config.json**.| **metadata** is mandatory when the ability launch type is **singleton**. For details about the ability launch type, see **launchType** in the [Internal Structure of the abilities Attribute](../quick-start/module-structure.md#internal-structure-of-the-abilities-attribute).| + | name | Ability name, corresponding to the **ExtensionAbility** class name derived from **Ability**.| Yes| + | type | Ability type. The value is **dataShare**, indicating the development is based on the **datashare** template.| Yes| + | uri | URI used for communication. It is the unique identifier for the data consumer to connect to the provider.| Yes| + | exported | Whether it is visible to other applications. Data sharing is allowed only when the value is **true**.| Yes| + | readPermission | Permission required for accessing data. If this parameter is not set, the read permission is not verified by default.| No| + | writePermission | Permission required for modifying data. If this parameter is not set, write permission verification is not performed by default.| No| + | metadata | Configuration for silent access, including the **name** and **resource** fields.
The **name** field identifies the configuration, which has a fixed value of **ohos.extension.dataShare**.
The **resource** field has a fixed value of **$profile:data_share_config**, which indicates that the profile name is **data_share_config.json**.| **metadata** is mandatory when the ability launch type is **singleton**. For details about the ability launch type, see **launchType** in the [Internal Structure of the abilities Attribute](../quick-start/module-structure.md#internal-structure-of-the-abilities-attribute).| **module.json5 example** diff --git a/en/application-dev/database/share-data-by-silent-access.md b/en/application-dev/database/share-data-by-silent-access.md index 142642f98646003c675fcbd15d9369b6664948a6..50ff03f084c889a807c6caf4d7c369bfbe0d2a51 100644 --- a/en/application-dev/database/share-data-by-silent-access.md +++ b/en/application-dev/database/share-data-by-silent-access.md @@ -3,7 +3,7 @@ ## When to Use -According to big data statistics, in a typical cross-application data access scenario, applications are started nearly 83 times on average in a day. +In a typical cross-application data access scenario, an application may be started multiple times. To reduce the number of application startup times and improve the access speed, OpenHarmony provides the silent access feature, which allows direct access to the database without starting the data provider. diff --git a/en/application-dev/database/share-device-data-across-apps-overview.md b/en/application-dev/database/share-device-data-across-apps-overview.md index 38aead4c3c77553daab497ab3436291a409a227f..6392e579a8e078e4ff41751aa2ebcc1481ac58a0 100644 --- a/en/application-dev/database/share-device-data-across-apps-overview.md +++ b/en/application-dev/database/share-device-data-across-apps-overview.md @@ -1,46 +1,47 @@ -# DataShare Overview - +# Cross-Application Data Sharing Overview ## Function -The **DataShare** module allows an application to share its data with other applications. Currently, data can be shared only between applications on the same device. +The application data on a device, such as the Contacts, short message service (SMS), and Gallery data, always needs to be shared with other applications. However, certain data, such as the accounts and passwords, cannot be shared. Certain data, such as SMS messages, can be accessed but not modified by other applications. The **DataShare** module provides a secure and easy-to-use mechanism for sharing data of an application with other applications on the same device. -Data needs to be shared in a wealth of scenarios. For example, the Contacts, short message service (SMS), and Gallery data always needs to be shared with other applications. However, certain data, such as accounts and passwords, cannot be shared. Some data, such as SMS messages, can be queried but not modified by other applications. **DataShare** provides a secure and convenient sharing mechanism for application data. +## Basic Concepts -The data provider can directly use **DataShare** to share data with other applications without complex encapsulation. The data consumer only needs to use a set of APIs because the DataShare access mode does not vary with the data provision mode. This greatly reduces the learning time and development difficulty. +Before developing cross-application data sharing on a device, understand the following concepts: -Data can be shared across applications in either of the following ways: +- Data provider: an application that provides data and implements related services. It is also called the data producer or server. -- Using **DataShareExtensionAbility** - An extension ability is implemented in the HAP to invoke a callback. When the data consumer calls an API, the extension ability of the data provider will be automatically started to invoke the registered callback. +- Data consumer: an application that accesses the data or services provided by the data provider. It is also called the client. - You can use **DataShareExtensionAbility** when the cross-application data access involves service operations other than mere addition, deletion, modification, and query of data in databases. +- **ValuesBucket**: a set of data to be inserted. It can be one or more data records in KV pairs. In each KV pair, the key must be of the string type, and the value can be a number, a string, a Boolean value, or an unsigned integer array. -- Using Silent Access - Database access rules are configured in the HAP. When the data consumer calls an API, the system ability automatically obtains the access rules in the HAP and returns data without starting the data provider. +- **ResultSet**: a set of query results. It provides flexible modes for obtaining various data. - You can use the silent access feature when the cross-application data access involves only the operations for adding, deleting, modifying, and querying data in databases. +- **Predicates**: an object that specifies the conditions for updating, deleting, or querying data in a database. -## Basic Concepts +## Implementation -Before developing cross-application data sharing on a device, understand the following concepts: +The data provider can directly use **DataShare** to share data with other applications without complex encapsulation. The data consumer only needs to use a set of APIs to access the data, because the **DataShare** access mode does not vary with the data provisioning mode. This greatly reduces the learning time and development difficulty. -- Data provider: an application that provides data and implements related services. It is also called the producer or server. +The cross-application data sharing can be implemented in either of the following ways: -- Data consumer: an application that accesses the data or services provided by the data provider. It is also called the client. +- **DataShareExtensionAbility** -- **ValuesBucket**: a set of data to be inserted. It can be one or more data records in KV pairs. In each KV pair, the key must be of the string type, and the value can be a number, a string, a Boolean value, or an unsigned integer array. + You can implement an ExtensionAbility with a callback in the HAP. When the data consumer calls an API, the ExtensionAbility of the data provider will be automatically started to invoke the registered callback. -- **ResultSet**: a set of query results. It provides flexible modes for users to obtain various data. + This method is recommended when the cross-application data access involves service operations other than mere addition, deletion, modification, and query of data in databases. -- **Predicates**: an object that specifies the conditions for updating, deleting, or querying data in a database. +- Silent access + + You can configure database access rules in the HAP. When the data consumer calls an API, the system ability automatically obtains the access rules in the HAP and returns data without starting the data provider. + + This method is recommended when the cross-application data access involves only the operations for adding, deleting, modifying, and querying data in databases. ## Constraints -- **DataShare** is subject to the limitations on the database used by the data provider. For example, the supported data models, length of the keys and values, and maximum number of databases that can be accessed at a time by each application vary with the database in use. +- **DataShare** is subject to the limitations on the database used by the data provider. The supported data models, length of the keys and values, and maximum number of databases that can be accessed at a time by each application vary with the database in use. -- The payloads of **ValuesBucket**, **Predicates**, and **ResultSet** are restricted by IPC. +- The payloads of **ValuesBucket**, **Predicates**, and **ResultSet** are restricted by inter-process communication (IPC). - Currently, **dataShare** supports development based on the stage model only. diff --git a/en/application-dev/database/sync-app-data-across-devices-overview.md b/en/application-dev/database/sync-app-data-across-devices-overview.md index 875b70fef7d4b3bcd6b78a2102ec40c80d7da5f9..c2f6361786325ccd753aa8fa4afa3446d37b6e89 100644 --- a/en/application-dev/database/sync-app-data-across-devices-overview.md +++ b/en/application-dev/database/sync-app-data-across-devices-overview.md @@ -36,14 +36,4 @@ Strong consistency has high requirements on distributed data management and may ## Access Control Mechanism in Cross-Device Synchronization -In the application data synchronization across devices, data access is controlled based on the device level and [data security label](access-control-by-device-and-data-level.md#data-security-labels). In principle, data can be synchronized only to the devices whose data security labels are not higher than the device's security level. The access control matrix is as follows: - -|Device Security Level|Data Security Labels of the Synchornizable Device| -|---|---| -|SL1|S1| -|SL2|S1 to S2| -|SL3|S1 to S3| -|SL4|S1 to S4| -|SL5|S1 to S4| - -For example, the security level of development boards RK3568 and Hi3516 is SL1. The database with data security label S1 can be synchronized with RK3568 and Hi3516, but the database with database labels S2-S4 cannot. +When data is synchronized across devices, access control is performed based on the device level and data security label. For details, see [Access Control Mechanism in Cross-Device Synchronization](access-control-by-device-and-data-level.md#access-control-mechanism-in-cross-device-synchronization). diff --git a/en/application-dev/device-usage-statistics/device-usage-statistics-use-guide.md b/en/application-dev/device-usage-statistics/device-usage-statistics-use-guide.md index 82027e91a9c15b1fd1b62a8c5ef4cddc2f9c0ef3..067f372d7e27e568d3208f651b57132ecc3edd72 100644 --- a/en/application-dev/device-usage-statistics/device-usage-statistics-use-guide.md +++ b/en/application-dev/device-usage-statistics/device-usage-statistics-use-guide.md @@ -1,4 +1,4 @@ -# Device Usage Statistics Development (API Version 9) +# Device Usage Statistics Development ## When to Use @@ -38,7 +38,7 @@ import usageStatistics from '@ohos.resourceschedule.usageStatistics'; ## How to Develop 1. Before obtaining the device usage statistics, check whether the **ohos.permission.BUNDLE_ACTIVE_INFO** permission is configured. For details about how to configure a permission, see [Declaring Permissions](../security/accesstoken-guidelines.md). - + 2. Query events of all applications based on the specified start time and end time. This requires the **ohos.permission.BUNDLE_ACTIVE_INFO** permission to be configured. ```js diff --git a/en/application-dev/device/usb-guidelines.md b/en/application-dev/device/usb-guidelines.md index 68c8c3de013e75d56854bf0cf0e3a71aca9eb261..ef09e1ee89940220f8b9d1936362d34ebf8bf7a6 100644 --- a/en/application-dev/device/usb-guidelines.md +++ b/en/application-dev/device/usb-guidelines.md @@ -1,156 +1,161 @@ # USB Service Development + ## When to Use In Host mode, you can obtain the list of connected USB devices, enable or disable the devices, manage device access permissions, and perform data transfer or control transfer. -## APIs + +## Available APIs The USB service provides the following functions: query of USB device list, bulk data transfer, control transfer, and access permission management. The following table lists the USB APIs currently available. For details, see the [API Reference](../reference/apis/js-apis-usbManager.md). -**Table 1** Open USB APIs +**Table 1** Open USB APIs -| API | Description | +| Name | Description | | ------------------------------------------------------------ | ------------------------------------------------------------ | -| hasRight(deviceName: string): boolean | Checks whether the user has the device access permissions. | -| requestRight(deviceName: string): Promise\ | Requests the temporary permission for a given application to access the USB device. This API uses a promise to return the result. | -| connectDevice(device: USBDevice): Readonly\ | Connects to the USB device based on the device list returned by `getDevices()`. | -| getDevices(): Array> | Obtains the list of USB devices connected to the USB host. If no USB device is connected, an empty list is returned. | -| setConfiguration(pipe: USBDevicePipe, config: USBConfiguration): number | Sets the USB device configuration. | -| setInterface(pipe: USBDevicePipe, iface: USBInterface): number | Sets a USB interface. | -| claimInterface(pipe: USBDevicePipe, iface: USBInterface, force ?: boolean): number | Claims a USB interface. | -| bulkTransfer(pipe: USBDevicePipe, endpoint: USBEndpoint, buffer: Uint8Array, timeout ?: number): Promise\ | Performs bulk transfer. | -| closePipe(pipe: USBDevicePipe): number | Closes a USB device pipe. | -| releaseInterface(pipe: USBDevicePipe, iface: USBInterface): number | Releases a USB interface. | -| getFileDescriptor(pipe: USBDevicePipe): number | Obtains the file descriptor. | -| getRawDescriptor(pipe: USBDevicePipe): Uint8Array | Obtains the raw USB descriptor. | -| controlTransfer(pipe: USBDevicePipe, controlparam: USBControlParams, timeout ?: number): Promise<number> | Performs control transfer. | +| hasRight(deviceName: string): boolean | Checks whether the user has the device access permissions.| +| requestRight(deviceName: string): Promise<boolean> | Requests the device access permissions for the application. This API uses a promise to return the result. | +| removeRight(deviceName: string): boolean | Revokes the device access permissions of the application.| +| connectDevice(device: USBDevice): Readonly<USBDevicePipe> | Connects to the USB device based on the device information returned by `getDevices()`. | +| getDevices(): Array<Readonly<USBDevice>> | Obtains the list of USB devices connected to the host. If no device is connected, an empty list is returned. | +| setConfiguration(pipe: USBDevicePipe, config: USBConfiguration): number | Sets the USB device configuration. | +| setInterface(pipe: USBDevicePipe, iface: USBInterface): number | Sets a USB interface. | +| claimInterface(pipe: USBDevicePipe, iface: USBInterface, force ?: boolean): number | Claims a USB interface. | +| bulkTransfer(pipe: USBDevicePipe, endpoint: USBEndpoint, buffer: Uint8Array, timeout ?: number): Promise<number> | Performs bulk transfer. | +| closePipe(pipe: USBDevicePipe): number | Closes a USB device pipe. | +| releaseInterface(pipe: USBDevicePipe, iface: USBInterface): number | Releases a USB interface. | +| getFileDescriptor(pipe: USBDevicePipe): number | Obtains the file descriptor. | +| getRawDescriptor(pipe: USBDevicePipe): Uint8Array | Obtains the raw USB descriptor. | +| controlTransfer(pipe: USBDevicePipe, controlparam: USBControlParams, timeout ?: number): Promise<number> | Performs control transfer. | + ## How to Develop -You can set a USB device as the USB host to connect to other USB devices for data transfer. The development procedure is as follows: - -1. Obtain the USB device list. - - ```js - // Import the USB API package. - import usb from '@ohos.usbManager'; - // Obtain the USB device list. - let deviceList = usb.getDevices(); - /* - Example deviceList structure - [ - { - name: "1-1", - serial: "", - manufacturerName: "", - productName: "", - version: "", - vendorId: 7531, - productId: 2, - clazz: 9, - subClass: 0, - protocol: 1, - devAddress: 1, - busNum: 1, - configs: [ - { - id: 1, - attributes: 224, - isRemoteWakeup: true, - isSelfPowered: true, - maxPower: 0, - name: "1-1", - interfaces: [ - { - id: 0, - protocol: 0, - clazz: 9, - subClass: 0, - alternateSetting: 0, - name: "1-1", - endpoints: [ - { - address: 129, - attributes: 3, - interval: 12, - maxPacketSize: 4, - direction: 128, - number: 1, - type: 3, - interfaceId: 0, - } - ] - } - ] - } - ] - } - ] - */ - ``` - +You can set a USB device as a host to connect to a device for data transfer. The development procedure is as follows: + + +1. Obtain the USB device list. + + ```js + // Import the USB API package. + import usb from '@ohos.usbManager'; + // Obtain the USB device list. + let deviceList = usb.getDevices(); + /* + Example deviceList structure: + [ + { + name: "1-1", + serial: "", + manufacturerName: "", + productName: "", + version: "", + vendorId: 7531, + productId: 2, + clazz: 9, + subClass: 0, + protocol: 1, + devAddress: 1, + busNum: 1, + configs: [ + { + id: 1, + attributes: 224, + isRemoteWakeup: true, + isSelfPowered: true, + maxPower: 0, + name: "1-1", + interfaces: [ + { + id: 0, + protocol: 0, + clazz: 9, + subClass: 0, + alternateSetting: 0, + name: "1-1", + endpoints: [ + { + address: 129, + attributes: 3, + interval: 12, + maxPacketSize: 4, + direction: 128, + number: 1, + type: 3, + interfaceId: 0, + } + ] + } + ] + } + ] + } + ] + */ + ``` 2. Obtain the device operation permissions. - ```js - let deviceName = deviceList[0].name; - // Request the permissions to operate a specified device. - usb.requestRight(deviceName).then(hasRight => { - console.info("usb device request right result: " + hasRight); - }).catch(error => { - console.info("usb device request right failed : " + error); - }); - ``` + ```js + let deviceName = deviceList[0].name; + // Request the permissions to operate a specified device. + usb.requestRight(deviceName).then(hasRight => { + console.info("usb device request right result: " + hasRight); + }).catch(error => { + console.info("usb device request right failed : " + error); + }); + ``` 3. Open the device. - ```js - // Open the device, and obtain the USB device pipe for data transfer. - let interface1 = deviceList[0].configs[0].interfaces[0]; - /* - Claim the corresponding interface from deviceList. - interface1 must be one present in the device configuration. - */ - usb.claimInterface(pipe, interface1, true); - ``` + ```js + // Open the device, and obtain the USB device pipe for data transfer. + let pipe = usb.connectDevice(deviceList[0]); + let interface1 = deviceList[0].configs[0].interfaces[0]; + /* + Claim the corresponding interface from **deviceList**. + interface1 must be one present in the device configuration. + */ + usb.claimInterface(pipe, interface1, true); + ``` 4. Perform data transfer. - ```js - /* + ```js + /* Read data. Select the corresponding RX endpoint from deviceList for data transfer. - (endpoint.direction == 0x80); dataUint8Array indicates the data to read. The data type is Uint8Array. - */ - let inEndpoint = interface1.endpoints[2]; - let outEndpoint = interface1.endpoints[1]; - let dataUint8Array = new Uint8Array(1024); - usb.bulkTransfer(pipe, inEndpoint, dataUint8Array, 15000).then(dataLength => { - if (dataLength >= 0) { - console.info("usb readData result Length : " + dataLength); - } else { - console.info("usb readData failed : " + dataLength); - } - }).catch(error => { - console.info("usb readData error : " + JSON.stringify(error)); - }); - // Send data. Select the corresponding TX endpoint from deviceList for data transfer. (endpoint.direction == 0) - usb.bulkTransfer(pipe, outEndpoint, dataUint8Array, 15000).then(dataLength => { - if (dataLength >= 0) { - console.info("usb writeData result write length : " + dataLength); - } else { - console.info("writeData failed"); - } - }).catch(error => { - console.info("usb writeData error : " + JSON.stringify(error)); - }); - ``` - -5. Release the USB interface, and close the USB device. - - ```js - usb.releaseInterface(pipe, interface); - usb.closePipe(pipe); - ``` \ No newline at end of file + (endpoint.direction == 0x80); dataUint8Array indicates the data to read. The data type is Uint8Array. + */ + let inEndpoint = interface1.endpoints[2]; + let outEndpoint = interface1.endpoints[1]; + let dataUint8Array = new Uint8Array(1024); + usb.bulkTransfer(pipe, inEndpoint, dataUint8Array, 15000).then(dataLength => { + if (dataLength >= 0) { + console.info("usb readData result Length : " + dataLength); + } else { + console.info("usb readData failed : " + dataLength); + } + }).catch(error => { + console.info("usb readData error : " + JSON.stringify(error)); + }); + // Send data. Select the corresponding TX endpoint from deviceList for data transfer. (endpoint.direction == 0) + usb.bulkTransfer(pipe, outEndpoint, dataUint8Array, 15000).then(dataLength => { + if (dataLength >= 0) { + console.info("usb writeData result write length : " + dataLength); + } else { + console.info("writeData failed"); + } + }).catch(error => { + console.info("usb writeData error : " + JSON.stringify(error)); + }); + ``` + +5. Release the USB interface, and close the USB device. + + ```js + usb.releaseInterface(pipe, interface1); + usb.closePipe(pipe); + ``` \ No newline at end of file diff --git a/en/application-dev/dfx/Readme-EN.md b/en/application-dev/dfx/Readme-EN.md index c6b449f197ba66d8bd6f4021abffe6ce31a69028..b5990650c61eae7ed57a0b1dbc35489947de8bc8 100644 --- a/en/application-dev/dfx/Readme-EN.md +++ b/en/application-dev/dfx/Readme-EN.md @@ -6,4 +6,7 @@ - [HiLog Development (Native)](hilog-guidelines.md) - Error Management - [Development of Error Manager](errormanager-guidelines.md) - - [Development of Application Recovery](apprecovery-guidelines.md) \ No newline at end of file + - [Development of Application Recovery](apprecovery-guidelines.md) +- Log Management + - [Application Freeze (appfreeze) Log Analysis](appfreeze-guidelines.md) + - [Process Crash (cppcrash) Log Analysis](cppcrash-guidelines.md) diff --git a/en/application-dev/dfx/appfreeze-guidelines.md b/en/application-dev/dfx/appfreeze-guidelines.md new file mode 100644 index 0000000000000000000000000000000000000000..05b52c4d8070386ec350701cefb2c6b63ef67d55 --- /dev/null +++ b/en/application-dev/dfx/appfreeze-guidelines.md @@ -0,0 +1,200 @@ +# Application Freeze (appfreeze) Log Analysis + +## Introduction + +Application freeze (appfreeze) means that an application does not respond to user operations (for example, clicking) within a given period of time. OpenHarmony provides a mechanism for detecting appfreeze faults and generates appfreeze logs for fault analysis. + +> NOTE +> +> This guide applies only to applications in the stage model. +> Before using this guide, you must have basic knowledge about the JS applications, C++ program stacks, and application-related subsystems. + +## How to Obtain + +appfreeze log is a type of fault logs managed together with the native process crash, JS application crash, and system process crash logs . You can obtain the log in any of the following ways. + +### Collecting Logs by Using Shell + +appfreeze logs start with **appfreeze-** in **/data/log/faultlog/faultlogger/**. + +The log files are named in the format of **appfreeze-application package name-application UID-time (seconds level)**. + +![appfreeze_20230308145160](figures/appfreeze_20230308145160.png) + +### Collecting Logs by Using DevEco Studio + +DevEco Studio collects device fault logs and saves them to FaultLog. + +The logs are displayed by the bundle name, fault, and time. + +![appfreeze_20230308145161](figures/appfreeze_20230308145161.png) + + +### Collecting Logs by Using faultLogger APIs + +The FaultLogger module provides APIs to query various fault information. For details, see [@ohos.faultLogger](../reference/apis/js-apis-faultLogger.md). + + +## appfreeze Detection + +Currently, appfreeze detection supports the fault types listed in the following table. + +| Fault Type| Description| +| -------- | -------- | +| THREAD_BLOCK_6S | The application main thread times out due to a suspension.| +| APPLICATION_BLOCK_INPUT | The user input response times out.| +| LIFECYCLE_TIMEOUT | Ability lifecycle switching times out.| +| APP_LIFECYCLE_TIMEOUT | Application lifecycle switching times out.| + +### Application Main Thread Timeout + +If this fault occurs, the main thread of the current application is suspended or too many tasks are executed, affecting task execution smoothness and experience. + +Such a fault can be detected as follows: The watchdog thread of the application periodically inserts an activation detection subthread to the main thread and inserts a timeout reporting subthread to its own thread. If activation detection is not executed within 3 seconds, the THREAD_BLOCK_3S event is reported; if activation detection is not executed within 6 seconds, the THREAD_BLOCK_6S event is reported. The two events together form an appfreeze log. The following figure shows the working principle. + +![appfreeze_20230308145163](figures/appfreeze_20230308145163.png) + +### User Input Response Timeout + +This fault affects user experience. If this fault occurs, the system does not respond to a click event within 10 seconds. + +Such a fault can be detected as follows: When a user clicks a certain button of the application, the input system sends a click event to the application. If the input system does not receive a response from the application within 10 seconds, a fault event is reported. The following figure shows the working principle. + +![appfreeze_20230308145162](figures/appfreeze_20230308145162.png) + +### Lifecycle Switching Timeout + +This fault refers to an ability lifecycle switching timeout (LIFECYCLE\_TIMEOUT) or an application lifecycle switching timeout (APP\_LIFECYCLE\_TIMEOUT). + +The fault occurs during lifecycle switching and affects the switchover between abilities in the current application or the switchover between applications. + +Such a fault can be detected as follows: Upon the start of a lifecycle switchover process, the main thread inserts a timeout task to the watchdog thread, and then removes the timeout task when the lifecycle switchover is complete. If the timeout duration expires, a fault event is reported. + +![appfreeze_20230308145164](figures/appfreeze_20230308145164.png) + +The timeout duration varies according to the lifecycle. + +| Lifecycle| Timeout Duration| +| -------- | -------- | +| Load | 10s | +| Terminate | 10s | +| Connect | 3s | +| Disconnect | 0.5s | +| Foreground | 5s | +| Background | 3s | + +## appfreeze Log Analysis + +To identify the cause of appfreeze, analyze the appfreeze logs together with HiLog logs. + +The following example uses main tread suspension as an example to illustrate how to conduct log analysis. You can treat other types of faults in a similar way. + +appfreeze logs are divided into several parts, including header information, and general and specific information in the body. + +### Log Header Information + +| Field| Description| +| -------- | -------- | +| Reason | Reason why the application does not respond. For details, see [appfreeze Detection](#appfreeze-detection).| +| PID | PID of the failed process, which can be used to search for related process information in the log.| +| PACKAGE_NAME | Application package name.| + +![appfreeze_20230310105865](figures/appfreeze_20230310105865.png) + +### General Information in the Log Body + +General information is present in all logs. It contains the fields listed in the following table. You can search for these fields to locate the related information in the log. + +| Field| Description| +| -------- | -------- | +| EVENTNAME | One or more fault events that constitute the cause of main thread suspension.| +| TIMESTAMP | Time when the fault event reported. You can narrow down the time range for viewing HiLog logs based on the timeout duration described in [appfreeze Detection](#appfreeze-detection).| +| PID | PID of the failed process, which can be used with the timestamp and timeout duration to search for related process information in the log.| +| PACKAGE_NAME | Application package name.| +| MSG | Dump information or description of the fault.| +| OpenStacktraceCatcher | Stack trace information of the process.| +| BinderCatcher | Information about IPC calls between a process and other system processes, such as the call waiting time.| +| PeerBinder Stacktrace | Information about stack trace of the peer process.| +| cpuusage | CPU usage of the device.| +| memory | Memory usage of the process.| + +The following is an example process stack of OpenStacktraceCatcher. + +In this example, when the stack surface window sends events through IPC, the process is stuck in the IPC communication phase. + +![appfreeze_20230310105869](figures/appfreeze_20230310105869.png) + +Example BinderCatcher information: + +In the following example, process 1561 sends an IPC request to process 685 but does not receive any response within 10 seconds. + +![appfreeze_20230310105868](figures/appfreeze_20230310105868.png) + +Example PeerBinder Stacktrace information: + +The following example shows the stack information of process 685, which is suspended at the peer end. + +![appfreeze_20230310105870](figures/appfreeze_20230310105870.png) + +Example CPU usage information: + +The following example shows the CPU usage information of the device. + +![appfreeze_20230310105871](figures/appfreeze_20230310105871.png) + +Example memory usage information: + +The following example shows the memory usage information of the process. + +![appfreeze_20230310105872](figures/appfreeze_20230310105872.png) + +### Specific Information in the Log Body (Application Main Thread Timeout) + +According to [Application Main Thread Timeout] (#application-main-thread-timeout), the log in which **Reason** is **THREAD\_BLOCK\_6S** consists of two parts: THREAD\_BLOCK\_3S and THREAD\_BLOCK\_6S. By comparing the two parts, you can determine whether the appfreeze is due to a suspension or an excess number of tasks. + +THREAD\_BLOCK\_3S is followed by THREAD\_BLOCK\_6S in the log. You can use the **EVENTNAME** field to search for the locations of the two events in the log. + +Both events contain the **MSG** field, which stores information about the processing queue of the main thread when the suspension occurs. Hence, you can view the status of the event processing queue of the main thread at the two time points. + +The example log shows that the event carrying **05:06:18.145** in the low-priority queue is being processed, and it is present in both the THREAD_BLOCK_3S and THREAD_BLOCK_6S. This indicates that the main thread suspension is not caused by an excess number of tasks. + +Because THREAD_BLOCK_6S indicates a main thread suspension, you only need to analyze the stack information of the main thread (the ID of the main thread is the same as the process ID). In the example log, the main thread stack is run in the JS through ArkUI and therefore it can be concluded that the suspension occurs in the JS. Because stack is present in both THREAD_BLOCK_3S and THREAD_BLOCK_6S in the same position, the JS suspension is not caused by an excess number of tasks. +THREAD_BLOCK_3S: + +![appfreeze_20230310105866](figures/appfreeze_20230310105866.png) + +THREAD_BLOCK_6S: + +![appfreeze_20230310105867](figures/appfreeze_20230310105867.png) + +Then, you can check for the code segment being executed on the application side based on the HiLog log. + +Generally, you can view the [general information in the log body](#general-information-in-the-log-body) to check for the cause of the suspension, for example, IPC suspension, high CPU usage, memory leakage, or high memory usage. + +### Specific Information in the Log Body (User Input Response Timeout) + +If **Reason** is **APPLICATION\_BLOCK\_INPUT**, no response is received within 10 seconds after a user click. + +You can find the event description in **MSG**. + +For details, see [General Information in the Log Body](#general-information-in-the-log-body). Note that there is a high probability that the main thread is suspended in the case of no response to the user input. You can compare the stack and BinderCatcher information in two log records for further analysis. If there is no log record indicating a main thread suspension, a large number of other events may exist before the input event. This may not cause a main thread suspension but can probably result in no response to user input. + +### Specific Information in the Log Body (Lifecycle Switching Timeout) + +For a lifecycle switching timeout, **Reason** can be **LIFECYCLE\_TIMEOUT** or **APP\_LIFECYCLE\_TIMEOUT**. + +**LIFECYCLE\_TIMEOUT** indicates a lifecycle switching timeout at the ability level, and **APP\_LIFECYCLE\_TIMEOUT** indicates a lifecycle switching timeout at the application level. + +MSG indicates the lifecycle that encounters a timeout. + +In this example, **LIFECYCLE\_TIMEOUT** indicates that the timeout occurs during switching of the ability to the background, and **APP\_LIFECYCLE\_TIMEOUT** indicates that the timeout occurs in the application termination phase. You can locate related HiLog logs according to the timeout duration described in [Lifecycle Switching Timeout] (#lifecycle-switching-timeout). + +LIFECYCLE_TIMEOUT: + +![appfreeze_20230310105873](figures/appfreeze_20230310105873.png) + +APP_LIFECYCLE_TIMEOUT: + +![appfreeze_20230310105874](figures/appfreeze_20230310105874.png) + +For details about other log information, see [General Information in the Log Body](#general-information-in-the-log-body). Note that there is a high probability that the main thread is suspended during lifecycle switching. You can compare the stack and BinderCatcher information in two log records for further analysis. diff --git a/en/application-dev/dfx/apprecovery-guidelines.md b/en/application-dev/dfx/apprecovery-guidelines.md index 5c297d3357d83feb0b6c1465f67ec2b085ade7b3..284de5ca6d5f6027f2cce975a29b3259b2778021 100644 --- a/en/application-dev/dfx/apprecovery-guidelines.md +++ b/en/application-dev/dfx/apprecovery-guidelines.md @@ -5,48 +5,29 @@ During application running, some unexpected behaviors are inevitable. For example, unprocessed exceptions and errors are thrown, and the call or running constraints of the recovery framework are violated. Process exit is treated as the default exception handling method. However, if user data is generated during application use, process exit may interrupt user operations and cause data loss. -Application recovery helps to restore the application state and save temporary data upon next startup in the case of an abnormal process exit, thus providing more consistent user experience. The application state includes two parts, namely, the page stack of the and the data saved in **onSaveState**. +In this way, application recovery APIs may help you save temporary data, restart an application after it exits, and restore its status and data, which deliver a better user experience. -In API version 9, application recovery is supported only for a single ability of the application developed using the stage model. Application state saving and automatic restart are performed when a JsError occurs. - -In API version 10, application recovery is also supported for multiple abilities of the application developed using the stage model. Application state storage and restore are performed when an AppFreeze occurs. If an application is killed in control mode, the application state will be restored upon next startup. +Currently, the APIs support only the development of an application that adopts the stage model, single process, and single ability. ## Available APIs -The application recovery APIs are provided by the **appRecovery** module, which can be imported via **import**. For details, see [Development Example](#development-example). +The application recovery APIs are provided by the **appRecovery** module, which can be imported via **import**. For details, see [Development Example](#development-example). This document describes behaviors of APIs in API version 9, and the content will update with changes. ### Available APIs | API | Description | | ------------------------------------------------------------ | ---------------------------------------------------- | -| enableAppRecovery(restart?: RestartFlag, saveOccasion?: SaveOccasionFlag, saveMode?: SaveModeFlag) : void;9+ | Enables application recovery. After this API is called, the first ability that is displayed when the application is started from the initiator can be restored.| -| saveAppState(): boolean;9+ | Saves the state of the ability that supports recovery in the current application.| -| restartApp(): void;9+ | Restarts the current process and starts the ability specified by **setRestartWant**. If no ability is specified, a foreground ability that supports recovery is restarted.| -| saveAppState(context?: UIAbilityContext): boolean;10+ | Saves the ability state specified by **Context**.| -| setRestartWant(want: Want): void;10+ | Sets the abilities to restart when **restartApp** is actively called and **RestartFlag** is not **NO_RESTART**. The abilities must be under the same bundle name and must be a **UiAbility**.| +| enableAppRecovery(restart?: RestartFlag, saveOccasion?: SaveOccasionFlag, saveMode?: SaveModeFlag) : void; | Enables the application recovery function.| +| saveAppState(): boolean; | Saves the ability status of an application. | +| restartApp(): void; | Restarts the current process. If there is saved ability status, it will be passed to the **want** parameter's **wantParam** attribute of the **onCreate** lifecycle callback of the ability.| -No error will be thrown if the preceding APIs are used in the troubleshooting scenario. The following are some notes on API usage: +The APIs are used for troubleshooting and do not return any exception. Therefore, you need to be familiar with when they are used. **enableAppRecovery**: This API should be called during application initialization. For example, you can call this API in **onCreate** of **AbilityStage**. For details, see [Parameter Description](../reference/apis/js-apis-app-ability-appRecovery.md). -**saveAppState**: After this API is called, the recovery framework invokes **onSaveState** for all abilities that support recovery in the current process. If you choose to save data in **onSaveState**, the related data and ability page stack are persistently stored in the local cache of the application. To save data of the specified ability, you need to specify the context corresponding to that ability. - -**setRestartWant**: This API specifies the ability to be restarted by **appRecovery**. - -**restartApp**: After this API is called, the recovery framework kills the current process and restarts the ability specified by **setRestartWant**, with **APP_RECOVERY** set as the startup cause. In API version 9 and scenarios where an ability is not specified by **setRestartWant**, the last foreground ability that supports recovery is started. If the no foreground ability supports recovery, the application crashes. If a saved state is available for the restarted ability, the saved state is passed as the **wantParam** attribute in the **want** parameter of the ability's **onCreate** callback. - -### Application State Management -Since API version 10, application recovery is not limited to automatic restart in the case of an exception. Therefore, you need to understand when the application will load the saved state. -If the last exit of an application is not initiated by a user and a saved state is available for recovery, the startup reason is set to **APP_RECOVERY** when the application is started by the user next time, and the recovery state of the application is cleared. -The application recovery status flag is set when **saveAppState** is actively or passively called. The flag is cleared when the application exits normally or the saved state is consumed. (A normal exit is usually triggered by pressing the back key or clearing recent tasks.) - -![Application recovery status management](./figures/application_recovery_status_management.png) - -### Application State Saving and Restore -API version 10 or later supports saving of the application state when an application is suspended. If a JsError occurs, **onSaveState** is called in the main thread. If an AppFreeze occurs, however, the main thread may be suspended, and therefore **onSaveState** is called in a non-main thread. The following figure shows the main service flow. +**saveAppState**: After this API is called, the framework calls back **onSaveState** of the ability. If data saving is accepted in this API, relevant data and the page stack of the ability are persisted to the local cache of the application. -![Application recovery from the freezing state](./figures/application_recovery_from_freezing.png) -When the application is suspended, the callback is not executed in the JS thread. Therefore, you are advised not to use the imported dynamic Native library or access the **thread_local** object created by the main thread in the code of the **onSaveState** callback. +**restartApp**: After this API is called, the framework kills the current application process and restarts the ability in the foreground, with **APP_RECOVERY** specified as the startup cause. ### Framework Fault Management @@ -59,7 +40,9 @@ Fault management is an important way for applications to deliver a better user e - Fault query is the process of calling APIs of [faultLogger](../reference/apis/js-apis-faultLogger.md) to obtain the fault information. The figure below does not illustrate the time when [faultLogger](../reference/apis/js-apis-faultLogger.md) is called. You can refer to the [LastExitReason](../reference/apis/js-apis-app-ability-abilityConstant.md#abilityconstantlastexitreason) passed during application initialization to determine whether to call [faultLogger](../reference/apis/js-apis-faultLogger.md) to query information about the previous fault. + ![Fault rectification process](./figures/fault_rectification.png) + It is recommended that you call [errorManager](../reference/apis/js-apis-app-ability-errorManager.md) to handle the exception. After the processing is complete, you can call the **saveAppState** API and restart the application. If you do not register [ErrorObserver](../reference/apis/js-apis-inner-application-errorObserver.md) or enable application recovery, the application process will exit according to the default processing logic of the system. Users can restart the application from the home screen. If you have enabled application recovery, the recovery framework first checks whether application state saving is supported and whether the application state saving is enabled. If so, the recovery framework invokes [onSaveState](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityonsavestate) of the [Ability](../reference/apis/js-apis-app-ability-uiAbility.md). Finally, the application is restarted. @@ -71,7 +54,7 @@ Common fault types include JavaScript application crash, application freezing, a | Fault | Fault Listening | State Saving| Automatic Restart| Log Query| | ----------|--------- |--------- |--------- |--------- | | [JS_CRASH](../reference/apis/js-apis-faultLogger.md#faulttype) | Supported|Supported|Supported|Supported| -| [APP_FREEZE](../reference/apis/js-apis-faultLogger.md#faulttype) | Not supported|Supported|Supported|Supported| +| [APP_FREEZE](../reference/apis/js-apis-faultLogger.md#faulttype) | Not supported|Not supported|Supported|Supported| | [CPP_CRASH](../reference/apis/js-apis-faultLogger.md#faulttype) | Not supported|Not supported|Not supported|Supported| **State Saving** in the table header means saving of the application state when a fault occurs. To protect user data as much as possible when an AppFreeze occurs, you can adopt either the periodic or automatic way, and the latter will save user data when an ability is switched to the background. @@ -96,31 +79,19 @@ export default class MyAbilityStage extends AbilityStage { appRecovery.SaveModeFlag.SAVE_WITH_FILE); } } -``` -### Enabling Application Recovery for the Specified Abilities -Generally, the ability configuration list is named **module.json5**. -```json -{ - "abilities": [ - { - "name": "EntryAbility", - "recoverable": true, - }] -} - ``` ### Saving and Restoring Data After enabling **appRecovery**, you can use this function by either actively or passively saving the application state and restoring data in the ability. -The following is an example of **EntryAbility**: +The following is an example of **MainAbility**: #### Importing the Service Package ```ts -import errorManager from '@ohos.app.ability.errorManager'; -import appRecovery from '@ohos.app.ability.appRecovery'; -import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import errorManager from '@ohos.app.ability.errorManager' +import appRecovery from '@ohos.app.ability.appRecovery' +import AbilityConstant from '@ohos.app.ability.AbilityConstant' ``` #### Actively Saving the Application State and Restoring Data @@ -139,7 +110,7 @@ import AbilityConstant from '@ohos.app.ability.AbilityConstant'; onWindowStageCreate(windowStage) { // Main window is created, set main page for this ability - console.log("[Demo] EntryAbility onWindowStageCreate") + console.log("[Demo] MainAbility onWindowStageCreate") globalThis.registerObserver = (() => { registerId = errorManager.on('error', callback); @@ -151,12 +122,12 @@ import AbilityConstant from '@ohos.app.ability.AbilityConstant'; - Save data. -After the callback triggers **appRecovery.saveAppState()**, **onSaveState(state, wantParams)** of **EntryAbility** is triggered. +After the callback triggers **appRecovery.saveAppState()**, **onSaveState(state, wantParams)** of **MainAbility** is triggered. ```ts onSaveState(state, wantParams) { // Ability has called to save app data - console.log("[Demo] EntryAbility onSaveState") + console.log("[Demo] MainAbility onSaveState") wantParams["myData"] = "my1234567"; return AbilityConstant.OnSaveResult.ALL_AGREE; } @@ -164,12 +135,12 @@ After the callback triggers **appRecovery.saveAppState()**, **onSaveState(state, - Restore data. -After the callback triggers **appRecovery.restartApp()**, the application is restarted. After the restart, **onCreate(want, launchParam)** of **EntryAbility** is called, and the saved data is stored in **parameters** of **want**. +After the callback triggers **appRecovery.restartApp()**, the application is restarted. After the restart, **onCreate(want, launchParam)** of **MainAbility** is called, and the saved data is in **parameters** of **want**. ```ts storage: LocalStorage onCreate(want, launchParam) { - console.log("[Demo] EntryAbility onCreate") + console.log("[Demo] MainAbility onCreate") globalThis.abilityWant = want; if (launchParam.launchReason == AbilityConstant.LaunchReason.APP_RECOVERY) { this.storage = new LocalStorage(); @@ -185,7 +156,7 @@ onCreate(want, launchParam) { ```ts onWindowStageDestroy() { // Main window is destroyed, release UI related resources - console.log("[Demo] EntryAbility onWindowStageDestroy") + console.log("[Demo] MainAbility onWindowStageDestroy") globalThis.unRegisterObserver = (() => { errorManager.off('error', registerId, (err) => { @@ -200,10 +171,10 @@ onWindowStageDestroy() { This is triggered by the recovery framework. You do not need to register an **ErrorObserver** callback. You only need to implement **onSaveState** for application state saving and **onCreate** for data restore. ```ts -export default class EntryAbility extends Ability { +export default class MainAbility extends Ability { storage: LocalStorage onCreate(want, launchParam) { - console.log("[Demo] EntryAbility onCreate") + console.log("[Demo] MainAbility onCreate") globalThis.abilityWant = want; if (launchParam.launchReason == AbilityConstant.LaunchReason.APP_RECOVERY) { this.storage = new LocalStorage(); @@ -215,7 +186,7 @@ export default class EntryAbility extends Ability { onSaveState(state, wantParams) { // Ability has called to save app data - console.log("[Demo] EntryAbility onSaveState") + console.log("[Demo] MainAbility onSaveState") wantParams["myData"] = "my1234567"; return AbilityConstant.OnSaveResult.ALL_AGREE; } diff --git a/en/application-dev/dfx/cppcrash-guidelines.md b/en/application-dev/dfx/cppcrash-guidelines.md new file mode 100644 index 0000000000000000000000000000000000000000..4454422fe4f3aec6c781090a2e833ee103488dab --- /dev/null +++ b/en/application-dev/dfx/cppcrash-guidelines.md @@ -0,0 +1,110 @@ +# cppcrash Log Analysis + +## Introduction + +A process crash refers to a C/C++ runtime crash. The FaultLogger module of OpenHarmony provides capabilities such as process crash detection, log collection, log storage, and log reporting, helping you to locate faults more effectively. + +In this document, you'll be guided through how to implement process crash detection, crash log collection, and crash log analysis. Before getting started, make sure you have basic knowledge about C/C++ program stacks. + +## Process Crash Detection + +Process crash detection is implemented based on the Linux signal mechanism. Currently, C/C++ crash exception signals listed in the following table are supported. + +| Signal Value| Signal| Description| Trigger Cause| +| ------ | --------- | --------------- | ------------------------------------------- | +| 4 | SIGILL | Invalid instruction | An invalid, incorrectly formatted, unknown, or privileged instruction is executed.| +| 5 | SIGTRAP | Breakpoint or trap | An exception occurs or a trap instruction is executed.| +| 6 | SIGABRT | Process abort | The process is aborted abnormally. Generally, this problem occurs if the process calls the `abort()` function of the standard function library.| +| 7 | SIGBUS | Illegal memory access | The process accesses an aligned or nonexistent physical address.| +| 8 | SIGFPE | Floating-point exception | The process performs an incorrect arithmetic operation, for example, a 0 divisor, floating point overflow, or integer overflow.| +| 11 | SIGSEGV | Invalid memory access | The process accesses an invalid memory reference.| +| 16 | SIGSTKFLT | Stack error | The processor performs an incorrect stack operation, such as a pop when the stack is empty or a push when the stack is full.| +| 31 | SIGSYS | Incorrect system call | An incorrect or invalid parameter is used in a system call.| + +## Crash Log Collection + +Process crash log is the fault log managed together with the app freeze and JS application crash logs by the FaultLogger module. You can collect process crash logs in any of the following ways: + +### Collecting Logs by Using Shell + +- Fault logs in the `/data/log/faultlog/faultlogger/` directory of the device. The log files are named in the format of `cppcrash-process name-process UID-time (seconds level)`. They contain only information such as the device name, system version, and process crash call stack. + + ![cppcrash-faultlogger-log](figures/20230407112159.png) + +- Fault logs in the `/data/log/faultlog/temp/` directory of the device. The log files are named in the format of `cppcrash-process name-process PID-system timestamp (seconds level)`. In addition to basic information, they also contain information such as the stack memory and process maps at the time of process crash. + + ![cppcrash-temp-log](figures/20230407111853.png) + +### Collecting Logs by Using DevEco Studio + +DevEco Studio collects process crash logs from `/data/log/faultlog/faultlogger/` to FaultLog, where logs are displayed by process name, fault, and time. + +![DevEco Studio cppcrash](figures/20230407112620.png) + +### Collecting Logs by Using faultLogger APIs + +The FaultLogger module provides APIs to query various fault information. For details, see [@ohos.faultLogger](../reference/apis/js-apis-faultLogger.md). + +## Process Crash Log Analysis + +### Log Format + +The following is an example process crash log archived by DevEco Studio in FaultLog: + +``` +Generated by HiviewDFX@OpenHarmony +================================================================== +Device info:OpenHarmony 3.2 <- Device information +Build info:OpenHarmony 4.0.5.5 <- Version information +Module name:crasher_c <- Module name +Pid:1205 <- Process ID +Uid:0 <- User ID +Reason:Signal:SIGSEGV(SEGV_ACCERR)@0x0042d33d <- Exception information +Thread name:crasher <- Abnormal thread +#00 pc 0000332c /data/crasher(TriggerSegmentFaultException+15)(8bc37ceb8d6169e919d178fdc7f5449e) <- Call stack +#01 pc 000035c7 /data/crasher(ParseAndDoCrash+277)(8bc37ceb8d6169e919d178fdc7f5449e) +#02 pc 00003689 /data/crasher(main+39)(8bc37ceb8d6169e919d178fdc7f5449e) +#03 pc 000c3b08 /system/lib/ld-musl-arm.so.1(__libc_start_main+116) +#04 pc 000032f8 /data/crasher(_start_c+112)(8bc37ceb8d6169e919d178fdc7f5449e) +#05 pc 00003284 /data/crasher(_start+32)(8bc37ceb8d6169e919d178fdc7f5449e) +... +``` + +### Locating Faults Through Logs + +1. Determine the faulty module and fault type based on fault logs. + + Generally, you can identify the faulty module based on the crash process name and identify the crash cause based on the signal. Besides, you can restore the function call chain of the crash stack based on the method name in the stack. + + In the example, **SIGSEGV** is thrown by the Linux kernel because of access to an invalid memory address. The problem occurs in the **TriggerSegmentFaultException** function. + + In most scenarios, a crash is caused by the top layer of the crash stack, such as null pointer access and proactive program abort. + + If the cause cannot be located through the call stack, you need to check for other faults, for example, memory corruption or stack overflow. + +2. Use the addr2line tool of Linux to parse the code line number to restore the call stack at the time of process crash. + + When using the addr2line tool to parse the code line number of the crash stack, make sure that binary files with debugging information is used. Generally, such files are generated during version build or application build. + + Application binary files are located in DevEco Studio's temporary directory for application build, for example, `build/default/intermediates/libs`. + + System binary files are stored in the directories listed below. For versions that are directly obtained, the binary files are archived in the image package. + ``` + \code root directory\out\product\lib.unstripped + \code root directory\out\product\exe.unstripped + ``` + + You can run `apt-get install addr2line` to install the addr2line tool on Linux. + + On On DevEco Studio, you can also use the llvm-addr2line tool archived in the SDK to parse code line numbers. The usage method is the same. + + The following example shows how to use the addr2line tool to parse the code line number based on the offset address: + + ``` + root:~/OpenHarmony/out/rk3568/exe.unstripped/hiviewdfx/faultloggerd$ addr2line -e crasher 0000332c + base/hiviewdfx/faultloggerd/tools/crasher/dfx_crasher.c:57 + ``` + + In this example, the crash is caused by assignment of a value to an unwritable area. It is in code line 57 in the **dfx_crasher.c** file. You can modify it to avoid the crash. + + If the obtained code line number is seemingly incorrect, you can fine-tune the address (for example, subtract the address by 1) or disable some compilation optimization items. It is known that the obtained code line number may be incorrect when Link Time Optimization (LTO) is enabled. diff --git a/en/application-dev/dfx/errormanager-guidelines.md b/en/application-dev/dfx/errormanager-guidelines.md index 8509fff09e51cd31665e80fab6dce0f2472ab08d..4679cfcfc78893590fe73eab770e49fc68a1a828 100644 --- a/en/application-dev/dfx/errormanager-guidelines.md +++ b/en/application-dev/dfx/errormanager-guidelines.md @@ -23,8 +23,7 @@ When an asynchronous callback is used, the return value can be processed directl | API | Description | | ------------------------------ | ------------------------------------------------------------ | -| onUnhandledException(errMsg: string): void | Called when an uncaught exception is reported after the application is registered.| -| onException?(errObject: Error): void | Called when an application exception is reported to the JavaScript layer after the application is registered.| +| onUnhandledException(errMsg: string): void | Called when an application generates an uncaught exception after being registered.| ### Result Codes for Unregistering an Observer @@ -44,13 +43,6 @@ let registerId = -1; let callback = { onUnhandledException: function (errMsg) { console.log(errMsg); - }, - onException: function (errorObj) { - console.log('onException, name: ', errorObj.name); - console.log('onException, message: ', errorObj.message); - if (typeof(errorObj.stack) === 'string') { - console.log('onException, stack: ', errorObj.stack); - } } } diff --git a/en/application-dev/dfx/figures/20230407111853.png b/en/application-dev/dfx/figures/20230407111853.png new file mode 100644 index 0000000000000000000000000000000000000000..cedfb46aecd8a3a1a9482619e4b0ea5f18eccc4a Binary files /dev/null and b/en/application-dev/dfx/figures/20230407111853.png differ diff --git a/en/application-dev/dfx/figures/20230407112159.png b/en/application-dev/dfx/figures/20230407112159.png new file mode 100644 index 0000000000000000000000000000000000000000..c2bce4198850fc25bdb2a4328c1b600d99d39e88 Binary files /dev/null and b/en/application-dev/dfx/figures/20230407112159.png differ diff --git a/en/application-dev/dfx/figures/20230407112620.png b/en/application-dev/dfx/figures/20230407112620.png new file mode 100644 index 0000000000000000000000000000000000000000..59a25256717ee791e0a3c40ec1d46c78d889a60f Binary files /dev/null and b/en/application-dev/dfx/figures/20230407112620.png differ diff --git a/en/application-dev/dfx/figures/appfreeze_20230308145160.png b/en/application-dev/dfx/figures/appfreeze_20230308145160.png new file mode 100644 index 0000000000000000000000000000000000000000..2be8a97cf7b2518a0361cb0f8965642731282350 Binary files /dev/null and b/en/application-dev/dfx/figures/appfreeze_20230308145160.png differ diff --git a/en/application-dev/dfx/figures/appfreeze_20230308145161.png b/en/application-dev/dfx/figures/appfreeze_20230308145161.png new file mode 100644 index 0000000000000000000000000000000000000000..92c236037b7c75f6480b3781ee6b1aa15e44cc51 Binary files /dev/null and b/en/application-dev/dfx/figures/appfreeze_20230308145161.png differ diff --git a/en/application-dev/dfx/figures/appfreeze_20230308145162.png b/en/application-dev/dfx/figures/appfreeze_20230308145162.png new file mode 100644 index 0000000000000000000000000000000000000000..9169db911499f350a302eb060300d2c83c9fae19 Binary files /dev/null and b/en/application-dev/dfx/figures/appfreeze_20230308145162.png differ diff --git a/en/application-dev/dfx/figures/appfreeze_20230308145163.png b/en/application-dev/dfx/figures/appfreeze_20230308145163.png new file mode 100644 index 0000000000000000000000000000000000000000..14c42dc9159174e7ddb283b1454963d40c6871f1 Binary files /dev/null and b/en/application-dev/dfx/figures/appfreeze_20230308145163.png differ diff --git a/en/application-dev/dfx/figures/appfreeze_20230308145164.png b/en/application-dev/dfx/figures/appfreeze_20230308145164.png new file mode 100644 index 0000000000000000000000000000000000000000..7311f26bd906fa24331eaa10b66643eb09cf266f Binary files /dev/null and b/en/application-dev/dfx/figures/appfreeze_20230308145164.png differ diff --git a/en/application-dev/dfx/figures/appfreeze_20230310105865.png b/en/application-dev/dfx/figures/appfreeze_20230310105865.png new file mode 100644 index 0000000000000000000000000000000000000000..0082b4a012d79e2a407934abc6b3e45e580e20dd Binary files /dev/null and b/en/application-dev/dfx/figures/appfreeze_20230310105865.png differ diff --git a/en/application-dev/dfx/figures/appfreeze_20230310105866.png b/en/application-dev/dfx/figures/appfreeze_20230310105866.png new file mode 100644 index 0000000000000000000000000000000000000000..87e25e01d01d5e039c1089ee7604d2e14403efee Binary files /dev/null and b/en/application-dev/dfx/figures/appfreeze_20230310105866.png differ diff --git a/en/application-dev/dfx/figures/appfreeze_20230310105867.png b/en/application-dev/dfx/figures/appfreeze_20230310105867.png new file mode 100644 index 0000000000000000000000000000000000000000..c77c4686a66c56dc051aaa3a1d7996a3cb93985b Binary files /dev/null and b/en/application-dev/dfx/figures/appfreeze_20230310105867.png differ diff --git a/en/application-dev/dfx/figures/appfreeze_20230310105868.png b/en/application-dev/dfx/figures/appfreeze_20230310105868.png new file mode 100644 index 0000000000000000000000000000000000000000..7c1f36e709e4b07908567a7124df5e45fbd9bad1 Binary files /dev/null and b/en/application-dev/dfx/figures/appfreeze_20230310105868.png differ diff --git a/en/application-dev/dfx/figures/appfreeze_20230310105869.png b/en/application-dev/dfx/figures/appfreeze_20230310105869.png new file mode 100644 index 0000000000000000000000000000000000000000..a55b3373405f2f4db972507e2f35102021c7f92a Binary files /dev/null and b/en/application-dev/dfx/figures/appfreeze_20230310105869.png differ diff --git a/en/application-dev/dfx/figures/appfreeze_20230310105870.png b/en/application-dev/dfx/figures/appfreeze_20230310105870.png new file mode 100644 index 0000000000000000000000000000000000000000..73c0549142e49e233b3ea38f8e1b6e44c642a30e Binary files /dev/null and b/en/application-dev/dfx/figures/appfreeze_20230310105870.png differ diff --git a/en/application-dev/dfx/figures/appfreeze_20230310105871.png b/en/application-dev/dfx/figures/appfreeze_20230310105871.png new file mode 100644 index 0000000000000000000000000000000000000000..ea8fe6bb1156255571e45e4e22d69cea70ae474f Binary files /dev/null and b/en/application-dev/dfx/figures/appfreeze_20230310105871.png differ diff --git a/en/application-dev/dfx/figures/appfreeze_20230310105872.png b/en/application-dev/dfx/figures/appfreeze_20230310105872.png new file mode 100644 index 0000000000000000000000000000000000000000..43406b804f9c981e636f4ad6099ce1abd69fb3d1 Binary files /dev/null and b/en/application-dev/dfx/figures/appfreeze_20230310105872.png differ diff --git a/en/application-dev/dfx/figures/appfreeze_20230310105873.png b/en/application-dev/dfx/figures/appfreeze_20230310105873.png new file mode 100644 index 0000000000000000000000000000000000000000..71457fa6a49bf657a3b4527c7a000818c824ba94 Binary files /dev/null and b/en/application-dev/dfx/figures/appfreeze_20230310105873.png differ diff --git a/en/application-dev/dfx/figures/appfreeze_20230310105874.png b/en/application-dev/dfx/figures/appfreeze_20230310105874.png new file mode 100644 index 0000000000000000000000000000000000000000..cb4fc75b47b439fe131121586f13bdbf41408082 Binary files /dev/null and b/en/application-dev/dfx/figures/appfreeze_20230310105874.png differ diff --git a/en/application-dev/dfx/figures/application_recovery_from_freezing.png b/en/application-dev/dfx/figures/application_recovery_from_freezing.png deleted file mode 100644 index 968b4cefc5e898209cdae117c7f9f667bc9fbd64..0000000000000000000000000000000000000000 Binary files a/en/application-dev/dfx/figures/application_recovery_from_freezing.png and /dev/null differ diff --git a/en/application-dev/dfx/figures/application_recovery_status_management.png b/en/application-dev/dfx/figures/application_recovery_status_management.png deleted file mode 100644 index 762504c1d1027be87233e589988be2091640191b..0000000000000000000000000000000000000000 Binary files a/en/application-dev/dfx/figures/application_recovery_status_management.png and /dev/null differ diff --git a/en/application-dev/dfx/figures/fault_rectification.png b/en/application-dev/dfx/figures/fault_rectification.png index a178b2691616d406d2668806ffcd4f89c8ca82a3..67aa40592f7bcad23e216222e898c1f1327a4efb 100644 Binary files a/en/application-dev/dfx/figures/fault_rectification.png and b/en/application-dev/dfx/figures/fault_rectification.png differ diff --git a/en/application-dev/dfx/hiappevent-guidelines.md b/en/application-dev/dfx/hiappevent-guidelines.md index 569b16d587af811d32e425a534ab4dc0df6a4be6..d21d4e3fa9e0fa0b795c82e7157cd6215eab5e0c 100644 --- a/en/application-dev/dfx/hiappevent-guidelines.md +++ b/en/application-dev/dfx/hiappevent-guidelines.md @@ -49,11 +49,11 @@ The following example illustrates how to log and subscribe to button click event ```js import hilog from '@ohos.hilog'; - import UIAbility from '@ohos.app.ability.UIAbility'; + import Ability from '@ohos.application.Ability' import Window from '@ohos.window' import hiAppEvent from '@ohos.hiviewdfx.hiAppEvent' - export default class EntryAbility extends UIAbility { + export default class EntryAbility extends Ability { onCreate(want, launchParam) { hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); diff --git a/en/application-dev/dfx/hilog-guidelines.md b/en/application-dev/dfx/hilog-guidelines.md index ef09dabc109c1797949d928bce98564ad9ad76ba..4d81bbe140bbcc3da72e58dc3c75ce9e3b88aee4 100644 --- a/en/application-dev/dfx/hilog-guidelines.md +++ b/en/application-dev/dfx/hilog-guidelines.md @@ -1,30 +1,30 @@ -# HiLog Development +# HiLog Development (Native) -## Overview +## Introduction HiLog is the log system of OpenHarmony that provides logging for the system framework, services, and applications to record information on user operations and system running status. > **NOTE** > -> This development guide is applicable only when you use Native APIs for application development. For details about the APIs, see [HiLog Native API Reference](https://gitee.com/openharmony-sig/interface_native_header/blob/master/en/native_sdk/dfx/log.h). +> This development guide is applicable only when you use Native APIs for application development. For details about the APIs, see [HiLog Native API Reference](../reference/native-apis/_hi_log.md). ## Available APIs | API/Macro| Description| | -------- | -------- | -| int OH_LOG_Print(LogType type, LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...) | Outputs logs based on the specified log type, log level, service domain, log tag, and variable parameters determined by the format specifier and privacy identifier in the printf format.
Input parameters: See [Parameter Description](#parameter-description).
Output parameters: None
Return value: total number of bytes if log printing is successful; **-1** otherwise.| -| #define OH_LOG_DEBUG(type, ...) ((void)OH_LOG_Print((type), LOG_DEBUG, LOG_DOMAIN, LOG_TAG, \_*VA*ARGS__))| Outputs DEBUG logs. This is a function-like macro.| -| #define OH_LOG_INFO(type, ...) ((void)OH_LOG_Print((type), LOG_INFO, LOG_DOMAIN, LOG_TAG, \_*VA*ARGS__)) | Outputs INFO logs. This is a function-like macro.| -| #define OH_LOG_WARN(type, ...) ((void)OH_LOG_Print((type), LOG_WARN, LOG_DOMAIN, LOG_TAG, \_*VA*ARGS__)) | Outputs WARN logs. This is a function-like macro.| -| #define OH_LOG_ERROR(type, ...) ((void)OH_LOG_Print((type), LOG_ERROR, LOG_DOMAIN, LOG_TAG, \_*VA*ARGS__)) | Outputs ERROR logs. This is a function-like macro.| -| #define OH_LOG_FATAL(type, ...) ((void)OH_LOG_Print((type), LOG_FATAL, LOG_DOMAIN, LOG_TAG, \_*VA*ARGS__)) | Outputs FATAL logs. This is a function-like macro.| -| bool OH_LOG_IsLoggable(unsigned int domain, const char *tag, LogLevel level) | Checks whether logs of the specified service domain, tag, and level can be printed.
Input parameters: See [Parameter Description](#parameter-description).
Output arguments: none
Return value: **true** if the specified logs can be printed; **false** otherwise.| +| int OH_LOG_Print(LogType type, LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...) | Outputs logs based on the specified log type, log level, service domain, log tag, and variable parameters determined by the format specifier and privacy identifier in the printf format.
Input arguments: See [Parameter Description](#parameter-description).
Output arguments: None
Return value: total number of bytes if log printing is successful; **-1** otherwise.| +| #define OH_LOG_DEBUG(type, ...) ((void)OH_LOG_Print((type), LOG_DEBUG, LOG_DOMAIN, LOG_TAG, \__VA_ARGS__))| Outputs DEBUG logs. This is a function-like macro.| +| #define OH_LOG_INFO(type, ...) ((void)OH_LOG_Print((type), LOG_INFO, LOG_DOMAIN, LOG_TAG, \__VA_ARGS__)) | Outputs INFO logs. This is a function-like macro.| +| #define OH_LOG_WARN(type, ...) ((void)OH_LOG_Print((type), LOG_WARN, LOG_DOMAIN, LOG_TAG, \__VA_ARGS__)) | Outputs WARN logs. This is a function-like macro.| +| #define OH_LOG_ERROR(type, ...) ((void)OH_LOG_Print((type), LOG_ERROR, LOG_DOMAIN, LOG_TAG, \__VA_ARGS__)) | Outputs ERROR logs. This is a function-like macro.| +| #define OH_LOG_FATAL(type, ...) ((void)OH_LOG_Print((type), LOG_FATAL, LOG_DOMAIN, LOG_TAG, \__VA_ARGS__)) | Outputs FATAL logs. This is a function-like macro.| +| bool OH_LOG_IsLoggable(unsigned int domain, const char *tag, LogLevel level) | Checks whether logs of the specified service domain, tag, and level can be printed.
Input arguments: See [Parameter Description](#parameter-description).
Output arguments: none
Return value: **true** if the specified logs can be printed; **false** otherwise.| ## Parameter Description | Name| Type | Mandatory| Description | | ------ | ------ | ---- | ------------------------------------------------------------ | -| type | enum | Yes | Enum of log printing types. The default value is **LOG_APP** for application logs.| +| type | enum | Yes | Log printing type. The default value is **LOG_APP** for application logs.| | level | enum | Yes | Log printing level. For details, see [Log Level](#loglevel).| | domain | number | Yes | Service domain of logs. The value ranges from **0x0** to **0xFFFF**.
You can define the value as required. | | tag | string | Yes | Log tag in the string format. You are advised to use this parameter to identify a particular service behavior or the class holding the ongoing method.| @@ -33,7 +33,7 @@ HiLog is the log system of OpenHarmony that provides logging for the system fram ## LogLevel -Log level. +Enumerates log levels. | Name | Value | Description | | ----- | ------ | ------------------------------------------------------------ | @@ -43,7 +43,7 @@ Log level. | ERROR | 6 | Log level used to record program or functional errors that affect the normal running or use of the functionality and can be fixed at a high cost, for example, by resetting data.| | FATAL | 7 | Log level used to record program or functionality crashes that cannot be rectified. -## Development Examples +## Development Example 1. Add the link of **libhilog_ndk.z.so** to **CMakeLists.txt**: ``` diff --git a/en/application-dev/dfx/hitracechain-guidelines.md b/en/application-dev/dfx/hitracechain-guidelines.md index 37ca65ece66a124eb8a72f1fd865f30d26024627..affd260b0503f3c4f4c4b748d5911d94f7fef9e3 100644 --- a/en/application-dev/dfx/hitracechain-guidelines.md +++ b/en/application-dev/dfx/hitracechain-guidelines.md @@ -2,7 +2,9 @@ ## Introduction -hiTraceChain is a lightweight implementation of the cloud-based distributed call chain tracing. It allows applications to trace cross-thread, cross-process, and cross-device service calls. The hiTraceChain module generates a unique **chainId** for a service process and passes it to various information (including application events, system time, and logs) specific to the service process. During debugging and fault locating, you can use the unique **chainId** to quickly correlate various information related to the service process. The hiTraceChain module provides APIs to implement call chain tracing throughout a service process. This can help you quickly obtain the run log for the call chain of a specified service process and locate faults in inter-device, inter-process, or inter-thread communications. +The hiTraceChain module provides APIs to implement call chain tracing throughout a service process. This can help you quickly obtain the run log for the call chain of a specified service process and locate faults in inter-device, inter-process, or inter-thread communications. + +hiTraceChain is a lightweight implementation of the cloud-based distributed call chain tracing. It allows applications to trace cross-thread, cross-process, and cross-device service calls. The hiTraceChain module generates a unique **chainId** for a service process and passes it to various information (including application events, system time, and logs) specific to the service process. During debugging and fault locating, you can use the unique **chainId** to quickly correlate various information related to the service process. ## Basic Concepts @@ -16,106 +18,47 @@ The APIs for distributed call chain tracing are provided by the **hiTraceChain** **APIs for distributed call chain tracing** -| API | Return Value | Description | -| ------------------------------------------------------------------------------------------------------------------- | -------------- | ------------ | -| hiTraceChain.begin(name: string, flags: number = HiTraceFlag.DEFAULT) | HiTraceId | Starts call chain tracing. | -| hiTraceChain.end(id: HiTraceId) | void | Stops call chain tracing. | +| API| Return Value| Description| +| ------------------------------------------------------------------------------------------------------------------- | -------------- | ------------ | +| hiTraceChain.begin(name: string, flags: number = HiTraceFlag.DEFAULT) | HiTraceId | Starts call chain tracing.| +| hiTraceChain.tracepoint(mode: HiTraceCommunicationMode, type: HiTraceTracepointType, id: HiTraceId, msg?: string) | void | Creates a trace point.| +| hiTraceChain.end(id: HiTraceId) | void | Stops call chain tracing.| ## How to Develop -The following example illustrates how to simulate one-time [system event logging](../reference/apis/js-apis-hisysevent.md) to implement cross-thread distributed call chain tracing in a single HAP service. - -1. Create an eTS application project. In the displayed **Project** window, choose **entry** > **src** > **main** > **ets** > **pages** > **index.ets**, and double-click **index.ets**. Then, add a button to trigger system event logging. - - ```ts - import hiTraceChain from '@ohos.hiTraceChain'; - import hiSysEvent from '@ohos.hiSysEvent'; - - @Entry - @Component - struct Index { - @State message: string = 'Start writing system event'; - - build() { - Row() { - Column() { - Button(this.message) - .fontSize(20) - .margin(5) - .width(350) - .height(60) - .fontWeight(FontWeight.Bold) - .onClick(() => { - try { - // Enable distributed call chain tracing before the service starts. - let traceId = hiTraceChain.begin("Write a new system event", hiTraceChain.HiTraceFlag.INCLUDE_ASYNC); - // Implement one-time system event logging when the service starts. - hiSysEvent.write({ - domain: "RELIABILITY", - name: "STACK", - eventType: hiSysEvent.EventType.FAULT, - params: { - PID: 1, - UID: 1, - PACKAGE_NAME: "com.demo.hitracechain", - PROCESS_NAME: "hitracechaindemo", - MSG: "no msg." - } - }).then((val) => { - console.info(`write result is ${val}`); - // Disable distributed call chain tracing when the service ends. - hiTraceChain.end(traceId); - }).catch((err) => { - console.error(`error message is ${err.message}`); - }); - } catch (err) { - console.error(`error message is ${err.message}`); - } - }) - } - .width('100%') - } - .height('100%') - } - } - ``` - -2. Touch the run button on the IDE to run the project. Then, touch the **Start writing system event** button on the application UI to trigger system event logging. - -3. View the information printed in the **Log** window. You can use **.*: \[([0-9a-zA-Z]{15}),.*].*** to access distributed call chain tracing information specific to the HAP service. The process ID of the HAP service is **8801**. Two threads, whose IDs are **8801** and **8819**, are involved in the system event logging. Based on the chain ID **edcfa53017a88e3**, you can then effectively trace the log information of the two threads. - ```text - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain I C02d03/HiTraceC: [edcfa53017a88e3, 0, 0] HiTraceBegin name:Write a new system event flags:0x01. - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02d03/HITRACE_UTIL_NAPI: [edcfa53017a88e3, 0, 0] Native2Js: chainId is edcfa53017a88e3. - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02d03/HITRACE_UTIL_NAPI: [edcfa53017a88e3, 0, 0] Native2Js: spanId is 0. - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02d03/HITRACE_UTIL_NAPI: [edcfa53017a88e3, 0, 0] Native2Js: parentSpanId is 0. - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02d03/HITRACE_UTIL_NAPI: [edcfa53017a88e3, 0, 0] Native2Js: flags is 1. - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] domain is RELIABILITY. - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] name is STACK. - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] eventType is 1. - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain E C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] napi value type not match: valueType=3, typeName=6. - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain E C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] napi value type not match: valueType=3, typeName=6. - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain E C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] napi value type not match: valueType=4, typeName=6. - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain E C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] napi value type not match: valueType=4, typeName=6. - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain E C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] napi value type not match: valueType=4, typeName=6. - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] create napi value of string type, value is JSHiSysEventWrite. - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain I C03900/Ace: [edcfa53017a88e3, 0, 0] [flutter_ace_view.cpp(operator())-(0)] Mark 0 id Touch Event Processed - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02800/ClientMsgHandler: [edcfa53017a88e3, 0, 0] in OnDispatchEventProcessed, enter - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02800/ANRHandler: [edcfa53017a88e3, 0, 0] in SetLastProcessedEventId, enter - 07-05 19:50:47.690 8801-8819/com.demo.hitracechain D C02d08/HISYSEVENT: [edcfa53017a88e3, 0, 0] size=312, sysevent={"domain_":"RELIABILITY","name_":"STACK","type_":1,"time_":47591447690,"tz_":"+0000","pid_":8801,"tid_":8819,"uid_":20010045,"traceid_":"edcfa53017a88e3","spanid_":"0","pspanid_":"0","trace_flag_":1,"UID":1,"PID":1,"MSG":"no msg.","PROCESS_NAME":"hitracechaindemo","PACKAGE_NAME":"com.demo.hitracechain"} - 07-05 19:50:47.690 8801-8801/com.demo.hitracechain D C02800/ANRHandler: [edcfa53017a88e3, 0, 0] in SetLastProcessedEventId, Processed event type:0, id:831, actionTime:6694499314, currentTime:6694501330, timeoutTime:4997984 - 07-05 19:50:47.691 8801-8801/com.demo.hitracechain D C02800/ANRHandler: [edcfa53017a88e3, 0, 0] in SetLastProcessedEventId, leave - 07-05 19:50:47.691 8801-8801/com.demo.hitracechain D C02800/ClientMsgHandler: [edcfa53017a88e3, 0, 0] in OnDispatchEventProcessed, leave - 07-05 19:50:47.691 8801-8819/com.demo.hitracechain D C02d08/HISYSEVENT: [edcfa53017a88e3, 0, 0] reset send buffer size old=245760, new=524288 - 07-05 19:50:47.691 8801-8819/com.demo.hitracechain D C02d08/HISYSEVENT: [edcfa53017a88e3, 0, 0] HiSysEvent send data successful - 07-05 19:50:47.691 8801-8801/com.demo.hitracechain D C02d08/NAPI_HISYSEVENT_UTIL: [edcfa53017a88e3, 0, 0] create napi value of int32 type, value is 0. - 07-05 19:50:47.691 8801-8801/com.demo.hitracechain E A0fefe/JsApp: [edcfa53017a88e3, 399db38, 0] write result is 0 - 07-05 19:50:47.691 8801-8801/com.demo.hitracechain D C02d03/HITRACE_UTIL_NAPI: [edcfa53017a88e3, 399db38, 0] Js2Native: chainId is edcfa53017a88e3. - 07-05 19:50:47.691 8801-8801/com.demo.hitracechain D C02d03/HITRACE_UTIL_NAPI: [edcfa53017a88e3, 399db38, 0] Js2Native: spanId is 0. - 07-05 19:50:47.691 8801-8801/com.demo.hitracechain D C02d03/HITRACE_UTIL_NAPI: [edcfa53017a88e3, 399db38, 0] Js2Native: parentSpanId is 0. - 07-05 19:50:47.691 8801-8801/com.demo.hitracechain D C02d03/HITRACE_UTIL_NAPI: [edcfa53017a88e3, 399db38, 0] Js2Native: flags is 1. - 07-05 19:50:47.691 8801-8801/com.demo.hitracechain I C02d03/HiTraceC: [edcfa53017a88e3, 399db38, 0] HiTraceEnd. - ``` +In this example, distributed call chain tracing begins when the application startup execution page is loaded and stops when the service usage is completed. + +1. Create a JS application project. In the displayed **Project** window, choose **entry** > **src** > **main** > **js** > **default** > **pages** > **index**, and double-click **index.js**. Add the code to implement call chain tracing upon page loading. The sample code is as follows: -## About Cross-Process/Cross-Device Distributed Call Chain Tracing + ``` + import hiTraceChain from '@ohos.hiTraceChain' + + export default { + data: { + title: "" + }, + onInit() { + this.title = this.$t('strings.world'); + + // 1. Enable distributed call chain tracing. + let asyncTraceId = hiTraceChain.begin("business", hiTraceChain.HiTraceFlag.INCLUDE_ASYNC | hiTraceChain.HiTraceFlag.DONOT_CREATE_SPAN); + + // 2. Start the service process. + console.log(`business start`); + + // 3. Add a trace point. + hiTraceChain.tracepoint(hiTraceChain.HiTraceCommunicationMode.THREAD, hiTraceChain.HiTraceTracepointType.SS, asyncTraceId, "Just an example"); + + // 4. Keep the service process running. + console.log(`business running`); + + // 5. End the service process. + console.log(`business end`); + + // 6. Stop call chain tracing. + hiTraceChain.end(asyncTraceId); + } + } + ``` -Cross-process/cross-device distributed call chain tracing depends on the NAPI implementation of the corresponding service APIs of each OpenHarmony module. For details, see the [HiTraceChain Development](../../device-dev/subsystems/subsys-dfx-hitracechain.md). +2. Click the run button on the application page. Then, you'll obtain the log information for service analysis. diff --git a/en/application-dev/dfx/hitracemeter-guidelines.md b/en/application-dev/dfx/hitracemeter-guidelines.md index 1547ba195a49da7891ba7184a0b716c66c500046..3244aa9356bbcd3748594061a3752fad8aa3d3f3 100644 --- a/en/application-dev/dfx/hitracemeter-guidelines.md +++ b/en/application-dev/dfx/hitracemeter-guidelines.md @@ -17,11 +17,11 @@ hiTraceMeter provides APIs for system performance tracing. You can call the APIs ## Constraints -- Due to the asynchronous I/O feature of JS, the hiTraceMeter module provides only asynchronous APIs. +Due to the asynchronous I/O feature of JS, the hiTraceMeter module provides only asynchronous APIs. ## Available APIs -The performance tracing APIs are provided by the **hiTraceMeter** module. For details, see [API Reference]( ../reference/apis/js-apis-hitracemeter.md). +The performance tracing APIs are provided by the **hiTraceMeter** module. For details, see [API Reference](../reference/apis/js-apis-hitracemeter.md). **APIs for performance tracing** diff --git a/en/application-dev/faqs/Readme-EN.md b/en/application-dev/faqs/Readme-EN.md index 63535a32ae16eca13b03d20b4bce93569e2fe1d0..5d67f4ab8aafba955da4a882b382f9df25896f3b 100644 --- a/en/application-dev/faqs/Readme-EN.md +++ b/en/application-dev/faqs/Readme-EN.md @@ -1,21 +1,31 @@ # FAQs -- [Programming Languages](faqs-language.md) -- [Ability Framework Development](faqs-ability.md) -- [Bundle Management Development](faqs-bundle.md) -- [ArkUI (ArkTS) Development](faqs-ui-ets.md) -- [ArkUI Web Component (ArkTS) Development](faqs-web-arkts.md) -- [ArkUI (JavaScript) Development](faqs-ui-js.md) +- [Full SDK Compilation](full-sdk-compile-guide.md) +- [Switching to Full SDK](full-sdk-switch-guide.md) +- [Application Model Development](faqs-ability.md) +- ArkUI Framework Development (ArkTS) + - [ArkTS Syntax Usage](faqs-arkui-arkts.md) + - [ArkUI Component Development (ArkTS)](faqs-arkui-component.md) + - [ArkUI Layout Development (ArkTS)](faqs-arkui-layout.md) + - [ArkUI Routing/Navigation Development (ArkTS)](faqs-arkui-route-nav.md) + - [ArkUI Animation/Interaction Event Development (ArkTS)](faqs-arkui-animation-interactive-event.md) +- [ArkUI Development (JS)](faqs-arkui-js.md) +- [Web Development](faqs-arkui-web.md) +- [Bundle Management Development](faqs-bundle-management.md) +- [Resource Manager Development](faqs-globalization.md) - [Common Event and Notification Development](faqs-event-notification.md) -- [Graphics and Image Development](faqs-graphics.md) +- [Graphics Development](faqs-graphics.md) +- [Window Management Development](faqs-window-manager.md) +- [Multimedia Development](faqs-multimedia.md) +- [Basic Security Capability Development](faqs-security.md) +- [Ability Access Control Development](faqs-ability-access-control.md) +- [Data Management Development](faqs-distributed-data-management.md) - [File Management Development](faqs-file-management.md) -- [Media Development](faqs-media.md) -- [Network and Connection Development](faqs-connectivity.md) -- [Data Management Development](faqs-data-management.md) -- [Device Management Development](faqs-device-management.md) +- [Network Management Development](faqs-network-management.md) - [DFX Development](faqs-dfx.md) -- [Intl Development](faqs-international.md) -- [Native API Usage](faqs-native.md) -- [Usage of Third- and Fourth-Party Libraries](faqs-third-party-library.md) -- [IDE Usage](faqs-ide.md) -- [Development Board](faqs-development-board.md) \ No newline at end of file +- [Pan-Sensor Development](faqs-sensor.md) +- [Startup Development](faqs-startup.md) +- [Distributed Device Development](faqs-distributed-device-profile.md) +- [SDK Usage](faqs-sdk.md) +- [Compiler and Runtime](faqs-compiler-runtime.md) +- [Usage of Third- and Fourth-Party Libraries](faqs-third-fourth-party-library.md) \ No newline at end of file diff --git a/en/application-dev/faqs/faqs-ability-access-control.md b/en/application-dev/faqs/faqs-ability-access-control.md new file mode 100644 index 0000000000000000000000000000000000000000..ab1786a5676957768211fb4884d4d5d42d2018a3 --- /dev/null +++ b/en/application-dev/faqs/faqs-ability-access-control.md @@ -0,0 +1,50 @@ +# Application Access Control Development + +## Can the app listen for the permission change after its permission is modified in Settings? + +Applicable to: OpenHarmony 3.1 Beta 5 (API version 9) + +Third-party apps cannot listen for the permission change. + +## Why is there no pop-up window displayed when an app applies for the **ohos.permission.LOCATION** permission? + +Applicable to: OpenHarmony 3.2 Release (API version 9) + +Applications developed using SDKs earlier than API version 9 can directly apply for the **ohos.permission.LOCATION** permission. +For the applications developed using the SDK of API version 9 or later, you need to apply for **ohos.permission.APPROXIMATELY_LOCATION** and then **ohos.permission.LOCATION**. + +**References** + +[Application Permission List](../security/permission-list.md#ohospermissionlocation) + +## What can I do to prevent the application from crashing when the application is started again after the user denies the permission requested? + +Applicable to: OpenHarmony SDK 3.2 Beta5 + +**Possible Causes** + +- If the permission required by a service is rejected by the user, the system directly returns the result and will no longer display a dialog box to request the permission. +- If related judgment is not performed after the permission is requested, the application will be rejected due to lack of the corresponding permission when accessing the target object under permission control, and terminated unexpectedly. + +**Solution** + +1. Before allowing an application to call an API protected by certain permission, verify whether the application has the permission. If the application has the permission, the application can call the API. Otherwise, a dialog box is dipslayed to ask user authorization. + +2. If the user rejects to grant the permission, ensure that other functions irrelevant to this permission are not affected. + +3. When this service is triggered again by the user or to implement a service function, on-screen message shall be provided to guide the user to grant the permission in **Settings**. + +**References** + +[Access Control (Permission) Overview](../security/accesstoken-overview.md) + +## What are the differences between **extensionAbilities** and **requestPermissions** in the **module.json5** file? + +Applicable to: OpenHarmony SDK 3.2 Beta5 + +- **requestPermissions**: specifies all the permissions required by an application for running. The permissions take effect only after being configured (declared) in the **module.json5** file. +- **extensionAbilitie.permissions**: specifies the permissions customized by the ExtensionAbility component. These permissions are required when an application needs to access the ExtensionAbility component. **extensionAbilitie.permissions** is used for permission verification only. + +**References** + +[module.json5 Configuration File](../quick-start/module-configuration-file.md) diff --git a/en/application-dev/faqs/faqs-ability.md b/en/application-dev/faqs/faqs-ability.md index aab3ecc19aff704dbc34b9f7aa4d174344735453..fef66125771888f9dfe3dce2ae4297ce858d56b8 100644 --- a/en/application-dev/faqs/faqs-ability.md +++ b/en/application-dev/faqs/faqs-ability.md @@ -1,68 +1,124 @@ -# Ability Framework Development +# Application Model Development -## Is a guide similar to the Data ability development in the FA model available for the stage model? +## 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 +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) -A guide is available for the **DataShareExtensionAbility** class, which provides APIs for sharing data with other applications and managing the data, in the stage model. +**Solution** -Reference: [DataShare Development](../database/database-datashare-guidelines.md) +Use the **UIAbility.onConfigurationUpdate\(\)** callback to subscribe to system environment variable changes (including the language, color mode, and screen orientation). -## What should I do if the UI does not respond when an ability is started? +**Reference** -Applicable to: OpenHarmony SDK 3.2.5.3, stage model of API version 9 +[Subscribing to System Environment Variable Changes](../application-models/subscribe-system-environment-variable-changes.md#using-uiability-for-subscription) -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. +## How do I redirect a user to a specified page after they touch a service widget? -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. +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) -3. You are advised to use the SDK and OpenHarmony SDK versions released on the same day. +**Solution** -Reference: [Release Testing Version](https://gitee.com/openharmony-sig/oh-inner-release-management/blob/master/Release-Testing-Version.md) +Configure a widget event with the redirected-to UIAbility specified, and call **loadContent** in the **onWindowStageCreate\(\)** callback of the target UIAbility to redirect to the specified page. -## How do I set the UI of an ability to transparent? +**Reference** -Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9 +[Developing Widget Events](../application-models/arkts-ui-widget-configuration.md) -Set the background color of the top container component to transparent, and then set the **opacity** attribute of the XComponent to **0.01**. +## How do I create a background service in the stage model? -Example: +Applicable to: OpenHarmony 3.2 Beta5 + +**Symptom** + +**ServiceExtensionAbility** in the stage model is a system API. Therefore, third-party applications cannot use it to create a background service. + +**Solution** + +Create a background task to provide the background service. + +**Reference** + +[Background Task](../task-management/background-task-overview.md) + +## Can I create a UIAbility and specify the process to run the UIAbility in the FA and Stage models? + +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) + +**Solution** + +Yes. + +- FA model + + The FA model supports multiple processes. By default, all components of an application run in the same process. This default scenario is suitable for most applications. To run a specific component in an independent process, configure the **process** tag under **ability** in the configuration file. Note that this tag is available only for system applications. + +- Stage model + + The stage model supports multiple processes. The process model is defined by the system, and third-party applications cannot be configured with multiple processes. To customize an independent process, you must request special permissions, and then specify the **process** tag under **module** in the configuration file. This tag specifies the process in which all the abilities in an HAP run. If this tag is not set, the bundle name is used as the process name by default. + + +## What are the differences between the stage model and the FA model in intra-process object sharing? + +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) + +**Solution** + +- In the stage model, multiple application components share the same ArkTS engine instance. Therefore, they can easily share objects and state with each other. This also reduces the memory usage of complex applications. +- In the FA model, each application component exclusively uses an ArkTS engine instance. Therefore, you are advised to use the stage model when developing complex applications in distributed scenarios. + +**Reference** + +[Data Synchronization Between UIAbility and UI](../application-models/uiability-data-sync-with-ui.md) + +## How do I use the lifecycle functions of AbilityStage? + +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) + +**Solution** + +Add the field **"srcEntry": "./ets/myabilitystage/MyAbilityStage.ts"** under **module** in the **module.json5** file. + +**Reference** + +[AbilityStage Component Container](../application-models/abilitystage.md) -``` -build() { - Stack() { - XComponent({ - id: 'componentId', - type: 'surface', - }) - .width('100%') - .height('100%') - .opacity(0.01) - // Page content - } - .width('100%') - .height('100%') - .backgroundColor('rgba(255,255,255, 0)') -} -``` + +## How do I delete the mission snapshot in Recents after terminateself is called in the multiton scenario? + +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) + +**Solution** + +You can set **removeMissionAfterTerminate** to **true** in the **module.json5** file. + +## Why can't I start a UIAbility instance by using startAbility\(\)? + +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) + +**Solution** + +- If the UIAbility is started using **startAbility**, check whether the **abilityName** field in **want** uses the bundle name as the prefix. If yes, delete the bundle name. +- Make sure the UIAbility's home page file configured by **onWindowStageCreate** in the **MainAbility.ts** file is defined in the **main\_pages.json** file. You are advised to use the SDK and OpenHarmony SDK versions released on the same day. ## 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 +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) + +**Solution** -Method 1: Add **.bind(this)** when calling the method. +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? +## What should I do when the error message "must have required property 'startWindowIcon'" is displayed during the UIAbility startup? -Applicable to: OpenHarmony SDK 3.2.3.5, stage model of API version 9 +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) -Configure the **startWindowIcon** attribute under **abilities** in the **module.json5** file. +**Solution** -Reference: [Application Package Structure (Stage Model)](../quick-start/module-configuration-file.md) +Configure the **startWindowIcon** attribute under **abilities** in the **module.json5** file. -Example: +**Example** ``` { @@ -77,75 +133,256 @@ Example: } ``` -## 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 +**Reference** -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. +[module.json5 File](../quick-start/module-configuration-file.md) ## Can I obtain the context through globalThis in the stage model? -Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9 +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) + +Do not use **globalThis** to obtain the context in the stage model. + +This is because all the processes of an application share a JS VM instance in the stage model. Multiple abilities can run on these processes and share the same global object. If **globalThis** is used, the context of different abilities of the same JS VM instance may be returned. + +**Reference** + +[Data Synchronization Between UIAbility and UI](../application-models/uiability-data-sync-with-ui.md) -Do not use **globalThis** to obtain the context in the stage model. This is because all the processes of an application share a JS VM instance in the stage model. Multiple abilities can run on these processes and share the same global object. If **globalThis** is used, the context of different abilities of the same JS VM instance may be returned. +## What should I do when an error indicating too large size is reported during HAP deployment? -Reference of the recommended operation: [Context (Stage Model)](../application-models/application-context-stage.md) +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) -## How do I obtain the HAP installation path of application B from application A? +**Symptom** -Applicable to: OpenHarmony SDK 3.0 or later, stage model of API version 9 +During HAP deployment, the following error message is displayed: -First, request the system permission. For details, see [Having Your App Automatically Signed](https://developer.harmonyos.com/en/docs/documentation/doc-guides/ohos-auto-configuring-signature-information-0000001271659465). Then, import the **bundle** module, and call **bundle.getApplicationInfo()** to obtain application information based on the bundle name. Finally, use **application.moduleSourceDirs** to obtain the application storage path. +Failure\[INSTALL\_FAILED\_SIZE\_TOO\_LARGE\] error while deploying hap? + +**Solution** + +You can split the HAP into multiple HAPs. ## How is data returned when startAbilityForResult is called? -Applicable to: OpenHarmony SDK3.0, stage model of API version 9 +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) + +**Solution** + +The target UIAbilities uses **AbilityContext.terminateSelfWithResult** to terminate itself and pass the result to **startAbilityForResult**. + +**Reference** + +[Starting UIAbility in the Same Application and Obtaining the Return Result](../application-models/uiability-intra-device-interaction.md) + + +## How do I obtain the system timestamp? + +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) + +**Solution** + +Use **getCurrentTime** of **@ohos.systemDateTime** to obtain the system time and time zone. + +**Example** + +Use the **@ohos.systemDateTime** API as follows: + + ``` + try { + systemDateTime.getCurrentTime(true, (error, time) => { + if (error) { + console.info(`Failed to get currentTime. message: ${error.message}, code: ${error.code}`); + return; + } + console.info(`Succeeded in getting currentTime : ${time}`); + }); + } catch(e) { + console.info(`Failed to get currentTime. message: ${e.message}, code: ${e.code}`); + } + ``` + -The callee uses **AbilityContext.terminateSelfWithResult** to destroy its ability and pass parameters to **startAbilityForResult**. For details, see [AbilityContext](../reference/apis/js-apis-ability-context.md#abilitycontextterminateselfwithresult). +**Reference** -## Can the lifecycle callback of a released FA widget be triggered when the widget is displayed in the service center so that the user login information can be obtained without opening the FA application? +[System time and time zone] (../reference/apis/js-apis-system-date-time.md#systemdatetimegetcurrenttime) -Applicable to: OpenHarmony SDK 3.2.5.5, FA model of API version 8 +## How do I obtain the cache directory of the current application? -After a widget is added, the **oncreate()** lifecycle is triggered so that related user information (silent login) can be displayed even when the application is not started. However, users must manually add the widget after the application is installed. +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) -## How do I obtain the context? +**Solution** -Applicable to: OpenHarmony SDK 3.2.7.5, stage model of API version 9 +Use **Context.cacheDir** to obtain the cache directory of the application. -You can use **this.context** to obtain the context in the **MainAbility.ts** file or call **getContext(this)** to obtain the context on the component page. +**Reference** -## What should I do when undefined is displayed for the calling of **abilityAccessCtrl.grantUserGrantedPermission** during API version 8 syntax verification? +[Obtaining the Application Development Path](../application-models/application-context-stage.md#obtaining-the-application-development-path) -Applicable to: OpenHarmony SDK 3.0, FA model of API version 8 +## In which JS file is the service widget lifecycle callback invoked? -**abilityAccessCtrl.grantUserGrantedPermission** is a system API. It is not available in the public SDK, which is provided as default on DevEco Studio. To use system APIs, switch to the full SDK. For details, see [Guide to Switching to Full SDK](../quick-start/full-sdk-switch-guide.md). +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) -## Which of the following Extension abilities are available in the public SDK: ServiceExtensionAbility, FormExtensionAbility, and DataShareExtensionAbility? +**Solution** -Applicable to: OpenHarmony SDK 3.2.5.6, stage model of API version 9 +When a widget is created, a **FormAblity.ts** file is generated, which contains the widget lifecycle. -Among the aforementioned Extension abilities, only **FormExtensionAbility** is available in the public SDK. **ServiceExtensionAbility** and **DataShareExtensionAbility** are system APIs and available only in the full SDK. +**Reference** -Public SDK: intended for application developers and does not contain system APIs that require system permissions. +[FormExtensionAbility](../reference/apis/js-apis-app-form-formExtensionAbility.md) -Full SDK: intended for original equipment manufacturers (OEMs) and contains system APIs that require system permissions. +## What should I do when the compilation on DevEco Studio fails while ServiceExtensionAbility and DataShareExtensionAbility APIs are used? -## Why can't I play GIF images cyclically on the widget? +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) -Applicable to: OpenHarmony SDK 3.2.5.6, stage model of API version 9 +**Symptom** -The system does not support the display of GIF images on the widget. +After the **ServiceExtensionAbility** and **DataShareExtensionAbility** APIs are used, DevEco Studio reports an error indicating that the compilation fails. + +**Cause** + +The following types of SDKs are provided: + +- Public SDK: intended for application developers and does not contain system APIs that require system permissions. +- Full SDK: intended for original equipment manufacturers (OEMs) and contains system APIs that require system permissions. + +The SDK downloaded using DevEco Studio is the public SDK. + +**Solution** + +Third-party application cannot use **ServiceExtensionAbility** and **DataShareExtensionAbility**. To develop a system application, first [download the full SDK](../faqs/full-sdk-switch-guide.md). + +## How do I obtain the temp and files paths at the application level? + +Applicable to: OpenHarmony 3.2 Beta5 + +**Solution** + +Obtain them from the application context. Specifically, use **this.context.getApplicationContext.tempDir** i to obtain the **temp** path, and use **this.context.getApplicationContext.filesDir** to obtain the **files** path. + +**Reference** + +[Obtaining the Application Development Path](../application-models/application-context-stage.md#obtaining-the-application-development-path) + +## Why the application is not deleted from the background mission list after it calls terminateSelf? + +Applicable to: OpenHarmony 3.2 Beta5 + +**Solution** + +This is because the **removeMissionAfterTerminate** field under **abilities** in the **module.json5** file of the UIAbility is set to **false** (default value). To enable the application snapshot to be automatically deleted when the application is destroyed, set this field to **true**. + +**Reference** + +[module.json5 File](../quick-start/module-configuration-file.md) + +## How does an application developed in the stage model start an application developed in the FA model? + +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) + +**Solution** + +Refer to the code snippet below: + +``` +let want = { + deviceId: "", // An empty deviceId indicates the local device. + bundleName: "com.example.myapplication", + abilityName: "EntryAbility", + moduleName: "Module1", // moduleName is optional. + parameters: { // Custom information. + }, +} +// context is the AbilityContext of the FA model to be started. +context.startAbility(want).then(() => { + ... +}).catch((err) => { + ... +}) +``` + +## Can atomic services be implemented using JavaScript code only? + +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) + +**Solution** + +Currently, the directory structure of new widgets is css+hml+json. This means that the widgets cannot be implemented by using JavaScript code only. Event triggering and parameter transfer can be processed in JSON files. + +## Can the lifecycle callback of a released FA widget be triggered when the widget is displayed in the service center so that the user login information can be obtained without opening the FA application? + +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) + +**Solution** + +After a widget is added, the **onCreate\(\)** lifecycle is triggered so that related user information (silent login) can be displayed even when the application is not started. However, users must manually add the widget after the application is installed. + +## What should I do when the error message "\[c4d4d3492eb8531, 0, 0\] ContextDeal::startAbility fetchAbilities failed" is displayed during switching to another application? + +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) + +**Symptom** + +The **startAbility** API reports an error during redirection. + +**Solution** + +Use **startAbility** for implementation as follows: + +``` +import featureAbility from '@ohos.ability.featureAbility' +function onStartRemoteAbility() { +console.info('onStartRemoteAbility begin'); +let params; +let wantValue = { + bundleName: 'ohos.samples.etsDemo', + abilityName: 'ohos.samples.etsDemo.RemoteAbility', + deviceId: getRemoteDeviceId(), + parameters: params +}; +console.info('onStartRemoteAbility want=' + JSON.stringify(wantValue)); +featureAbility.startAbility({ + want: wantValue +}).then((data) => { +console.info('onStartRemoteAbility finished, ' + JSON.stringify(data)); +}); +console.info('onStartRemoteAbility end'); +} +``` + +**Reference** + +See [Starting a Local PageAbility] (../application-models/start-local-pageability.md). ## How do I implement service login by touching a widget? -Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9 +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) + +**Solution** + +To create a service widget in the FA model, perform the following steps: + +1. Implement lifecycle callbacks for the widget. -You can start an ability upon the touch and implement service login in the ability. +2. Configure the widget configuration file. + +3. Persistently store widget data. + +4. Update widget data. + +5. Develop the widget UI page. + +6. Develop a widget event. You can start a UIAbility upon the touch and implement service login in the UIAbility. + +**Reference** + +[Widget Development in the FA Model](../application-models/widget-development-fa.md) ## How do I redirect to the application details page in Settings? -Applicable to: OpenHarmony SDK 3.2.6.5 +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) + +**Solution** Refer to the following code: @@ -157,58 +394,92 @@ this.context.startAbility( }) ``` -## How do I listen for screen rotation events? +## How do I get UIAbilityContext within the @Component component in the stage model? -Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9 +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) -Refer to the following code: +**Solution** + +You can use **UIAbility.Context** to obtain the context. + +**Example** ``` -let listener = mediaquery.matchMediaSync('(orientation: landscape)') -onPortrait(mediaQueryResult) { -if (mediaQueryResult.matches) { -// Do something here. - } else { -// Do something here. +import common from '@ohos.app.ability.common'; + +@Entry +@Component +struct AbilityContextTest { + // abilityContext + @State UIAbilityInfo: string = 'Obtaining abilityInfo' + UIAbilityContext: common.UIAbilityContext + + aboutToAppear() { + // Use getContext to obtain the context and convert it to abilityContext. + this.UIAbilityContext = getContext(this) as common.UIAbilityContext + } + + build() { + Row() { + Column({ space: 20 }) { + Text(this.UIAbilityInfo) + .fontSize(20) + .onClick(() => { + this.UIAbilityInfo = JSON.stringify(this.UIAbilityContext.abilityInfo) + console.log(`ContextDemo abilityInfo = ${this.UIAbilityInfo}`) + }) + } + .width('100%') } + .height('100%') + } } -listener.on('change', onPortrait) ``` -## How do I control the shadow background size during checkbox selection? +## What should I do when starting a continuous task fails? -Applicable to: OpenHarmony SDK 3.2.5.5, stage model of API version 9 +Applicable to: OpenHarmony 3.2 Release (API version 9) -Set the **padding** attribute of the **\** component to control the shadow size. +**Symptom** -## How do I set the widget background to transparent? +A ServiceAbility is started by calling **featureAbility.startAbility\(\)**. When the ServiceAbility attempts to start a continuous task, the error message \{"code":201,"message":"BussinessError 201: Permission denied."\} is reported. -Applicable to: OpenHarmony SDK 3.2.5.5 +**Solution** -1. Create the **widget/resources/styles/default.json** file in the root directory of the widget. - -2. Add the following code to the **default.json** file: +To start a continuous task in the background, you must configure the permission **ohos.permission.KEEP\_BACKGROUND\_RUNNING** in the **module.json5** file and declare the background mode for the ability that needs to use the continuous task. ``` -{ - "style": { - "app_background": "#00000000" - } +"module": { + "abilities": [ + { + "backgroundModes": [ + "dataTransfer", + "location" + ], // Background mode + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.KEEP_BACKGROUND_RUNNING" // Continuous task permission + } + ] } ``` -## How do I pass parameters for FA widgets? +**Reference** + +[ServiceAbility Configuration Items - backgroundModes](../application-models/serviceability-configuration.md) -Applicable to: OpenHarmony SDK 3.2.5.5 +[Continuous Task Permission](../security/permission-list.md#ohospermissionkeep_background_running) -Use **featureAbility.getWant()** and **featureAbility.getContext()** to send data through **router** in the JSON file and use **featureAbility** to receive data in the JS file. +[Continuous Task Development](../task-management/continuous-task-dev-guide.md#development-in-the-stage-model) -## How do I trigger router.disableAlertBeforeBackPage and router.enableAlertBeforeBackPage? +## How do FA widgets exchange data? -Applicable to: OpenHarmony SDK 3.2.5.5 +Applicable to: OpenHarmony 3.2 Beta5 (API version 9) -The following conditions must be met: +The widget interacts with the widget provider through the **postCardAction** API, and the provider updates data through the **updateForm** API. -1. Before the redirection to the previous page, a confirm dialog box will be displayed. Note that **router.disableAlertBeforeBackPage** is used to disable the display of a confirm dialog box before returning to the previous page (default), and **router.enableAlertBeforeBackPage** is used to enable the display. +**Reference** -2. The system return key is used. +[Widget Development in the FA Model](../application-models/widget-development-fa.md) diff --git a/en/application-dev/faqs/faqs-arkui-animation-interactive-event.md b/en/application-dev/faqs/faqs-arkui-animation-interactive-event.md new file mode 100644 index 0000000000000000000000000000000000000000..fbe2594e6591bb774aa116095e721ca889490cc8 --- /dev/null +++ b/en/application-dev/faqs/faqs-arkui-animation-interactive-event.md @@ -0,0 +1,269 @@ +# ArkUI Animation/Interaction Event Development (ArkTS) + +## What should I do if the onBlur and onFocus callbacks cannot be triggered? + +Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) + +**Symptom** + +The **onBlur** and **onFocus** callbacks of the focus event cannot be triggered. + +**Solution** + +Check the trigger device. By default, the focus event (and the **onBlur** and **onFocus** callbacks) can be triggered only by the Tab button and arrow buttons on the connected keyboard. To enable the focus event to be triggered by a touch, add the **focusOnTouch** attribute for the target component. + +**Reference** + +[Focus Control](../reference/arkui-ts/ts-universal-attributes-focus.md) + +## How do I disable the scroll event of a \ nested in the \? + +Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) + +Implement nested scrolling of the containers, by using the **onScrollFrameBegin** event and the **scrollBy** method. + +**Reference** + +[Scroll](../reference/arkui-ts/ts-container-scroll.md#example-2) + +## How do I enable a component to rotate continuously? + +Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) + +You can use [attribute animation](../reference/arkui-ts/ts-animatorproperty.md) to that effect. + +## How do I scroll a list with the keyboard? + +Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) + +**Solution** + +- Add **focusable\(true\)** to the list item to enable it to obtain focus. + +- Nest a focusable component, for example, **\