# 同应用进程嵌入式组件 (EmbeddedComponent)

EmbeddedComponent组件允许当前页面嵌入同一应用内其他EmbeddedUIExtensionAbility提供的UI内容，这些UI运行在独立进程中，提供更高的安全性和稳定性。

EmbeddedComponent组件主要用于实现跨模块、跨进程的嵌入式界面集成，其核心目标是通过模块化设计提升应用的灵活性和用户体验。

开发者在使用时需注意其使用限制和生命周期管理，合理设计应用架构以最大限度地发挥其优势。

#### 基本概念

*   EmbeddedComponent组件
    
    EmbeddedComponent组件用于在当前页面嵌入本应用内其他EmbeddedUIExtensionAbility提供的UI。它允许开发者将应用的某些功能或界面嵌入另一个界面中，实现更灵活的用户界面设计，适用于需要进程隔离的模块化开发场景。
    
*   EmbeddedUIExtensionAbility组件
    
    提供方应用中定义使用，用于实现跨进程界面嵌入功能，默认仅能被同应用的UIAbility拉起（从API版本26.0.0开始，满足特定权限条件时支持跨应用拉起，详见使用约束-应用范围），并需在多进程权限的场景下使用。
    

#### 使用约束

*   设备要求
    
    EmbeddedComponent组件仅可在支持EmbeddedUIExtensionAbility的设备上正常运行。
    
*   应用范围
    
    EmbeddedComponent组件只能在UIAbility中使用，且被拉起的EmbeddedUIExtensionAbility需与UIAbility属于同一应用；从API版本26.0.0开始，如果EmbeddedComponent所属应用申请了ohos.permission.SUPPORT\_CROSS\_APP\_EMBED\_FOR\_OA权限（该权限仅企业普通应用可申请），且该应用的appIdentifier在EmbeddedUIExtensionAbility支持的应用清单（即extensionAbilities标签的appIdentifierAllowList属性）中，则允许EmbeddedComponent跨应用拉起EmbeddedUIExtensionAbility。
    
*   属性限制
    
    EmbeddedComponent组件支持通用属性，且宽高默认值和最小值均为10vp；
    
    不支持如下与宽高相关的属性：
    
    "constraintSize"、"aspectRatio"、"layoutWeight"、"flexBasis"、"flexGrow"和"flexShrink"。
    
*   事件调用
    
    与屏幕坐标相关的事件信息会基于EmbeddedComponent的位置宽高进行坐标转换后传递给被拉起的EmbeddedUIExtensionAbility处理。
    
    EmbeddedComponent组件不支持点击等通用事件，仅支持onTerminated事件和onError事件。从API版本26.0.0开始，新增支持onDrawReady事件。
    

#### 获焦能力说明

API版本26.0.0之前，EmbeddedComponent组件获焦时，其拉起的EmbeddedUIExtensionAbility进程内焦点直接下发到第一个可获焦子节点。从API版本26.0.0开始，

1.  如果外部走焦到EmbeddedUIExtensionAbility，焦点正常下发到第一个可获焦子节点。
2.  如果由于层级页面切换导致焦点转移到EmbeddedUIExtensionAbility，则与UIAbility保持统一规则。两者在拉起一个层级页面且该页面未设置defaultFocus、未主动请求焦点时，焦点均停留在根容器，不下发到子节点。

#### 场景示例

该示例简单展示了EmbeddedComponent组件和EmbeddedUIExtensionAbility的基础使用方式。

**加载项首页**

加载项首页是EmbeddedComponent组件的宿主页面，负责加载和展示嵌入式UI扩展能力的内容。以下是一个完整的加载项首页实现示例：

```
import { Want } from '@kit.AbilityKit';

@Component
export struct Embedded {
  @State message: string = 'Message: ';
  private want: Want = {
    bundleName: 'com.samples.uiextensionandaccessibility',
    abilityName: 'ExampleEmbeddedAbility',
  };
  build() {
    // ...
      Row() {
        Column() {
          Text(this.message).fontSize(30)
          EmbeddedComponent(this.want, EmbeddedType.EMBEDDED_UI_EXTENSION)
            .width('100%')
            .height('90%')
            .onTerminated((info) => {
              // 点击extension页面内的terminateSelfWithResult按钮后触发onTerminated回调，文本框显示如下信息
              this.message = `Termination: code = ${info.code} , want = ${JSON.stringify(info.want)}`;
            })
            .onError((error) => {
              // 失败或异常触发onError回调，文本框显示如下报错内容
              this.message = `Error: code = ${error.code}`;
            })
            .onDrawReady(() => {
              // 从API版本26.0.0开始，新增支持被拉起的EmbeddedUIExtensionAbility绘制第一帧时触发onDrawReady回调
            })
        }
        .width('100%')
      }
      .height('100%')
      // ...
  }
}
```

在ArkTS项目中，EmbeddedUIExtensionAbility的实现代码通常位于项目的ets/extensionability目录下。例如，ExampleEmbeddedAbility.ets文件位于./ets/extensionability/目录中。

在实现加载项首页时，开发者需要注意以下几点：

