diff --git a/en/application-dev/napi/native-window-guidelines.md b/en/application-dev/napi/native-window-guidelines.md index f5a5ead9c083217c77692b34384f969c4b44dc00..2103abd1a285efe1b282a14f0857d88cdbd1877d 100644 --- a/en/application-dev/napi/native-window-guidelines.md +++ b/en/application-dev/napi/native-window-guidelines.md @@ -1,139 +1,142 @@ -# Native Window Development +# NativeWindow Development ## When to Use -**NativeWindow** is a local platform-based window of OpenHarmony that represents the producer of a graphics queue. It provides APIs for you to create a native window from **Surface**, create a native window buffer from **SurfaceBuffer**, and request and flush a buffer. -The following scenarios are common for native window development: +**NativeWindow** is a local platform-based window of OpenHarmony that represents the producer of a graphics queue. It provides APIs for you to request and flush a buffer and configure buffer attributes. -* Request a graphics buffer by using the NAPI provided by **NativeWindow**, write the produced graphics content to the buffer, and flush the buffer to the graphics queue. +The following scenarios are common for NativeWindow development: + +* Request a graphics buffer by using the native API provided by **NativeWindow**, write the produced graphics content to the buffer, and flush the buffer to the graphics queue. * Request and flush a buffer when adapting to the **eglswapbuffer** interface at the EGL. ## Available APIs | API| Description| | -------- | -------- | -| OH_NativeWindow_CreateNativeWindowFromSurface (void \*pSurface) | Creates a **NativeWindow** instance. A new **NativeWindow** instance is created each time this function is called.| -| OH_NativeWindow_DestroyNativeWindow (OHNativeWindow \*window) | Decreases the reference count of a **NativeWindow** instance by 1 and, when the reference count reaches 0, destroys the instance.| -| OH_NativeWindow_CreateNativeWindowBufferFromSurfaceBuffer (void \*pSurfaceBuffer) | Creates a **NativeWindowBuffer** instance. A new **NativeWindowBuffer** instance is created each time this function is called.| -| OH_NativeWindow_DestroyNativeWindowBuffer (OHNativeWindowBuffer \*buffer) | Decreases the reference count of a **NativeWindowBuffer** instance by 1 and, when the reference count reaches 0, destroys the instance.| -| OH_NativeWindow_NativeWindowRequestBuffer (OHNativeWindow \*window, OHNativeWindowBuffer \*\*buffer, int \*fenceFd) | Requests a **NativeWindowBuffer** through a **NativeWindow** instance for content production.| -| OH_NativeWindow_NativeWindowFlushBuffer (OHNativeWindow \*window, OHNativeWindowBuffer \*buffer, int fenceFd, Region region) | Flushes the **NativeWindowBuffer** filled with the content to the buffer queue through a **NativeWindow** instance for content consumption.| -| OH_NativeWindow_NativeWindowAbortBuffer (OHNativeWindow \*window, OHNativeWindowBuffer \*buffer) | Returns the **NativeWindowBuffer** to the buffer queue through a **NativeWindow** instance, without filling in any content. The **NativeWindowBuffer** can be used for another request.| -| OH_NativeWindow_NativeWindowHandleOpt (OHNativeWindow \*window, int code,...) | Sets or obtains the attributes of a native window, including the width, height, and content format.| -| OH_NativeWindow_GetBufferHandleFromNative (OHNativeWindowBuffer \*buffer) | Obtains the pointer to a **BufferHandle** of a **NativeWindowBuffer** instance.| -| OH_NativeWindow_NativeObjectReference (void \*obj) | Adds the reference count of a native object.| -| OH_NativeWindow_NativeObjectUnreference (void \*obj) | Decreases the reference count of a native object and, when the reference count reaches 0, destroys this object.| -| OH_NativeWindow_GetNativeObjectMagic (void \*obj) | Obtains the magic ID of a native object.| -| OH_NativeWindow_NativeWindowSetScalingMode (OHNativeWindow \*window, uint32_t sequence, OHScalingMode scalingMode) | Sets the scaling mode of the native window.| -| OH_NativeWindow_NativeWindowSetMetaData(OHNativeWindow \*window, uint32_t sequence, int32_t size, const OHHDRMetaData \*metaData) | Sets the HDR static metadata of the native window.| -| OH_NativeWindow_NativeWindowSetMetaDataSet(OHNativeWindow \*window, uint32_t sequence, OHHDRMetadataKey key, int32_t size, const uint8_t \*metaData) | Sets the HDR static metadata set of the native window.| -| OH_NativeWindow_NativeWindowSetTunnelHandle(OHNativeWindow \*window, const OHExtDataHandle \*handle) | Sets the tunnel handle to the native window.| +| OH_NativeWindow_NativeWindowRequestBuffer (OHNativeWindow \*window, OHNativeWindowBuffer \*\*buffer, int \*fenceFd) | Requests an **OHNativeWindowBuffer** through an **OHNativeWindow** instance for content production.| +| OH_NativeWindow_NativeWindowFlushBuffer (OHNativeWindow \*window, OHNativeWindowBuffer \*buffer, int fenceFd, Region region) | Flushes the **OHNativeWindowBuffer** filled with the content to the buffer queue through an **OHNativeWindow** instance for content consumption.| +| OH_NativeWindow_NativeWindowHandleOpt (OHNativeWindow \*window, int code,...) | Sets or obtains the attributes of an **OHNativeWindow**, including the width, height, and content format.| + +For details about the APIs, see [native_window](../reference/native-apis/_native_window.md). ## How to Develop -The following describes how to use the NAPI provided by **NativeWindow** to request a graphics buffer, write the produced graphics content to the buffer, and flush the buffer to the graphics queue. +The following describes how to use the native APIs provided by **NativeWindow** to request a graphics buffer, write the produced graphics content to the buffer, and flush the buffer to the graphics queue. + +**Adding Dynamic Link Libraries** + +Add the following libraries to **CMakeLists.txt**: +```txt +libace_ndk.z.so +libnative_window.so +``` + +**Header File** +```c++ +#include +#include +``` + +1. Obtain an **OHNativeWindow** instance. -1. Obtain a **NativeWindow** instance, which can be obtained by running the APIs provided by **OH_NativeXComponent_Callback**. - 1. Define **XComponent** in an .ets file. + You can call the APIs provided by [OH_NativeXComponent_Callback](../reference/native-apis/_o_h___native_x_component___callback.md) to obtain an **OHNativeWindow** instance. An example code snippet is provided below. For details about how to use the **\**, see [XComponent](../ui/arkts-common-components-xcomponent.md). + 1. Add an **\** to the .ets file. ```ts - XComponent({ id: 'xcomponentId', type: 'surface', libraryname: 'nativerender'}) - .onLoad((context) => { - this.context = context; - }) - .onDestroy(() => { - }) + XComponent({ id: 'xcomponentId', type: 'surface', libraryname: 'entry'}) + .width(360) + .height(360) + ``` + 2. Obtain **NativeXComponent** at the native C++ layer. + ```c++ + napi_value exportInstance = nullptr; + // Parse the attribute of the wrapped NativeXComponent pointer. + napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance); + OH_NativeXComponent *nativeXComponent = nullptr; + // Use the napi_unwrap API to parse the NativeXComponent instance pointer. + napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent)); + ``` + 3. Define **OH_NativeXComponent_Callback**. + ```c++ + // Define the callback. + void OnSurfaceCreatedCB(OH_NativeXComponent* component, void* window) + { + // Obtain an OHNativeWindow instance. + OHNativeWindow* nativeWindow = static_cast(window); + // ... + } + void OnSurfaceChangedCB(OH_NativeXComponent* component, void* window) + { + // Obtain an OHNativeWindow instance. + OHNativeWindow* nativeWindow = static_cast(window); + // ... + } + void OnSurfaceDestroyedCB(OH_NativeXComponent* component, void* window) + { + // Obtain an OHNativeWindow instance. + OHNativeWindow* nativeWindow = static_cast(window); + // ... + } + void DispatchTouchEventCB(OH_NativeXComponent* component, void* window) + { + // Obtain an OHNativeWindow instance. + OHNativeWindow* nativeWindow = static_cast(window); + // ... + } + ``` + ```c++ + // Initialize OH_NativeXComponent_Callback. + OH_NativeXComponent_Callback callback; + callback.OnSurfaceCreated = OnSurfaceCreatedCB; + callback.OnSurfaceChanged = OnSurfaceChangedCB; + callback.OnSurfaceDestroyed = OnSurfaceDestroyedCB; + callback.DispatchTouchEvent = DispatchTouchEventCB; ``` - 2. Obtain **NativeXComponent** at the native C++ layer. - ```c++ - napi_value exportInstance = nullptr; - napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance); - - OH_NativeXComponent *nativeXComponent = nullptr; - napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent)); - - char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { }; - uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; - OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize); - ``` - 3. Define **OH_NativeXComponent_Callback**. - ```c++ - // Define the callback. - void OnSurfaceCreatedCB(OH_NativeXComponent* component, void* window) - { - // Obtain a NativeWindow instance. - OHNativeWindow* nativeWindow = window; - // ... - } - void OnSurfaceChangedCB(OH_NativeXComponent* component, void* window) - { - // Obtain a NativeWindow instance. - OHNativeWindow* nativeWindow = window; - // ... - } - void OnSurfaceDestroyedCB(OH_NativeXComponent* component, void* window) - { - // Obtain a NativeWindow instance. - OHNativeWindow* nativeWindow = window; - // ... - } - void DispatchTouchEventCB(OH_NativeXComponent* component, void* window) - { - // Obtain a NativeWindow instance. - OHNativeWindow* nativeWindow = window; - // ... - } - ``` - ```c++ - // Initialize OH_NativeXComponent_Callback. - OH_NativeXComponent_Callback callback_; - callback_->OnSurfaceCreated = OnSurfaceCreatedCB; - callback_->OnSurfaceChanged = OnSurfaceChangedCB; - callback_->OnSurfaceDestroyed = OnSurfaceDestroyedCB; - callback_->DispatchTouchEvent = DispatchTouchEventCB; - ``` 4. Register **OH_NativeXComponent_Callback** with **NativeXComponent**. - ```c++ - OH_NativeXComponent_RegisterCallback(nativeXComponent, &callback_); - ``` + ```c++ + // Register the callback. + OH_NativeXComponent_RegisterCallback(nativeXComponent, &callback); + ``` -2. Set the attributes of a native window buffer by using **OH_NativeWindow_NativeWindowHandleOpt**. +2. Set the attributes of an **OHNativeWindowBuffer** by using **OH_NativeWindow_NativeWindowHandleOpt**. ```c++ - // Set the read and write scenarios of the native window buffer. - int code = SET_USAGE; - int32_t usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA; - int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, usage); - // Set the width and height of the native window buffer. - code = SET_BUFFER_GEOMETRY; + // Set the width and height of the OHNativeWindowBuffer. + int32_t code = SET_BUFFER_GEOMETRY; int32_t width = 0x100; int32_t height = 0x100; - ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, width, height); - // Set the step of the native window buffer. + // The nativeWindow instance is obtained from the callback in the previous step. + int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, width, height); + // Set the step of the OHNativeWindowBuffer. code = SET_STRIDE; int32_t stride = 0x8; ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, stride); - // Set the format of the native window buffer. - code = SET_FORMAT; - int32_t format = PIXEL_FMT_RGBA_8888; - ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, format); ``` -3. Request a native window buffer from the graphics queue. +3. Request an **OHNativeWindowBuffer** from the graphics queue. ```c++ - struct NativeWindowBuffer* buffer = nullptr; + OHNativeWindowBuffer* buffer = nullptr; int fenceFd; - // Obtain the NativeWindowBuffer instance by calling OH_NativeWindow_NativeWindowRequestBuffer. - OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow_, &buffer, &fenceFd); - // Obtain the buffer handle by calling OH_NativeWindow_GetNativeBufferHandleFromNative. - BufferHandle* bufferHandle = OH_NativeWindow_GetNativeBufferHandleFromNative(buffer); + // Obtain the OHNativeWindowBuffer instance by calling OH_NativeWindow_NativeWindowRequestBuffer. + OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &buffer, &fenceFd); + // Obtain the buffer handle by calling OH_NativeWindow_GetBufferHandleFromNative. + BufferHandle* bufferHandle = OH_NativeWindow_GetBufferHandleFromNative(buffer); ``` -4. Write the produced content to the native window buffer. +4. Map memory. + ```c++ + #include + + // Use mmap() to obtain the memory virtual address of buffer handle. + void* mappedAddr = mmap(bufferHandle->virAddr, bufferHandle->size, PROT_READ | PROT_WRITE, MAP_SHARED, bufferHandle->fd, 0); + if (mappedAddr == MAP_FAILED) { + // mmap failed + } + ``` + +5. Write the produced content to the **OHNativeWindowBuffer**. ```c++ - auto image = static_cast(buffer->sfbuffer->GetVirAddr()); static uint32_t value = 0x00; value++; - - uint32_t *pixel = static_cast(image); + uint32_t *pixel = static_cast(mappedAddr); // Use the address obtained by mmap() to access the memory. for (uint32_t x = 0; x < width; x++) { for (uint32_t y = 0; y < height; y++) { *pixel++ = value; @@ -141,10 +144,18 @@ The following describes how to use the NAPI provided by **NativeWindow** to requ } ``` -5. Flush the native window buffer to the graphics queue. +5. Flush the **OHNativeWindowBuffer** to the graphics queue. ```c++ - // Set the refresh region. If Rect in Region is a null pointer or rectNumber is 0, all contents in the native window buffer are changed. + // Set the refresh region. If Rect in Region is a null pointer or rectNumber is 0, all contents in the OHNativeWindowBuffer are changed. Region region{nullptr, 0}; // Flush the buffer to the consumer through OH_NativeWindow_NativeWindowFlushBuffer, for example, by displaying it on the screen. - OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow_, buffer, fenceFd, region); + OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, buffer, fenceFd, region); + ``` +6. Unmap memory. + ```c++ + // Unmap the memory when the memory is no longer required. + int result = munmap(mappedAddr, bufferHandle->size); + if (result == -1) { + // munmap failed + } ``` diff --git a/en/application-dev/reference/apis/js-apis-window.md b/en/application-dev/reference/apis/js-apis-window.md index 7a9a4b303be2b022b3b19adecf31c2ba09d3be27..6d9cd71677622b0005fb4fd5ee6fc2b621fcba73 100644 --- a/en/application-dev/reference/apis/js-apis-window.md +++ b/en/application-dev/reference/apis/js-apis-window.md @@ -2514,7 +2514,7 @@ try { ### on('avoidAreaChange')9+ -on(type: 'avoidAreaChange', callback: Callback<{AvoidAreaType, AvoidArea}>): void +on(type: 'avoidAreaChange', callback: Callback<{type: AvoidAreaType, area: AvoidArea}>): void Enables listening for changes to the area where the window cannot be displayed. @@ -2525,7 +2525,7 @@ Enables listening for changes to the area where the window cannot be displayed. | Name | Type | Mandatory| Description | | -------- |------------------------------------------------------------------| ---- |--------------------------------------| | type | string | Yes | Event type. The value is fixed at **'avoidAreaChange'**, indicating the event of changes to the area where the window cannot be displayed.| -| callback | Callback<{[AvoidAreaType](#avoidareatype7), [AvoidArea](#avoidarea7)}> | Yes | Callback used to return the area and area type.| +| callback | Callback<{type: [AvoidAreaType](#avoidareatype7), area: [AvoidArea](#avoidarea7)}> | Yes | Callback used to return the area and area type.| **Example** @@ -2542,7 +2542,7 @@ try { ### off('avoidAreaChange')9+ -off(type: 'avoidAreaChange', callback?: Callback<{AvoidAreaType, AvoidArea}>): void +off(type: 'avoidAreaChange', callback?: Callback<{type: AvoidAreaType, area: AvoidArea}>): void Disables listening for changes to the area where the window cannot be displayed. @@ -2553,7 +2553,7 @@ Disables listening for changes to the area where the window cannot be displayed. | Name | Type | Mandatory | Description | | -------- |-----------------------------------------------------------------------------|-----|------------------------------------| | type | string | Yes | Event type. The value is fixed at **'avoidAreaChange'**, indicating the event of changes to the area where the window cannot be displayed.| -| callback | Callback<{[AvoidAreaType](#avoidareatype7), [AvoidArea](#avoidarea7)}> | No | Callback used to return the area and area type.| +| callback | Callback<{type: [AvoidAreaType](#avoidareatype7), area: [AvoidArea](#avoidarea7)}> | No | Callback used to return the area and area type.| **Example** @@ -2788,7 +2788,16 @@ class TestRemoteObject extends rpc.RemoteObject { } let token = new TestRemoteObject('testObject'); +let windowClass = null; +let config = {name: "dialogWindow", windowType: window.WindowType.TYPE_DIALOG, ctx: this.context}; try { + window.createWindow(config, (err, data) => { + if (err.code) { + console.error('Failed to create the window. Cause: ' + JSON.stringify(err)); + return; + } + windowClass = data; + }); windowClass.bindDialogTarget(token, () => { console.info('Dialog Window Need Destroy.'); }, (err) => { @@ -2861,7 +2870,16 @@ class TestRemoteObject extends rpc.RemoteObject { } let token = new TestRemoteObject('testObject'); +let windowClass = null; +let config = {name: "dialogWindow", windowType: window.WindowType.TYPE_DIALOG, ctx: this.context}; try { + window.createWindow(config, (err, data) => { + if (err.code) { + console.error('Failed to create the window. Cause: ' + JSON.stringify(err)); + return; + } + windowClass = data; + }); let promise = windowClass.bindDialogTarget(token, () => { console.info('Dialog Window Need Destroy.'); }); @@ -2875,6 +2893,172 @@ try { } ``` +### bindDialogTarget9+ + +bindDialogTarget(requestInfo: dialogRequest.RequestInfo, deathCallback: Callback<void>, callback: AsyncCallback<void>): void + +Binds the modal window to the target window, and adds a callback to listen for modal window destruction events. This API uses an asynchronous callback to return the result. + +**System API**: This is a system API. + +**System capability**: SystemCapability.WindowManager.WindowManager.Core + +**Parameters** + +| Name | Type | Mandatory| Description | +| ----------- | ------------------------- | ---- | -------------------- | +| requestInfo | [dialogRequest.RequestInfo](js-apis-app-ability-dialogRequest.md#requestinfo) | Yes | **RequestInfo** of the target window.| +| deathCallback | Callback<void> | Yes | Callback used to listen for modal window destruction events.| +| callback | AsyncCallback<void> | Yes | Callback used to return the result.| + +**Error codes** + +For details about the error codes, see [Window Error Codes](../errorcodes/errorcode-window.md). + +| ID| Error Message| +| ------- | -------------------------------------------- | +| 1300002 | This window state is abnormal. | +| 1300003 | This window manager service works abnormally. | + +**Example** + +```js +import ServiceExtensionAbility from '@ohos.app.ability.ServiceExtensionAbility'; +import rpc from '@ohos.rpc'; +import dialogRequest from '@ohos.app.ability.dialogRequest'; +import window from '@ohos.window'; + +export default class ServiceExtAbility extends ServiceExtensionAbility { + onCreate(want) { + console.info('onCreate'); + } + + onRequest(want, startId) { + console.info('onRequest'); + let windowClass = null; + let config = {name: "dialogWindow", windowType: window.WindowType.TYPE_DIALOG, ctx: this.context}; + try { + window.createWindow(config, (err, data) => { + if (err.code) { + console.error('Failed to create the window. Cause: ' + JSON.stringify(err)); + return; + } + windowClass = data; + }); + let requestInfo = dialogRequest.getRequestInfo(want) + windowClass.bindDialogTarget(requestInfo, () => { + console.info('Dialog Window Need Destroy.'); + }, (err) => { + if (err.code) { + console.error('Failed to bind dialog target. Cause:' + JSON.stringify(err)); + return; + } + console.info('Succeeded in binding dialog target.'); + }); + } catch(err) { + console.error('Failed to bind dialog target. Cause:' + JSON.stringify(err)) + } + } + + onConnect(want) { + console.info('onConnect'); + } + + onDisconnect(want) { + console.info('onDisconnect'); + } + + onDestroy() { + console.info('onDestroy'); + } +} +``` + +### bindDialogTarget9+ + +bindDialogTarget(requestInfo: dialogRequest.RequestInfo, deathCallback: Callback<void>): Promise<void> + +Binds the modal window to the target window, and adds a callback to listen for modal window destruction events. This API uses a promise to return the result. + +**System API**: This is a system API. + +**System capability**: SystemCapability.WindowManager.WindowManager.Core + +**Parameters** + +| Name | Type | Mandatory| Description | +| ----------- | ------------------------- | ---- | -------------------- | +| requestInfo | [dialogRequest.RequestInfo](js-apis-app-ability-dialogRequest.md#requestinfo) | Yes | **RequestInfo** of the target window.| +| deathCallback | Callback<void> | Yes | Callback used to listen for modal window destruction events.| + +**Return value** + +| Type | Description | +| ------------------- | ------------------------- | +| Promise<void> | Promise that returns no value.| + +**Error codes** + +For details about the error codes, see [Window Error Codes](../errorcodes/errorcode-window.md). + +| ID| Error Message| +| ------- | -------------------------------------------- | +| 1300002 | This window state is abnormal. | +| 1300003 | This window manager service works abnormally. | + +**Example** + +```js +import ServiceExtensionAbility from '@ohos.app.ability.ServiceExtensionAbility'; +import rpc from '@ohos.rpc'; +import dialogRequest from '@ohos.app.ability.dialogRequest'; +import window from '@ohos.window'; + +export default class ServiceExtAbility extends ServiceExtensionAbility { + onCreate(want) { + console.info('onCreate'); + } + + onRequest(want, startId) { + console.info('onRequest'); + let windowClass = null; + let config = {name: "dialogWindow", windowType: window.WindowType.TYPE_DIALOG, ctx: this.context}; + try { + window.createWindow(config, (err, data) => { + if (err.code) { + console.error('Failed to create the window. Cause: ' + JSON.stringify(err)); + return; + } + windowClass = data; + }); + let requestInfo = dialogRequest.getRequestInfo(want) + let promise = windowClass.bindDialogTarget(requestInfo, () => { + console.info('Dialog Window Need Destroy.'); + }); + promise.then(()=> { + console.info('Succeeded in binding dialog target.'); + }).catch((err)=>{ + console.error('Failed to bind dialog target. Cause:' + JSON.stringify(err)); + }); + } catch(err) { + console.error('Failed to bind dialog target. Cause:' + JSON.stringify(err)) + } + } + + onConnect(want) { + console.info('onConnect'); + } + + onDisconnect(want) { + console.info('onDisconnect'); + } + + onDestroy() { + console.info('onDestroy'); + } +} +``` + ### isWindowSupportWideGamut9+ isWindowSupportWideGamut(callback: AsyncCallback<boolean>): void diff --git a/en/device-dev/subsystems/subsys-remote-start.md b/en/device-dev/subsystems/subsys-remote-start.md deleted file mode 100644 index 2c3b0e4d5866b238e62f7c488d1033d0f0565027..0000000000000000000000000000000000000000 --- a/en/device-dev/subsystems/subsys-remote-start.md +++ /dev/null @@ -1,107 +0,0 @@ -# Distributed Remote Startup - -## Overview - -The Distributed Manager Service sets up a distributed service platform in OpenHarmony by using a proxy between the primary and secondary devices. With the Distributed Manager Service, the primary device \(OpenHarmony-powered smart TV\) can start a Feature Ability \(FA\) deployed on the secondary device \(a memory-constrained OpenHarmony device such as an IP camera or a lite wearable\). - -For example, if a user presses the **Remind Me** button for a TV program on the smart TV, the smart TV will start the corresponding reminder FA on the lite wearable to remind the user when the particular TV program is available. - -## Basic Concepts - -- FA - - Feature Ability, representing an ability with a UI for interacting with users - - -- Remote startup - - Cross-device FA startup, which is the counterpart of local FA startup - - -## Available APIs - -The following table describes the API that can be used by smart TVs to remotely start an FA. This API is provided in the **AbilitySlice** class. For details, see the Java API reference for OpenHarmony application development. - -**Table 1** API for remotely starting an FA on the distributed network - - - - - - - - - - -

