鸿蒙Ability Kit(程序框架服务)【UIExtensionAbility】

UIExtensionAbility

概述

[UIExtensionAbility]是UI类型的ExtensionAbility组件,需要与[UIExtensionComponent]一起配合使用,开发者可以在UIAbility的页面中通过UIExtensionComponent嵌入提供方应用的UIExtensionAbility提供的UI。UIExtensionAbility会在独立于UIAbility的进程中运行,完成其页面的布局和渲染。常用于有进程隔离诉求的系统弹窗、状态栏、胶囊等模块化开发的场景。

说明:

当前UIExtensionAbility和UIExtensionComponent仅支持系统应用使用。

生命周期

[UIExtensionAbility]提供了onCreate、onSessionCreate、onSessionDestroy、onForeground、onBackground和onDestroy生命周期回调,根据需要重写对应的回调方法。

  • [onCreate]:当UIExtensionAbility创建时回调,执行初始化业务逻辑操作。
  • [onSessionCreate]:当UIExtensionAbility界面内容对象创建后调用。
  • [onSessionDestroy]:当UIExtensionAbility界面内容对象销毁后调用。
  • [onForeground]:当UIExtensionAbility从后台转到前台时触发。
  • [onBackground]:当UIExtensionAbility从前台转到后台时触发。
  • [onDestroy]:当UIExtensionAbility销毁时回调,可以执行资源清理等操作。

选择合适的UIExtensionAbility进程模型

UIExtensionAbility支持多实例,每个嵌入式显示对应一个UIExtensionAbility实例。多实例场景下默认是多进程,可配置多进程模型。 UIExtensionAbility支持多实例,每个嵌入式显示对应一个UIExtensionAbility实例。 当应用中存在多个UIExtensionAbility实例,这些实例可以为多个独立进程,也可以共用同一个进程,还可以分为多组、同组实例共用同一个进程。通过module.json5配置文件中的extensionProcessMode字段,即可为选择对应的进程模型,三种模型对比如下:

进程模型extensionProcessMode字段配置说明
同一bundle中所有UIExtensionAbility共进程bundleUIExtensionAbility实例之间的通信无需跨IPC通信;实例之间的状态不独立,会存在相互影响。
相同name的UIExtensionAbility共进程type将同UIExtensionAbility类配置在同一个进程下,便于应用针对UIExtensionAbility类型对实例进行管理。
每个UIExtensionAbility为独立进程instanceUIExtensionAbility实例之间的状态不会彼此影响,安全性更高;实例之间只能通过跨进程进行通信。

Bundle中的所有UIExtensionAbility共进程

同一个bundle下的UIExtensionAbility配置在同一个进程中,便于多实例间的通信。需要关注的是,各个实例之间的状态会彼此影响,当进程中的一个实例异常退出,将导致进程中所有的实例也都会退出;

图1 bundle模型配置示意图
uiextability-bundle-processmodel

Index.ets示例代码如下:

@Entry
@Component
struct Index {
  @State message: string = 'UIExtension UserA';
  private myProxy: UIExtensionProxy | undefined = undefined;

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(30)
          .size({ width: '100%', height: '50'})
          .fontWeight(FontWeight.Bold)
          .textAlign(TextAlign.Center)

        UIExtensionComponent(
          {
            bundleName: 'com.samples.uiextensionability',
            abilityName: 'UIExtensionProvider',
            moduleName: 'entry',
            parameters: {
              'ability.want.params.uiExtensionType': 'sys/commonUI',
            }
          })
          .onRemoteReady((proxy) => {
            this.myProxy = proxy;
          })
          .onReceive((data) => {
            this.message = JSON.stringify(data);
          })
          .onResult((data) => {
            this.message = JSON.stringify(data);
          })
          .onRelease((code) => {
            this.message = "release code:" + code;
          })
          .offset({ x: 0, y: 10})
          .size({ width: 300, height: 300})
          .border({ width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Dotted})

