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 23无 24 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<TerminationInfo>) 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