1# UIExtensionComponent (系统接口)
2
3UIExtensionComponent用于支持在本页面内嵌入其他应用提供的UI。展示的内容在另外一个进程中运行,本应用并不参与其中的布局和渲染。
4
5通常用于有进程隔离诉求的模块化开发场景。
6
7> **说明:**
8>
9> 该组件从API Version 10开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
10>
11> 本模块为系统接口。
12
13## 使用约束
14
15本组件不支持预览。
16
17被拉起的Ability必须是带UI的Ability扩展,如何实现带UI的Ability扩展请参考[实现带UI的Ability扩展](../../apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md)。
18
19必须显示设置组件宽高为非0有效值。
20
21## 子组件
22
2324
25## 接口
26
27UIExtensionComponent(want: Want, options?: UIExtensionOptions)
28
29**参数:**
30
31| 参数名                | 参数类型                                                   | 必填 | 参数描述           |
32| --------------------- | ---------------------------------------------------------- | ---- | ------------------ |
33| want                  | [Want](../../apis-ability-kit/js-apis-app-ability-want.md) | 是   | 要加载的Ability。  |
34| options<sup>11+</sup> | [UIExtensionOptions](#uiextensionoptions11)                | 否   | 需要传递的构造项。 |
35
36## 属性
37
38支持[通用属性](ts-universal-attributes-size.md)。
39
40## 事件
41
42不支持[点击](ts-universal-events-click.md)等通用事件。
43
44将事件经过坐标转换后传递给对端Ability处理。
45
46支持以下事件:
47
48### onRemoteReady
49
50onRemoteReady(callback: [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<UIExtensionProxy>)
51
52UIExtensionAbility连接完成时的回调,之后可使用proxy向被拉起的Ability发送数据。
53
54**参数:**
55
56| 参数名                       | 类型   | 说明                                                         |
57| ---------------------------- | ------ | ------------------------------------------------------------ |
58| proxy                        | UIExtensionProxy | 用于向对端Ability发送数据。                          |
59
60### onReceive
61
62onReceive(callback: ReceiveCallback)
63
64收到被拉起的Ability发送的数据时触发的回调。
65
66**参数:**
67
68| 参数名                       | 类型   | 说明                                                         |
69| ---------------------------- | ------ | ------------------------------------------------------------ |
70| data                        | [ReceiveCallback](#receivecallback14) | 收到来自对端Ability的数据。                 |
71
72### onResult<sup>(deprecated)</sup>
73
74onResult(callback: [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<{code: number; want?: Want}>)
75
76被拉起的Ability扩展调用terminateSelfWithResult时会先触发本回调函数,再触发OnRelease。
77
78本回调内可处理对端Ability的结果数据,可参考[AbilityResult](../../apis-ability-kit/js-apis-inner-ability-abilityResult.md)。
79
80> **说明:**
81> 从 API version 10 开始支持,从 API version 12 开始废弃,建议使用[onTerminated](#onterminated12)替代。
82
83**参数:**
84
85| 参数名                       | 类型   | 说明                                                         |
86| ---------------------------- | ------ | ------------------------------------------------------------ |
87| code                        | number | 收到来自对端Ability的处理結果code。                          |
88| want                        | Want | 收到来自对端Ability的处理結果[Want](../../apis-ability-kit/js-apis-app-ability-want.md)。 |
89
90### onRelease<sup>(deprecated)</sup>
91
92onRelease(callback: [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<number>)
93
94用于处理被拉起的Ability销毁时的回调。
95
96被拉起的Ability扩展调用terminateSelfWithResult或者terminateSelf时会触发本回调,此时releaseCode为0,即正常销毁。
97
98被拉起的Ability扩展意外Crash或被kill时,触发本回调,此时releaseCode为1。
99
100> **说明:**
101> 从 API version 10 开始支持,从 API version 12 开始废弃,建议使用[onTerminated](#onterminated12)或者[onError](#onerror)替代。
102
103**参数:**
104
105| 参数名                       | 类型   | 说明                                                         |
106| ---------------------------- | ------ | ------------------------------------------------------------ |
107| releaseCode                        | number | 对端Ability销毁时的code,0为正常销毁,1为异常销毁。                          |
108
109### onError
110
111onError(callback:[ErrorCallback](../../apis-basic-services-kit/js-apis-base.md#errorcallback))
112
113被拉起的Ability扩展在运行过程中发生异常时触发本回调。可通过回调参数中的code、name和message获取错误信息并做处理。
114
115**参数:**
116
117| 参数名                       | 类型   | 说明                                                         |
118| ---------------------------- | ------ | ------------------------------------------------------------ |
119| err                        | [BusinessError](../../apis-basic-services-kit/js-apis-base.md#businesserror) | 报错信息。    |
120
121### onTerminated<sup>12+<sup>
122
123onTerminated(callback: Callback&lt;TerminationInfo&gt;)
124
125被拉起的UIExtensionAbility通过调用`terminateSelfWithResult`或者`terminateSelf`正常退出时,触发本回调函数。
126
127**参数:**
128
129| 参数名   | 类型   | 说明                                                                                     |
130| -------  | ------ | ---------------------------------------------------------------------------------------- |
131| callback | [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<[TerminationInfo](#terminationinfo12)> | 回调函数,入参用于接收UIExtensionAbility的返回结果,类型为[TerminationInfo](#terminationinfo12)。 |
132
133> **说明:**
134>
135> - 若UIExtensionAbility通过调用`terminateSelfWithResult`退出,其携带的信息会传给回调函数的入参;
136> - 若UIExtensionAbility通过调用`terminateSelf`退出,上述回调函数的入参中,"code"取默认值"0","want"为"undefined"。
137
138### TerminationInfo<sup>12+<sup>
139
140用于表示被拉起的UIExtensionAbility通过调用`terminateSelfWithResult`或者`terminateSelf`正常退出时的返回结果。
141
142| 属性名  | 类型   | 说明                                                 |
143| ------- | ------ | ---------------------------------------------------  |
144| code    | number | 被拉起UIExtensionAbility退出时返回的结果码。 |
145| want    | [Want](../../apis-ability-kit/js-apis-app-ability-want.md)   | 被拉起UIExtensionAbility退出时返回的数据。   |
146
147## ReceiveCallback<sup>14+<sup>
148type ReceiveCallback = Callback\<Record\<string, Object\>\>
149
150用于封装被拉起的Ability发送的数据。
151
152**系统能力:** SystemCapability.ArkUI.ArkUI.Full
153
154**参数:**
155| 参数名                       | 类型   | 说明                                                         |
156| ---------------------------- | ------ | ------------------------------------------------------------ |
157| data                        | Record\<string, Object\> | 收到来自对端Ability的数据。                 |
158
159## UIExtensionOptions<sup>11+</sup>
160用于在UIExtensionComponent进行构造的时传递可选的构造参数。
161
162**参数:**
163
164| 参数名               | 参数类型                                 | 必填 | 参数描述                                                                                                      |
165| ----                 | ---------------------------------------- | ---- | ---------------                                                                                               |
166| isTransferringCaller | boolean                                  | 否   | 在使用UIExtensionComponent嵌套时,设置当前UIExtensionComponent是否转发上一级的Caller信息。</br> 默认值:false。 |
167| placeholder<sup>12+<sup> | [ComponentContent](../js-apis-arkui-ComponentContent.md)       | 否   | 设置占位符,在UIExtensionComponent与UIExtensionAbility建立连接前显示。 |
168| dpiFollowStrategy<sup>12+<sup> | [DpiFollowStrategy](ts-container-ui-extension-component-sys.md#dpifollowstrategy12)                  | 否   | 提供接口支持设置DPI跟随宿主或跟随UIExtensionAbility。</br> 默认值:FOLLOW_UI_EXTENSION_ABILITY_DPI。 |
169| areaChangePlaceholder<sup>13+<sup> | Record<string, [ComponentContent](../js-apis-arkui-ComponentContent.md)>       | 否   | 设置尺寸变化占位符,在UIExtensionComponent尺寸发生变化并且UIExtension内部渲染未完成时显示, key值支持"FOLD_TO_EXPAND"(折叠展开尺寸变化)、"UNDEFINED"(默认尺寸变化)。 |
170
171## DpiFollowStrategy<sup>12+</sup>
172
173| 名称                             | 描述             |
174| -------------------------------- | --------------- |
175| FOLLOW_HOST_DPI                  | 表示DPI跟随宿主。 |
176| FOLLOW_UI_EXTENSION_ABILITY_DPI  | 表示DPI跟随UIExtensionAbility。 |
177
178## UIExtensionProxy
179
180用于在双方建立连接成功后,组件使用方向被拉起的Ability发送数据、订阅和取消订阅注册。
181
182### send
183
184send(data: Record\<string, Object\>): void
185
186用于在双方建立连接成功后,组件使用方向被拉起的Ability发送数据的场景,提供异步发送数据。
187
188**系统能力:** SystemCapability.ArkUI.ArkUI.Full
189
190**参数:**
191
192| 参数名  | 参数类型                                     | 必填   | 参数描述            |
193| ---- | ---------------------------------------- | ---- | --------------- |
194| data | Record\<string, Object\> | 是    | 异步发送给被拉起的扩展Ability的数据。 |
195
196### sendSync<sup>11+</sup>
197
198sendSync(data: Record\<string, Object\>): Record\<string, Object\>
199
200用于在双方建立连接成功后,组件使用方向被拉起的Ability发送数据的场景,提供同步发送数据。
201
202**系统能力:** SystemCapability.ArkUI.ArkUI.Full
203
204**参数:**
205
206| 参数名  | 参数类型                                     | 必填   | 参数描述            |
207| ---- | ---------------------------------------- | ---- | --------------- |
208| data | Record\<string, Object\> | 是    | 同步发送给被拉起的扩展Ability的数据。 |
209
210**返回值:**
211
212| 类型 | 描述 |
213| ---- | ----|
214| Record\<string, Object\> | 扩展Ability回复的数据。 |
215
216**错误码:**
217
218| 错误号 | 描述 |
219| ---- | ----|
220| 100011 | 扩展Ability未注册同步回调 |
221| 100012 | 数据发送失败 |
222
223### on('asyncReceiverRegister')<sup>11+</sup>
224
225on(type: 'asyncReceiverRegister', callback: Callback\<UIExtensionProxy\>): void
226
227用于在双方建立连接成功后,组件使用方订阅被拉起的Ability发生异步注册的场景。
228
229**系统能力:** SystemCapability.ArkUI.ArkUI.Full
230
231**参数:**
232
233| 参数名  | 参数类型 |必填 | 参数描述 |
234| ------ | -------- |---- | ------- |
235| type   | string | 是 | 代表订阅扩展Ability发生异步注册回调。 |
236| callback   | Callback\<UIExtensionProxy\> | 是 | 订阅扩展Ability注册setReceiveDataCallback后触发的回调。 |
237
238### on('syncReceiverRegister')<sup>11+</sup>
239
240on(type: 'syncReceiverRegister', callback: Callback\<UIExtensionProxy\>): void;
241
242用于在双方建立连接成功后,组件使用方订阅被拉起的Ability发生同步注册的场景。
243
244**系统能力:** SystemCapability.ArkUI.ArkUI.Full
245
246**参数:**
247
248| 参数名  | 参数类型 |必填 | 参数描述 |
249| ------ | -------- |---- | ------- |
250| type   | string | 是 | 订阅扩展Ability发生同步注册回调。 |
251| callback   | Callback\<UIExtensionProxy\> | 是 | 扩展Ability注册setReceiveDataForResultCallback后触发的回调。 |
252
253### off('asyncReceiverRegister')<sup>11+</sup>
254
255off(type: 'asyncReceiverRegister', callback?: Callback\<UIExtensionProxy\>): void
256
257用于在双方建立连接成功后,组件使用方取消订阅被拉起的Ability发生异步注册的场景。
258
259**系统能力:** SystemCapability.ArkUI.ArkUI.Full
260
261**参数:**
262
263| 参数名  | 参数类型 | 必填 | 参数描述 |
264| ------ | -------- | ----- | ------- |
265| type   | string | 是 | 取消订阅扩展Ability发生异步注册回调。 |
266| callback | Callback\<UIExtensionProxy\> | 否 | 为空代表取消订阅所有扩展Ability异步注册后触发回调。<br> 非空代表取消订阅异步对应回调。 |
267
268### off('syncReceiverRegister')<sup>11+</sup>
269
270off(type: 'syncReceiverRegister', callback?: Callback\<UIExtensionProxy\>): void
271
272用于在双方建立连接成功后,组件使用方取消订阅被拉起的Ability发生同步注册的场景。
273
274**系统能力:** SystemCapability.ArkUI.ArkUI.Full
275
276**参数:**
277
278| 参数名  | 参数类型 | 必填 | 参数描述 |
279| ------ | -------- | ----- | ------- |
280| type   | string | 是 | 取消订阅扩展Ability发生同步注册回调。 |
281| callback | Callback\<UIExtensionProxy\> | 否 | 为空代表取消订阅所有扩展Ability同步注册后触发回调<br> 非空代表取消订阅同步对应回调。 |
282
283## 示例
284
285本示例仅展示组件使用的方法和扩展的Ability,实际运行需在设备中安装bundleName为"com.example.uiextensionprovider",abilityName为"UIExtensionProvider"的Ability扩展。
286
287```ts
288// 组件使用示例:
289import { ComponentContent } from '@kit.ArkUI';
290class Params {
291}
292@Builder
293function LoadingBuilder(params: Params) {
294  Column() {
295   LoadingProgress()
296      .color(Color.Blue)
297  }
298}
299@Builder
300function AreaChangePlaceholderBuilder(params: Params) {
301  Column() {
302  }
303  .width('100%')
304  .height('100%')
305  .backgroundColor(Color.Orange)
306}
307@Entry
308@Component
309struct Second {
310  @State message1: string = 'Hello World 1'
311  @State message2: string = 'Hello World 2'
312  @State message3: string = 'Hello World 3'
313  @State visible: Visibility = Visibility.Hidden
314  @State wid: number = 300
315  @State hei: number = 300
316  private proxy: UIExtensionProxy | null = null;
317  private initPlaceholder = new ComponentContent(this.getUIContext(), wrapBuilder(LoadingBuilder), new Params);
318  private areaChangePlaceholder = new ComponentContent(this.getUIContext(), wrapBuilder(AreaChangePlaceholderBuilder), new Params);
319
320
321  build() {
322    Row() {
323      Column() {
324        Text(this.message1).fontSize(30)
325        Text(this.message2).fontSize(30)
326        Text(this.message3).fontSize(30)
327        UIExtensionComponent({
328          bundleName : "com.example.newdemo",
329          abilityName: "UIExtensionProvider",
330          parameters: {
331            "ability.want.params.uiExtensionType": "sys/commonUI"
332          }},
333          {
334            placeholder: this.initPlaceholder,
335            areaChangePlaceholder: {
336              "FOLD_TO_EXPAND" : this.areaChangePlaceholder,
337            }
338          })
339          .width(this.wid)
340          .height(this.hei)
341          .border({width: 5, color: Color.Blue})
342          .onReceive((data) => {
343            console.info('Lee onReceive, for test')
344            this.message3 = JSON.stringify(data['data'])
345          })
346          .onTerminated((info) => {
347            console.info('onTerminated: code =' + info.code + ', want = ' + JSON.stringify(info.want));
348          })
349          .onRemoteReady((proxy) => {
350            console.info('onRemoteReady, for test')
351            this.proxy = proxy
352
353            this.proxy.on("syncReceiverRegister", syncRegisterCallback1);
354            // this.proxy.on("syncReceiverRegister", syncRegisterCallback2);
355
356
357            // this.proxy.off("syncReceiverRegister");
358
359            // this.proxy.off("syncReceiverRegister", (proxy) => {
360            //   console.info("off invoke for test, type is syncReceiverRegister");
361            // });
362
363            this.proxy.on("asyncReceiverRegister", (proxy1) => {
364              console.info("on invoke for test, type is asyncReceiverRegister");
365            });
366            //
367            // this.proxy.off("asyncReceiverRegister");
368          })
369
370        Button("点击向UIExtensionAbility发送数据").onClick(() => {
371          if (this.proxy != undefined) {
372            this.proxy.send({data: "你好1"})
373
374            try {
375              let re = this.proxy.sendSync({data: "你好2"})
376              console.info("for test, re=" + JSON.stringify(re));
377            } catch (err) {
378              console.error(`sendSync failed for test. errCode=${err.code}, msg=${err.message}`);
379            }
380          }
381        })
382      }
383      .width('100%')
384    }
385    .height('100%')
386  }
387}
388
389function syncRegisterCallback1(proxy: UIExtensionProxy) {
390  console.info("on invoke for test, syncRegisterCallback1, type is syncReceiverRegister");
391}
392
393function syncRegisterCallback2(proxy: UIExtensionProxy) {
394  console.info("on invoke for test, syncRegisterCallback2, type is syncReceiverRegister");
395}
396```
397
398```ts
399// 扩展入口文件UIExtensionProvider.ts
400import { UIExtensionAbility, UIExtensionContentSession, Want } from '@kit.AbilityKit';
401
402const TAG: string = '[UIExtAbility]'
403export default class UIExtAbility extends UIExtensionAbility {
404  
405  onCreate() {
406    console.log(TAG, `UIExtAbility onCreate`)
407  }
408
409  onForeground() {
410    console.log(TAG, `UIExtAbility onForeground`)
411  }
412
413  onBackground() {
414    console.log(TAG, `UIExtAbility onBackground`)
415  }
416
417  onDestroy() {
418    console.log(TAG, `UIExtAbility onDestroy`)
419  }
420
421  onSessionCreate(want: Want, session: UIExtensionContentSession) {
422    console.log(TAG, `UIExtAbility onSessionCreate, want: ${JSON.stringify(want)}`)
423    let param: Record<string, UIExtensionContentSession> = {
424      'session': session
425    };
426    let storage: LocalStorage = new LocalStorage(param);
427    session.loadContent('pages/extension', storage);
428  }
429
430  onSessionDestroy(session: UIExtensionContentSession) {
431    console.log(TAG, `UIExtAbility onSessionDestroy`)
432  }
433}
434```
435
436```ts
437// 扩展Ability入口页面文件extension.ets
438import { UIExtensionContentSession } from '@kit.AbilityKit';
439import { router } from '@kit.ArkUI';
440
441let storage = LocalStorage.getShared()
442AppStorage.setOrCreate('message', 'UIExtensionAbility')
443
444@Entry(storage)
445@Component
446struct Extension {
447  @StorageLink('message') storageLink: string = '';
448  private session: UIExtensionContentSession | undefined = storage.get<UIExtensionContentSession>('session');
449
450  onPageShow() {
451    if (this.session != undefined) {
452      this.session.setReceiveDataCallback((data)=> {
453        this.storageLink = JSON.stringify(data)
454        console.info("invoke for test, handle callback set by setReceiveDataCallback successfully");
455      })
456
457      this.session.setReceiveDataForResultCallback(func1)
458    }
459  }
460
461  build() {
462    Row() {
463      Column() {
464        Text(this.storageLink)
465          .fontSize(20)
466          .fontWeight(FontWeight.Bold)
467        Button("点击向Component发送数据").onClick(()=>{
468          if (this.session != undefined) {
469            this.session.sendData({"data": 543321})
470            console.info('send 543321, for test')
471          }
472        })
473        Button("terminate").onClick(()=> {
474          if (this.session != undefined) {
475            this.session.terminateSelf();
476          }
477          storage.clear()
478        })
479        Button("terminate with result").onClick(()=>{
480          if (this.session != undefined) {
481            this.session.terminateSelfWithResult({
482              resultCode: 0,
483              want: {
484                bundleName: "myBundleName",
485                parameters: { "result": 123456 }
486              }
487            })
488          }
489          storage.clear()
490        })
491
492        Button("点击跳转").onClick(()=> {
493          router.pushUrl({url: 'pages/hello'})
494        })
495      }
496    }
497    .height('100%')
498  }
499}
500function func1(data: Record<string, Object>): Record<string, Object> {
501  let linkToMsg: SubscribedAbstractProperty<string> = AppStorage.link('message');
502  linkToMsg.set(JSON.stringify(data))
503  console.info("invoke for test, handle callback set by setReceiveDataForResultCallback successfully");
504  return data;
505}
506
507```
508