• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# UIExtensionAbility
2
3## Overview
4
5[UIExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md) is an ExtensionAbility component of the UI type. It is usually used in modular development scenarios where process isolation is required, for example, system dialog boxes, status bars, and capsules. There are two forms: embedded and system pop-ups.
6- The UIExtensionAbility in embedded mode must be used together with the [UIExtensionComponent](../reference/apis-arkui/arkui-ts/ts-container-ui-extension-component-sys.md). Specifically, with the UIExtensionComponent, you can embed the UI provided by the UIExtensionAbility of another application into a UIAbility of your application. The UIExtensionAbility runs in a process independent of the UIAbility for UI layout and rendering.
7- To start the UIExtensionAbility in system pop-up mode, call [requestModalUIExtensionAbility](../reference/apis-ability-kit/js-apis-inner-application-serviceExtensionContext-sys.md#serviceextensioncontextrequestmodaluiextension11) or the specified interface encapsulated in the application.
8
9## Constraints
10- Currently, the UIExtensionAbility of the **sys/commonUI**, **sysDialog**, and **sysPicker** types can be used only by system applications. For details about the UIExtensionAbility types and corresponding permission control, see the [module.json5 file](../quick-start/module-configuration-file.md).
11- The UIExtensionAbility can be started only by applications that are running in the foreground.
12
13## Lifecycle
14The [UIExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md) class provides the lifecycle callbacks [onCreate](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md#oncreate), [onSessionCreate](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md#onsessioncreate), [onSessionDestroy](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md#onsessiondestroy), [onForeground](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md#onforeground), [onBackground](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md#onbackground), and [onDestroy](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md#ondestroy). You must override them as required.
15
16- **onCreate**: called to initialize the service logic when a UIExtensionAbility is created.
17- **onSessionCreate**: called when a UIExtensionContentSession instance is created for the UIExtensionAbility.
18- **onSessionDestroy**: called when a UIExtensionContentSession instance is destroyed for the UIExtensionAbility.
19- **onForeground**: called when the UIExtensionAbility is switched from the background to the foreground.
20- **onBackground**: called when the UIExtensionAbility is switched from the foreground to the background.
21- **onDestroy**: called to clear resources when the UIExtensionAbility is destroyed.
22
23## Selecting a Proper Process Model for the UIExtensionAbility
24The [UIExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md) supports the multiton pattern. Each embedded UI corresponds to a UIExtensionAbility instance. In the multiton scenario, the multi-process model is used by default.
25
26When multiple UIExtensionAbility instances exist in an application, these instances can run in independent processes or share one process. They can also be grouped, and each group share one process. You can select a process model based on the **extensionProcessMode** field in the [module.json5](../quick-start/module-configuration-file.md) file. The table below describes the comparison between the process models.
27| Process Model| extensionProcessMode Field Value| Description|
28| --------| --------| --------|
29| One process for all UIExtensionAbility instances in the same bundle|bundle|	The UIExtensionAbility instances do not need to communicate with each other across IPCs. Their statuses are dependent and affect each other.|
30| One process for all UIExtensionAbility instances with the same name| type |The UIExtensionAbility instances of the same type are configured in the same process so that your application can manage them by type.|
31| One process for each UIExtensionAbility instance| instance | The UIExtensionAbility instances communicate with each other only across IPCs. Their statuses do not affect each other, which is more secure.|
32### One Process for All UIExtensionAbility Instances in the Bundle
33The [UIExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md) instances of the same bundle are configured in a process. This makes communication between multiple instances easier. However, the status of these instances affects each other. When an instance in the process exits abnormally, all instances in the process exit.
34
35**Figure 1** Bundle-based process model configuration
36
37![uiextability-bundle-processmodel](figures/uiextability-bundle-processmodel.png)
38
39The sample code of **Index.ets** is as follows:
40```ts
41import { BusinessError } from '@kit.BasicServicesKit';
42
43@Entry
44@Component
45struct Index {
46  @State message: string = 'UIExtension UserA';
47  private myProxy: UIExtensionProxy | undefined = undefined;
48
49  build() {
50    Row() {
51      Column() {
52        Text(this.message)
53          .fontSize(30)
54          .size({ width: '100%', height: '50' })
55          .fontWeight(FontWeight.Bold)
56          .textAlign(TextAlign.Center)
57
58        UIExtensionComponent(
59          {
60            bundleName: 'com.samples.uiextensionability',
61            abilityName: 'UIExtensionProvider',
62            moduleName: 'entry',
63            parameters: {
64              'ability.want.params.uiExtensionType': 'sys/commonUI',
65            }
66          })
67          .onRemoteReady((proxy) => {
68            this.myProxy = proxy;
69          })
70          .onReceive((data) => {
71            this.message = JSON.stringify(data);
72          })
73          .onTerminated((terminateInfo: TerminationInfo) => {
74            // This callback is triggered when the started UIExtensionAbility is terminated by calling terminateSelfWithResult or terminateSelf.
75            // It returns the result of the UIExtensionAbility's normal exit, including the result code and Want data.
76            this.message = `terminate code: ${terminateInfo.code}, want: ${terminateInfo.want}`;
77          })
78          .onError((error: BusinessError) => {
79            // This callback is invoked when an error occurs during the running of the started UIExtensionAbility.
80            // It returns the error code and error message when the UIExtensionAbility encounters an exception.
81            this.message = `error code: ${error.code}, error msg: ${error.message}`;
82          })
83          .offset({ x: 0, y: 10 })
84          .size({ width: 300, height: 300 })
85          .border({
86            width: 5,
87            color: 0x317AF7,
88            radius: 10,
89            style: BorderStyle.Dotted
90          })
91
92        UIExtensionComponent(
93          {
94            bundleName: 'com.samples.uiextension2',
95            abilityName: 'UIExtensionProviderB',
96            moduleName: 'entry',
97            parameters: {
98              'ability.want.params.uiExtensionType': 'sys/commonUI',
99            }
100          })
101          .onRemoteReady((proxy) => {
102            this.myProxy = proxy;
103          })
104          .onReceive((data) => {
105            this.message = JSON.stringify(data);
106          })
107          .onTerminated((terminateInfo: TerminationInfo) => {
108            // This callback is triggered when the started UIExtensionAbility is terminated by calling terminateSelfWithResult or terminateSelf.
109            // It returns the result of the UIExtensionAbility's normal exit, including the result code and Want data.
110            this.message = `terminate code: ${terminateInfo.code}, want: ${terminateInfo.want}`;
111          })
112          .onError((error: BusinessError) => {
113            // This callback is invoked when an error occurs during the running of the started UIExtensionAbility.
114            // It returns the error code and error message when the UIExtensionAbility encounters an exception.
115            this.message = `error code: ${error.code}, error msg: ${error.message}`;
116          })
117          .offset({ x: 0, y: 50 })
118          .size({ width: 300, height: 300 })
119          .border({
120            width: 5,
121            color: 0x317AF7,
122            radius: 10,
123            style: BorderStyle.Dotted
124          })
125      }
126      .width('100%')
127    }
128    .height('100%')
129  }
130}
131```
132**Figure 2** Index page generated based on the preceding code
133
134![uiextension-bundle-example](figures/uiextability-bundle-example.png)
135
136If this process model is used, the process name format is as follows:
137
138process name [{bundleName}:{UIExtensionAbility type}]
139
140Example: process name [com.ohos.intentexecutedemo:xxx]
141
142**Figure 3** Bundle-based process model
143
144![uiextension-bundle-process-example](figures/uiextability-bundle-process-example.png)
145
146### One Process for All UIExtensionAbility Instances of the Same Type
147Processes are allocated based on the [UIExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md) type. Multiple UIExtensionAbility instances of the same type are configured in the same process so that your application can manage the instances by type.
148
149**Figure 4** Type-based process model configuration
150
151![uiextability-type-processmodel](figures/uiextability-type-processmodel.png)
152
153The sample code of **Index.ets** is as follows:
154```ts
155import { BusinessError } from '@kit.BasicServicesKit';
156
157@Entry
158@Component
159struct Index {
160  @State message: string = 'UIExtension User';
161  private myProxy: UIExtensionProxy | undefined = undefined;
162
163  build() {
164    Row() {
165      Column() {
166        Text(this.message)
167          .fontSize(30)
168          .size({ width: '100%', height: '50' })
169          .fontWeight(FontWeight.Bold)
170          .textAlign(TextAlign.Center)
171
172        UIExtensionComponent(
173          {
174            bundleName: 'com.samples.uiextensionability',
175            abilityName: 'UIExtensionProviderA',
176            moduleName: 'entry',
177            parameters: {
178              'ability.want.params.uiExtensionType': 'sys/commonUI',
179            }
180          })
181          .onRemoteReady((proxy) => {
182            this.myProxy = proxy;
183          })
184          .onReceive((data) => {
185            this.message = JSON.stringify(data);
186          })
187          .onTerminated((terminateInfo: TerminationInfo) => {
188            // This callback is triggered when the started UIExtensionAbility is terminated by calling terminateSelfWithResult or terminateSelf.
189            // It returns the result of the UIExtensionAbility's normal exit, including the result code and Want data.
190            this.message = `terminate code: ${terminateInfo.code}, want: ${terminateInfo.want}`;
191          })
192          .onError((error: BusinessError) => {
193            // This callback is invoked when an error occurs during the running of the started UIExtensionAbility.
194            // It returns the error code and error message when the UIExtensionAbility encounters an exception.
195            this.message = `error code: ${error.code}, error msg: ${error.message}`;
196          })
197          .offset({ x: 0, y: 10 })
198          .size({ width: 300, height: 300 })
199          .border({
200            width: 5,
201            color: 0x317AF7,
202            radius: 10,
203            style: BorderStyle.Dotted
204          })
205
206        UIExtensionComponent(
207          {
208            bundleName: 'com.samples.uiextensionability',
209            abilityName: 'UIExtensionProviderB',
210            moduleName: 'entry',
211            parameters: {
212              'ability.want.params.uiExtensionType': 'sys/commonUI',
213            }
214          })
215          .onRemoteReady((proxy) => {
216            this.myProxy = proxy;
217          })
218          .onReceive((data) => {
219            this.message = JSON.stringify(data);
220          })
221          .onTerminated((terminateInfo: TerminationInfo) => {
222            // This callback is triggered when the started UIExtensionAbility is terminated by calling terminateSelfWithResult or terminateSelf.
223            // It returns the result of the UIExtensionAbility's normal exit, including the result code and Want data.
224            this.message = `terminate code: ${terminateInfo.code}, want: ${terminateInfo.want}`;
225          })
226          .onError((error: BusinessError) => {
227            // This callback is invoked when an error occurs during the running of the started UIExtensionAbility.
228            // It returns the error code and error message when the UIExtensionAbility encounters an exception.
229            this.message = `error code: ${error.code}, error msg: ${error.message}`;
230          })
231          .offset({ x: 0, y: 50 })
232          .size({ width: 300, height: 300 })
233          .border({
234            width: 5,
235            color: 0x317AF7,
236            radius: 10,
237            style: BorderStyle.Dotted
238          })
239      }
240      .width('100%')
241    }
242    .height('100%')
243  }
244}
245```
246**Figure 5** Index page generated based on the preceding code
247
248![uiextability-type-example](figures/uiextability-type-example.png)
249
250If this process model is used, the process name format is as follows:
251
252process name [{bundleName}:{UIExtensionAbility name}]
253
254Example: process name [com.ohos.intentexecutedemo:xxx]
255
256**Figure 6** Type-based process model
257
258![uiextability-type-process-example](figures/uiexteability-type-precess-example.png)
259
260### One Process for Each UIExtensionAbility Instance
261Processes are allocated based on the [UIExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md) instance. That is, each UIExtensionAbility instance has an independent process. In this mode, UIExtensionAbility instances can communicate with each other only through IPCs. However, their statuses do not affect each other, improving security.
262
263**Figure 7** Instance-specific process model configuration
264
265![uiextability-instance-processmodel](figures/uiextability-instance-processmodel.png)
266
267
268The sample code of **Index.ets** is as follows:
269```ts
270import { BusinessError } from '@kit.BasicServicesKit';
271
272@Entry
273@Component
274struct Index {
275  @State message: string = 'UIExtension User'
276  private myProxy: UIExtensionProxy | undefined = undefined;
277
278  build() {
279    Row() {
280      Column() {
281        Text(this.message)
282          .fontSize(30)
283          .size({ width: '100%', height: '50' })
284          .fontWeight(FontWeight.Bold)
285          .textAlign(TextAlign.Center)
286
287        UIExtensionComponent(
288          {
289            bundleName: 'com.samples.uiextensionability',
290            abilityName: 'UIExtensionProvider',
291            moduleName: 'entry',
292            parameters: {
293              'ability.want.params.uiExtensionType': 'sys/commonUI',
294            }
295          })
296          .onRemoteReady((proxy) => {
297            this.myProxy = proxy;
298          })
299          .onReceive((data) => {
300            this.message = JSON.stringify(data);
301          })
302          .onTerminated((terminateInfo: TerminationInfo) => {
303            // This callback is triggered when the started UIExtensionAbility is terminated by calling terminateSelfWithResult or terminateSelf.
304            // It returns the result of the UIExtensionAbility's normal exit, including the result code and Want data.
305            this.message = `terminate code: ${terminateInfo.code}, want: ${terminateInfo.want}`;
306          })
307          .onError((error: BusinessError) => {
308            // This callback is invoked when an error occurs during the running of the started UIExtensionAbility.
309            // It returns the error code and error message when the UIExtensionAbility encounters an exception.
310            this.message = `error code: ${error.code}, error msg: ${error.message}`;
311          })
312          .offset({ x: 0, y: 10 })
313          .size({ width: 300, height: 300 })
314          .border({
315            width: 5,
316            color: 0x317AF7,
317            radius: 10,
318            style: BorderStyle.Dotted
319          })
320
321        UIExtensionComponent(
322          {
323            bundleName: 'com.samples.uiextensionability',
324            abilityName: 'UIExtensionProvider',
325            moduleName: 'entry',
326            parameters: {
327              'ability.want.params.uiExtensionType': 'sys/commonUI',
328            }
329          })
330          .onRemoteReady((proxy) => {
331            this.myProxy = proxy;
332          })
333          .onReceive((data) => {
334            this.message = JSON.stringify(data);
335          })
336          .onTerminated((terminateInfo: TerminationInfo) => {
337            // This callback is triggered when the started UIExtensionAbility is terminated by calling terminateSelfWithResult or terminateSelf.
338            // It returns the result of the UIExtensionAbility's normal exit, including the result code and Want data.
339            this.message = `terminate code: ${terminateInfo.code}, want: ${terminateInfo.want}`;
340          })
341          .onError((error: BusinessError) => {
342            // This callback is invoked when an error occurs during the running of the started UIExtensionAbility.
343            // It returns the error code and error message when the UIExtensionAbility encounters an exception.
344            this.message = `error code: ${error.code}, error msg: ${error.message}`;
345          })
346          .offset({ x: 0, y: 50 })
347          .size({ width: 300, height: 300 })
348          .border({
349            width: 5,
350            color: 0x317AF7,
351            radius: 10,
352            style: BorderStyle.Dotted
353          })
354      }
355      .width('100%')
356    }
357    .height('100%')
358  }
359}
360```
361**Figure 8** Index page generated based on the preceding code
362
363![uiextability-instance-example](figures/uiextability-instance-example.png)
364
365If this process model is used, the process name format is as follows:
366
367process name [{bundleName}: {UIExtensionAbility type}: {instance suffix}]
368
369Example: process name [com.ohos.intentexecutedemo:xxx:n]
370
371**Figure 9** Instance-specific process model
372
373![uiextability-instance-process-example](figures/uiextability-instance-process-example.png)
374
375The UIExtensionAbility provides related capabilities through the [UIExtensionContext](../reference/apis-ability-kit/js-apis-inner-application-uiExtensionContext.md) and [UIExtensionContentSession](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionContentSession.md). In this document, the started UIExtensionAbility is called the provider, and the [UIExtensionComponent](../reference/apis-arkui/arkui-ts/ts-container-ui-extension-component-sys.md) that starts the UIExtensionAbility is called the client.
376
377## How to Develop
378
379 For details about how to develop a system dialog box, see [requestModalUIExtension](../reference/apis-ability-kit/js-apis-inner-application-serviceExtensionContext-sys.md#serviceextensioncontextrequestmodaluiextension11).
380
381### Developing the UIExtensionAbility Provider
382
383To implement a provider, create a [UIExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md) in DevEco Studio as follows:
384
3851. In the **ets** directory of the **Module** project, right-click and choose **New > Directory** to create a directory named **uiextensionability**.
386
3872. Right-click the **uiextensionability** directory, and choose **New > File** to create a file named **UIExtensionAbility.ets**.
388
3893. Open the **UIExtensionAbility.ets** file and import its dependencies. Customize a class that inherits from **UIExtensionAbility** and implement the lifecycle callbacks [onCreate](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md#oncreate), [onSessionCreate](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md#onsessioncreate), [onSessionDestroy](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md#onsessiondestroy), [onForeground](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md#onforeground), [onBackground](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md#onbackground), and [onDestroy](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md#ondestroy).
390
391    ```ts
392    import { Want, UIExtensionAbility, UIExtensionContentSession } from '@kit.AbilityKit';
393
394    const TAG: string = '[testTag] UIExtAbility';
395
396    export default class UIExtAbility extends UIExtensionAbility {
397      onCreate() {
398        console.log(TAG, `onCreate`);
399      }
400
401      onForeground() {
402        console.log(TAG, `onForeground`);
403      }
404
405      onBackground() {
406        console.log(TAG, `onBackground`);
407      }
408
409      onDestroy() {
410        console.log(TAG, `onDestroy`);
411      }
412
413      onSessionCreate(want: Want, session: UIExtensionContentSession) {
414        console.log(TAG, `onSessionCreate, want: ${JSON.stringify(want)}}`);
415        let storage: LocalStorage = new LocalStorage();
416        storage.setOrCreate('session', session);
417        session.loadContent('pages/Extension', storage);
418      }
419
420      onSessionDestroy(session: UIExtensionContentSession) {
421        console.log(TAG, `onSessionDestroy`);
422      }
423    }
424    ```
425
4264. Write the entry page file **pages/extension.ets**, which will be loaded in [onSessionCreate](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md#onsessioncreate) of the [UIExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md), and declare "pages/Extension" in the **entry\src\main\resources\base\profile\main_pages.json** file. The content of **extension.ets** is as follows:
427
428    ```ts
429    import { UIExtensionContentSession } from '@kit.AbilityKit';
430
431    const TAG: string = `[testTag] ExtensionPage`;
432
433    @Entry()
434    @Component
435    struct Extension {
436      @State message: string = `UIExtension provider`;
437      localStorage: LocalStorage | undefined = this.getUIContext().getSharedLocalStorage();
438      private session: UIExtensionContentSession | undefined = this.localStorage?.get<UIExtensionContentSession>('session');
439
440      onPageShow() {
441        console.info(TAG, 'show');
442      }
443
444      build() {
445        Row() {
446          Column() {
447            Text(this.message)
448              .fontSize(30)
449              .fontWeight(FontWeight.Bold)
450              .textAlign(TextAlign.Center)
451
452            Button("send data")
453              .width('80%')
454              .type(ButtonType.Capsule)
455              .margin({ top: 20 })
456              .onClick(() => {
457                this.session?.sendData({ "data": 543321 });
458              })
459
460            Button("terminate self")
461              .width('80%')
462              .type(ButtonType.Capsule)
463              .margin({ top: 20 })
464              .onClick(() => {
465                this.session?.terminateSelf();
466                this.localStorage?.clear();
467              })
468
469            Button("terminate self with result")
470              .width('80%')
471              .type(ButtonType.Capsule)
472              .margin({ top: 20 })
473              .onClick(() => {
474                this.session?.terminateSelfWithResult({
475                  resultCode: 0,
476                  want: {
477                    bundleName: "com.example.uiextensiondemo",
478                    parameters: { "result": 123456 }
479                  }
480                })
481              })
482          }
483        }
484        .height('100%')
485      }
486    }
487    ```
488
4895. Register the [UIExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md) in the [module.json5 file](../quick-start/module-configuration-file.md) of the module. Set **type** to that configured for the UIExtensionAbility and **srcEntry** to the code path of the UIExtensionAbility. The **extensionProcessMode** field identifies the multiton process model. Here, **bundle** is used as an example.
490
491    ```json
492    {
493      "module": {
494        "extensionAbilities": [
495          {
496            "name": "UIExtensionProvider",
497            "srcEntry": "./ets/uiextensionability/UIExtensionAbility.ets",
498            "description": "UIExtensionAbility",
499            "type": "sys/commonUI",
500            "exported": true,
501            "extensionProcessMode": "bundle"
502          },
503        ]
504      }
505    }
506    ```
507## Developing the UIExtensionAbility Client
508
509You can load the [UIExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md) in the application through the [UIExtensionComponent](../reference/apis-arkui/arkui-ts/ts-container-ui-extension-component-sys.md) on the [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) page. For example, add the following content to the home page file **pages/Index.ets**:
510
511```ts
512import { BusinessError } from '@kit.BasicServicesKit';
513
514@Entry
515@Component
516struct Index {
517  @State message: string = 'UIExtension User';
518  private myProxy: UIExtensionProxy | undefined = undefined;
519
520  build() {
521    Row() {
522      Column() {
523        Text(this.message)
524          .fontSize(30)
525          .size({ width: '100%', height: '50' })
526          .fontWeight(FontWeight.Bold)
527          .textAlign(TextAlign.Center)
528
529        UIExtensionComponent(
530          {
531            bundleName: 'com.example.uiextensiondemo',
532            abilityName: 'UIExtensionProvider',
533            moduleName: 'entry',
534            parameters: {
535              'ability.want.params.uiExtensionType': 'sys/commonUI',
536            }
537          })
538          .onRemoteReady((proxy) => {
539            this.myProxy = proxy;
540          })
541          .onReceive((data) => {
542            this.message = JSON.stringify(data);
543          })
544          .onTerminated((terminateInfo: TerminationInfo) => {
545            // This callback is triggered when the started UIExtensionAbility is terminated by calling terminateSelfWithResult or terminateSelf.
546            // It returns the result of the UIExtensionAbility's normal exit, including the result code and Want data.
547            this.message = `terminate code: ${terminateInfo.code}, want: ${terminateInfo.want}`;
548          })
549          .onError((error: BusinessError) => {
550            // This callback is invoked when an error occurs during the running of the started UIExtensionAbility.
551            // It returns the error code and error message when the UIExtensionAbility encounters an exception.
552            this.message = `error code: ${error.code}, error msg: ${error.message}`;
553          })
554          .offset({ x: 0, y: 30 })
555          .size({ width: 300, height: 300 })
556          .border({
557            width: 5,
558            color: 0x317AF7,
559            radius: 10,
560            style: BorderStyle.Dotted
561          })
562
563        Button("sendData")
564          .type(ButtonType.Capsule)
565          .offset({ x: 0, y: 60 })
566          .width('80%')
567          .type(ButtonType.Capsule)
568          .margin({
569            top: 20
570          })
571          .onClick(() => {
572            this.myProxy?.send({
573              "data": 123456,
574              "message": "data from component"
575            })
576          })
577      }
578      .width('100%')
579    }
580    .height('100%')
581  }
582}
583```
584