关于前端:OpenHarmonyUIAbility组件间交互设备内

5次阅读

共计 12641 个字符,预计需要花费 32 分钟才能阅读完成。

UIAbility 是系统调度的最小单元。在设施内的功能模块之间跳转时,会波及到启动特定的 UIAbility,该 UIAbility 能够是利用内的其余 UIAbility,也能够是其余利用的 UIAbility(例如启动三方领取 UIAbility)。

本章节将从如下场景别离介绍设施内 UIAbility 间的交互方式。

  • 启动利用内的 UIAbility
  • 启动利用内的 UIAbility 并获取返回后果
  • 启动其余利用的 UIAbility
  • 启动其余利用的 UIAbility 并获取返回后果
  • 启动 UIAbility 的指定页面
  • 通过 Call 调用实现 UIAbility 交互(仅对系统利用凋谢)

启动利用内的 UIAbility

当一个利用内蕴含多个 UIAbility 时,存在利用内启动 UIAbility 的场景。例如在领取利用中从入口 UIAbility 启动收付款 UIAbility。

假如利用中有两个 UIAbility:EntryAbility 和 FuncAbility(能够在同一个 Module 中,也能够在不同的 Module 中),须要从 EntryAbility 的页面中启动 FuncAbility。

1. 在 EntryAbility 中,通过调用 startAbility()办法启动 UIAbility,want 为 UIAbility 实例启动的入口参数,其中 bundleName 为待启动利用的 Bundle 名称,abilityName 为待启动的 UIAbility 名称,moduleName 在待启动的 UIAbility 属于不同的 Module 时增加,parameters 为自定义信息参数。示例中的 context 的获取形式参见获取 UIAbility 的 Context 属性。

