管理中心
我的
您当前正在浏览新版开发者文档中心,目录分类和层级有所调整。点击左侧当前文档分类名称前的“☰”图标,可切换文档分类。 了解新版目录
问题处理与运维开发与测试问题应用框架开发UI框架组件使用如何实现EmbeddedComponent和EmbeddedUIExtensionAbility之间的双向通信

如何实现EmbeddedComponent和EmbeddedUIExtensionAbility之间的双向通信

问题现象

EmbeddedComponent和EmbeddedUIExtensionAbility之间进程隔离,目前官网场景示例只提供了terminateSelfWithResult方法,没有提供更多资料参考,如何实现EmbeddedComponent和EmbeddedUIExtensionAbility之间的双向通信?

背景知识

  • EmbeddedComponent:EmbeddedComponent组件用于在当前页面嵌入本应用内其他EmbeddedUIExtensionAbility提供的UI。
  • EmbeddedUIExtensionAbility:提供方应用中定义使用,用于实现跨进程界面嵌入功能,仅能被同应用的UIAbility拉起,并需在多进程权限的场景下使用。
  • @ohos.commonEventManager (公共事件模块):提供了公共事件相关的能力,包括发布公共事件、订阅公共事件、以及退订公共事件,可用于实现跨进程的事件通信能力。

解决方案

