网站建设与维护实训,小游戏网站,建设域名网站,茶叶外贸网站建设UIAbility是系统调度的最小单元。在设备内的功能模块之间跳转时#xff0c;会涉及到启动特定的UIAbility#xff0c;该UIAbility可以是应用内的其他UIAbility#xff0c;也可以是其他应用的UIAbility#xff08;例如启动三方支付UIAbility#xff09;。
本文将从如下场景…UIAbility是系统调度的最小单元。在设备内的功能模块之间跳转时会涉及到启动特定的UIAbility该UIAbility可以是应用内的其他UIAbility也可以是其他应用的UIAbility例如启动三方支付UIAbility。
本文将从如下场景分别介绍设备内UIAbility间的交互方式。对于跨设备的应用组件交互请参见 应用组件跨设备交互流转。
启动应用内的UIAbility启动应用内的UIAbility并获取返回结果启动其他应用的UIAbility启动其他应用的UIAbility并获取返回结果启动UIAbility指定窗口模式仅对系统应用开放启动UIAbility的指定页面通过Call调用实现UIAbility交互仅对系统应用开放
启动应用内的UIAbility
当一个应用内包含多个UIAbility时存在应用内启动UIAbility的场景。例如在支付应用中从入口UIAbility启动收付款UIAbility。
假设应用中有两个UIAbilityEntryAbility和FuncAbility可以在同一个Module中也可以在不同的Module中需要从EntryAbility的页面中启动FuncAbility。
在EntryAbility中通过调用 startAbility()方法启动UIAbilitywant 为UIAbility实例启动的入口参数其中bundleName为待启动应用的Bundle名称abilityName为待启动的Ability名称moduleName在待启动的UIAbility属于不同的Module时添加parameters为自定义信息参数。示例中的context的获取方式请参见 获取UIAbility的上下文信息。
import common from ohos.app.ability.common;
import Want from ohos.app.ability.Want;
import { BusinessError } from ohos.base;
import hilog from ohos.hilog;const TAG: string [Page_UIAbilityComponentsInteractive];
const DOMAIN_NUMBER: number 0xFF00;Entry
Component
struct Page_UIAbilityComponentsInteractive {private context getContext(this) as common.UIAbilityContext;build() {...Button().onClick(() {// context为Ability对象的成员在非Ability对象内部调用需要// 将Context对象传递过去let wantInfo: Want {deviceId: , // deviceId为空表示本设备bundleName: com.samples.myapplication,moduleName: entry, // moduleName非必选abilityName: FuncAbilityA,parameters: { // 自定义信息info: 来自EntryAbility Page_UIAbilityComponentsInteractive页面},}// context为调用方UIAbility的UIAbilityContextthis.context.startAbility(wantInfo).then(() {hilog.info(DOMAIN_NUMBER, TAG, startAbility success.);}).catch((error: BusinessError) {hilog.error(DOMAIN_NUMBER, TAG, startAbility failed.);});})}
}在FuncAbility的 onCreate() 生命周期回调文件中接收EntryAbility传递过来的参数。
import UIAbility from ohos.app.ability.UIAbility;
import AbilityConstant from ohos.app.ability.AbilityConstant;
import Want from ohos.app.ability.Want;export default class FuncAbility extends UIAbility {onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {// 接收调用方UIAbility传过来的参数let funcAbilityWant want;let info funcAbilityWant?.parameters?.info;// ...}
}说明 被拉起的FuncAbility中可以通过获取传递过来的want参数的parameters来获取拉起方UIAbility的PID、Bundle Name等信息。 在FuncAbility业务完成之后如需要停止当前UIAbility实例在FuncAbility中通过调用 terminateSelf() 方法实现。
import common from ohos.app.ability.common;
import hilog from ohos.hilog;const TAG: string [Page_UIAbilityComponentsInteractive];
const DOMAIN_NUMBER: number 0xFF00;Entry
Component
struct Page_UIAbilityComponentsInteractive {build() {...Button().onClick(() {let context: common.UIAbilityContext getContext(this) as common.UIAbilityContext; // UIAbilityContext// context为需要停止的UIAbility实例的AbilityContextcontext.terminateSelf((err) {if (err.code) {hilog.error(DOMAIN_NUMBER, TAG, Failed to terminate Self. Code is ${err.code}, message is ${err.message});return;}});})}
}说明 调用 terminateSelf() 方法停止当前UIAbility实例时默认会保留该实例的快照Snapshot即在最近任务列表中仍然能查看到该实例对应的任务。如不需要保留该实例的快照可以在其对应UIAbility的 module.json5配置文件中将 abilities标签的removeMissionAfterTerminate字段配置为true。 如需要关闭应用所有的UIAbility实例可以调用 ApplicationContext 的 killAllProcesses() 方法实现关闭应用所有的进程。
启动应用内的UIAbility并获取返回结果
在一个EntryAbility启动另外一个FuncAbility时希望在被启动的FuncAbility完成相关业务后能将结果返回给调用方。例如在应用中将入口功能和帐号登录功能分别设计为两个独立的UIAbility在帐号登录UIAbility中完成登录操作后需要将登录的结果返回给入口UIAbility。
在EntryAbility中调用 startAbilityForResult() 接口启动FuncAbility异步回调中的data用于接收FuncAbility停止自身后返回给EntryAbility的信息。
import common from ohos.app.ability.common;
import hilog from ohos.hilog;
import Want from ohos.app.ability.Want;
import { BusinessError } from ohos.base;const TAG: string [Page_UIAbilityComponentsInteractive];
const DOMAIN_NUMBER: number 0xFF00;Entry
Component
struct Page_UIAbilityComponentsInteractive {build() {Button().onClick(() {let context: common.UIAbilityContext getContext(this) as common.UIAbilityContext; // UIAbilityContextlet want: Want {deviceId: , // deviceId为空表示本设备bundleName: com.samples.stagemodelabilitydevelop,moduleName: entry, // moduleName非必选abilityName: FuncAbilityA,parameters: { // 自定义信息info: 来自EntryAbility UIAbilityComponentsInteractive页面}};context.startAbilityForResult(want).then((data) {// ...}).catch((err: BusinessError) {hilog.error(DOMAIN_NUMBER, TAG, Failed to start ability for result. Code is ${err.code}, message is ${err.message});});})}
}在FuncAbility停止自身时需要调用terminateSelfWithResult() 方法入参abilityResult为FuncAbility需要返回给EntryAbility的信息。
import common from ohos.app.ability.common;
import hilog from ohos.hilog;const TAG: string [Page_FuncAbilityA];
const DOMAIN_NUMBER: number 0xFF00;Entry
Component
struct Page_FuncAbilityA {build() {Button().onClick(() {let context: common.UIAbilityContext getContext(this) as common.UIAbilityContext; // UIAbilityContextconst RESULT_CODE: number 1001;let abilityResult: common.AbilityResult {resultCode: RESULT_CODE,want: {bundleName: com.samples.stagemodelabilitydevelop,moduleName: entry, // moduleName非必选abilityName: FuncAbilityB,parameters: {info: 来自FuncAbility Index页面},},};context.terminateSelfWithResult(abilityResult, (err) {if (err.code) {hilog.error(DOMAIN_NUMBER, TAG, Failed to terminate self with result. Code is ${err.code}, message is ${err.message});return;}});})}
}FuncAbility停止自身后EntryAbility通过 startAbilityForResult() 方法回调接收被FuncAbility返回的信息RESULT_CODE需要与前面的数值保持一致。
import common from ohos.app.ability.common;
import hilog from ohos.hilog;
import Want from ohos.app.ability.Want;
import { BusinessError } from ohos.base;
import promptAction from ohos.promptAction;const TAG: string [EntryAbility];
const DOMAIN_NUMBER: number 0xFF00;Entry
Component
struct Page_UIAbilityComponentsInteractive {build() {Button().onClick(() {let context: common.UIAbilityContext getContext(this) as common.UIAbilityContext; // UIAbilityContextconst RESULT_CODE: number 1001;let want: Want {deviceId: , // deviceId为空表示本设备bundleName: com.samples.stagemodelabilitydevelop,moduleName: entry, // moduleName非必选abilityName: FuncAbilityA,parameters: { // 自定义信息info: 来自EntryAbility UIAbilityComponentsInteractive页面}};context.startAbilityForResult(want).then((data) {if (data?.resultCode RESULT_CODE) {// 解析被调用方UIAbility返回的信息let info data.want?.parameters?.info;hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(info) ?? );if (info ! null) {promptAction.showToast({message: JSON.stringify(info)});}}hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(data.resultCode) ?? );}).catch((err: BusinessError) {hilog.error(DOMAIN_NUMBER, TAG, Failed to start ability for result. Code is ${err.code}, message is ${err.message});});})}
}启动其他应用的UIAbility
启动其他应用的UIAbility通常用户只需要完成一个通用的操作例如需要选择一个文档应用来查看某个文档的内容信息。系统会根据调用方的want参数来识别和启动匹配到的应用UIAbility。
启动UIAbility有 显式Want启动和隐式Want启动 两种方式。 显式Want启动启动一个确定应用的UIAbility在want参数中需要设置该应用bundleName和abilityName当需要拉起某个明确的UIAbility时通常使用显式Want启动方式。 隐式Want启动根据匹配条件由用户选择启动哪一个UIAbility即不明确指出要启动哪一个UIAbilityabilityName参数未设置在调用 startAbility() 方法时其入参want中指定了一系列的entities字段表示目标UIAbility额外的类别信息如浏览器、视频播放器和actions字段表示要执行的通用操作如查看、分享、应用详情等等参数信息然后由系统去分析want并帮助找到合适的UIAbility来启动。当需要拉起其他应用的UIAbility时开发者通常不知道用户设备中应用的安装情况也无法确定目标应用的bundleName和abilityName通常使用隐式Want启动方式。
本文主要讲解如何通过隐式Want启动其他应用的UIAbility。
将多个待匹配的文档应用安装到设备在其对应UIAbility的 module.json5配置文件 中配置skills标签的entities字段和actions字段。 {module: {abilities: [{...skills: [{entities: [...entity.system.default],actions: [...ohos.want.action.viewData]}]}]}}在调用方want参数中的entities和action需要被包含在待匹配UIAbility的skills配置的entities和actions中。系统匹配到符合entities和actions参数条件的UIAbility后会弹出选择框展示匹配到的UIAbility实例列表供用户选择使用。
import common from ohos.app.ability.common;
import Want from ohos.app.ability.Want;
import { BusinessError } from ohos.base;
import hilog from ohos.hilog;const TAG: string [Page_UIAbilityComponentsInteractive];
const DOMAIN_NUMBER: number 0xFF00;Entry
Component
struct Page_UIAbilityComponentsInteractive {build() {Button().onClick(() {let context: common.UIAbilityContext getContext(this) as common.UIAbilityContext; // UIAbilityContextlet want: Want {deviceId: , // deviceId为空表示本设备// uncomment line below if wish to implicitly query only in the specific bundle.// bundleName: com.samples.stagemodelabilityinteraction,action: ohos.want.action.viewData,// entities can be omitted.entities: [entity.system.default]};// context为调用方UIAbility的UIAbilityContextcontext.startAbility(want).then(() {hilog.info(DOMAIN_NUMBER, TAG, Succeeded in starting FuncAbility.);}).catch((err: BusinessError) {hilog.error(DOMAIN_NUMBER, TAG, Failed to start FuncAbility. Code is ${err.code}, message is ${err.message});});})}
}效果示意如下图所示点击“打开PDF文档”时会弹出选择框供用户选择。 在文档应用使用完成之后如需要停止当前UIAbility实例通过调用 terminateSelf() 方法实现。
import common from ohos.app.ability.common;
import hilog from ohos.hilog;const TAG: string [Page_FromStageModel];
const DOMAIN_NUMBER: number 0xFF00;Entry
Component
struct Page_FromStageModel {State message: string Hello Worldbuild() {Button().onClick(() {let context: common.UIAbilityContext getContext(this) as common.UIAbilityContext; // UIAbilityContext// context为需要停止的UIAbility实例的AbilityContextcontext.terminateSelf((err) {if (err.code) {hilog.error(DOMAIN_NUMBER, TAG, Failed to terminate self. Code is ${err.code}, message is ${err.message});return;}});})}
}启动其他应用的UIAbility并获取返回结果
当使用隐式Want启动其他应用的UIAbility并希望获取返回结果时调用方需要使用 startAbilityForResult() 方法启动目标UIAbility。例如主应用中需要启动三方支付并获取支付结果。
在支付应用对应UIAbility的 module.json5配置文件 中配置skills的entities字段和actions字段。
{module: {abilities: [{...skills: [{entities: [...entity.system.default],actions: [...ohos.want.action.editData]}]}]}
}调用方使用 startAbilityForResult() 方法启动支付应用的UIAbility在调用方want参数中的entities和action需要被包含在待匹配UIAbility的skills标签配置的entities和actions中。异步回调中的data用于后续接收支付UIAbility停止自身后返回给调用方的信息。系统匹配到符合entities和actions参数条件的UIAbility后会弹出选择框展示匹配到的UIAbility实例列表供用户选择使用。
import common from ohos.app.ability.common;
import hilog from ohos.hilog;
import Want from ohos.app.ability.Want;
import { BusinessError } from ohos.base;const TAG: string [Page_UIAbilityComponentsInteractive];
const DOMAIN_NUMBER: number 0xFF00;Entry
Component
struct Page_UIAbilityComponentsInteractive {build() {Button().onClick(() {let context: common.UIAbilityContext getContext(this) as common.UIAbilityContext; // UIAbilityContextlet want: Want {deviceId: , // deviceId为空表示本设备bundleName: com.samples.stagemodelabilitydevelop,moduleName: entry, // moduleName非必选abilityName: FuncAbilityA,parameters: { // 自定义信息info: 来自EntryAbility UIAbilityComponentsInteractive页面}};context.startAbilityForResult(want).then((data) {// ...}).catch((err: BusinessError) {hilog.error(DOMAIN_NUMBER, TAG, Failed to start ability for result. Code is ${err.code}, message is ${err.message});});})}
}在支付UIAbility完成支付之后需要调用 terminateSelfWithResult() 方法实现停止自身并将abilityResult参数信息返回给调用方。
import common from ohos.app.ability.common;
import hilog from ohos.hilog;const TAG: string [Page_FuncAbilityA];
const DOMAIN_NUMBER: number 0xFF00;Entry
Component
struct Page_FuncAbilityA {build() {Button().onClick(() {let context: common.UIAbilityContext getContext(this) as common.UIAbilityContext; // UIAbilityContextconst RESULT_CODE: number 1001;let abilityResult: common.AbilityResult {resultCode: RESULT_CODE,want: {bundleName: com.samples.stagemodelabilitydevelop,moduleName: entry, // moduleName非必选abilityName: FuncAbilityB,parameters: {info: 来自FuncAbility Index页面},},};context.terminateSelfWithResult(abilityResult, (err) {if (err.code) {hilog.error(DOMAIN_NUMBER, TAG, Failed to terminate self with result. Code is ${err.code}, message is ${err.message});return;}});})}
}在调用方 startAbilityForResult() 方法回调中接收支付应用返回的信息RESULT_CODE需要与前面 terminateSelfWithResult() 返回的数值保持一致。
import common from ohos.app.ability.common;
import hilog from ohos.hilog;
import Want from ohos.app.ability.Want;
import { BusinessError } from ohos.base;
import promptAction from ohos.promptAction;const TAG: string [EntryAbility];
const DOMAIN_NUMBER: number 0xFF00;Entry
Component
struct Page_UIAbilityComponentsInteractive {build() {Button().onClick(() {let context: common.UIAbilityContext getContext(this) as common.UIAbilityContext; // UIAbilityContextconst RESULT_CODE: number 1001;let want: Want {deviceId: , // deviceId为空表示本设备bundleName: com.samples.stagemodelabilitydevelop,moduleName: entry, // moduleName非必选abilityName: FuncAbilityA,parameters: { // 自定义信息info: 来自EntryAbility UIAbilityComponentsInteractive页面}};context.startAbilityForResult(want).then((data) {if (data?.resultCode RESULT_CODE) {// 解析被调用方UIAbility返回的信息let info data.want?.parameters?.info;hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(info) ?? );if (info ! null) {promptAction.showToast({message: JSON.stringify(info)});}}hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(data.resultCode) ?? );}).catch((err: BusinessError) {hilog.error(DOMAIN_NUMBER, TAG, Failed to start ability for result. Code is ${err.code}, message is ${err.message});});})}
}启动UIAbility指定窗口模式仅对系统应用开放
当用户打开应用时应用程序会以不同的窗口模式进行展示即启动UIAbility的窗口模式。应用程序可以启动为全屏模式悬浮窗模式或分屏模式。
全屏模式是指应用程序启动后占据整个屏幕用户无法同时查看其他窗口或应用程序。全屏模式通常适用于那些要求用户专注于特定任务或界面的应用程序。
悬浮窗模式是指应用程序启动后以浮动窗口的形式显示在屏幕上用户可以轻松切换到其他窗口或应用程序。悬浮窗通常适用于需要用户同时处理多个任务的应用程序。
分屏模式允许用户在同一屏幕上同时运行两个应用程序其中一个应用程序占据屏幕左侧/上侧的一部分另一个应用程序占据右侧/下侧的一部分。分屏模式主要用于提高用户的多任务处理效率。
使用 startAbility() 方法启动UIAbility时可以通过在入参中增加 StartOptions 参数的windowMode属性来配置启动UIAbility的窗口模式。 说明 如果在使用 startAbility() 方法启动UIAbility时入参中未指定 StartOptions 参数的windowMode属性那么UIAbility将以系统默认的窗口展示形态启动。为了确保启动的UIAbility展示形态能够被支持需要在该UIAbility对应的 module.json5配置文件中 abilities标签的supportWindowMode字段确认启动的展示形态被支持。
以下是具体的操作步骤以悬浮窗模式为例假设需要从EntryAbility的页面中启动FuncAbility
在调用 startAbility() 方法时增加 StartOptions 参数。在 StartOptions 参数中设置windowMode字段为WINDOW_MODE_FLOATING表示启动的UIAbility将以悬浮窗的形式展示。windowMode属性仅适用于系统应用三方应用可以使用displayId属性。
import AbilityConstant from ohos.app.ability.AbilityConstant;
import common from ohos.app.ability.common;
import hilog from ohos.hilog;
import StartOptions from ohos.app.ability.StartOptions;
import Want from ohos.app.ability.Want;
import { BusinessError } from ohos.base;const TAG: string [Page_UIAbilityComponentsInteractive];
const DOMAIN_NUMBER: number 0xFF00;Entry
Component
struct Page_UIAbilityComponentsInteractive {build() {Button().onClick(() {let context: common.UIAbilityContext getContext(this) as common.UIAbilityContext; // UIAbilityContextlet want: Want {deviceId: , // deviceId为空表示本设备bundleName: com.samples.stagemodelabilitydevelop,moduleName: entry, // moduleName非必选abilityName: FuncAbilityB,parameters: { // 自定义信息info: 来自EntryAbility Index页面}};let options: StartOptions {windowMode: AbilityConstant.WindowMode.WINDOW_MODE_FLOATING};// context为调用方UIAbility的UIAbilityContextcontext.startAbility(want, options).then(() {hilog.info(DOMAIN_NUMBER, TAG, Succeeded in starting ability.);}).catch((err: BusinessError) {hilog.error(DOMAIN_NUMBER, TAG, Failed to start ability. Code is ${err.code}, message is ${err.message});});})}
}效果示意如下图所示。 启动UIAbility的指定页面
概述
一个UIAbility可以对应多个页面在不同的场景下启动该UIAbility时需要展示不同的页面例如从一个UIAbility的页面中跳转到另外一个UIAbility时希望启动目标UIAbility的指定页面。
UIAbility的启动分为两种情况UIAbility冷启动和UIAbility热启动。
UIAbility冷启动指的是UIAbility实例处于完全关闭状态下被启动这需要完整地加载和初始化UIAbility实例的代码、资源等。UIAbility热启动指的是UIAbility实例已经启动并在前台运行过由于某些原因切换到后台再次启动该UIAbility实例这种情况下可以快速恢复UIAbility实例的状态。
本文主要讲解 目标UIAbility冷启动 两种启动指定页面的场景以及在讲解启动指定页面之前会讲解到在调用方如何指定启动页面。
调用方UIAbility指定启动页面
调用方UIAbility启动另外一个UIAbility时通常需要跳转到指定的页面。例如FuncAbility包含两个页面Index对应首页Second对应功能A页面此时需要在传入的want参数中配置指定的页面路径信息可以通过want中的parameters参数增加一个自定义参数传递页面跳转信息。
import common from ohos.app.ability.common;
import hilog from ohos.hilog;
import Want from ohos.app.ability.Want;
import { BusinessError } from ohos.base;const TAG: string [Page_UIAbilityComponentsInteractive];
const DOMAIN_NUMBER: number 0xFF00;Entry
Component
struct Page_UIAbilityComponentsInteractive {build() {Button().onClick(() {let context: common.UIAbilityContext getContext(this) as common.UIAbilityContext; // UIAbilityContextlet want: Want {deviceId: , // deviceId为空表示本设备bundleName: com.samples.stagemodelabilityinteraction,moduleName: entry, // moduleName非必选abilityName: FuncAbility,parameters: { // 自定义参数传递页面信息router: FuncA}};// context为调用方UIAbility的UIAbilityContextcontext.startAbility(want).then(() {hilog.info(DOMAIN_NUMBER, TAG, Succeeded in starting ability.);}).catch((err: BusinessError) {hilog.error(DOMAIN_NUMBER, TAG, Failed to start ability. Code is ${err.code}, message is ${err.message});});})}
}目标UIAbility冷启动
目标UIAbility冷启动时在目标UIAbility的onCreate()生命周期回调中接收调用方传过来的参数。然后在目标UIAbility的onWindowStageCreate()生命周期回调中解析EntryAbility传递过来的want参数获取到需要加载的页面信息url传入windowStage.loadContent()方法。
import AbilityConstant from ohos.app.ability.AbilityConstant;
import UIAbility from ohos.app.ability.UIAbility;
import Want from ohos.app.ability.Want;
import window from ohos.window;export default class FuncAbility extends UIAbility {funcAbilityWant: Want | undefined undefined;onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {// 接收调用方UIAbility传过来的参数this.funcAbilityWant want;}onWindowStageCreate(windowStage: window.WindowStage) {// Main window is created, set main page for this abilitylet url pages/Index;if (this.funcAbilityWant?.parameters?.router this.funcAbilityWant.parameters.router funcA) {url pages/Page_ColdStartUp;}windowStage.loadContent(url, (err, data) {// ...});}
}目标UIAbility热启动
在应用开发中会遇到目标UIAbility实例之前已经启动过的场景这时再次启动目标UIAbility时不会重新走初始化逻辑只会直接触发onNewWant()生命周期方法。为了实现跳转到指定页面需要在onNewWant()中解析参数进行处理。
例如短信应用和联系人应用配合使用的场景。
用户先打开短信应用短信应用的UIAbility实例启动显示短信应用的主页。用户将设备回到桌面界面短信应用进入后台运行状态。用户打开联系人应用找到联系人张三。用户点击联系人张三的短信按钮会重新启动短信应用的UIAbility实例。由于短信应用的UIAbility实例已经启动过了此时会触发该UIAbility的onNewWant()回调而不会再走onCreate()和onWindowStageCreate()等初始化逻辑。
图1 目标UIAbility热启动 开发步骤如下所示。
冷启动短信应用的UIAbility实例时在onWindowStageCreate()生命周期回调中通过调用 getUIContext() 接口获取UI上下文实例 UIContext 对象。
import hilog from ohos.hilog;
import UIAbility from ohos.app.ability.UIAbility;
import Want from ohos.app.ability.Want;
import window from ohos.window;import { UIContext } from ohos.arkui.UIContext;const DOMAIN_NUMBER: number 0xFF00;
const TAG: string [EntryAbility];export default class EntryAbility extends UIAbility {funcAbilityWant: Want | undefined undefined;uiContext: UIContext | undefined undefined;// ...onWindowStageCreate(windowStage: window.WindowStage): void {// Main window is created, set main page for this abilitylet url pages/Index;if (this.funcAbilityWant?.parameters?.router this.funcAbilityWant.parameters.router funcA) {url pages/Page_ColdStartUp;}windowStage.loadContent(url, (err, data) {if (err.code) {return;}let windowClass: window.Window;windowStage.getMainWindow((err, data) {if (err.code) {hilog.error(DOMAIN_NUMBER, TAG, Failed to obtain the main window. Code is ${err.code}, message is ${err.message});return;}windowClass data;this.uiContext windowClass.getUIContext();})});}
}在短信应用UIAbility的onNewWant()回调中解析调用方传递过来的want参数通过调用UIContext中的getRouter() 方法获取 Router 对象并进行指定页面的跳转。此时再次启动该短信应用的UIAbility实例时即可跳转到该短信应用的UIAbility实例的指定页面。
import AbilityConstant from ohos.app.ability.AbilityConstant;
import hilog from ohos.hilog;
import UIAbility from ohos.app.ability.UIAbility;
import Want from ohos.app.ability.Want;
import { BusinessError } from ohos.base;import { Router, UIContext } from ohos.arkui.UIContext;const DOMAIN_NUMBER: number 0xFF00;
const TAG: string [EntryAbility];export default class EntryAbility extends UIAbility {funcAbilityWant: Want | undefined undefined;uiContext: UIContext | undefined undefined;onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {if (want?.parameters?.router want.parameters.router funcB) {let funcAUrl pages/Page_HotStartUp;if (this.uiContext) {let router: Router this.uiContext.getRouter();router.pushUrl({url: funcAUrl}).catch((err: BusinessError) {hilog.error(DOMAIN_NUMBER, TAG, Failed to push url. Code is ${err.code}, message is ${err.message});});}}}// ...
}说明 当被调用方 UIAbility组件启动模式 设置为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调用相关名词解释
名词描述CallerAbility进行Call调用的UIAbility调用方。CalleeAbility被Call调用的UIAbility被调用方。Caller实际对象由startAbilityByCall接口返回CallerAbility可使用Caller与CalleeAbility进行通信。Callee实际对象被CalleeAbility持有可与Caller进行通信。
Call调用示意图如下所示。
图1 Call调用示意图 CallerAbility调用startAbilityByCall接口获取Caller并使用Caller对象的call方法向CalleeAbility发送数据。CalleeAbility持有一个Callee对象通过Callee的on方法注册回调函数当接收到Caller发送的数据时将会调用对应的回调函数。 说明 当前仅支持系统应用使用Call调用。CalleeAbility的启动模式需要为单实例。Call调用既支持本地设备内Call调用也支持跨设备Call调用下面介绍设备内Call调用方法。
接口说明
Call功能主要接口如下表所示。具体的API详见 接口文档。
表2 Call功能主要接口
接口名描述startAbilityByCall(want: Want): Promise启动指定UIAbility并获取其Caller通信接口默认为后台启动通过配置want可实现前台启动详见 接口文档。AbilityContext与ServiceExtensionContext均支持该接口。on(method: string, callback: CalleeCallBack): void通用组件Callee注册method对应的callback方法。off(method: string): void通用组件Callee解注册method的callback方法。call(method: string, data: rpc.Parcelable): Promise向通用组件Callee发送约定序列化数据。callWithResult(method: string, data: rpc.Parcelable): Promiserpc.MessageSequence向通用组件Callee发送约定序列化数据, 并将Callee返回的约定序列化数据带回。release(): void释放通用组件的Caller通信接口。on(type: “release”, callback: OnReleaseCallback): void注册通用组件通信断开监听通知。
设备内通过Call调用实现UIAbility交互涉及如下两部分开发
创建Callee被调用端访问Callee被调用端
开发步骤创建Callee被调用端
在Callee被调用端需要实现指定方法的数据接收回调函数、数据的序列化及反序列化方法。在需要接收数据期间通过on接口注册监听无需接收数据时通过off接口解除监听。
配置UIAbility的启动模式。
例如将CalleeAbility配置为单实例模式singleton。
导入UIAbility模块。
import UIAbility from ohos.app.ability.UIAbility;定义约定的序列化数据。 调用端及被调用端发送接收的数据格式需协商一致如下示例约定数据由number和string组成。
import type rpc from ohos.rpc;class MyParcelable {num: number 0;str: string ;constructor(num: number, string: string) {this.num num;this.str string;};mySequenceable(num, string): void {this.num num;this.str string;};marshalling(messageSequence: rpc.MessageSequence): boolean {messageSequence.writeInt(this.num);messageSequence.writeString(this.str);return true;};unmarshalling(messageSequence: rpc.MessageSequence): boolean {this.num messageSequence.readInt();this.str messageSequence.readString();return true;};
};实现Callee.on监听及Callee.off解除监听。
被调用端Callee的监听函数注册时机取决于应用开发者。注册监听之前的数据不会被处理取消监听之后的数据不会被处理。如下示例在UIAbility的onCreate注册’MSG_SEND_METHOD’监听在onDestroy取消监听收到序列化数据后作相应处理并返回应用开发者根据实际需要做相应处理。具体示例代码如下
import type AbilityConstant from ohos.app.ability.AbilityConstant;
import UIAbility from ohos.app.ability.UIAbility;
import type Want from ohos.app.ability.Want;
import hilog from ohos.hilog;
import Logger from ../utils/Logger;
import type rpc from ohos.rpc;
import type { Caller } from ohos.app.ability.UIAbility;const MSG_SEND_METHOD: string CallSendMsg;
const DOMAIN_NUMBER: number 0xFF00;
const TAG: string [CalleeAbility];class MyParcelable {num: number 0;str: string ;constructor(num: number, string: string) {this.num num;this.str string;}mySequenceable(num, string): void {this.num num;this.str string;}marshalling(messageSequence: rpc.MessageSequence): boolean {messageSequence.writeInt(this.num);messageSequence.writeString(this.str);return true;};unmarshalling(messageSequence: rpc.MessageSequence): boolean {this.num messageSequence.readInt();this.str messageSequence.readString();return true;};
};function sendMsgCallback(data: rpc.MessageSequence): rpc.Parcelable {hilog.info(DOMAIN_NUMBER, TAG, %{public}s, CalleeSortFunc called);// 获取Caller发送的序列化数据let receivedData: MyParcelable new MyParcelable(0, );data.readParcelable(receivedData);hilog.info(DOMAIN_NUMBER, TAG, %{public}s, receiveData[${receivedData.num}, ${receivedData.str}]);let num: number receivedData.num;// 作相应处理// 返回序列化数据result给Callerreturn new MyParcelable(num 1, send ${receivedData.str} succeed) as rpc.Parcelable;
}export default class CalleeAbility extends UIAbility {caller: Caller | undefined;onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {try {this.callee.on(MSG_SEND_METHOD, sendMsgCallback);} catch (error) {hilog.error(DOMAIN_NUMBER, TAG, %{public}s, Failed to register. Error is ${error});};}releaseCall(): void {try {if (this.caller) {this.caller.release();this.caller undefined;}Logger.info(caller release succeed);} catch (error) {Logger.info(caller release failed with ${error});};}onDestroy(): void {try {this.callee.off(MSG_SEND_METHOD);hilog.info(DOMAIN_NUMBER, TAG, %{public}s, Callee OnDestroy);this.releaseCall();} catch (error) {hilog.error(DOMAIN_NUMBER, TAG, %{public}s, Failed to register. Error is ${error});};}
}开发步骤访问Callee被调用端
导入UIAbility模块。
import UIAbility from ohos.app.ability.UIAbility;获取Caller通信接口。 UIAbilityContext属性实现了startAbilityByCall方法用于获取指定通用组件的Caller通信接口。如下示例通过this.context获取UIAbility实例的context属性使用startAbilityByCall拉起Callee被调用端并获取Caller通信接口注册Caller的onRelease监听。应用开发者根据实际需要做相应处理。
import { Caller } from ohos.app.ability.UIAbility;
import { BusinessError } from ohos.base;
import common from ohos.app.ability.common;
import promptAction from ohos.promptAction;
import hilog from ohos.hilog;
import Want from ohos.app.ability.Want;const DOMAIN_NUMBER: number 0xFF00;
const TAG: string [Page_UIAbilityComponentsInteractive];Entry
Component
struct Page_UIAbilityComponentsInteractive {caller: Caller | undefined undefined;// 注册caller的release监听private regOnRelease(caller: Caller): void {hilog.info(DOMAIN_NUMBER, TAG, caller is ${caller});try {caller.on(release, (msg: string) {hilog.info(DOMAIN_NUMBER, TAG, caller onRelease is called ${msg});})hilog.info(DOMAIN_NUMBER, TAG, succeeded in registering on release.);} catch (err) {let code (err as BusinessError).code;let message (err as BusinessError).message;hilog.error(DOMAIN_NUMBER, TAG, Failed to caller register on release. Code is ${code}, message is ${message});};}build() {Button().onClick(() {let context: common.UIAbilityContext getContext(this) as common.UIAbilityContext; // UIAbilityContextlet want: Want {bundleName: com.samples.stagemodelabilityinteraction,abilityName: CalleeAbility,parameters: { // 自定义信息info: CallSendMsg}};context.startAbilityByCall(want).then((caller: Caller) {hilog.info(DOMAIN_NUMBER, TAG, Succeeded in starting ability.Code is ${caller});if (caller undefined) {hilog.info(DOMAIN_NUMBER, TAG, get caller failed);return;}else {hilog.info(DOMAIN_NUMBER, TAG, get caller success);this.regOnRelease(caller);promptAction.showToast({message: $r(app.string.CallerSuccess)});}}).catch((err: BusinessError) {hilog.error(DOMAIN_NUMBER, TAG, Failed to start ability. Code is ${err.code}, message is ${err.message});});})}
}为了能让大家更好的学习鸿蒙HarmonyOS NEXT开发技术这边特意整理了《鸿蒙开发学习手册》共计890页希望对大家有所帮助https://qr21.cn/FV7h05
《鸿蒙开发学习手册》
如何快速入门https://qr21.cn/FV7h05
基本概念构建第一个ArkTS应用…… 开发基础知识https://qr21.cn/FV7h05
应用基础知识配置文件应用数据管理应用安全管理应用隐私保护三方应用调用管控机制资源分类与访问学习ArkTS语言…… 基于ArkTS 开发https://qr21.cn/FV7h05
Ability开发UI开发公共事件与通知窗口管理媒体安全网络与链接电话服务数据管理后台任务(Background Task)管理设备管理设备使用信息统计DFX国际化开发折叠屏系列…… 鸿蒙开发面试真题含参考答案https://qr18.cn/F781PH 鸿蒙开发面试大盘集篇共计319页https://qr18.cn/F781PH
1.项目开发必备面试题 2.性能优化方向 3.架构方向 4.鸿蒙开发系统底层方向 5.鸿蒙音视频开发方向 6.鸿蒙车载开发方向 7.鸿蒙南向开发方向