1# UIServiceExtensionAbility (for System Applications Only)
2
3## Overview
4
5[UIServiceExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-uiServiceExtensionAbility-sys.md) is an [ExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-extensionAbility.md) component of the UIService type. It provides UI pages (such as preview pages) and background service capabilities. This component internally holds a [UIServiceExtensionContext](../reference/apis-ability-kit/js-apis-inner-application-uiserviceExtensionContext-sys.md), which provides a variety of APIs for external systems.
6
7In this document, the component that starts or connects to a UIServiceExtensionAbility is called the client, and the UIServiceExtensionAbility is called the server.
8
9An application can use a UIServiceExtensionAbility in two modes:
10- Call [startUIServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartuiserviceextensionability13) in the [UIAbilityContext](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md), [UIExtensionContext](../reference/apis-ability-kit/js-apis-inner-application-uiExtensionContext.md), or [ServiceExtensionContext](../reference/apis-ability-kit/js-apis-inner-application-serviceExtensionContext-sys.md) class to start a UIServiceExtensionAbility.
11- Call [connectUIServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextconnectuiserviceextensionability13) in the [UIAbilityContext](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md) or [UIExtensionContext](../reference/apis-ability-kit/js-apis-inner-application-uiExtensionContext.md) class to connect to a UIServiceExtensionAbility.
12
13Note the following:
14
15- Only one window is created during the start or connection of the UIServiceExtensionAbility.
16- If the window fails to be created or is destroyed, the UIServiceExtensionAbility is automatically destroyed.
17- The start, connection, and disconnection operations can be performed only in the main thread, but not in the Worker and TaskPool threads.
18- Applications can start and connect to a UIServiceExtensionAbility provided by the system only when they gain focus in the foreground.
19
20## Lifecycle
21
22The UIServiceExtensionAbility provides the following lifecycle callbacks: [onCreate()](../reference/apis-ability-kit/js-apis-app-ability-uiServiceExtensionAbility-sys.md#uiserviceextensionabilityoncreate), [onWindowWillCreate()](../reference/apis-ability-kit/js-apis-app-ability-uiServiceExtensionAbility-sys.md#uiserviceextensionabilityonwindowwillcreate), [onWindowDidCreate()](../reference/apis-ability-kit/js-apis-app-ability-uiServiceExtensionAbility-sys.md#uiserviceextensionabilityonwindowdidcreate), [onRequest()](../reference/apis-ability-kit/js-apis-app-ability-uiServiceExtensionAbility-sys.md#uiserviceextensionabilityonrequest), [onConnect()](../reference/apis-ability-kit/js-apis-app-ability-uiServiceExtensionAbility-sys.md#uiserviceextensionabilityonconnect), [onDisconnect()](../reference/apis-ability-kit/js-apis-app-ability-uiServiceExtensionAbility-sys.md#uiserviceextensionabilityondisconnect), [onData()](../reference/apis-ability-kit/js-apis-app-ability-uiServiceExtensionAbility-sys.md#uiserviceextensionabilityondata), and [onDestroy()](../reference/apis-ability-kit/js-apis-app-ability-uiServiceExtensionAbility-sys.md#uiserviceextensionabilityondestroy). Override them as required. The figure below shows the lifecycle transitions.
23
24  **Figure 1** UIServiceExtensionAbility lifecycle
25
26![UIServiceExtensionAbility-lifecycle](figures/UIServiceExtension-lifecycle.png)
27
28
29
30- **onCreate**
31
32  This callback is invoked when a UIServiceExtensionAbility is created for the first time. You can perform initialization operations, for example, registering a common event listener, in this callback.
33
34  > **NOTE**
35  >
36  > If the UIServiceExtensionAbility has been created, starting it again does not trigger the **onCreate()** callback.
37
38- **onRequest**
39
40  This callback is invoked when another component calls [startUIServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartuiserviceextensionability13) to start a UIServiceExtensionAbility. After this callback is invoked, the UIServiceExtensionAbility is started and runs in the foreground. This callback is invoked each time [startUIServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartuiserviceextensionability13) is called.
41
42- **onWindowWillCreate**
43
44  This callback is invoked before a window is created. Through this callback, you can pass window parameters to the system. If **config.windowAttribute** is set to **window.ExtensionWindowAttribute.SUB_WINDOW**, a subwindow is created. If it is set to **window.ExtensionWindowAttribute.SYSTEM_WINDOW**, a system window is created.
45
46  Currently, both the subwindow and system window can be created for the UIServiceExtensionAbility started by [UIAbilityContext](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md) and [UIExtensionContext](../reference/apis-ability-kit/js-apis-inner-application-uiExtensionContext.md), but only the system window can be created for the UIServiceExtensionAbility started by [ServiceExtensionContext](../reference/apis-ability-kit/js-apis-inner-application-serviceExtensionContext-sys.md). In addition, only one window is created for a UIServiceExtensionAbility.
47
48- **onWindowDidCreate**
49
50  This callback is invoked when a window is created. You can operate the window through a [Window](../reference/apis-arkui/js-apis-window-sys.md#window) object. You can use [window.on('windowVisibilityChange')](../reference/apis-arkui/js-apis-window.md#onwindowvisibilitychange11) to bind and process window events, such as window showing, hiding, and destruction.
51
52- **onConnect**
53
54  This callback is invoked when another component calls [connectUIServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextconnectuiserviceextensionability13) to connect to a UIServiceExtensionAbility. In this callback, a remote proxy object, namely, [UIServiceHostProxy](../reference/apis-ability-kit/js-apis-inner-application-uiservicehostproxy-sys.md), is returned, through which the server communicates with the client. For the same client, if the values of **DeviceId**, **BundleName**, **ModuleName**, and **AbilityName** in the want object and the callback object are the same, [onConnect()](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md#serviceextensionabilityonconnect) is invoked only for the first connection. If any of them is different, [onConnect()](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md#serviceextensionabilityonconnect) is invoked again.
55
56- **onData**
57
58  This callback is invoked to receive data sent by the caller through [UIServiceProxy](../reference/apis-ability-kit/js-apis-inner-application-uiserviceproxy.md).
59
60- **onDisconnect**
61
62  This callback is invoked when the connection is interrupted, which occurs when the client exits or [disconnectServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextdisconnectuiserviceextensionability13) is called.
63
64- **onDestroy**
65
66  This callback is invoked when a UIServiceExtensionAbility is no longer required and the instance is ready for destruction. You can clear resources, for example, deregistering the listener, in this callback.
67
68## Implementing an Extension Base Class of the UIService Type
69
70### Preparations
71
72Only system applications can implement a UIServiceExtensionAbility. You must make the following preparations before development:
73
74- **Switching to the full SDK**: All the APIs provided by the UIServiceExtensionAbility 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 [Switching to Full SDK](../faqs/full-sdk-switch-guide.md).
75
76- **Requesting the AllowAppUsePrivilegeExtension privilege**: Only applications with the **AllowAppUsePrivilegeExtension** privilege can implement a UIServiceExtensionAbility. For details about how to request the privilege, see [Application Privilege Configuration](../../device-dev/subsystems/subsys-app-privilege-config-guide.md).
77
78### Creating a UIServiceExtensionAbility
79
80To manually create a UIServiceExtensionAbility in a project in DevEco Studio, perform the following steps:
81
821. In the **ets** directory of a module in the project, right-click and choose **New > Directory** to create a directory named **UIServiceExt**.
83
842. In the **UIServiceExt** directory, right-click and choose **New > ArkTS File** to create a file named **UIServiceExt.ets**.
85
86    ```
87    ├── ets
88    │ ├── UIServiceExt
89    │ │   ├── UIServiceExt.ets
90    ```
91
923. In the **UIServiceExt.ets** file, import the UIServiceExtensionAbility module. Customize a class that inherits from the UIServiceExtensionAbility and implement the lifecycle callbacks.
93
94    ```ts
95    import { common, UIServiceExtensionAbility, Want } from '@kit.AbilityKit';
96    import { hilog } from '@kit.PerformanceAnalysisKit';
97    import { window } from '@kit.ArkUI';
98
99    export default class UIServiceExtAbility extends UIServiceExtensionAbility {
100      // Create a UIServiceExtensionAbility.
101      onCreate(want: Want) {
102        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
103      }
104      // Callback for request processing.
105      onRequest(want: Want, startId: number) {
106        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onRequest');
107      }
108      // Callback invoked when a connection is set up.
109      onConnect(want: Want, proxy: common.UIServiceHostProxy) {
110        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onConnect');
111      }
112      // Callback invoked when a connection is interrupted.
113      onDisconnect(want: Want, proxy: common.UIServiceHostProxy) {
114        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDisconnect');
115      }
116      // Callback invoked when a window is about to create.
117      onWindowWillCreate(config: window.ExtensionWindowConfig): void {
118        hilog.info(0x0000, TestTag, '%{public}s', 'Ability onWindowWillCreate');
119        let rect: window.Rect = {
120          left: 100, top: 100, width: 500, height: 500
121        };
122        config.windowRect = rect;
123        // Create a subwindow.
124        config.windowName = 'sub_window'
125        config.windowAttribute = window.ExtensionWindowAttribute.SUB_WINDOW;
126        config.windowRect = rect;
127        config.subWindowOptions = {
128          title: 'sub_window_title',
129          decorEnabled: true,
130          // Whether the window is a modal window.
131          isModal: false
132        }
133        hilog.info(0x0000, TestTag, '%{public}s', 'Ability onWindowWillCreate end');
134      }
135      // Callback invoked when a window is created.
136      onWindowDidCreate(window: window.Window) {
137        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowDidCreate');
138        window.setUIContent('uiservice/page/WindowPage')
139        window.showWindow()
140      }
141      // Callback invoked to receive data.
142      onData(proxy: common.UIServiceHostProxy, data: Record<string, Object>) {
143        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onData');
144      }
145      // Callback invoked to destroy the instance.
146      onDestroy() {
147        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
148      }
149    }
150    ```
151
1524. Register the UIServiceExtensionAbility in the [module.json5 file](../quick-start/module-configuration-file.md) of the module in the project. Set **type** to **"uiService"** and **srcEntry** to the code path of the UIServiceExtensionAbility component.
153
154    ```json
155    {
156      "module": {
157        // ...
158        "extensionAbilities": [
159          {
160            "name": "UIServiceExtAbility",
161            "icon": "$media:icon",
162            "description": "uiService",
163            "type": "uiService",
164            "exported": true,
165            "srcEntry": "./ets/UIServiceExtAbility/UIServiceExtAbility.ets"
166          }
167        ]
168      }
169    }
170    ```
171
172### Starting a UIServiceExtensionAbility
173
174An application calls [startUIServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartuiserviceextensionability13) to start a UIServiceExtensionAbility. The [onRequest()](../reference/apis-ability-kit/js-apis-app-ability-uiServiceExtensionAbility-sys.md#uiserviceextensionabilityonrequest) callback is invoked, through which the background service receives the **Want** object passed by the caller. Once the UIServiceExtensionAbility is started, its lifecycle is independent of the client. In other words, even if the client is destroyed, the background service remains alive. However, the service is destroyed if the window fails to be created or is destroyed. Therefore, the background service must be stopped by calling [terminateSelf()](../reference/apis-ability-kit/js-apis-inner-application-uiserviceExtensionContext-sys.md#uiserviceextensioncontextterminateself13) of [UIServiceExtensionContext](../reference/apis-ability-kit/js-apis-inner-application-uiserviceExtensionContext-sys.md) when its work is complete.
175
176Start a new UIServiceExtensionAbility 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).
177
178
179```ts
180import { common, Want } from '@kit.AbilityKit';
181import { BusinessError } from '@kit.BasicServicesKit';
182
183@Entry
184@Component
185struct Index {
186  build() {
187    Column() {
188      Row() {
189        // Create a Start button.
190        Button('start ability')
191          .enabled(true)
192          .onClick(() => {
193            let context = getContext(this) as common.UIAbilityContext;
194            let startWant: Want = {
195              bundleName: 'com.acts.uiserviceextensionability',
196              abilityName: 'UiServiceExtAbility',
197            };
198            try {
199              // Start the UIServiceExtensionAbility.
200              context.startUIServiceExtensionAbility(startWant).then(() => {
201                console.log('startUIServiceExtensionAbility success');
202              }).catch((error: BusinessError) => {
203                console.log('startUIServiceExtensionAbility error', JSON.stringify(error));
204              })
205            } catch (err) {
206              console.log('startUIServiceExtensionAbility failed', JSON.stringify(err));
207            }
208          })
209      }
210    }
211  }
212}
213```
214
215### Connecting to a UIServiceExtensionAbility
216
217An application can use [connectUIServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextconnectuiserviceextensionability13) to connect to a service (specified in the [Want](../reference/apis-ability-kit/js-apis-app-ability-want.md) object). The [onConnect()](../reference/apis-ability-kit/js-apis-app-ability-serviceExtensionAbility-sys.md#serviceextensionabilityonconnect) callback is invoked, through which the service receives the [Want](../reference/apis-ability-kit/js-apis-app-ability-want.md) object passed by the caller. In this way, a connection is established.
218
219When the client calls [connectUIServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextconnectuiserviceextensionability13) to connect to the server, the client receives a [UIServiceProxy](../reference/apis-ability-kit/js-apis-inner-application-uiserviceproxy.md) object returned by the server and saves it. Through this proxy object, the client sends data to the server, and disconnects from the server by calling [disconnectServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextdisconnectuiserviceextensionability13).
220
221- Call [connectUIServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextconnectuiserviceextensionability13) to connect to a UIServiceExtensionAbility. For details about how to obtain the context, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability).
222    ```ts
223    import { common, Want } from '@kit.AbilityKit';
224    import { BusinessError } from '@kit.BasicServicesKit';
225
226    @Entry
227    @Component
228    struct Page_UIServiceExtensionAbility {
229      @State uiServiceProxy: common.UIServiceProxy | null = null;
230
231      build() {
232        Column() {
233          //...
234          Row() {
235            //...
236          }.onClick(() => {
237            const context = getContext(this) as common.UIAbilityContext;
238            const want: Want = {
239              deviceId: '',
240              bundleName: 'com.example.myapplication',
241              abilityName: ''
242            };
243            // Define a callback.
244            const callback: common.UIServiceExtensionConnectCallback = {
245              onData: (data: Record<string, Object>): void => {
246                console.log('onData:', JSON.stringify(data));
247              },
248              onDisconnect: (): void => {
249                console.log('onDisconnect');
250              }
251            };
252            // Connect to the UIServiceExtensionAbility.
253            context.connectUIServiceExtensionAbility(want, callback).then((uiServiceProxy: common.UIServiceProxy) => {
254              this.uiServiceProxy = uiServiceProxy;
255              console.log('connectUIServiceExtensionAbility success');
256            }).catch((error: BusinessError) => {
257              console.log('connectUIServiceExtensionAbility failed', JSON.stringify(error));
258            })
259          })
260        }
261      }
262    }
263    ```
264
265- Call [disconnectUIServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextdisconnectuiserviceextensionability13) to disconnect from a UIServiceExtensionAbility.
266    ```ts
267    import { common } from '@kit.AbilityKit';
268    import { BusinessError } from '@kit.BasicServicesKit';
269
270    @Entry
271    @Component
272    struct Page_UIServiceExtensionAbility {
273      @State uiServiceProxy: common.UIServiceProxy | null = null;
274
275      build() {
276        Column() {
277          //...
278          Row() {
279            //...
280          }.onClick(() => {
281            const context = getContext(this) as common.UIAbilityContext;
282            // this.uiServiceProxy is the proxy object saved during connection.
283            context.disconnectUIServiceExtensionAbility(this.uiServiceProxy).then(() => {
284              console.log('disconnectUIServiceExtensionAbility success');
285            }).catch((error: BusinessError) => {
286              console.log('disconnectUIServiceExtensionAbility failed', JSON.stringify(error));
287            })
288          })
289        }
290      }
291    }
292    ```
293
294
295
296## Bidirectional Communication Between the Client and Server
297
298After a UIServiceExtensionAbility is started, the following operations are possible:
299
3001. The client calls [connectUIServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiExtensionContext.md#uiextensioncontextconnectuiserviceextensionability13) to obtain a [UIServiceProxy](../reference/apis-ability-kit/js-apis-inner-application-uiserviceproxy.md) object, through which it can send data to the server.
3012. The server obtains a [UIServiceHostProxy](../reference/apis-ability-kit/js-apis-inner-application-uiservicehostproxy-sys.md) object through the [onConnect()](../reference/apis-ability-kit/js-apis-app-ability-uiServiceExtensionAbility-sys.md#uiserviceextensionabilityonconnect) callback and sends data to the client through this proxy.
302
303![UIServiceExtensionAbility-bidirectionalcommunication](figures/UIServiceExtension-bidirectionalcommunication.png)
304
305
306### Communication Between the Client and Server
307- Data transmission on the client
308
309  The client connects to the server through [connectUIServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiExtensionContext.md#uiextensioncontextconnectuiserviceextensionability13) and obtains a [UIServiceProxy](../reference/apis-ability-kit/js-apis-inner-application-uiserviceproxy.md) object. The client calls [sendData()](../reference/apis-ability-kit/js-apis-inner-application-uiserviceproxy.md#uiserviceproxysenddata) of the proxy object to send data to the server. The server receives data through the [onData()](../reference/apis-ability-kit/js-apis-app-ability-uiServiceExtensionAbility-sys.md#uiserviceextensionabilityondata) callback.
310    ```ts
311    import { common, Want} from '@kit.AbilityKit';
312    import { BusinessError } from '@kit.BasicServicesKit';
313
314    @Entry
315    @Component
316    struct Index {
317      comProxy: common.UIServiceProxy | null = null;
318      connectCallback : common.UIServiceExtensionConnectCallback = {
319        onData:(data: Record<string, Object>) => {
320          console.log("received data", JSON.stringify(data));
321        },
322        onDisconnect:() => {
323          console.log("onDisconnect");
324        }
325      }
326
327      build() {
328        Column() {
329          Row() {
330            // Create a Connect button.
331            Button("connect ability")
332              .enabled(true)
333              .onClick(() => {
334                let context = getContext(this) as common.UIAbilityContext;
335                let startWant:Want = {
336                  bundleName: 'com.acts.uiserviceextensionability',
337                  abilityName: 'UiServiceExtAbility',
338                };
339                try {
340                // Connect to the UIServiceExtensionAbility.
341                context.connectUIServiceExtensionAbility(startWant, this.connectCallback).then((proxy: common.UIServiceProxy) => {
342                    this.comProxy = proxy;
343                    let formData: Record<string, string> = {
344                      'test': 'test'
345                    };
346                    try {
347                      this.comProxy.sendData(formData);
348                    } catch (err) {
349                      console.log('sendData failed', JSON.stringify(err));
350                    };
351                  }).catch((err: BusinessError) => {
352                    console.log("connectUIServiceExtensionAbility failed", JSON.stringify(err));
353                  });
354                } catch(err) {
355                  console.log("connectUIServiceExtensionAbility failed", JSON.stringify(err));
356                }
357              })
358          }
359        }
360      }
361    }
362    ```
363
364- Data transmission on the server
365
366  The server receives data transferred by the client through [onData()](../reference/apis-ability-kit/js-apis-app-ability-uiServiceExtensionAbility-sys.md#uiserviceextensionabilityondata). Through the [UIServiceHostProxy](../reference/apis-ability-kit/js-apis-inner-application-uiservicehostproxy-sys.md) object, which is saved during the connection, the server calls [sendData()](../reference/apis-ability-kit/js-apis-inner-application-uiservicehostproxy-sys.md#uiservicehostproxysenddata) to send data to the client.
367    ```ts
368    import { common, Want, UIServiceExtensionAbility} from '@kit.AbilityKit';
369    import { window } from '@kit.ArkUI';
370
371    export default class MyServiceExtAbility extends UIServiceExtensionAbility {
372      comProxy : common.UIServiceHostProxy | null = null;
373      // Callback invoked when a UIServiceExtensionAbility is created.
374      onCreate(want: Want) {
375        console.log('UIServiceExtensionAbility onCreate');
376      }
377
378      // Callback for request processing.
379      onRequest(want: Want, startId: number) {
380        console.log('UIServiceExtensionAbility onRequest');
381      }
382
383      // Callback invoked when a connection is set up.
384      onConnect(want: Want, proxy: common.UIServiceHostProxy) {
385        console.log('UIServiceExtensionAbility onConnect');
386        this.comProxy = proxy;
387      }
388
389      // Callback invoked when a connection is interrupted.
390      onDisconnect(want: Want, proxy: common.UIServiceHostProxy) {
391        console.log('UIServiceExtensionAbility onDisconnect');
392        this.comProxy = null;
393      }
394
395      // Callback invoked to receive data.
396      onData(proxy: common.UIServiceHostProxy, data: Record<string, Object>) {
397        console.log('UIServiceExtensionAbility onData');
398        try {
399          let formData: Record<string, string> = {
400            'Data' : 'reply message'
401          };
402          proxy.sendData(formData);
403        } catch (err) {
404          console.log('sendData failed',JSON.stringify(err));
405        };
406
407      }
408
409      onWindowWillCreate(extensionWindowConfig: window.ExtensionWindowConfig) {
410        console.log('UIServiceExtensionAbility onWindowWillCreate');
411      }
412
413      onWindowDidCreate(window: window.Window) {
414        console.log('UIServiceExtensionAbility onWindowDidCreate');
415      }
416
417      onDestroy() {
418        console.log('UIServiceExtensionAbility onDestroy');
419      }
420    }
421    ```
422