目录

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

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

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

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

基本概念

使用约束

获焦能力说明

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/目录中。

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

提供方应用生命周期实现

提供方应用是指提供嵌入式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`);
  }
}

关键实现说明:

入口页面

以下提供方应用的入口组件实现,展示了如何使用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信息。