1e41f4b71Sopenharmony_ci# ServiceExtensionAbility
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## Overview
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ci[ServiceExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md) is an [ExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-extensionAbility.md) component of the SERVICE type that provides capabilities related to background services. It holds an internal [ServiceExtensionContext](../reference/apis-ability-kit/js-apis-inner-application-serviceExtensionContext-sys.md), which provides a variety of APIs for external systems.
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ciIn this document, the started ServiceExtensionAbility is called the server, and the component that starts the ServiceExtensionAbility is called the client.
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ciA 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-ability-kit/js-apis-inner-application-uiAbilityContext-sys.md#uiabilitycontextstartserviceextensionability) method to start background services or call the [connectServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextconnectserviceextensionability) 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 a ServiceExtensionAbility are as follows:
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ci- **Starting**: In the case that AbilityA starts ServiceB, they are weakly associated. After AbilityA exits, ServiceB remains running.
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ci- **Connecting**: In the case that AbilityA connects to ServiceB, they are strongly associated. After AbilityA exits, ServiceB also exits.
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ciNote the following:
16e41f4b71Sopenharmony_ci
17e41f4b71Sopenharmony_ci- 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()** method. When the client exits or calls the [disconnectServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextdisconnectserviceextensionability) method, the connection is interrupted. After all connections are interrupted, the ServiceExtensionAbility automatically exits.
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ci- Once a ServiceExtensionAbility is started by means of starting, it will not exit automatically. System applications can call the [stopServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext-sys.md#uiabilitycontextstopserviceextensionability) method to stop it.
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci- The connection or disconnection operation can be performed only in the main thread, but not in the **Worker** and **TaskPool** threads.
22e41f4b71Sopenharmony_ci
23e41f4b71Sopenharmony_ci> **NOTE**
24e41f4b71Sopenharmony_ci>
25e41f4b71Sopenharmony_ci> Currently, third-party applications cannot implement a ServiceExtensionAbility. To implement transaction processing in the background, they can use [background tasks](../task-management/background-task-overview.md).
26e41f4b71Sopenharmony_ci>
27e41f4b71Sopenharmony_ci> A UIAbility of a third-party application can connect to a ServiceExtensionAbility provided by a system application through the context.
28e41f4b71Sopenharmony_ci>
29e41f4b71Sopenharmony_ci> Third-party applications can connect to a ServiceExtensionAbility provided by a system application only when they gain focus in the foreground.
30e41f4b71Sopenharmony_ci
31e41f4b71Sopenharmony_ci## Lifecycle
32e41f4b71Sopenharmony_ci
33e41f4b71Sopenharmony_ciThe [ServiceExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md) class provides the lifecycle callbacks [onCreate()](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md#serviceextensionabilityoncreate), [onRequest()](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md#serviceextensionabilityonrequest), [onConnect()](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md#serviceextensionabilityonconnect), [onDisconnect()](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md#serviceextensionabilityondisconnect), and [onDestroy()](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md#serviceextensionabilityondestroy). Override them as required. The following figure shows the ServiceExtensionAbility lifecycle.
34e41f4b71Sopenharmony_ci
35e41f4b71Sopenharmony_ci**Figure 1** ServiceExtensionAbility lifecycle
36e41f4b71Sopenharmony_ci
37e41f4b71Sopenharmony_ci![ServiceExtensionAbility-lifecycle](figures/ServiceExtensionAbility-lifecycle.png)
38e41f4b71Sopenharmony_ci
39e41f4b71Sopenharmony_ci- **onCreate**
40e41f4b71Sopenharmony_ci
41e41f4b71Sopenharmony_ci  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.
42e41f4b71Sopenharmony_ci
43e41f4b71Sopenharmony_ci  > **NOTE**
44e41f4b71Sopenharmony_ci  >
45e41f4b71Sopenharmony_ci  > If a ServiceExtensionAbility has been created, starting it again does not trigger the **onCreate()** callback.
46e41f4b71Sopenharmony_ci
47e41f4b71Sopenharmony_ci- **onRequest**
48e41f4b71Sopenharmony_ci
49e41f4b71Sopenharmony_ci  This callback is triggered when another component calls the [startServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext-sys.md#uiabilitycontextstartserviceextensionability) method to start a ServiceExtensionAbility. After being started, the ServiceExtensionAbility runs in the background. This callback is triggered each time the **startServiceExtensionAbility()** method is called.
50e41f4b71Sopenharmony_ci
51e41f4b71Sopenharmony_ci- **onConnect**
52e41f4b71Sopenharmony_ci
53e41f4b71Sopenharmony_ci  This callback is triggered when another component calls the [connectServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextconnectserviceextensionability) method to connect to a ServiceExtensionAbility. In this method, a remote proxy object, namely, [IRemoteObject](../reference/apis-ipc-kit/js-apis-rpc.md#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()** method to connect to this ServiceExtensionAbility, the system returns the saved IRemoteObject, without triggering the callback.
54e41f4b71Sopenharmony_ci
55e41f4b71Sopenharmony_ci- **onDisconnect**
56e41f4b71Sopenharmony_ci
57e41f4b71Sopenharmony_ci  This callback is triggered when the last connection is interrupted. A connection is interrupted when the client exits or the [disconnectServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextdisconnectserviceextensionability) method is called.
58e41f4b71Sopenharmony_ci
59e41f4b71Sopenharmony_ci- **onDestroy**
60e41f4b71Sopenharmony_ci
61e41f4b71Sopenharmony_ci  This callback is triggered when a ServiceExtensionAbility is no longer used and the instance is ready for destruction. You can clear resources in this callback, for example, deregistering the listener.
62e41f4b71Sopenharmony_ci
63e41f4b71Sopenharmony_ci## Implementing a Background Service (for System Applications Only)
64e41f4b71Sopenharmony_ci
65e41f4b71Sopenharmony_ci### Preparations
66e41f4b71Sopenharmony_ci
67e41f4b71Sopenharmony_ciOnly system applications can implement a [ServiceExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md). You must make the following preparations before development:
68e41f4b71Sopenharmony_ci
69e41f4b71Sopenharmony_ci- **Switching to the full SDK**: All the APIs provided by the **ServiceExtensionAbility** class 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).
70e41f4b71Sopenharmony_ci
71e41f4b71Sopenharmony_ci- **Requesting the AllowAppUsePrivilegeExtension privilege**: Only applications with the **AllowAppUsePrivilegeExtension** privilege can implement a ServiceExtensionAbility. For details about how to request the privilege, see [Application Privilege Configuration Guide](../../device-dev/subsystems/subsys-app-privilege-config-guide.md).
72e41f4b71Sopenharmony_ci
73e41f4b71Sopenharmony_ci### Defining IDL APIs
74e41f4b71Sopenharmony_ci
75e41f4b71Sopenharmony_ciAs a background service, a 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**:
76e41f4b71Sopenharmony_ci
77e41f4b71Sopenharmony_ci```cpp
78e41f4b71Sopenharmony_ciinterface OHOS.IIdlServiceExt {
79e41f4b71Sopenharmony_ci  int ProcessData([in] int data);
80e41f4b71Sopenharmony_ci  void InsertDataToMap([in] String key, [in] int val);
81e41f4b71Sopenharmony_ci}
82e41f4b71Sopenharmony_ci```
83e41f4b71Sopenharmony_ci
84e41f4b71Sopenharmony_ciCreate the **IdlServiceExt** directory in the **ets** directory of a module in a 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.
85e41f4b71Sopenharmony_ci
86e41f4b71Sopenharmony_ci```
87e41f4b71Sopenharmony_ci├── ets
88e41f4b71Sopenharmony_ci│ ├── IdlServiceExt
89e41f4b71Sopenharmony_ci│ │   ├── i_idl_service_ext.ts      # File generated by the IDL tool.
90e41f4b71Sopenharmony_ci│ │   ├── idl_service_ext_proxy.ts  # File generated by the IDL tool.
91e41f4b71Sopenharmony_ci│ │   ├── idl_service_ext_stub.ts   # File generated by the IDL tool.
92e41f4b71Sopenharmony_ci│ │   ├── idl_service_ext_impl.ts   # Customize this file to implement IDL APIs.
93e41f4b71Sopenharmony_ci│ └
94e41f4b71Sopenharmony_ci95e41f4b71Sopenharmony_ci```
96e41f4b71Sopenharmony_ci
97e41f4b71Sopenharmony_ciAn example of **idl_service_ext_impl.ts** is as follows:
98e41f4b71Sopenharmony_ci
99e41f4b71Sopenharmony_ci```ts
100e41f4b71Sopenharmony_ciimport IdlServiceExtStub from './idl_service_ext_stub';
101e41f4b71Sopenharmony_ciimport hilog from '@ohos.hilog';
102e41f4b71Sopenharmony_ciimport type { insertDataToMapCallback } from './i_idl_service_ext';
103e41f4b71Sopenharmony_ciimport type { processDataCallback } from './i_idl_service_ext';
104e41f4b71Sopenharmony_ci
105e41f4b71Sopenharmony_ciconst ERR_OK = 0;
106e41f4b71Sopenharmony_ciconst TAG: string = "[IdlServiceExtImpl]";
107e41f4b71Sopenharmony_ciconst DOMAIN_NUMBER: number = 0xFF00;
108e41f4b71Sopenharmony_ci
109e41f4b71Sopenharmony_ci// You need to implement APIs in this type.
110e41f4b71Sopenharmony_ciexport default class ServiceExtImpl extends IdlServiceExtStub {
111e41f4b71Sopenharmony_ci  processData(data: number, callback: processDataCallback): void {
112e41f4b71Sopenharmony_ci    // Implement service logic.
113e41f4b71Sopenharmony_ci    hilog.info(DOMAIN_NUMBER, TAG, `processData: ${data}`);
114e41f4b71Sopenharmony_ci    callback(ERR_OK, data + 1); // The verification is successful, and service logic is executed normally.
115e41f4b71Sopenharmony_ci  }
116e41f4b71Sopenharmony_ci
117e41f4b71Sopenharmony_ci  insertDataToMap(key: string, val: number, callback: insertDataToMapCallback): void {
118e41f4b71Sopenharmony_ci    // Implement service logic.
119e41f4b71Sopenharmony_ci    hilog.info(DOMAIN_NUMBER, TAG, `insertDataToMap, key: ${key}  val: ${val}`);
120e41f4b71Sopenharmony_ci    callback(ERR_OK);
121e41f4b71Sopenharmony_ci  }
122e41f4b71Sopenharmony_ci}
123e41f4b71Sopenharmony_ci```
124e41f4b71Sopenharmony_ci
125e41f4b71Sopenharmony_ci### Creating a ServiceExtensionAbility
126e41f4b71Sopenharmony_ci
127e41f4b71Sopenharmony_ciTo manually create a ServiceExtensionAbility in the DevEco Studio project, perform the following steps:
128e41f4b71Sopenharmony_ci
129e41f4b71Sopenharmony_ci1. In the **ets** directory of a module in the project, right-click and choose **New > Directory** to create a directory named **ServiceExtAbility**.
130e41f4b71Sopenharmony_ci
131e41f4b71Sopenharmony_ci2. In the **ServiceExtAbility** directory, right-click and choose **New > ArkTS File** to create a file named **ServiceExtAbility.ets**.
132e41f4b71Sopenharmony_ci
133e41f4b71Sopenharmony_ci    ```
134e41f4b71Sopenharmony_ci    ├── ets
135e41f4b71Sopenharmony_ci    │ ├── IdlServiceExt
136e41f4b71Sopenharmony_ci    │ │   ├── i_idl_service_ext.ets      # File generated by the IDL tool.
137e41f4b71Sopenharmony_ci    │ │   ├── idl_service_ext_proxy.ets  # File generated by the IDL tool.
138e41f4b71Sopenharmony_ci    │ │   ├── idl_service_ext_stub.ets   # File generated by the IDL tool.
139e41f4b71Sopenharmony_ci    │ │   ├── idl_service_ext_impl.ets   # Customize this file to implement IDL APIs.
140e41f4b71Sopenharmony_ci    │ ├── ServiceExtAbility
141e41f4b71Sopenharmony_ci    │ │   ├── ServiceExtAbility.ets
142e41f4b71Sopenharmony_ci143e41f4b71Sopenharmony_ci    ```
144e41f4b71Sopenharmony_ci
145e41f4b71Sopenharmony_ci3. In the **ServiceExtAbility.ets** file, import the [ServiceExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md) module. Customize a class that inherits from ServiceExtensionAbility and implement the lifecycle callbacks. Return the previously defined **ServiceExtImpl** object in the [onConnect](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md#serviceextensionabilityoncreate) lifecycle callback.
146e41f4b71Sopenharmony_ci
147e41f4b71Sopenharmony_ci    ```ts
148e41f4b71Sopenharmony_ci    import { ServiceExtensionAbility, Want } from '@kit.AbilityKit';
149e41f4b71Sopenharmony_ci    import { rpc } from '@kit.IPCKit';
150e41f4b71Sopenharmony_ci    import { hilog } from '@kit.PerformanceAnalysisKit';
151e41f4b71Sopenharmony_ci    import ServiceExtImpl from '../IdlServiceExt/idl_service_ext_impl';
152e41f4b71Sopenharmony_ci    
153e41f4b71Sopenharmony_ci    const TAG: string = '[ServiceExtAbility]';
154e41f4b71Sopenharmony_ci    const DOMAIN_NUMBER: number = 0xFF00;
155e41f4b71Sopenharmony_ci    
156e41f4b71Sopenharmony_ci    export default class ServiceExtAbility extends ServiceExtensionAbility {
157e41f4b71Sopenharmony_ci      serviceExtImpl: ServiceExtImpl = new ServiceExtImpl('ExtImpl');
158e41f4b71Sopenharmony_ci    
159e41f4b71Sopenharmony_ci      onCreate(want: Want): void {
160e41f4b71Sopenharmony_ci        let serviceExtensionContext = this.context;
161e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, `onCreate, want: ${want.abilityName}`);
162e41f4b71Sopenharmony_ci      };
163e41f4b71Sopenharmony_ci    
164e41f4b71Sopenharmony_ci      onRequest(want: Want, startId: number): void {
165e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, `onRequest, want: ${want.abilityName}`);
166e41f4b71Sopenharmony_ci      };
167e41f4b71Sopenharmony_ci    
168e41f4b71Sopenharmony_ci      onConnect(want: Want): rpc.RemoteObject {
169e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, `onConnect, want: ${want.abilityName}`);
170e41f4b71Sopenharmony_ci        // Return the ServiceExtImpl object, through which the client can communicate with the ServiceExtensionAbility.
171e41f4b71Sopenharmony_ci        return this.serviceExtImpl as rpc.RemoteObject;
172e41f4b71Sopenharmony_ci      };
173e41f4b71Sopenharmony_ci    
174e41f4b71Sopenharmony_ci      onDisconnect(want: Want): void {
175e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, `onDisconnect, want: ${want.abilityName}`);
176e41f4b71Sopenharmony_ci      };
177e41f4b71Sopenharmony_ci    
178e41f4b71Sopenharmony_ci      onDestroy(): void {
179e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, 'onDestroy');
180e41f4b71Sopenharmony_ci      };
181e41f4b71Sopenharmony_ci    };
182e41f4b71Sopenharmony_ci    ```
183e41f4b71Sopenharmony_ci
184e41f4b71Sopenharmony_ci4. Register the ServiceExtensionAbility in the [module.json5 file](../quick-start/module-configuration-file.md) of the module in the project. Set **type** to **"service"** and **srcEntry** to the code path of the ServiceExtensionAbility component.
185e41f4b71Sopenharmony_ci
186e41f4b71Sopenharmony_ci    ```json
187e41f4b71Sopenharmony_ci    {
188e41f4b71Sopenharmony_ci      "module": {
189e41f4b71Sopenharmony_ci        // ...
190e41f4b71Sopenharmony_ci        "extensionAbilities": [
191e41f4b71Sopenharmony_ci          {
192e41f4b71Sopenharmony_ci            "name": "ServiceExtAbility",
193e41f4b71Sopenharmony_ci            "icon": "$media:icon",
194e41f4b71Sopenharmony_ci            "description": "service",
195e41f4b71Sopenharmony_ci            "type": "service",
196e41f4b71Sopenharmony_ci            "exported": true,
197e41f4b71Sopenharmony_ci            "srcEntry": "./ets/ServiceExtAbility/ServiceExtAbility.ets"
198e41f4b71Sopenharmony_ci          }
199e41f4b71Sopenharmony_ci        ]
200e41f4b71Sopenharmony_ci      }
201e41f4b71Sopenharmony_ci    }
202e41f4b71Sopenharmony_ci    ```
203e41f4b71Sopenharmony_ci
204e41f4b71Sopenharmony_ci## Starting a Background Service (for System Applications Only)
205e41f4b71Sopenharmony_ci
206e41f4b71Sopenharmony_ciA system application uses the [startServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext-sys.md#uiabilitycontextstartserviceextensionability) method to start a background service. The [onRequest()](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.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-ability-kit/js-apis-inner-application-serviceExtensionContext-sys.md#serviceextensioncontextterminateself) when its work is complete. Alternatively, another component can call [stopServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext-sys.md#abilitycontextstopserviceextensionability) to stop the background service.
207e41f4b71Sopenharmony_ci
208e41f4b71Sopenharmony_ci> **NOTE**
209e41f4b71Sopenharmony_ci> **startServiceExtensionAbility()**, **stopServiceExtensionAbility()**, and **terminateSelf()** provided by the **ServiceExtensionContext** class are system APIs and cannot be called by third-party applications.
210e41f4b71Sopenharmony_ci
211e41f4b71Sopenharmony_ci1. Start a new [ServiceExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md) 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).
212e41f4b71Sopenharmony_ci
213e41f4b71Sopenharmony_ci    ```ts
214e41f4b71Sopenharmony_ci    import { common, Want } from '@kit.AbilityKit';
215e41f4b71Sopenharmony_ci    import { promptAction } from '@kit.ArkUI';
216e41f4b71Sopenharmony_ci    import { hilog } from '@kit.PerformanceAnalysisKit';
217e41f4b71Sopenharmony_ci    import { BusinessError } from '@kit.BasicServicesKit';
218e41f4b71Sopenharmony_ci
219e41f4b71Sopenharmony_ci    const TAG: string = '[Page_ServiceExtensionAbility]';
220e41f4b71Sopenharmony_ci    const DOMAIN_NUMBER: number = 0xFF00;
221e41f4b71Sopenharmony_ci    
222e41f4b71Sopenharmony_ci    @Entry
223e41f4b71Sopenharmony_ci    @Component
224e41f4b71Sopenharmony_ci    struct Page_ServiceExtensionAbility {
225e41f4b71Sopenharmony_ci      build() {
226e41f4b71Sopenharmony_ci        Column() {
227e41f4b71Sopenharmony_ci          //...
228e41f4b71Sopenharmony_ci          List({ initialIndex: 0 }) {
229e41f4b71Sopenharmony_ci            ListItem() {
230e41f4b71Sopenharmony_ci              Row() {
231e41f4b71Sopenharmony_ci                //...
232e41f4b71Sopenharmony_ci              }
233e41f4b71Sopenharmony_ci              .onClick(() => {
234e41f4b71Sopenharmony_ci                let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
235e41f4b71Sopenharmony_ci                let want: Want = {
236e41f4b71Sopenharmony_ci                  deviceId: '',
237e41f4b71Sopenharmony_ci                  bundleName: 'com.samples.stagemodelabilitydevelop',
238e41f4b71Sopenharmony_ci                  abilityName: 'ServiceExtAbility'
239e41f4b71Sopenharmony_ci                };
240e41f4b71Sopenharmony_ci                context.startServiceExtensionAbility(want).then(() => {
241e41f4b71Sopenharmony_ci                  hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in starting ServiceExtensionAbility.');
242e41f4b71Sopenharmony_ci                  // The background service is started.
243e41f4b71Sopenharmony_ci                  promptAction.showToast({
244e41f4b71Sopenharmony_ci                    message: 'SuccessfullyStartBackendService'
245e41f4b71Sopenharmony_ci                  });
246e41f4b71Sopenharmony_ci                }).catch((err: BusinessError) => {
247e41f4b71Sopenharmony_ci                  hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ServiceExtensionAbility. Code is ${err.code}, message is ${err.message}`);
248e41f4b71Sopenharmony_ci                });
249e41f4b71Sopenharmony_ci              })
250e41f4b71Sopenharmony_ci            }
251e41f4b71Sopenharmony_ci            //...
252e41f4b71Sopenharmony_ci          }
253e41f4b71Sopenharmony_ci          //...
254e41f4b71Sopenharmony_ci        }
255e41f4b71Sopenharmony_ci        //...
256e41f4b71Sopenharmony_ci      }
257e41f4b71Sopenharmony_ci    }
258e41f4b71Sopenharmony_ci    ```
259e41f4b71Sopenharmony_ci
260e41f4b71Sopenharmony_ci2. Stop the [ServiceExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md) in the system application.
261e41f4b71Sopenharmony_ci
262e41f4b71Sopenharmony_ci    ```ts
263e41f4b71Sopenharmony_ci    import { common, Want } from '@kit.AbilityKit';
264e41f4b71Sopenharmony_ci    import { promptAction } from '@kit.ArkUI';
265e41f4b71Sopenharmony_ci    import { hilog } from '@kit.PerformanceAnalysisKit';
266e41f4b71Sopenharmony_ci    import { BusinessError } from '@kit.BasicServicesKit';
267e41f4b71Sopenharmony_ci    
268e41f4b71Sopenharmony_ci    const TAG: string = '[Page_ServiceExtensionAbility]';
269e41f4b71Sopenharmony_ci    const DOMAIN_NUMBER: number = 0xFF00;
270e41f4b71Sopenharmony_ci    
271e41f4b71Sopenharmony_ci    @Entry
272e41f4b71Sopenharmony_ci    @Component
273e41f4b71Sopenharmony_ci    struct Page_ServiceExtensionAbility {
274e41f4b71Sopenharmony_ci      build() {
275e41f4b71Sopenharmony_ci        Column() {
276e41f4b71Sopenharmony_ci          //...
277e41f4b71Sopenharmony_ci          List({ initialIndex: 0 }) {
278e41f4b71Sopenharmony_ci            ListItem() {
279e41f4b71Sopenharmony_ci              Row() {
280e41f4b71Sopenharmony_ci                //...
281e41f4b71Sopenharmony_ci              }
282e41f4b71Sopenharmony_ci              .onClick(() => {
283e41f4b71Sopenharmony_ci                let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
284e41f4b71Sopenharmony_ci                let want: Want = {
285e41f4b71Sopenharmony_ci                  deviceId: '',
286e41f4b71Sopenharmony_ci                  bundleName: 'com.samples.stagemodelabilitydevelop',
287e41f4b71Sopenharmony_ci                  abilityName: 'ServiceExtAbility'
288e41f4b71Sopenharmony_ci                };
289e41f4b71Sopenharmony_ci                context.stopServiceExtensionAbility(want).then(() => {
290e41f4b71Sopenharmony_ci                  hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in stopping ServiceExtensionAbility.');
291e41f4b71Sopenharmony_ci                  promptAction.showToast({
292e41f4b71Sopenharmony_ci                    message: 'SuccessfullyStoppedAStartedBackendService'
293e41f4b71Sopenharmony_ci                  });
294e41f4b71Sopenharmony_ci                }).catch((err: BusinessError) => {
295e41f4b71Sopenharmony_ci                  hilog.error(DOMAIN_NUMBER, TAG, `Failed to stop ServiceExtensionAbility. Code is ${err.code}, message is ${err.message}`);
296e41f4b71Sopenharmony_ci                });
297e41f4b71Sopenharmony_ci              })
298e41f4b71Sopenharmony_ci            }
299e41f4b71Sopenharmony_ci            //...
300e41f4b71Sopenharmony_ci          }
301e41f4b71Sopenharmony_ci          //...
302e41f4b71Sopenharmony_ci        }
303e41f4b71Sopenharmony_ci        //...
304e41f4b71Sopenharmony_ci      }
305e41f4b71Sopenharmony_ci    }
306e41f4b71Sopenharmony_ci    ```
307e41f4b71Sopenharmony_ci
308e41f4b71Sopenharmony_ci3. Enable the [ServiceExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md) to stop itself.
309e41f4b71Sopenharmony_ci
310e41f4b71Sopenharmony_ci    ```ts
311e41f4b71Sopenharmony_ci    import { common } from '@kit.AbilityKit';
312e41f4b71Sopenharmony_ci    import { promptAction } from '@kit.ArkUI';
313e41f4b71Sopenharmony_ci    import { hilog } from '@kit.PerformanceAnalysisKit';
314e41f4b71Sopenharmony_ci    import { BusinessError } from '@kit.BasicServicesKit';
315e41f4b71Sopenharmony_ci
316e41f4b71Sopenharmony_ci    const TAG: string = '[Page_ServiceExtensionAbility]';
317e41f4b71Sopenharmony_ci    const DOMAIN_NUMBER: number = 0xFF00;
318e41f4b71Sopenharmony_ci    
319e41f4b71Sopenharmony_ci    @Entry
320e41f4b71Sopenharmony_ci    @Component
321e41f4b71Sopenharmony_ci    struct Page_ServiceExtensionAbility {
322e41f4b71Sopenharmony_ci      build() {
323e41f4b71Sopenharmony_ci        Column() {
324e41f4b71Sopenharmony_ci          //...
325e41f4b71Sopenharmony_ci          List({ initialIndex: 0 }) {
326e41f4b71Sopenharmony_ci            ListItem() {
327e41f4b71Sopenharmony_ci              Row() {
328e41f4b71Sopenharmony_ci                //...
329e41f4b71Sopenharmony_ci              }
330e41f4b71Sopenharmony_ci              .onClick(() => {
331e41f4b71Sopenharmony_ci                let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
332e41f4b71Sopenharmony_ci                context.terminateSelf().then(() => {
333e41f4b71Sopenharmony_ci                  hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in terminating self.');
334e41f4b71Sopenharmony_ci                  // The background service is stopped.
335e41f4b71Sopenharmony_ci                  promptAction.showToast({
336e41f4b71Sopenharmony_ci                    message: 'SuccessfullyStopStartedBackendService'
337e41f4b71Sopenharmony_ci                  });
338e41f4b71Sopenharmony_ci                }).catch((err: BusinessError) => {
339e41f4b71Sopenharmony_ci                  hilog.error(DOMAIN_NUMBER, TAG, `Failed to terminate self. Code is ${err.code}, message is ${err.message}`);
340e41f4b71Sopenharmony_ci                });
341e41f4b71Sopenharmony_ci              })
342e41f4b71Sopenharmony_ci            }
343e41f4b71Sopenharmony_ci            //...
344e41f4b71Sopenharmony_ci          }
345e41f4b71Sopenharmony_ci          //...
346e41f4b71Sopenharmony_ci        }
347e41f4b71Sopenharmony_ci        //...
348e41f4b71Sopenharmony_ci      }
349e41f4b71Sopenharmony_ci    }
350e41f4b71Sopenharmony_ci    ```
351e41f4b71Sopenharmony_ci
352e41f4b71Sopenharmony_ci> **NOTE**
353e41f4b71Sopenharmony_ci>
354e41f4b71Sopenharmony_ci> Background services remain alive in the background for a long time. To minimize resource usage, destroy a background service in time in either of the following ways when it finishes the requested task:
355e41f4b71Sopenharmony_ci>
356e41f4b71Sopenharmony_ci> - The background service calls the [terminateSelf()](../reference/apis-ability-kit/js-apis-inner-application-serviceExtensionContext-sys.md#serviceextensioncontextterminateself) method to automatically stop itself.
357e41f4b71Sopenharmony_ci> - Another component calls the [stopServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext-sys.md#abilitycontextstopserviceextensionability) method to stop the background service.
358e41f4b71Sopenharmony_ci> After either method is called, the system destroys the background service.
359e41f4b71Sopenharmony_ci
360e41f4b71Sopenharmony_ci## Connecting to a Background Service
361e41f4b71Sopenharmony_ci
362e41f4b71Sopenharmony_ciEither a system application or a third-party application can connect to a background service (specified in the **Want** object) through [connectServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextconnectserviceextensionability). The [onConnect()](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md#serviceextensionabilityonconnect) callback is invoked, through which the background service receives the [Want](../reference/apis-ability-kit/js-apis-app-ability-want.md) object passed by the caller. In this way, a persistent connection is established.
363e41f4b71Sopenharmony_ci
364e41f4b71Sopenharmony_ciThe ServiceExtensionAbility returns an [IRemoteObject](../reference/apis-ipc-kit/js-apis-rpc.md#iremoteobject) in the **onConnect()** callback. Through this IRemoteObject, you can define communication interfaces for RPC interaction between the client and server. Multiple clients can simultaneously connect to the same background service. After a client finishes the interaction, it must call [disconnectServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextdisconnectserviceextensionability) to disconnect from the service. If all clients connected to a background service are disconnected, the system destroys the service.
365e41f4b71Sopenharmony_ci
366e41f4b71Sopenharmony_ci- Call [connectServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextconnectserviceextensionability) 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).
367e41f4b71Sopenharmony_ci  
368e41f4b71Sopenharmony_ci  ```ts
369e41f4b71Sopenharmony_ci  import { common, Want } from '@kit.AbilityKit';
370e41f4b71Sopenharmony_ci  import { rpc } from '@kit.IPCKit';
371e41f4b71Sopenharmony_ci  import { promptAction } from '@kit.ArkUI';
372e41f4b71Sopenharmony_ci  import { hilog } from '@kit.PerformanceAnalysisKit';
373e41f4b71Sopenharmony_ci  // The client needs to import idl_service_ext_proxy.ts provided by the server to the local project.
374e41f4b71Sopenharmony_ci  import IdlServiceExtProxy from '../IdlServiceExt/idl_service_ext_proxy';
375e41f4b71Sopenharmony_ci  
376e41f4b71Sopenharmony_ci  const TAG: string = '[Page_ServiceExtensionAbility]';
377e41f4b71Sopenharmony_ci  const DOMAIN_NUMBER: number = 0xFF00;
378e41f4b71Sopenharmony_ci  
379e41f4b71Sopenharmony_ci  let connectionId: number;
380e41f4b71Sopenharmony_ci  let want: Want = {
381e41f4b71Sopenharmony_ci    deviceId: '',
382e41f4b71Sopenharmony_ci    bundleName: 'com.samples.stagemodelabilitydevelop',
383e41f4b71Sopenharmony_ci    abilityName: 'ServiceExtAbility'
384e41f4b71Sopenharmony_ci  };
385e41f4b71Sopenharmony_ci  
386e41f4b71Sopenharmony_ci  let options: common.ConnectOptions = {
387e41f4b71Sopenharmony_ci    onConnect(elementName, remote: rpc.IRemoteObject): void {
388e41f4b71Sopenharmony_ci      hilog.info(DOMAIN_NUMBER, TAG, 'onConnect callback');
389e41f4b71Sopenharmony_ci      if (remote === null) {
390e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, `onConnect remote is null`);
391e41f4b71Sopenharmony_ci        return;
392e41f4b71Sopenharmony_ci      }
393e41f4b71Sopenharmony_ci      let serviceExtProxy: IdlServiceExtProxy = new IdlServiceExtProxy(remote);
394e41f4b71Sopenharmony_ci      // Communication is carried out by API calling, without exposing RPC details.
395e41f4b71Sopenharmony_ci      serviceExtProxy.processData(1, (errorCode: number, retVal: number) => {
396e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, `processData, errorCode: ${errorCode}, retVal: ${retVal}`);
397e41f4b71Sopenharmony_ci      });
398e41f4b71Sopenharmony_ci      serviceExtProxy.insertDataToMap('theKey', 1, (errorCode: number) => {
399e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, `insertDataToMap, errorCode: ${errorCode}`);
400e41f4b71Sopenharmony_ci      })
401e41f4b71Sopenharmony_ci    },
402e41f4b71Sopenharmony_ci    onDisconnect(elementName): void {
403e41f4b71Sopenharmony_ci      hilog.info(DOMAIN_NUMBER, TAG, 'onDisconnect callback');
404e41f4b71Sopenharmony_ci    },
405e41f4b71Sopenharmony_ci    onFailed(code: number): void {
406e41f4b71Sopenharmony_ci      hilog.info(DOMAIN_NUMBER, TAG, 'onFailed callback', JSON.stringify(code));
407e41f4b71Sopenharmony_ci    }
408e41f4b71Sopenharmony_ci  };
409e41f4b71Sopenharmony_ci  @Entry
410e41f4b71Sopenharmony_ci  @Component
411e41f4b71Sopenharmony_ci  struct Page_ServiceExtensionAbility {
412e41f4b71Sopenharmony_ci    build() {
413e41f4b71Sopenharmony_ci      Column() {
414e41f4b71Sopenharmony_ci        //...
415e41f4b71Sopenharmony_ci        List({ initialIndex: 0 }) {
416e41f4b71Sopenharmony_ci          ListItem() {
417e41f4b71Sopenharmony_ci            Row() {
418e41f4b71Sopenharmony_ci              //...
419e41f4b71Sopenharmony_ci            }
420e41f4b71Sopenharmony_ci            .onClick(() => {
421e41f4b71Sopenharmony_ci              let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
422e41f4b71Sopenharmony_ci              // The ID returned after the connection is set up must be saved. The ID will be used for disconnection.
423e41f4b71Sopenharmony_ci              connectionId = context.connectServiceExtensionAbility(want, options);
424e41f4b71Sopenharmony_ci              // The background service is connected.
425e41f4b71Sopenharmony_ci              promptAction.showToast({
426e41f4b71Sopenharmony_ci                message: 'SuccessfullyConnectBackendService'
427e41f4b71Sopenharmony_ci              });
428e41f4b71Sopenharmony_ci              // connectionId = context.connectAbility(want, options);
429e41f4b71Sopenharmony_ci              hilog.info(DOMAIN_NUMBER, TAG, `connectionId is : ${connectionId}`);
430e41f4b71Sopenharmony_ci            })
431e41f4b71Sopenharmony_ci          }
432e41f4b71Sopenharmony_ci          //...
433e41f4b71Sopenharmony_ci        }
434e41f4b71Sopenharmony_ci        //...
435e41f4b71Sopenharmony_ci      }
436e41f4b71Sopenharmony_ci      //...
437e41f4b71Sopenharmony_ci    }
438e41f4b71Sopenharmony_ci  }
439e41f4b71Sopenharmony_ci  ```
440e41f4b71Sopenharmony_ci
441e41f4b71Sopenharmony_ci- Call [disconnectServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextdisconnectserviceextensionability) to disconnect from the background service.
442e41f4b71Sopenharmony_ci  
443e41f4b71Sopenharmony_ci  ```ts
444e41f4b71Sopenharmony_ci  import { common } from '@kit.AbilityKit';
445e41f4b71Sopenharmony_ci  import { promptAction } from '@kit.ArkUI';
446e41f4b71Sopenharmony_ci  import { hilog } from '@kit.PerformanceAnalysisKit';
447e41f4b71Sopenharmony_ci  import { BusinessError } from '@kit.BasicServicesKit';
448e41f4b71Sopenharmony_ci
449e41f4b71Sopenharmony_ci  const TAG: string = '[Page_ServiceExtensionAbility]';
450e41f4b71Sopenharmony_ci  const DOMAIN_NUMBER: number = 0xFF00;
451e41f4b71Sopenharmony_ci  
452e41f4b71Sopenharmony_ci  let connectionId: number;
453e41f4b71Sopenharmony_ci  @Entry
454e41f4b71Sopenharmony_ci  @Component
455e41f4b71Sopenharmony_ci  struct Page_ServiceExtensionAbility {
456e41f4b71Sopenharmony_ci    build() {
457e41f4b71Sopenharmony_ci      Column() {
458e41f4b71Sopenharmony_ci        //...
459e41f4b71Sopenharmony_ci        List({ initialIndex: 0 }) {
460e41f4b71Sopenharmony_ci          ListItem() {
461e41f4b71Sopenharmony_ci            Row() {
462e41f4b71Sopenharmony_ci              //...
463e41f4b71Sopenharmony_ci            }
464e41f4b71Sopenharmony_ci            .onClick(() => {
465e41f4b71Sopenharmony_ci              let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
466e41f4b71Sopenharmony_ci              // connectionId is returned when connectServiceExtensionAbility is called and needs to be manually maintained.
467e41f4b71Sopenharmony_ci              context.disconnectServiceExtensionAbility(connectionId).then(() => {
468e41f4b71Sopenharmony_ci                hilog.info(DOMAIN_NUMBER, TAG, 'disconnectServiceExtensionAbility success');
469e41f4b71Sopenharmony_ci                // The background service is disconnected.
470e41f4b71Sopenharmony_ci                promptAction.showToast({
471e41f4b71Sopenharmony_ci                  message: 'SuccessfullyDisconnectBackendService'
472e41f4b71Sopenharmony_ci                });
473e41f4b71Sopenharmony_ci              }).catch((error: BusinessError) => {
474e41f4b71Sopenharmony_ci                hilog.error(DOMAIN_NUMBER, TAG, 'disconnectServiceExtensionAbility failed');
475e41f4b71Sopenharmony_ci              });
476e41f4b71Sopenharmony_ci            })
477e41f4b71Sopenharmony_ci          }
478e41f4b71Sopenharmony_ci          //...
479e41f4b71Sopenharmony_ci        }
480e41f4b71Sopenharmony_ci        //...
481e41f4b71Sopenharmony_ci      }
482e41f4b71Sopenharmony_ci      //...
483e41f4b71Sopenharmony_ci    }
484e41f4b71Sopenharmony_ci  }
485e41f4b71Sopenharmony_ci
486e41f4b71Sopenharmony_ci  ```
487e41f4b71Sopenharmony_ci
488e41f4b71Sopenharmony_ci## Communication Between the Client and Server
489e41f4b71Sopenharmony_ci
490e41f4b71Sopenharmony_ciAfter obtaining the [rpc.IRemoteObject](../reference/apis-ipc-kit/js-apis-rpc.md#iremoteobject) from the [onConnect()](../reference/apis-ability-kit/js-apis-inner-ability-connectOptions.md#onconnect) lifecycle callback, the client can communicate with the ServiceExtensionAbility in either of the following ways:
491e41f4b71Sopenharmony_ci
492e41f4b71Sopenharmony_ci- Using the IDL APIs provided by the server for communication (recommended)
493e41f4b71Sopenharmony_ci
494e41f4b71Sopenharmony_ci  ```ts
495e41f4b71Sopenharmony_ci  // The client needs to import idl_service_ext_proxy.ts provided by the server to the local project.
496e41f4b71Sopenharmony_ci  import { common } from '@kit.AbilityKit';
497e41f4b71Sopenharmony_ci  import { rpc } from '@kit.IPCKit';
498e41f4b71Sopenharmony_ci  import { hilog } from '@kit.PerformanceAnalysisKit';
499e41f4b71Sopenharmony_ci  import IdlServiceExtProxy from '../IdlServiceExt/idl_service_ext_proxy';
500e41f4b71Sopenharmony_ci  
501e41f4b71Sopenharmony_ci  const TAG: string = '[Page_ServiceExtensionAbility]';
502e41f4b71Sopenharmony_ci  const DOMAIN_NUMBER: number = 0xFF00;
503e41f4b71Sopenharmony_ci  
504e41f4b71Sopenharmony_ci  let options: common.ConnectOptions = {
505e41f4b71Sopenharmony_ci    onConnect(elementName, remote: rpc.IRemoteObject): void {
506e41f4b71Sopenharmony_ci      hilog.info(DOMAIN_NUMBER, TAG, 'onConnect callback');
507e41f4b71Sopenharmony_ci      if (remote === null) {
508e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, `onConnect remote is null`);
509e41f4b71Sopenharmony_ci        return;
510e41f4b71Sopenharmony_ci      }
511e41f4b71Sopenharmony_ci      let serviceExtProxy: IdlServiceExtProxy = new IdlServiceExtProxy(remote);
512e41f4b71Sopenharmony_ci      // Communication is carried out by API calling, without exposing RPC details.
513e41f4b71Sopenharmony_ci      serviceExtProxy.processData(1, (errorCode: number, retVal: number) => {
514e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, `processData, errorCode: ${errorCode}, retVal: ${retVal}`);
515e41f4b71Sopenharmony_ci      });
516e41f4b71Sopenharmony_ci      serviceExtProxy.insertDataToMap('theKey', 1, (errorCode: number) => {
517e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, `insertDataToMap, errorCode: ${errorCode}`);
518e41f4b71Sopenharmony_ci      })
519e41f4b71Sopenharmony_ci    },
520e41f4b71Sopenharmony_ci    onDisconnect(elementName): void {
521e41f4b71Sopenharmony_ci      hilog.info(DOMAIN_NUMBER, TAG, 'onDisconnect callback');
522e41f4b71Sopenharmony_ci    },
523e41f4b71Sopenharmony_ci    onFailed(code: number): void {
524e41f4b71Sopenharmony_ci      hilog.info(DOMAIN_NUMBER, TAG, 'onFailed callback', JSON.stringify(code));
525e41f4b71Sopenharmony_ci    }
526e41f4b71Sopenharmony_ci  };
527e41f4b71Sopenharmony_ci  ```
528e41f4b71Sopenharmony_ci
529e41f4b71Sopenharmony_ci- Calling [sendMessageRequest](../reference/apis-ipc-kit/js-apis-rpc.md#sendmessagerequest9) to send messages to the server (not recommended)
530e41f4b71Sopenharmony_ci
531e41f4b71Sopenharmony_ci  ```ts
532e41f4b71Sopenharmony_ci  import { common } from '@kit.AbilityKit';
533e41f4b71Sopenharmony_ci  import { promptAction } from '@kit.ArkUI';
534e41f4b71Sopenharmony_ci  import { rpc } from '@kit.IPCKit';
535e41f4b71Sopenharmony_ci  import { hilog } from '@kit.PerformanceAnalysisKit';
536e41f4b71Sopenharmony_ci  import { BusinessError } from '@kit.BasicServicesKit';
537e41f4b71Sopenharmony_ci
538e41f4b71Sopenharmony_ci  const TAG: string = '[Page_CollaborateAbility]';
539e41f4b71Sopenharmony_ci  const DOMAIN_NUMBER: number = 0xFF00;
540e41f4b71Sopenharmony_ci  const REQUEST_CODE = 1;
541e41f4b71Sopenharmony_ci  let options: common.ConnectOptions = {
542e41f4b71Sopenharmony_ci    onConnect(elementName, remote): void {
543e41f4b71Sopenharmony_ci      hilog.info(DOMAIN_NUMBER, TAG, 'onConnect callback');
544e41f4b71Sopenharmony_ci      if (remote === null) {
545e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, `onConnect remote is null`);
546e41f4b71Sopenharmony_ci        return;
547e41f4b71Sopenharmony_ci      }
548e41f4b71Sopenharmony_ci      let option = new rpc.MessageOption();
549e41f4b71Sopenharmony_ci      let data = new rpc.MessageSequence();
550e41f4b71Sopenharmony_ci      let reply = new rpc.MessageSequence();
551e41f4b71Sopenharmony_ci
552e41f4b71Sopenharmony_ci      data.writeInt(99);
553e41f4b71Sopenharmony_ci      // You can send data to the target application for corresponding operations.
554e41f4b71Sopenharmony_ci      // @param code Indicates the service request code sent by the client.
555e41f4b71Sopenharmony_ci      // @param data Indicates the {@link MessageSequence} object sent by the client.
556e41f4b71Sopenharmony_ci      // @param reply Indicates the response message object sent by the remote service.
557e41f4b71Sopenharmony_ci      // @param options Specifies whether the operation is synchronous or asynchronous.
558e41f4b71Sopenharmony_ci      // @return Returns {@code true} if the operation is successful; returns {@code false} otherwise.
559e41f4b71Sopenharmony_ci
560e41f4b71Sopenharmony_ci      remote.sendMessageRequest(REQUEST_CODE, data, reply, option).then((ret: rpc.RequestResult) => {
561e41f4b71Sopenharmony_ci        let errCode = reply.readInt(); // Receive the information (100) returned by the target device if the connection is successful.
562e41f4b71Sopenharmony_ci        let msg: number = 0;
563e41f4b71Sopenharmony_ci        if (errCode === 0) {
564e41f4b71Sopenharmony_ci          msg = reply.readInt();
565e41f4b71Sopenharmony_ci        }
566e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, `sendRequest msg:${msg}`);
567e41f4b71Sopenharmony_ci        // The background service is connected.
568e41f4b71Sopenharmony_ci        promptAction.showToast({
569e41f4b71Sopenharmony_ci          message: `sendRequest msg:${msg}`
570e41f4b71Sopenharmony_ci        });
571e41f4b71Sopenharmony_ci      }).catch((error: BusinessError) => {
572e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, `sendRequest failed, ${JSON.stringify(error)}`);
573e41f4b71Sopenharmony_ci      });
574e41f4b71Sopenharmony_ci    },
575e41f4b71Sopenharmony_ci    onDisconnect(elementName): void {
576e41f4b71Sopenharmony_ci      hilog.info(DOMAIN_NUMBER, TAG, 'onDisconnect callback');
577e41f4b71Sopenharmony_ci    },
578e41f4b71Sopenharmony_ci    onFailed(code): void {
579e41f4b71Sopenharmony_ci      hilog.info(DOMAIN_NUMBER, TAG, 'onFailed callback');
580e41f4b71Sopenharmony_ci    }
581e41f4b71Sopenharmony_ci  };
582e41f4b71Sopenharmony_ci  //...
583e41f4b71Sopenharmony_ci  ```
584e41f4b71Sopenharmony_ci
585e41f4b71Sopenharmony_ci## Client Identity Verification by the Server
586e41f4b71Sopenharmony_ci
587e41f4b71Sopenharmony_ciWhen a 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:
588e41f4b71Sopenharmony_ci
589e41f4b71Sopenharmony_ci- **Verifying the client identity based on callerUid**
590e41f4b71Sopenharmony_ci
591e41f4b71Sopenharmony_ci  Call the [getCallingUid()](../reference/apis-ipc-kit/js-apis-rpc.md#getcallinguid) method to obtain the UID of the client, and then call the [getBundleNameByUid()](../reference/apis-ability-kit/js-apis-bundleManager-sys.md#bundlemanagergetbundlenamebyuid) method to obtain the corresponding bundle name. In this way, the client identity is verified. Note that [getBundleNameByUid()](../reference/apis-ability-kit/js-apis-bundleManager-sys.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 request to the server. The sample code is as follows:
592e41f4b71Sopenharmony_ci
593e41f4b71Sopenharmony_ci  ```ts
594e41f4b71Sopenharmony_ci  import { bundleManager } from '@kit.AbilityKit';
595e41f4b71Sopenharmony_ci  import { rpc } from '@kit.IPCKit';
596e41f4b71Sopenharmony_ci  import { hilog } from '@kit.PerformanceAnalysisKit';
597e41f4b71Sopenharmony_ci  import { BusinessError } from '@kit.BasicServicesKit';
598e41f4b71Sopenharmony_ci  import IdlServiceExtStub from './idl_service_ext_stub';
599e41f4b71Sopenharmony_ci  import type { InsertDataToMapCallback } from './i_idl_service_ext';
600e41f4b71Sopenharmony_ci  import type { ProcessDataCallback } from './i_idl_service_ext';
601e41f4b71Sopenharmony_ci  
602e41f4b71Sopenharmony_ci  const ERR_OK = 0;
603e41f4b71Sopenharmony_ci  const ERR_DENY = -1;
604e41f4b71Sopenharmony_ci  const TAG: string = "[IdlServiceExtImpl]";
605e41f4b71Sopenharmony_ci  const DOMAIN_NUMBER: number = 0xFF00;
606e41f4b71Sopenharmony_ci  
607e41f4b71Sopenharmony_ci  // You need to implement APIs in this type.
608e41f4b71Sopenharmony_ci  export default class ServiceExtImpl extends IdlServiceExtStub {
609e41f4b71Sopenharmony_ci    processData(data: number, callback: ProcessDataCallback): void {
610e41f4b71Sopenharmony_ci      // Implement service logic.
611e41f4b71Sopenharmony_ci      hilog.info(DOMAIN_NUMBER, TAG, `processData: ${data}`);
612e41f4b71Sopenharmony_ci      let callerUid = rpc.IPCSkeleton.getCallingUid();
613e41f4b71Sopenharmony_ci      bundleManager.getBundleNameByUid(callerUid).then((callerBundleName) => {
614e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, 'getBundleNameByUid: ' + callerBundleName);
615e41f4b71Sopenharmony_ci        // Identify the bundle name of the client.
616e41f4b71Sopenharmony_ci        if (callerBundleName !== 'com.samples.stagemodelabilitydevelop') { // The verification fails.
617e41f4b71Sopenharmony_ci          hilog.info(DOMAIN_NUMBER, TAG, 'The caller bundle is not in trustlist, reject');
618e41f4b71Sopenharmony_ci          return;
619e41f4b71Sopenharmony_ci        }
620e41f4b71Sopenharmony_ci        // The verification is successful, and service logic is executed normally.
621e41f4b71Sopenharmony_ci      }).catch((err: BusinessError) => {
622e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, 'getBundleNameByUid failed: ' + err.message);
623e41f4b71Sopenharmony_ci      });
624e41f4b71Sopenharmony_ci      //...
625e41f4b71Sopenharmony_ci    };
626e41f4b71Sopenharmony_ci  
627e41f4b71Sopenharmony_ci    insertDataToMap(key: string, val: number, callback: InsertDataToMapCallback): void {
628e41f4b71Sopenharmony_ci      // Implement service logic.
629e41f4b71Sopenharmony_ci      hilog.info(DOMAIN_NUMBER, TAG, `insertDataToMap, key: ${key}  val: ${val}`);
630e41f4b71Sopenharmony_ci      callback(ERR_OK);
631e41f4b71Sopenharmony_ci    };
632e41f4b71Sopenharmony_ci  };
633e41f4b71Sopenharmony_ci  ```
634e41f4b71Sopenharmony_ci
635e41f4b71Sopenharmony_ci- **Verifying the client identity based on callerTokenId**
636e41f4b71Sopenharmony_ci
637e41f4b71Sopenharmony_ci  Call the [getCallingTokenId()](../reference/apis-ipc-kit/js-apis-rpc.md#getcallingtokenid) method to obtain the token ID of the client, and then call the [verifyAccessTokenSync()](../reference/apis-ability-kit/js-apis-abilityAccessCtrl.md#verifyaccesstokensync) method to check whether the client has the required permission. Currently, the system does not support permission customization. Therefore, only [system-defined permissions](../security/AccessToken/permissions-for-all.md) can be verified. The sample code is as follows:
638e41f4b71Sopenharmony_ci
639e41f4b71Sopenharmony_ci  ```ts
640e41f4b71Sopenharmony_ci  import { abilityAccessCtrl, bundleManager } from '@kit.AbilityKit';
641e41f4b71Sopenharmony_ci  import { rpc } from '@kit.IPCKit';
642e41f4b71Sopenharmony_ci  import { hilog } from '@kit.PerformanceAnalysisKit';
643e41f4b71Sopenharmony_ci  import { BusinessError } from '@kit.BasicServicesKit';
644e41f4b71Sopenharmony_ci  import IdlServiceExtStub from './idl_service_ext_stub';
645e41f4b71Sopenharmony_ci  import type { InsertDataToMapCallback } from './i_idl_service_ext';
646e41f4b71Sopenharmony_ci  import type { ProcessDataCallback } from './i_idl_service_ext';
647e41f4b71Sopenharmony_ci  
648e41f4b71Sopenharmony_ci  const ERR_OK = 0;
649e41f4b71Sopenharmony_ci  const ERR_DENY = -1;
650e41f4b71Sopenharmony_ci  const TAG: string = '[IdlServiceExtImpl]';
651e41f4b71Sopenharmony_ci  const DOMAIN_NUMBER: number = 0xFF00;
652e41f4b71Sopenharmony_ci  
653e41f4b71Sopenharmony_ci  // You need to implement APIs in this type.
654e41f4b71Sopenharmony_ci  export default class ServiceExtImpl extends IdlServiceExtStub {
655e41f4b71Sopenharmony_ci    processData(data: number, callback: ProcessDataCallback): void {
656e41f4b71Sopenharmony_ci      // Implement service logic.
657e41f4b71Sopenharmony_ci      hilog.info(DOMAIN_NUMBER, TAG, `processData: ${data}`);
658e41f4b71Sopenharmony_ci  
659e41f4b71Sopenharmony_ci      let callerUid = rpc.IPCSkeleton.getCallingUid();
660e41f4b71Sopenharmony_ci      bundleManager.getBundleNameByUid(callerUid).then((callerBundleName) => {
661e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, 'getBundleNameByUid: ' + callerBundleName);
662e41f4b71Sopenharmony_ci        // Identify the bundle name of the client.
663e41f4b71Sopenharmony_ci        if (callerBundleName !== 'com.samples.stagemodelabilitydevelop') { // The verification fails.
664e41f4b71Sopenharmony_ci          hilog.info(DOMAIN_NUMBER, TAG, 'The caller bundle is not in trustlist, reject');
665e41f4b71Sopenharmony_ci          return;
666e41f4b71Sopenharmony_ci        }
667e41f4b71Sopenharmony_ci        // The verification is successful, and service logic is executed normally.
668e41f4b71Sopenharmony_ci      }).catch((err: BusinessError) => {
669e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, 'getBundleNameByUid failed: ' + err.message);
670e41f4b71Sopenharmony_ci      });
671e41f4b71Sopenharmony_ci  
672e41f4b71Sopenharmony_ci      let callerTokenId = rpc.IPCSkeleton.getCallingTokenId();
673e41f4b71Sopenharmony_ci      let accessManger = abilityAccessCtrl.createAtManager();
674e41f4b71Sopenharmony_ci      /* The permission to be verified varies depending on the service requirements.
675e41f4b71Sopenharmony_ci       * ohos.permission.GET_BUNDLE_INFO_PRIVILEGED is only an example.
676e41f4b71Sopenharmony_ci       */
677e41f4b71Sopenharmony_ci      let grantStatus = accessManger.verifyAccessTokenSync(callerTokenId, 'ohos.permission.GET_BUNDLE_INFO_PRIVILEGED');
678e41f4b71Sopenharmony_ci      if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) {
679e41f4b71Sopenharmony_ci        hilog.info(DOMAIN_NUMBER, TAG, 'PERMISSION_DENIED');
680e41f4b71Sopenharmony_ci        callback(ERR_DENY, data); // The verification fails and an error is returned.
681e41f4b71Sopenharmony_ci        return;
682e41f4b71Sopenharmony_ci      }
683e41f4b71Sopenharmony_ci      hilog.info(DOMAIN_NUMBER, TAG, 'verify access token success.');
684e41f4b71Sopenharmony_ci      callback(ERR_OK, data + 1); // The verification is successful, and service logic is executed normally.
685e41f4b71Sopenharmony_ci    };
686e41f4b71Sopenharmony_ci  
687e41f4b71Sopenharmony_ci    insertDataToMap(key: string, val: number, callback: InsertDataToMapCallback): void {
688e41f4b71Sopenharmony_ci      // Implement service logic.
689e41f4b71Sopenharmony_ci      hilog.info(DOMAIN_NUMBER, TAG, `insertDataToMap, key: ${key}  val: ${val}`);
690e41f4b71Sopenharmony_ci      callback(ERR_OK);
691e41f4b71Sopenharmony_ci    };
692e41f4b71Sopenharmony_ci  };
693e41f4b71Sopenharmony_ci  ```
694e41f4b71Sopenharmony_ci
695