        UIExtensionComponent(
          {
            bundleName: 'com.samples.uiextension2',
            abilityName: 'UIExtensionProviderB',
            moduleName: 'entry',
            parameters: {
              'ability.want.params.uiExtensionType': 'sys/commonUI',
            }
          })
          .onRemoteReady((proxy) => {
            this.myProxy = proxy;
          })
          .onReceive((data) => {
            this.message = JSON.stringify(data);
          })
          .onResult((data) => {
            this.message = JSON.stringify(data);
          })
          .onRelease((code) => {
            this.message = "release code:" + code;
          })
          .offset({ x: 0, y: 50})
          .size({ width: 300, height: 300})
          .border({ width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Dotted})
      }
      .width('100%')
    }
    .height('100%')
  }
}

图2 根据上述代码,生成的Index页面如下:
uiextension-bundle-example

采用该进程模型,进程名格式为: process name [{bundleName}:{UIExtensionAbility的类型}] 例如,process name [com.ohos.intentexecutedemo:xxx]。 图3 进程模型展示
uiextension-bundle-process-example

同UIExtensionAbility类的所有UIExtensionAbility共进程

根据UIExtensionAbility类进行分配进程,拉起多个同样的UIExtensionAbility实例时,这些实例将配置在同一个进程中。将同UIExtensionAbility类配置在同一个进程下,方便应用针对UIExtensionAbility类型对实例进行管理;

图4 type模型配置示意图
uiextability-type-processmodel

Index.ets示例代码如下:

@Entry
@Component
struct Index {
  @State message: string = 'UIExtension User';
  private myProxy: UIExtensionProxy | undefined = undefined;

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(30)
          .size({ width: '100%', height: '50'})
          .fontWeight(FontWeight.Bold)
          .textAlign(TextAlign.Center)

        UIExtensionComponent(
          {
            bundleName: 'com.samples.uiextensionability',
            abilityName: 'UIExtensionProviderA',
            moduleName: 'entry',
            parameters: {
              'ability.want.params.uiExtensionType': 'sys/commonUI',
            }
          })
          .onRemoteReady((proxy) => {
            this.myProxy = proxy;
          })
          .onReceive((data) => {
            this.message = JSON.stringify(data);
          })
          .onResult((data) => {
            this.message = JSON.stringify(data);
          })
          .onRelease((code) => {
            this.message = "release code:" + code;
          })
          .offset({ x: 0, y: 10})
          .size({ width: 300, height: 300})
          .border({ width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Dotted})

        UIExtensionComponent(
          {
            bundleName: 'com.samples.uiextensionability',
            abilityName: 'UIExtensionProviderB',
            moduleName: 'entry',
            parameters: {
              'ability.want.params.uiExtensionType': 'sys/commonUI',
            }
          })
          .onRemoteReady((proxy) => {
            this.myProxy = proxy;
          })
          .onReceive((data) => {
            this.message = JSON.stringify(data);
          })
          .onResult((data) => {
            this.message = JSON.stringify(data);
          })
          .onRelease((code) => {
            this.message = "release code:" + code;
          })
          .offset({ x: 0, y: 50})
          .size({ width: 300, height: 300})
          .border({ width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Dotted})
      }
      .width('100%')
    }
    .height('100%')
  }
}

图5 根据上述代码,生成的Index页面如下:
uiextability-type-example

采用该进程模型,进程名格式为: process name [{bundleName}:{UIExtensionAbility名}] 例如,process name [com.ohos.intentexecutedemo:xxx]。 图6 进程模型展示
uiextability-type-process-example

UIExtensionAbility实例独立进程

根据UIExtensionAbility实例进行分配进程,配置了instance的UIExtensionAbility实例,将每个实例独立一个进程。独立进程的场景下,UIExtensionAbility实例之间只能通过跨进程进行通信,但实例之间的状态不会彼此影响,安全性更高;

图7 instance模型配置示意图
uiextability-instance-processmodel

Index.ets示例代码如下:

