目录

In-Application Embedded Component (EmbeddedComponent)

The EmbeddedComponent allows the current page to embed UI content provided by other EmbeddedUIExtensionAbility instances within the same app. These UIs run in independent processes, offering higher security and stability.

The EmbeddedComponent is primarily used for cross-module, cross-process embedded UI integration. Its core objective is to improve application flexibility and user experience through modular design.

Be aware of the component's usage constraints and lifecycle management to maximize its benefits in application architecture.

Basic Concepts

Constraints

Focus Behavior

Before API version 26.0.0, when the EmbeddedComponent gained focus, the focus within the EmbeddedUIExtensionAbility process it started was directly dispatched to the first focusable child node. Starting from API version 26.0.0,

  1. If focus moves from outside to the EmbeddedUIExtensionAbility, focus is normally dispatched to the first focusable child node.

  2. If focus is transferred to the EmbeddedUIExtensionAbility due to page level switching, the same rule as the UIAbility applies. When either starts a hierarchical page and that page has neither set defaultFocus nor actively requested focus, focus remains on the root container and is not dispatched to child nodes.

Scenario Example

This example demonstrates the basic usage of the EmbeddedComponent and EmbeddedUIExtensionAbility.

Host Page

The add-on home page is the host page for the EmbeddedComponent, responsible for loading and displaying the content of the embedded UI extension capability. The following is a complete implementation example of an add-on home page.

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) => {
              // onTerminated is triggered when the terminateSelfWithResult button is clicked on the extension page.
              this.message = `Termination: code = ${info.code} , want = ${JSON.stringify(info.want)}`;
            })
            .onError((error) => {
              // onError is triggered on failure or exception.
              this.message = `Error: code = ${error.code}`;
            })
            .onDrawReady(() => {
              // Starting from API version 26.0.0, the onDrawReady callback is triggered when the launched EmbeddedUIExtensionAbility draws the first frame.
            })
        }
        .width('100%')
      }
      .height('100%')
      // ...
  }
}

In an ArkTS project, the implementation code of the EmbeddedUIExtensionAbility is typically located in the ets/extensionability directory of the project. For example, the ExampleEmbeddedAbility.ets file is located in the ./ets/extensionability/ directory.

Key considerations for implementing the host page:

Provider Application Lifecycle Implementation

The provider application implements embedded UI extension abilities. Below is an example lifecycle implementation:

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);
    // Load the Extension.ets page content.
    session.loadContent('pages/EmbeddedComponent/Extension', storage);
  }

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

Key implementation details:

Entry Page

The following is an implementation of the entry component of the provider application, which demonstrates how to use UIExtensionContentSession and how to exit the embedded page and return the result through a button click event. This code file needs to be declared in the main_pages.json configuration file.

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(() => {
        // Call terminateSelfWithResult to exit when the button is clicked.
        this.session?.terminateSelfWithResult({
          resultCode: 1,
          want: {
            bundleName: 'com.samples.uiextensionandaccessibility',
            abilityName: 'ExampleEmbeddedAbility',
          }
        });
      })
    }.width('100%').height('100%')
  }
}

Key considerations for implementing the entry page:

  1. Session management

    Properly obtain and use the UIExtensionContentSession instances to ensure communication with the host application.

  2. Result return

    When returning results to the host through terminateSelfWithResult, specify:

    • resultCode: result code.

    • want: recipient of the result.

  3. Page lifecycle

    Manage the lifecycle of the entry page to ensure proper resource cleanup.

  4. Style configuration

    Properly configure page element styles to display the page as expected.

Configuration

To enable embedded UI extension abilities, configure the application's configuration file.

Add the ExampleEmbeddedAbility configuration under the extensionAbilities tag in the module.json5 file:

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

Expected Results

  1. Start the application on the device that supports EmbeddedUIExtensionAbility.

  2. Clicking the terminateSelfWithResult button hides the provider content and displays onTerminated information.