*   多进程模型检测
    
    在应用启动时，建议检测设备是否已开启多进程模型。如果未开启，应提供明确的错误提示或引导用户开启。
    
*   异常处理
    
    通过onError事件处理加载或运行嵌入式能力时可能出现的错误，提升用户体验。
    
*   生命周期管理
    
    了解并管理好嵌入式组件的生命周期，确保资源的正确释放和回收。
    
*   样式配置
    
    合理配置EmbeddedComponent组件的大小和位置，确保嵌入式界面能够以期望的尺寸和位置显示。
    

**提供方应用生命周期实现**

提供方应用是指提供嵌入式UI扩展能力的应用。以下是提供方应用生命周期实现的代码示例：

```
import { EmbeddedUIExtensionAbility, UIExtensionContentSession, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

const TAG: string = '[ExampleEmbeddedAbility]'

export default class ExampleEmbeddedAbility extends EmbeddedUIExtensionAbility {
  onCreate() {
    hilog.info(0x0000, TAG, '%{public}s', `onCreate`);
  }

  onForeground() {
    hilog.info(0x0000, TAG, '%{public}s',  `onForeground`);
  }

  onBackground() {
    hilog.info(0x0000, TAG, '%{public}s', `onBackground`);
  }

  onDestroy() {
    hilog.info(0x0000, TAG, '%{public}s', `onDestroy`);
  }

  onSessionCreate(want: Want, session: UIExtensionContentSession) {
    hilog.info(0x0000, TAG, '%{public}s', `onSessionCreate, want: ${JSON.stringify(want)}`);
    let param: Record<string, UIExtensionContentSession> = {
      'session': session
    };
    let storage: LocalStorage = new LocalStorage(param);
    // 加载Extension.ets页面内容
    session.loadContent('pages/EmbeddedComponent/Extension', storage);
  }

  onSessionDestroy(session: UIExtensionContentSession) {
    hilog.info(0x0000, TAG, '%{public}s', `onSessionDestroy`);
  }
}
```

关键实现说明：

*   生命周期阶段
    
    onCreate → onForeground：EmbeddedUIExtensionAbility初始化到可见的完整流程；
    
    onBackground → onForeground：前后台切换时的状态迁移；
    
    onDestroy：EmbeddedUIExtensionAbility被销毁时的资源回收点。
    
*   会话管理
    
    onSessionCreate：创建独立存储上下文并加载UI界面；
    
    onSessionDestroy：处理会话结束时（如用户主动关闭）的清理操作。
    
*   上下文传递
    
    通过LocalStorage实现UIExtensionContentSession的跨组件传递；
    
    使用loadContent方法绑定ArkTS页面与扩展能力上下文。
    

**入口页面**

以下提供方应用的入口组件实现，展示了如何使用UIExtensionContentSession会话以及如何通过按钮点击事件退出嵌入式页面并返回结果，该代码文件需要在main\_pages.json配置文件中声明使用。

```
import { UIExtensionContentSession } from '@kit.AbilityKit';

@Entry()
@Component
struct Extension {
  @State message: string = 'EmbeddedUIExtensionAbility Index';
  private storage: LocalStorage | undefined = this.getUIContext().getSharedLocalStorage();
  private session: UIExtensionContentSession | undefined = this.storage?.get<UIExtensionContentSession>('session');

  build() {
    Column() {
      Text(this.message)
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
      Button('terminateSelfWithResult').fontSize(20).onClick(() => {
        // 点击按钮后调用terminateSelfWithResult退出
        this.session?.terminateSelfWithResult({
          resultCode: 1,
          want: {
            bundleName: 'com.samples.uiextensionandaccessibility',
            abilityName: 'ExampleEmbeddedAbility',
          }
        });
      })
    }.width('100%').height('100%')
  }
}
```

在实现入口页面时，开发者需要注意以下几点：

1.  会话管理
    
    正确获取并使用UIExtensionContentSession会话对象，确保与宿主应用的通信正常。
    
2.  结果返回
    
    通过terminateSelfWithResult方法向宿主应用返回结果时，需要指定：
    
    *   resultCode：结果代码；
        
    *   want：目标意图，指定结果的接收方。
        
3.  页面生命周期
    
    了解并管理好入口页面的生命周期，确保资源的正确释放和回收。
    
4.  样式配置
    
    合理配置页面元素的样式，确保界面显示效果符合预期。
    

**添加配置项**

为了使嵌入式UI扩展能力正常工作，需要在应用的配置文件中进行相应的设置。

在module.json5配置文件的"extensionAbilities"标签下增加ExampleEmbeddedAbility配置，以注册ExampleEmbeddedAbility嵌入式UI扩展能力。

```
{
  "name": "ExampleEmbeddedAbility",
  "srcEntry": "./ets/extensionability/ExampleEmbeddedAbility.ets",
  "type": "embeddedUI"
}
```

**预期效果**

1.  在支持EmbeddedUIExtensionAbility的设备上启动应用；
    
2.  点击terminateSelfWithResult按钮，提供方内容消失，页面显示onTerminated信息。