@Entry
@Component
struct Index {
  @State message: string = 'UIExtension User'
  private myProxy: UIExtensionProxy | undefined = undefined;

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(30)
          .size({ width: '100%', height: '50'})
          .fontWeight(FontWeight.Bold)
          .textAlign(TextAlign.Center)

        UIExtensionComponent(
          {
            bundleName: 'com.samples.uiextensionability',
            abilityName: 'UIExtensionProvider',
            moduleName: 'entry',
            parameters: {
              'ability.want.params.uiExtensionType': 'sys/commonUI',
            }
          })
          .onRemoteReady((proxy) => {
            this.myProxy = proxy;
          })
          .onReceive((data) => {
            this.message = JSON.stringify(data);
          })
          .onResult((data) => {
            this.message = JSON.stringify(data);
          })
          .onRelease((code) => {
            this.message = "release code:" + code;
          })
          .offset({ x: 0, y: 10})
          .size({ width: 300, height: 300})
          .border({ width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Dotted})

        UIExtensionComponent(
          {
            bundleName: 'com.samples.uiextensionability',
            abilityName: 'UIExtensionProvider',
            moduleName: 'entry',
            parameters: {
              'ability.want.params.uiExtensionType': 'sys/commonUI',
            }
          })
          .onRemoteReady((proxy) => {
            this.myProxy = proxy;
          })
          .onReceive((data) => {
            this.message = JSON.stringify(data);
          })
          .onResult((data) => {
            this.message = JSON.stringify(data);
          })
          .onRelease((code) => {
            this.message = "release code:" + code;
          })
          .offset({ x: 0, y: 50})
          .size({ width: 300, height: 300})
          .border({ width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Dotted})
      }
      .width('100%')
    }
    .height('100%')
  }
}

图8 根据上述代码,生成的Index页面如下:
uiextability-instance-example

采用该进程模型,进程名格式为: process name [{bundleName}:{UIExtensionAbility的类型}: {实例后缀}] 例如,process name [com.ohos.intentexecutedemo:xxx:n]。 图9 进程模型展示
uiextability-instance-process-example

UIExtensionAbility通过[UIExtensionContext]和[UIExtensionContentSession]提供相关能力。本文描述中称被启动的UIExtensionAbility为提供方,称启动UIExtensionAbility的UIExtensionComponent组件为使用方。

开发步骤

为了便于表述,本例中将提供UIExtensionAbility能力的一方称为提供方,将启动UIExtensionAbility的一方称为使用方,本例中使用方通过UIExtensionComponent容器启动UIExtensionAbility。

开发UIExtensionAbility提供方