Method

-

Description

-

void startAbility(Want want)

-

Remotely starts an FA based on the specified Want information. If the name and type of the want parameter are different from those used in the integrated development environment (IDE), use the parameter name and type in the IDE.

-
- -**Table 2** Description of the want parameter - - - - - - - - - - - - -

Parameter

-

Type

-

Description

-

want

-

ohos.aafwk.content.Want

-

When you use startAbility(Want want) to remotely start an FA, you must first specify the deviceId, bundleName, and abilityName attributes of the target FA in the Want object.

-
- -## Limitations and Constraints - -- The primary device can remotely start an FA of the secondary device, but the secondary device cannot remotely start an FA of the primary device. -- Before the remote startup, ensure that the two OpenHarmony devices are on the same network segment and can ping each other on the distributed network. Otherwise, the remote startup fails. -- Currently, only the FAs that have the same public key \(that is, the same Huawei certificate\) can be started between the primary and secondary devices. - -## How to Develop - -To enable the primary device \(smart TV\) to start an FA of the secondary device \(assuming that the target FA has been developed\), perform the following steps: - -1. Complete FA development for the smart TV on DevEco Studio. -2. Obtain the IDs of online secondary devices. - - ``` - // Import the header files required for device selection. - import ohos.distributedschedule.interwork.DeviceInfo; - import ohos.distributedschedule.interwork.DeviceManager; - - // Obtain the online device list. - List deviceInfoListOnline = DeviceManager.getDmsDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE); - String remote_device_id; - if (deviceInfoListOnline.size() > 0) - { - remote_device_id = deviceInfoListOnline[0].GetDeviceId(); // Obtain the ID of the first device in the online device list. - } - ``` - -3. Create a **Want** instance. You should first create an **ElementName** object with **deviceId**, **bundleName**, **abilityName** specified and add this object to the **Want** instance. Then, set the multi-device startup flag **Want.FLAG\_ABILITYSLICE\_MULTI\_DEVICE** to the **Want** instance to enable remote FA startup. - - ``` - // Import related header files. - import ohos.aafwk.ability.Ability; - import ohos.aafwk.content.Want; - import ohos.bundle.ElementName; - - // Start the remote FA on the secondary device. - Want want = new Want(); // Create a Want instance that encapsulates information about the remote FA to start. - // Use the device ID obtained in step 2 and specify the FA information. - ElementName name = new ElementName(remote_device_id, "com.huawei.remote_package_name", "remote_class_name"); - want.setElement(name); // Add information about the target FA for startup to the Want instance. - want.setFlags(Want.FLAG_ABILITYSLICE_MULTI_DEVICE); // Set the multi-device startup flag. If this flag is not set, remote FA startup will be unavailable. - startAbility(want); // Start the specified FA based on the want parameter. If the name and type of the want parameter are different from those used in the IDE, use the parameter name and type in the IDE. - ``` - -