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 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 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