开发者在实现一个UIExtensionAbility提供方时,需要在DevEco Studio工程中手动新建一个UIExtensionAbility,具体步骤如下。

  1. 在工程Module对应的ets目录下,右键选择“New > Directory”,新建一个目录并命名为uiextensionability。

  2. 在uiextensionability目录,右键选择“New > File”,新建一个.ts文件并命名为UIExtensionAbility.ts。

  3. 打开UIExtensionAbility.ts,导入UIExtensionAbility的依赖包,自定义类继承UIExtensionAbility并实现onCreate、onSessionCreate、onSessionDestroy、onForeground、onBackground和onDestroy生命周期回调。

    import Want from '@ohos.app.ability.Want';
    import UIExtensionAbility from '@ohos.app.ability.UIExtensionAbility';
    import UIExtensionContentSession from '@ohos.app.ability.    UIExtensionContentSession';
    
    const TAG: string = '[testTag] UIExtAbility '
    
    export default class UIExtAbility extends UIExtensionAbility {
      onCreate() {
        console.log(TAG, `onCreate`);
      }
    
      onForeground() {
        console.log(TAG, `onForeground`);
      }
    
      onBackground() {
        console.log(TAG, `onBackground`);
      }
    
      onDestroy() {
        console.log(TAG, `onDestroy`);
      }
    
      onSessionCreate(want: Want, session: UIExtensionContentSession) {
        console.log(TAG, `onSessionCreate, want: ${JSON.stringify(want)}}`);
        let storage: LocalStorage = new LocalStorage();
        storage.setOrCreate('session', session);
        session.loadContent('pages/Extension',storage);
      }
    
      onSessionDestroy(session: UIExtensionContentSession) {
        console.log(TAG, `onSessionDestroy`);
      }
    }
    
  4. UIExtensionAbility的onSessionCreate中加载了入口页面文件pages/extension.ets, 并在entry\src\main\resources\base\profile\main_pages.json文件中添加"pages/Extension"声明,extension.ets内容如下:

    import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession';
    
    let storage = LocalStorage.GetShared();
    const TAG: string = `[testTag] ExtensionPage`;
    
    @Entry(storage)
    @Component
    struct Extension {
      @State message: string = `UIExtension provider`;
      private session: UIExtensionContentSession | undefined = storage.get<UIExtensionContentSession>('session');
      onPageShow() {
        console.info(TAG, 'show');
      }
    
      build() {
        Row() {
          Column() {
            Text(this.message)
              .fontSize(30)
              .fontWeight(FontWeight.Bold)
              .textAlign(TextAlign.Center)
    
            Button("send data")
              .width('80%')
              .type(ButtonType.Capsule)
              .margin({
                top:20
              })
              .onClick(() => {
                this.session?.sendData({ "data": 543321});
              })
    
            Button("terminate self")
              .width('80%')
              .type(ButtonType.Capsule)
              .margin({
                top:20
              })
              .onClick(() => {
                this.session?.terminateSelf();
                storage.clear();
              })
    
            Button("terminate self with result")
              .width('80%')
              .type(ButtonType.Capsule)
              .margin({
                top:20
              })
              .onClick(() => {
                this.session?.terminateSelfWithResult({
                  resultCode: 0,
                  want: {
                    bundleName:"com.example.uiextensiondemo",
                    parameters: { "result": 123456 }
                  }
                })
              })
            }
          }
        .height('100%')
      }
    }
    
  5. 在工程Module对应的[module.json5配置文件]中注册UIExtensionAbility,type标签需要设置为UIExtensionAbility中配置的对应类型,srcEntry标签表示当前UIExtensionAbility组件所对应的代码路径。extensionProcessMode标签标识多实例的进程模型,此处以"bundle"为例。

    {
      "module": {
        "extensionAbilities": [
          {
            "name": "UIExtensionProvider",
            "srcEntry": "./ets/uiextensionability/UIExtensionAbility.ets",
            "description": "UIExtensionAbility",
            "type": "sys/commonUI",
            "exported": true,
            "extensionProcessMode": "bundle"
          },
        ]
      }
    }
    

开发UIExtensionAbility使用方

开发者可以在UIAbility的页面中通过UIExtensionComponent容器加载自己应用内的UIExtensionAbility。 如在首页文件:pages/Index.ets中添加如下内容:

@Entry
@Component
struct Index {
  @State message: string = 'UIExtension User';
  private myProxy: UIExtensionProxy | undefined = undefined;

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(30)
          .size({ width: '100%', height: '50'})
          .fontWeight(FontWeight.Bold)
          .textAlign(TextAlign.Center)

        UIExtensionComponent(
          {
            bundleName: 'com.example.uiextensiondemo',
            abilityName: 'UIExtensionProvider',
            moduleName: 'entry',
            parameters: {
              'ability.want.params.uiExtensionType': 'sys/commonUI',
            }
          })
          .onRemoteReady((proxy) => {
            this.myProxy = proxy;
          })
          .onReceive((data) => {
            this.message = JSON.stringify(data);
          })
          .onResult((data) => {
            this.message = JSON.stringify(data);
          })
          .onRelease((code) => {
            this.message = "release code:" + code;
          })
          .offset({ x: 0, y: 30})
          .size({ width: 300, height: 300})
          .border({ width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Dotted})