EmbeddedComponent和EmbeddedUIExtensionAbility属于两个进程,可以利用commonEventManager进行双向通信,详细步骤如下:

  1. 在项目的ets/extensionAbility(extensionAbility目录需要手动创建)目录下新建EmbeddedUIExtensionAbility,代码如下:
    收起
    自动换行
    深色代码主题
    复制
    1. import { EmbeddedUIExtensionAbility, UIExtensionContentSession, Want } from '@kit.AbilityKit';
    2. const TAG: string = '[ExampleEmbeddedAbility]';
    3. export default class ExampleEmbeddedAbility extends EmbeddedUIExtensionAbility {
    4. onCreate() {
    5. console.info(TAG, `onCreate`);
    6. }
    7. onForeground() {
    8. console.info(TAG, `onForeground`);
    9. }
    10. onBackground() {
    11. console.info(TAG, `onBackground`);
    12. }
    13. onDestroy() {
    14. console.info(TAG, `onDestroy`);
    15. }
    16. onSessionCreate(want: Want, session: UIExtensionContentSession) {
    17. try {
    18. console.info(TAG, `onSessionCreate, want: ${JSON.stringify(want)}`);
    19. } catch (error) {
    20. console.info(TAG, `error`);
    21. }
    22. let param: Record<string, UIExtensionContentSession> = {
    23. 'session': session
    24. };
    25. let storage: LocalStorage = new LocalStorage(param);
    26. // 加载pages/extension.ets页面内容
    27. session.loadContent('pages/Extension', storage);
    28. }
    29. onSessionDestroy() {
    30. console.info(TAG, `onSessionDestroy`);
    31. }
    32. };
  2. 在项目main_pages.json中增加声明Extension:
    收起
    自动换行
    深色代码主题
    复制
    1. {
    2. "src": [
    3. "pages/Index",
    4. "pages/Extension"
    5. ]
    6. }
  3. 在module.json5配置文件的"extensionAbilities"标签下增加ExampleEmbeddedAbility配置:
    收起
    自动换行
    深色代码主题
    复制
    1. {
    2. "module": {
    3. "name": "entry",
    4. "type": "entry",
    5. "description": "$string:module_desc",
    6. "mainElement": "EntryAbility",
    7. "deviceTypes": [
    8. "tablet",
    9. "2in1"
    10. ],
    11. "deliveryWithInstall": true,
    12. "installationFree": false,
    13. "pages": "$profile:main_pages",
    14. "abilities": [
    15. {
    16. "name": "EntryAbility",
    17. "srcEntry": "./ets/entryability/EntryAbility.ets",
    18. "description": "$string:EntryAbility_desc",
    19. "icon": "$media:layered_image",
    20. "label": "$string:EntryAbility_label",
    21. "startWindowIcon": "$media:startIcon",
    22. "startWindowBackground": "$color:start_window_background",
    23. "exported": true,
    24. "skills": [
    25. {
    26. "entities": [
    27. "entity.system.home"
    28. ],
    29. "actions": [
    30. "ohos.want.action.home"
    31. ]
    32. }
    33. ]
    34. }
    35. ],
    36. "extensionAbilities": [
    37. {
    38. "name": "EntryBackupAbility",
    39. "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
    40. "type": "backup",
    41. "exported": false,
    42. "metadata": [
    43. {
    44. "name": "ohos.extension.backup",
    45. "resource": "$profile:backup_config"
    46. }
    47. ],
    48. },
    49. {
    50. "name": "ExampleEmbeddedAbility",
    51. "srcEntry": "./ets/extensionAbility/ExampleEmbeddedAbility.ets",
    52. "type": "embeddedUI"
    53. }
    54. ]
    55. }
    56. }
  4. 在Index页面中实现主页面UI布局并且接收来自EmbeddedUIExtensionAbility的信息:
    收起
    自动换行
    深色代码主题
    复制
    1. import { Want } from '@kit.AbilityKit';
    2. import { BusinessError, commonEventManager } from '@kit.BasicServicesKit';
    3. let options: commonEventManager.CommonEventPublishData = {
    4. code: 0,
    5. data: 'Hello',
    6. isOrdered: true // 有序公共事件
    7. };
    8. @Entry
    9. @Component
    10. struct Index {
    11. @State message: string = 'Message from ExampleEmbeddedAbility: ';
    12. private want: Want = {
    13. bundleName: 'com.example.mycommon',
    14. abilityName: 'ExampleEmbeddedAbility',
    15. };
    16. aboutToAppear(): void {
    17. // 定义订阅者,用于保存创建成功的订阅者对象,后续使用其完成订阅及退订的动作
    18. let subscriber: commonEventManager.CommonEventSubscriber;
    19. // 订阅者信息
    20. let subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {
    21. events: ['event']
    22. };
    23. // 创建订阅者
    24. try {
    25. commonEventManager.createSubscriber(subscribeInfo,
    26. (err: BusinessError, commonEventSubscriber: commonEventManager.CommonEventSubscriber) => {
    27. if (!err) {
    28. console.info(`Succeeded in creating subscriber.`);
    29. subscriber = commonEventSubscriber;
    30. // 订阅公共事件
    31. try {
    32. commonEventManager.subscribe(subscriber,
    33. (err: BusinessError, data: commonEventManager.CommonEventData) => {
    34. if (err) {
    35. console.error(`Failed to subscribe. Code is ${err.code}, message is ${err.message}`);
    36. return;
    37. }
    38. let receiveData = JSON.parse(JSON.stringify(data)) as commonEventManager.CommonEventPublishData;
    39. this.message += receiveData.data;
    40. console.info(`Succeeded in subscribing, data is ${JSON.stringify(data)}`);
    41. });
    42. } catch (error) {
    43. let err: BusinessError = error as BusinessError;
    44. console.error(`Failed to subscribe. Code is ${err.code}, message is ${err.message}`);
    45. }
    46. return;
    47. }
    48. console.error(`Failed to create subscriber. Code is ${err.code}, message is ${err.message}`);
    49. });
    50. } catch (error) {
    51. let err: BusinessError = error as BusinessError;
    52. console.error(`Failed to create subscriber. Code is ${err.code}, message is ${err.message}`);
    53. }
    54. }
    55. build() {
    56. Row() {
    57. Column() {
    58. Text(this.message).fontSize(20);
    59. Button('发送数据')
    60. .width('80%')
    61. .onClick(() => {
    62. try {
    63. commonEventManager.publish('event2', options, (err: BusinessError) => {
    64. if (err) {
    65. console.error(`Failed to publish common event. Code is ${err.code}, message is ${err.message}`);
    66. return;
    67. }
    68. console.info(`Succeeded in publishing common event.`);
    69. });
    70. } catch (error) {
    71. let err: BusinessError = error as BusinessError;
    72. console.error(`Failed to publish common event. Code is ${err.code}, message is ${err.message}`);
    73. }
    74. });
    75. Text('EmbeddedComponent').fontSize(20);
    76. }
    77. .width('50%')
    78. .height(300)
    79. .justifyContent(FlexAlign.SpaceBetween)
    80. .borderColor(Color.Orange)
    81. .borderWidth(2);
    82. Column() {
    83. EmbeddedComponent(this.want, EmbeddedType.EMBEDDED_UI_EXTENSION)
    84. .width('100%')
    85. .height('100%')
    86. .onError((error) => {
    87. // 失败或异常触发onError回调,文本框显示如下报错内容
    88. this.message = 'Error: code = ' + error.code;
    89. });
    90. }
    91. .width('50%')
    92. .height(300)
    93. .borderColor(Color.Blue)
    94. .borderWidth(2)
    95. .margin({ left: 5 });
    96. }
    97. .height('100%')
    98. .width('100%');
    99. }
    100. }

    注意:bundleName需要和项目的包名一致。

  5. 在Extension页面中实现EmbeddedComponent的UI布局并且发送事件信息:
    收起
    自动换行
    深色代码主题
    复制
    1. import { BusinessError, commonEventManager } from '@kit.BasicServicesKit';
    2. // 公共事件相关信息,以发布有序公共事件为例
    3. let options: commonEventManager.CommonEventPublishData = {
    4. code: 0,
    5. data: 'Good',
    6. isOrdered: true // 有序公共事件
    7. };
    8. @Entry
    9. @Component
    10. struct Extension {
    11. @State message: string = 'Message from EmbeddedComponent: ';
    12. aboutToAppear(): void {
    13. // 定义订阅者,用于保存创建成功的订阅者对象,后续使用其完成订阅及退订的动作
    14. let subscriber: commonEventManager.CommonEventSubscriber;
    15. // 订阅者信息
    16. let subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {
    17. events: ['event2']
    18. };
    19. // 创建订阅者
    20. try {
    21. commonEventManager.createSubscriber(subscribeInfo,
    22. (err: BusinessError, commonEventSubscriber: commonEventManager.CommonEventSubscriber) => {
    23. if (!err) {
    24. console.info(`Succeeded in creating subscriber.`);
    25. subscriber = commonEventSubscriber;
    26. // 订阅公共事件
    27. try {
    28. commonEventManager.subscribe(subscriber,
    29. (err: BusinessError, data: commonEventManager.CommonEventData) => {
    30. if (err) {
    31. console.error(`Failed to subscribe. Code is ${err.code}, message is ${err.message}`);
    32. return;
    33. }
    34. let receiveData = JSON.parse(JSON.stringify(data)) as commonEventManager.CommonEventPublishData;
    35. this.message += receiveData.data;
    36. console.info(`Succeeded in subscribing, data is ${JSON.stringify(data)}`);
    37. });
    38. } catch (error) {
    39. let err: BusinessError = error as BusinessError;
    40. console.error(`Failed to subscribe. Code is ${err.code}, message is ${err.message}`);
    41. }
    42. return;
    43. }
    44. console.error(`Failed to create subscriber. Code is ${err.code}, message is ${err.message}`);
    45. });
    46. } catch (error) {
    47. let err: BusinessError = error as BusinessError;
    48. console.error(`Failed to create subscriber. Code is ${err.code}, message is ${err.message}`);
    49. }
    50. }
    51. build() {
    52. Column() {
    53. Text(this.message).fontSize(20);
    54. Button('发送数据')
    55. .width('80%')
    56. .onClick(() => {
    57. // 发布公共事件
    58. try {
    59. commonEventManager.publish('event', options, (err: BusinessError) => {
    60. if (err) {
    61. console.error(`Failed to publish common event. Code is ${err.code}, message is ${err.message}`);
    62. return;
    63. }
    64. console.info(`Succeeded in publishing common event.`);
    65. });
    66. } catch (error) {
    67. let err: BusinessError = error as BusinessError;
    68. console.error(`Failed to publish common event. Code is ${err.code}, message is ${err.message}`);
    69. }
    70. });
    71. Text('ExampleEmbeddedAbility').fontSize(20);
    72. }.width('100%').height('100%').justifyContent(FlexAlign.SpaceBetween);
    73. }
    74. }