使用通过UIServiceExtensionAbility实现的系统悬浮窗

概述

UIServiceExtensionAbility组件是带用户界面(UI)的扩展服务组件。系统应用可以通过UIServiceExtensionAbility组件实现一个具有特定功能、带UI的服务能力,并将其UI服务开放给其他三方应用调用。

本文描述中称被启动的UIServiceExtensionAbility组件为服务端,称UIServiceExtensionAbility组件的启动方为客户端。

应用可以通过启动和连接两种形式使用UIServiceExtensionAbility组件:

约束限制

  • 当前仅支持2in1设备。

  • 三方应用需要在前台获焦的情况下才能连接系统提供的UIServiceExtensionAbility组件。

  • UIServiceExtensionAbility组件的生命周期与绑定的窗口强关联,窗口销毁后UIServiceExtensionAbility组件也一起销毁。

启动UIServiceExtensionAbility组件

应用通过startUIServiceExtensionAbility()方法启动一个UIServiceExtensionAbility组件。UIServiceExtensionAbility组件启动后,其生命周期独立于客户端,即使客户端已经销毁,该后台服务仍可继续运行,窗口创建失败或销毁后该服务会被销毁。

如下示例通过startUIServiceExtensionAbility方法启动一个UIServiceExtensionAbility组件,示例中的context的获取方式请参见获取UIAbility的上下文信息

import { common, Want } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct Start {
  build() {
    Column() {
      Row() {
        // 创建启动按钮
        Button('start UIServiceExtensionAbility')
          .enabled(true)
          .onClick(() => {
            let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
            let startWant: Want = {
              bundleName: 'com.samples.uiserviceextensionability', // 仅作为示例代码,需要替换为实际的UIServiceExtensionAbility组件的包名。
              abilityName: 'UiServiceExtAbility', // 仅作为示例代码,需要替换为实际的UIServiceExtensionAbility组件名称。
            };
            try {
              // 启动UIServiceExtensionAbility组件
              context.startUIServiceExtensionAbility(startWant).then(() => {
                console.info('startUIServiceExtensionAbility success.');
              }).catch((error: BusinessError) => {
                console.error(`startUIServiceExtensionAbility failed, err code: ${error.code}, err msg: ${error.message}.`);
              });
            } catch (err) {
              let code = (err as BusinessError).code;
              let msg = (err as BusinessError).message;
              console.error(`startUIServiceExtensionAbility failed, err code: ${code}, err msg: ${msg}.`);
            }
          })
      }
    }
  }
}

客户端连接服务端

客户端通过connectUIServiceExtensionAbility()连接服务端,获取并保存UIServiceProxy对象。通过该proxy对象的sendData()方法发送数据给服务端。服务端通过UIServiceExtensionAbility类onData()(系统接口)方法接收客户端数据。

如下示例通过connectUIServiceExtensionAbility方法连接一个UIServiceExtensionAbility组件,示例中的context的获取方式请参见获取UIAbility的上下文信息

import { common, Want } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct Connect {
  comProxy: common.UIServiceProxy | null = null;
  connectCallback: common.UIServiceExtensionConnectCallback = {
    onData: (data: Record<string, Object>) => {
      console.info(`data received, data: ${JSON.stringify(data)}.`);
    },
    onDisconnect: () => {
      console.info(`onDisconnect.`);
    }
  }

  build() {
    Column() {
      Row() {
        // 创建连接按钮
        Button('connect ability')
          .enabled(true)
          .onClick(() => {
            let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
            let startWant: Want = {
              bundleName: 'com.acts.uiserviceextensionability', // 仅作为示例代码,需要替换为实际的UIServiceExtensionAbility组件的包名。
              abilityName: 'UiServiceExtAbility', // 仅作为示例代码,需要替换为实际的UIServiceExtensionAbility组件名称。
            };
            try {
              // 连接UIServiceExtensionAbility组件
              context.connectUIServiceExtensionAbility(startWant, this.connectCallback)
                .then((proxy: common.UIServiceProxy) => {
                  this.comProxy = proxy;
                  let formData: Record<string, string> = {
                    'test': 'test'
                  };
                  try {
                    this.comProxy.sendData(formData);
                  } catch (err) {
                    let code = (err as BusinessError).code;
                    let msg = (err as BusinessError).message;
                    console.error(`sendData failed, err code:${code}, err msg:${msg}.`);
                  }
                })
                .catch((err: BusinessError) => {
                  console.error(`connectUIServiceExtensionAbility failed, err code: ${err.code}, err msg: ${err.message}.`);
                });
            } catch (err) {
              let code = (err as BusinessError).code;
              let msg = (err as BusinessError).message;
              console.error(`connectUIServiceExtensionAbility failed, err code:${code}, err msg:${msg}.`);
            }
          })
      }
    }
  }
}