let wantInfo = {
    deviceId: '', // deviceId 为空示意本设施
    bundleName: 'com.example.myapplication',
    abilityName: 'FuncAbility',
    moduleName: 'module1', // moduleName 非必选
    parameters: { // 自定义信息
        info: '来自 EntryAbility Index 页面',
    },
}
// context 为调用方 UIAbility 的 AbilityContext
this.context.startAbility(wantInfo).then(() => {// ...}).catch((err) => {// ...})

2. 在 FuncAbility 的生命周期回调文件中接管 EntryAbility 传递过去的参数。

import UIAbility from '@ohos.app.ability.UIAbility';
import Window from '@ohos.window';
export default class FuncAbility extends UIAbility {onCreate(want, launchParam) {
    // 接管调用方 UIAbility 传过来的参数
        let funcAbilityWant = want;
        let info = funcAbilityWant?.parameters?.info;
        // ...
    }
}

3. 在 FuncAbility 业务实现之后,如须要进行以后 UIAbility 实例,在 FuncAbility 中通过调用 terminateSelf()办法实现。

// context 为须要进行的 UIAbility 实例的 AbilityContext
this.context.terminateSelf((err) => {// ...});

启动利用内的 UIAbility 并获取返回后果

在一个 EntryAbility 启动另外一个 FuncAbility 时,心愿在被启动的 FuncAbility 实现相干业务后,能将后果返回给调用方。例如在利用中将入口性能和帐号登录性能别离设计为两个独立的 UIAbility,在帐号登录 UIAbility 中实现登录操作后,须要将登录的后果返回给入口 UIAbility。

1. 在 EntryAbility 中,调用 startAbilityForResult()接口启动 FuncAbility,异步回调中的 data 用于接管 FuncAbility 进行本身后返回给 EntryAbility 的信息。示例中的 context 的获取形式参见获取 UIAbility 的 Context 属性。

let wantInfo = {
    deviceId: '', // deviceId 为空示意本设施
    bundleName: 'com.example.myapplication',
    abilityName: 'FuncAbility',
    moduleName: 'module1', // moduleName 非必选
    parameters: { // 自定义信息
        info: '来自 EntryAbility Index 页面',
    },
}
// context 为调用方 UIAbility 的 AbilityContext
this.context.startAbilityForResult(wantInfo).then((data) => {// ...}).catch((err) => {// ...})

2. 在 FuncAbility 进行本身时,须要调用 terminateSelfWithResult()办法,入参 abilityResult 为 FuncAbility 须要返回给 EntryAbility 的信息。

const RESULT_CODE: number = 1001;
let abilityResult = {
    resultCode: RESULT_CODE,
    want: {
        bundleName: 'com.example.myapplication',
        abilityName: 'FuncAbility',
        moduleName: 'module1',
        parameters: {info: '来自 FuncAbility Index 页面',},
    },
}
// context 为被调用方 UIAbility 的 AbilityContext
this.context.terminateSelfWithResult(abilityResult, (err) => {// ...});

3.FuncAbility 进行本身后,EntryAbility 通过 startAbilityForResult()办法回调接管被 FuncAbility 返回的信息,RESULT_CODE 须要与后面的数值保持一致。

const RESULT_CODE: number = 1001;
// ...
// context 为调用方 UIAbility 的 AbilityContext
this.context.startAbilityForResult(want).then((data) => {if (data?.resultCode === RESULT_CODE) {
        // 解析被调用方 UIAbility 返回的信息
        let info = data.want?.parameters?.info;
        // ...
    }
}).catch((err) => {// ...})

启动其余利用的 UIAbility

启动其余利用的 UIAbility,通常用户只须要实现一个通用的操作(例如须要抉择一个文档利用来查看某个文档的内容信息),举荐应用隐式 Want 启动。零碎会依据调用方的 want 参数来辨认和启动匹配到的利用 UIAbility。

启动 UIAbility 有显式 Want 启动和隐式 Want 启动两种形式。

  • 显式 Want 启动:启动一个确定利用的 UIAbility,在 want 参数中须要设置该利用 bundleName 和 abilityName,当须要拉起某个明确的 UIAbility 时,通常应用显式 Want 启动形式。
  • 隐式 Want 启动:依据匹配条件由用户抉择启动哪一个 UIAbility,即不明确指出要启动哪一个 UIAbility(abilityName 参数未设置),在调用 startAbility()办法时,其入参 want 中指定了一系列的 entities 字段(示意指标 UIAbility 额定的类别信息,如浏览器、视频播放器)和 actions 字段(示意要执行的通用操作,如查看、分享、利用详情等)等参数信息,而后由零碎去剖析 want,并帮忙找到适合的 UIAbility 来启动。当须要拉起其余利用的 UIAbility 时,开发者通常不晓得用户设施中利用的装置状况,也无奈确定指标利用的 bundleName 和 abilityName,通常应用隐式 Want 启动形式。

本章节次要解说如何通过隐式 Want 启动其余利用的 UIAbility。

1. 将多个待匹配的文档利用装置到设施,在其对应 UIAbility 的 module.json5 配置文件中,配置 skills 的 entities 字段和 actions 字段。

{
  "module": {
    "abilities": [
      {
        // ...
        "skills": [
          {
            "entities": [
              // ...
              "entity.system.default"
            ],
            "actions": [
              // ...
              "ohos.want.action.viewData"
            ]
          }
        ]
      }
    ]
  }
}

2. 在调用方 want 参数中的 entities 和 action 须要被蕴含在待匹配 UIAbility 的 skills 配置的 entities 和 actions 中。零碎匹配到合乎 entities 和 actions 参数条件的 UIAbility 后,会弹出抉择框展现匹配到的 UIAbility 实例列表供用户抉择应用。示例中的 context 的获取形式参见获取 UIAbility 的 Context 属性。

let wantInfo = {
    deviceId: '', // deviceId 为空示意本设施
    // 如果心愿隐式仅在特定的捆绑包中进行查问,请勾销上面的正文。// bundleName: 'com.example.myapplication',
    action: 'ohos.want.action.viewData',
    // entities 能够被省略。entities: ['entity.system.default'],
}
// context 为调用方 UIAbility 的 AbilityContext
this.context.startAbility(wantInfo).then(() => {// ...}).catch((err) => {// ...})

成果示意如下图所示,点击“关上 PDF 文档”时,会弹出抉择框供用户抉择。

3. 在文档利用应用实现之后,如须要进行以后 UIAbility 实例,通过调用 terminateSelf()办法实现。

// context 为须要进行的 UIAbility 实例的 AbilityContext
this.context.terminateSelf((err) => {// ...});

启动其余利用的 UIAbility 并获取返回后果

当应用隐式 Want 启动其余利用的 UIAbility 并心愿获取返回后果时,调用方须要应用 startAbilityForResult()办法启动指标 UIAbility。例如主利用中须要启动三方领取并获取领取后果。

1. 在领取利用对应 UIAbility 的 module.json5 配置文件中,配置 skills 的 entities 字段和 actions 字段。

{
  "module": {
    "abilities": [
      {
        // ...
        "skills": [
          {
            "entities": [
              // ...
              "entity.system.default"
            ],
            "actions": [
              // ...
              "ohos.want.action.editData"
            ]
          }
        ]
      }
    ]
  }
}

2. 调用方应用 startAbilityForResult()办法启动领取利用的 UIAbility,在调用方 want 参数中的 entities 和 action 须要被蕴含在待匹配 UIAbility 的 skills 配置的 entities 和 actions 中。异步回调中的 data 用于后续接管领取 UIAbility 进行本身后返回给调用方的信息。零碎匹配到合乎 entities 和 actions 参数条件的 UIAbility 后,会弹出抉择框展现匹配到的 UIAbility 实例列表供用户抉择应用。

let wantInfo = {
    deviceId: '', // deviceId 为空示意本设施
    // uncomment line below if wish to implicitly query only in the specific bundle.
    // bundleName: 'com.example.myapplication',
    action: 'ohos.want.action.editData',
    // entities can be omitted.
    entities: ['entity.system.default'],
}
// context 为调用方 UIAbility 的 AbilityContext
this.context.startAbilityForResult(wantInfo).then((data) => {// ...}).catch((err) => {// ...})

3. 在领取 UIAbility 实现领取之后,须要调用 terminateSelfWithResult()办法实现进行本身,并将 abilityResult 参数信息返回给调用方。

const RESULT_CODE: number = 1001;
let abilityResult = {
    resultCode: RESULT_CODE,
    want: {
        bundleName: 'com.example.myapplication',
        abilityName: 'EntryAbility',
        moduleName: 'entry',
        parameters: {payResult: 'OKay',},
    },
}
// context 为被调用方 UIAbility 的 AbilityContext
this.context.terminateSelfWithResult(abilityResult, (err) => {// ...});

4. 在调用方 startAbilityForResult()办法回调中接管领取利用返回的信息,RESULT_CODE 须要与后面 terminateSelfWithResult()返回的数值保持一致。

const RESULT_CODE: number = 1001;
let want = {// Want 参数信息};
// context 为调用方 UIAbility 的 AbilityContext
this.context.startAbilityForResult(want).then((data) => {if (data?.resultCode === RESULT_CODE) {
        // 解析被调用方 UIAbility 返回的信息
        let payResult = data.want?.parameters?.payResult;
        // ...
    }
}).catch((err) => {// ...})

启动 UIAbility 的指定页面

一个 UIAbility 能够对应多个页面,在不同的场景下启动该 UIAbility 时须要展现不同的页面,例如从一个 UIAbility 的页面中跳转到另外一个 UIAbility 时,心愿启动指标 UIAbility 的指定页面。本文次要解说指标 UIAbility 首次启动和指标 UIAbility 非首次启动两种启动指定页面的场景,以及在解说启动指定页面之前会解说到在调用方如何指定启动页面。

调用方 UIAbility 指定启动页面

调用方 UIAbility 启动另外一个 UIAbility 时,通常须要跳转到指定的页面。例如 FuncAbility 蕴含两个页面(Index 对应首页,Second 对应性能 A 页面),此时须要在传入的 want 参数中配置指定的页面门路信息,能够通过 want 中的 parameters 参数减少一个自定义参数传递页面跳转信息。示例中的 context 的获取形式参见获取 UIAbility 的 Context 属性。

let wantInfo = {
    deviceId: '', // deviceId 为空示意本设施
    bundleName: 'com.example.myapplication',
    abilityName: 'FuncAbility',
    moduleName: 'module1', // moduleName 非必选
    parameters: { // 自定义参数传递页面信息
        router: 'funcA',
    },
}
// context 为调用方 UIAbility 的 AbilityContext
this.context.startAbility(wantInfo).then(() => {// ...}).catch((err) => {// ...})

指标 UIAbility 首次启动

指标 UIAbility 首次启动时,在指标 UIAbility 的 onWindowStageCreate()生命周期回调中,解析 EntryAbility 传递过去的 want 参数,获取到须要加载的页面信息 url,传入 windowStage.loadContent()办法。

import UIAbility from '@ohos.app.ability.UIAbility'
import Window from '@ohos.window'
export default class FuncAbility extends UIAbility {
    funcAbilityWant;
    onCreate(want, launchParam) {
        // 接管调用方 UIAbility 传过来的参数
        this.funcAbilityWant = want;
    }
    onWindowStageCreate(windowStage: Window.WindowStage) {
        // Main window is created, set main page for this ability
        let url = 'pages/Index';
        if (this.funcAbilityWant?.parameters?.router) {if (this.funcAbilityWant.parameters.router === 'funA') {url = 'pages/Second';}
        }
        windowStage.loadContent(url, (err, data) => {// ...});
    }
}

指标 UIAbility 非首次启动

常常还会遇到一类场景,当利用 A 曾经启动且处于主页面时,回到桌面,关上利用 B,并从利用 B 再次启动利用 A,且须要跳转到利用 A 的指定页面。例如联系人利用和短信利用配合应用的场景。关上短信利用主页,回到桌面,此时短信利用处于已关上状态且以后处于短信利用的主页。再关上联系人利用主页,进入联系人用户 A 查看详情,点击短信图标,筹备给用户 A 发送短信,此时会再次拉起短信利用且以后处于短信利用的发送页面。

针对以上场景,即当利用 A 的 UIAbility 实例已创立,并且处于该 UIAbility 实例对应的主页面中,此时,从利用 B 中须要再次启动利用 A 的该 UIAbility,并且须要跳转到不同的页面,这种状况下要如何实现呢?

1. 在指标 UIAbility 中,默认加载的是 Index 页面。因为以后 UIAbility 实例之前曾经创立实现,此时会进入 UIAbility 的 onNewWant()回调中且不会进入 onCreate()和 onWindowStageCreate()生命周期回调,在 onNewWant()回调中解析调用方传递过去的 want 参数,并挂在到全局变量 globalThis 中,以便于后续在页面中获取。

import UIAbility from '@ohos.app.ability.UIAbility'
export default class FuncAbility extends UIAbility {onNewWant(want, launchParam) {
        // 接管调用方 UIAbility 传过来的参数
        globalThis.funcAbilityWant = want;
        // ...
    }
}

2. 在 FuncAbility 中,此时须要在 Index 页面中通过页面路由 Router 模块实现指定页面的跳转,因为此时 FuncAbility 对应的 Index 页面是处于激活状态,不会从新变量申明以及进入 aboutToAppear()生命周期回调中。因而能够在 Index 页面的 onPageShow()生命周期回调中实现页面路由跳转的性能。

import router from '@ohos.router';
@Entry
@Component
struct Index {onPageShow() {
    let funcAbilityWant = globalThis.funcAbilityWant;
    let url2 = funcAbilityWant?.parameters?.router;
    if (url2 && url2 === 'funcA') {
      router.replaceUrl({url: 'pages/Second',})
    }
  }

  // 页面展现
  build() {// ...}
}

阐明
当被调用方 Ability 的启动模式设置为 multiton 启动模式时,每次启动都会创立一个新的实例,那么 onNewWant()回调就不会被用到。

通过 Call 调用实现 UIAbility 交互(仅对系统利用凋谢)

Call 调用是 UIAbility 能力的扩大,它为 UIAbility 提供一种可能被内部调用并与内部进行通信的能力。Call 调用反对前台与后盾两种启动形式,使 UIAbility 既能被拉起到前台展现 UI,也能够在后盾被创立并运行。Call 调用在调用方与被调用方间建设了 IPC 通信,因而利用开发者可通过 Call 调用实现不同 UIAbility 之间的数据共享。

Call 调用的外围接口是 startAbilityByCall 办法,与 startAbility 接口的不同之处在于:

  • startAbilityByCall 反对前台与后盾两种启动形式,而 startAbility 仅反对前台启动。
  • 调用方可应用 startAbilityByCall 所返回的 Caller 对象与被调用方进行通信,而 startAbility 不具备通信能力。

Call 调用的应用场景次要包含:

  • 须要与被启动的 UIAbility 进行通信。
  • 心愿被启动的 UIAbility 在后盾运行。
  • 表 1 Call 调用相干名词解释

Call 调用示意图如下所示。

图 1 Call 调用示意图

  • CallerAbility 调用 startAbilityByCall 接口获取 Caller,并应用 Caller 对象的 call 办法向 CalleeAbility 发送数据。
  • CalleeAbility 持有一个 Callee 对象,通过 Callee 的 on 办法注册回调函数,当接管到 Caller 发送的数据时将会调用对应的回调函数。

阐明
1. 以后仅支持系统利用应用 Call 调用。
2.CalleeAbility 的启动模式须要为单实例。
3.Call 调用既反对本地(设施内)Call 调用,也反对跨设施 Call 调用,上面介绍设施内 Call 调用办法。

接口阐明

Call 性能次要接口如下表所示。具体的 API 详见接口文档。

表 2 Call 性能次要接口

设施内通过 Call 调用实现 UIAbility 交互,波及如下两局部开发:

  • 创立 Callee 被调用端
  • 拜访 Callee 被调用端

开发步骤(创立 Callee 被调用端)

在 Callee 被调用端,须要实现指定办法的数据接管回调函数、数据的序列化及反序列化办法。在须要接收数据期间,通过 on 接口注册监听,无需接收数据时通过 off 接口解除监听。

配置 Ability 的启动模式。

配置 module.json5,将 CalleeAbility 配置为单实例 ”singleton”。

Ability 配置标签示例如下:

"abilities":[{
  "name": ".CalleeAbility",
  "srcEntrance": "./ets/CalleeAbility/CalleeAbility.ts",
  "launchType": "singleton",
  "description": "$string:CalleeAbility_desc",
  "icon": "$media:icon",
  "label": "$string:CalleeAbility_label",
  "visible": true
}]

2. 导入 UIAbility 模块。

import Ability from '@ohos.app.ability.UIAbility';

3. 定义约定的序列化数据。

调用端及被调用端发送接管的数据格式需协商一致,如下示例约定数据由 number 和 string 组成。

export default class MyParcelable {
    num: number = 0
    str: string = ""
    constructor(num, string) {
        this.num = num
        this.str = string
    }
    marshalling(messageSequence) {messageSequence.writeInt(this.num)
        messageSequence.writeString(this.str)
        return true
    }
    unmarshalling(messageSequence) {this.num = messageSequence.readInt()
        this.str = messageSequence.readString()
        return true
    }
}

4. 实现 Callee.on 监听及 Callee.off 解除监听。

被调用端 Callee 的监听函数注册机会,取决于利用开发者。注册监听之前的数据不会被解决,勾销监听之后的数据不会被解决。如下示例在 Ability 的 onCreate 注册 ’MSG_SEND_METHOD’ 监听,在 onDestroy 勾销监听,收到序列化数据后作相应解决并返回,利用开发者依据理论须要做相应解决。具体示例代码如下:

const TAG: string = '[CalleeAbility]';
const MSG_SEND_METHOD: string = 'CallSendMsg';
function sendMsgCallback(data) {console.info('CalleeSortFunc called');
    // 获取 Caller 发送的序列化数据
    let receivedData = new MyParcelable(0, '');
    data.readParcelable(receivedData);
    console.info(`receiveData[${receivedData.num}, ${receivedData.str}]`);
    // 作相应解决
    // 返回序列化数据 result 给 Caller
    return new MyParcelable(receivedData.num + 1, `send ${receivedData.str} succeed`);
}
export default class CalleeAbility extends Ability {onCreate(want, launchParam) {
        try {this.callee.on(MSG_SEND_METHOD, sendMsgCallback);
        } catch (error) {console.info(`${MSG_SEND_METHOD} register failed with error ${JSON.stringify(error)}`);
        }
    }
    onDestroy() {
        try {this.callee.off(MSG_SEND_METHOD);
        } catch (error) {console.error(TAG, `${MSG_SEND_METHOD} unregister failed with error ${JSON.stringify(error)}`);
        }
    }
}

开发步骤(拜访 Callee 被调用端)

导入 UIAbility 模块。

import Ability from '@ohos.app.ability.UIAbility';

2. 获取 Caller 通信接口。

Ability 的 context 属性实现了 startAbilityByCall 办法,用于获取指定通用组件的 Caller 通信接口。如下示例通过 this.context 获取 Ability 实例的 context 属性,应用 startAbilityByCall 拉起 Callee 被调用端并获取 Caller 通信接口,注册 Caller 的 onRelease 监听。利用开发者依据理论须要做相应解决。

// 注册 caller 的 release 监听
private regOnRelease(caller) {
    try {caller.on("release", (msg) => {console.info(`caller onRelease is called ${msg}`);
        })
        console.info('caller register OnRelease succeed');
    } catch (error) {console.info(`caller register OnRelease failed with ${error}`);
    }
}
async onButtonGetCaller() {
    try {
        this.caller = await context.startAbilityByCall({
            bundleName: 'com.samples.CallApplication',
            abilityName: 'CalleeAbility'
        })
        if (this.caller === undefined) {console.info('get caller failed')
            return
        }
        console.info('get caller success')
        this.regOnRelease(this.caller)
    } catch (error) {console.info(`get caller failed with ${error}`)
    }
}

作为一名合格一线开发程序员,大家心里必定会有很多疑难!鸿蒙零碎这么弱小~~

为了可能让大家跟上互联网时代的技术迭代,在这里跟大家分享一下我本人近期学习心得以及参考网上材料整顿出的一份最新版的鸿蒙学习晋升材料,有须要的小伙伴自行支付,限时开源,先到先得~~~~

支付以下高清学习路线原图请点击→《鸿蒙零根底入门学习指南》纯血鸿蒙 HarmonyOS 根底技能学习路线图

支付以上残缺高清学习路线图,请点击→《鸿蒙全套学习指南》小编本人整顿的局部学习材料(蕴含有高清视频、开发文档、电子书籍等)

以上分享的学习路线都适宜哪些人跟着学习?
- 应届生 / 计算机专业通过学习鸿蒙新兴技术,入行互联网,将来高起点待业。
- 0 根底转行提前布局新方向,抓住风口,自我晋升,取得更多就业机会。
- 技术晋升 / 进阶跳槽倒退瓶颈期,晋升职场竞争力,疾速把握鸿蒙技术,享受蓝海红利。

总结

如果你感觉这篇内容对你有帮忙,我想麻烦大家动动小手给我:点赞,转发,有你们的『点赞和评论』,才是我发明的能源。关注我,同时能够期待后续文章 ing,不定期分享原创常识。想要获取更多残缺鸿蒙最新 VIP 学习材料,请点击→《鸿蒙开发学习之 UI》

正文完
 0