        Button("sendData")
          .type(ButtonType.Capsule)
          .offset({ x: 0,y: 60})
          .width('80%')
          .type(ButtonType.Capsule)
          .margin({
            top: 20
          })
          .onClick(() => {
            this.myProxy?.send({
              "data": 123456,
              "message": "data from component"
            })
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/679389.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

strcpy、strncpy、strcat、strncat、strcmp、strstr字符串函数的使用和模拟

strcpy的使用和模拟&#xff08;作用&#xff09; 将一个字符串的内容复制到另外一个字符串中代替掉。 strcpy的使用效果 #include <stdio.h> #include <string.h>int main () {char str1[]"Sample string";char str2[40];char str3[40];strcpy (str2…

【学习笔记】Windows GDI绘图(十一)Graphics详解(下)

文章目录 Graphics的方法Graphics.FromImageSetClip设置裁切区域IntersectClip更新为相交裁切区域TranslateClip平移裁切区域IsVisible判断点或矩形是否在裁切区域内MeasureCharacterRanges测量字符区域MeasureString测量文本大小MultiplyTransform矩阵变换 Graphics的方法 Gr…

大模型时代的具身智能系列专题(九)

NYU Lerrel Pinto团队 Lerrel Pinto是NYU Courant的计算机科学助理教授&#xff0c;也是用机器人和人工智能实验室(CILVR小组)的一员。在加州大学伯克利分校读博士后&#xff0c;在CMU机器人研究所读博士&#xff0c;在印度理工学院古瓦哈蒂读本科。研究目标是让机器人在我们生…

JDBC学习笔记(二)进阶篇

一、JDBC 扩展 1.1 实体类和ROM 实体类代码&#xff1a; package com.atguigu.advanced.pojo;//类名就是数据库表的 t_ 后面的单词全写 public class Employee {private Integer empId;//emp_idprivate String empName;//emp_nameprivate Double empSalary;//emp_salarypriva…

二叉树遍历 和 线索二叉树

文章目录 1.1 二叉树遍历1.1 前提问题1&#xff1a; 什么叫二叉树的遍历&#xff1f;二叉树的三种遍历&#xff1a;三个概念&#xff1a;遍历 和 访问 和 经过重要概念&#xff1a;遍历过程中的经过节点&#xff0c;不代表访问节点 问题2&#xff1a;遍历和访问的联系&#xff…

利用conda进行R的安装

1.miniconda3的安装 官网&#xff1a;Miniconda — Conda documentation 找到对应系统、Python版本下载 wget https://mirrors.ustc.edu.cn/anaconda/miniconda/Miniconda3-latest-Linux-x86_64.sh #wget -c https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x…

Python项目代码太多if-else? 这样优化才优雅!

前言 代码中不可避免地会出现复杂的if-else条件逻辑,而简化这些条件表达式是一种提高代码可读性极为实用的技巧。 在 Python 中,有多种方法可以避免复杂的 if-else 条件逻辑,使代码更加清晰和易于维护。 筑基期 提前 return,去掉多余的 else 在 Python 中,使用"提…

C++基础编程100题-003 OpenJudge-1.1-05 输出保留12位小数的浮点数

更多资源请关注纽扣编程微信公众号 http://noi.openjudge.cn/ch0101/05/ 描述 读入一个双精度浮点数&#xff0c;保留12位小数&#xff0c;输出这个浮点数。 输入 只有一行&#xff0c;一个双精度浮点数。 输出 也只有一行&#xff0c;保留12位小数的浮点数。 样例输入…

Day 42 LVS四层负载均衡

一&#xff1a;负载均衡简介 1.集群是什么 ​ 集群&#xff08;cluster&#xff09;技术是一种较新的技术&#xff0c;通过集群技术&#xff0c;可以在付出较低成本的情况下获得在性能、可靠性、灵活性方面的相对较高的收益&#xff0c;其任务调度则是集群系统中的核心技术 …

LangChain学习之 Question And Answer的操作

1. 学习背景 在LangChain for LLM应用程序开发中课程中&#xff0c;学习了LangChain框架扩展应用程序开发中语言模型的用例和功能的基本技能&#xff0c;遂做整理为后面的应用做准备。视频地址&#xff1a;基于LangChain的大语言模型应用开发构建和评估。 2. Q&A的作用 …

web刷题记录(2)

[鹤城杯 2021]EasyP 就是php的代码审计 从中可以看出来&#xff0c;就是对四个if语句的绕过&#xff0c;然后过滤了一些语句 代码分析&#xff1a; 通过include utils.php;导入了一个叫做"utils.php"的文件&#xff0c;这意味着在该文件中可能定义了一些与本代码相…

通信协议:常见的芯片间通信协议

相关阅读 通信协议https://blog.csdn.net/weixin_45791458/category_12452508.html?spm1001.2014.3001.5482 本文将简单介绍一些常见的芯片间通信协议&#xff0c;但不会涉及到协议的具体细节。首先说明&#xff0c;芯片间通信方式根据通信时钟的区别可以分为&#xff1a;异步…

计算机网络ppt和课后题总结(上)

试在下列条件下比较电路交换和分组交换。要传送的报文共 x(bit)。从源点到终点共经过 k 段链路&#xff0c;每段链路的传播时延为 d(s)&#xff0c;数据率为 b(b/s)。在电路交换时电路的建立时间为 s(s)。在分组交换时分组长度为 p(bit)&#xff0c;且各结点的排队等待时间可忽…

基于YOLOv7的口罩检测

目录 1. 作者介绍2. YOLOv7网络模型2.1 算法简介2.2 数据集介绍2.3 YOLO格式数据集制作 3. 代码实现3.1 分割数据集3.2 修改数据配置文件3.3 修改训练代码&#xff0c;进行训练3.4 修改测试代码&#xff0c;进行测试3.5 检测结果 1. 作者介绍 曹宇欢&#xff0c;女&#xff0c…

跨越国界, 纷享销客助力企业全球业务增长

出海&#xff0c;已不再是企业的“备胎”&#xff0c;而是必须面对的“大考”&#xff01;在这个全球化的大潮中&#xff0c;有的企业乘风破浪&#xff0c;勇攀高峰&#xff0c;也有的企业在异国他乡遭遇了“水土不服”。 面对“要么出海&#xff0c;要么出局”的抉择&#xff…

盲盒风尚:拆盒吧引领新潮消费趋势

在当下这个快速变化的消费时代&#xff0c;拆盒吧以其独特的盲盒经济模式&#xff0c;成为了新潮文化消费的引领者。不同于传统的购物方式&#xff0c;拆盒吧通过创新的玩法和多元化的产品线&#xff0c;为消费者带来了前所未有的购物体验。 一、拆盒吧&#xff1a;解锁盲盒新玩…

现代密码学-国密算法

商用密码算法种类 商用密码算法 密码学概念、协议与算法之间的依赖关系 数字签名、证书-公钥密码、散列类算法 消息验证码-对称密码 &#xff0c;散列类 安全目标与算法之间的关系 机密性--对称密码、公钥密码 完整性--散列类算法 可用性--散列类、公钥密码 真实性--公…

数据结构之初始泛型

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;数据结构&#xff08;Java版&#xff09; 目录 深入了解包装类 包装类的由来 装箱与拆箱 面试题 泛型 泛型的语法与使用…

可长期操作的赚钱项目,时间自由,但不适合大学生

如何评价现在的csgo市场&#xff1f; 可长期操作的赚钱项目&#xff0c;时间自由&#xff0c;但不适合大学生。 都在问&#xff0c;有哪些可以长期做下去的赚钱项目&#xff0c;童话就不拐弯抹角了&#xff0c;csgo/steam游戏搬砖一定是最适合长期做下去的赚钱项目。 不说别人…

CondaSSLError: OpenSSL appears to be unavailable on this machine.

conda create -n x1 python3.7报错 PS C:\Users\Richardo.M.Song\Desktop\lele_seg\x1> conda create -n x1 python3.7 Collecting package metadata (current_repodata.json): failed CondaSSLError: OpenSSL appears to be unavailable on this machine. OpenSSL is requ…