首页 > 编程笔记 > 通用技能 阅读:268

鸿蒙Want用法详解(附带实例)

在 Stage 模型中,Want 是对象间信息传递的载体,可以用于应用组件间的信息传递。而在 FA 模型中,Intent 是与之有相同概念的类。

Want 的使用场景之一是作为 startAbility 的参数,其中包含了指定的启动目标,以及启动时需携带的相关数据,如 bundleName 和 abilityName 字段分别指明目标 Ability 所在应用的包名以及对应包内的 Ability 名称。当 AbilityA 启动 AbilityB 并需要传入一些数据给 AbilityB 时,Want 可以作为一个数据载体将数据传送给 AbilityB,如下图所示:


图 1 Want用法示意图

Want的类型

Want 的类型主要是分为显式和隐式。

1) 显式Want

在启动 Ability 时指定了 abilityName 和 bundleName 的 Want 称为显式 Want。

当有明确处理请求的对象时,通过提供目标 Ability 所在应用的 bundleName,并在 Want 内指定 abilityName 便可启动目标 Ability。显式 Want 通常在启动当前应用开发中某个已知 Ability 时被用到,示例如下:
import { Want } from '@kit.AbilityKit';

let wantInfo: Want = {
    deviceId: '', // deviceId为空,表示本设备
    bundleName: 'com.example.myapplication',
    abilityName: 'FuncAbility',
}

2) 隐式Want

在启动 Ability 时未指定 abilityName 的 Want 称为隐式 Want。

当需要处理的对象不明确时,可以使用隐式 Want,在当前应用中使用其他应用提供的某个能力,而不关心提供该能力的具体应用。隐式 Want 使用 skills 标签来定义需要使用的能力,并由系统匹配声明支持该请求的所有应用来处理请求。

例如,需要打开一个链接的请求时,系统将匹配所有声明支持该请求的应用,然后让用户选择使用哪个应用打开链接:
import { Want } from '@kit.AbilityKit';

let wantInfo: Want = {
    action: 'ohos.want.action.search',
    entities: [ 'entity.system.browsable'],
    uri: 'https://www.test.com:8080/query/student',
    type: 'text/plain',
};
其中,action 表示调用方要执行的通用操作(如查看、分享、应用详情)。在隐式 Want 中,可定义该字段,配合 uri 或 parameters 来表示对数据要执行的操作(如打开并查看该 uri 数据)。例如,当 uri 为一段网址时,action 为 ohos.want.action.viewData 则表示匹配可查看该网址的 Ability。在 Want 内声明 action 字段表示希望被调用方应用支持声明的操作。在被调用方应用配置文件 skills 字段内声明 actions 表示该应用支持声明操作。

常见的 action 包括:
entities 表示目标 Ability 的类别信息(如浏览器、视频播放器),在隐式 Want 中是对 action 的补充。在隐式 Want 中,开发者可定义该字段,用来过滤匹配应用的类别,例如必须是浏览器。在 Want 内声明 entities 字段表示希望被调用方应用属于声明的类别。在被调用方应用配置文件 skills 字段内声明 entities 表示该应用所支持的类别。

常用的 entities 包括:
所有 action 和 entities 都定义在 wantConstant 模块中。

Want的参数及属性

Want 的参数及属性说明如下表所示。

表:Want的参数及属性说明
名称 读写属性 类型 必填 描述
deviceId 只读 string 否 表示目标 Ability 所在设备 ID。如果未设置该字段,则表明本设备
bundleName 只读 string 否 表示目标 Ability 所在应用名称
moduleName 只读 string 否 表示目标 Ability 所属的模块名称
abilityName 只读 string 否 表示目标 Ability 的名称。如果未设置该字段,则该 Want 为隐式。如果在 Want 中同时指定了 bundleName、moduleName 和 abilityName,则 Want 可以直接匹配到指定的 Ability
uri 只读 string 否 表示携带的数据,一般配合 type 使用,指明待处理的数据类型。如果在 Want 中指定了 uri,则 Want 将匹配指定的 Uri 信息,包括 scheme、schemeSpecificPart、authority 和 path 信息
type 只读 string 否 表示携带数据类型,使用 MIME 类型规范。例如“text/plain”“image/*”等
action 只读 string 否 表示要执行的通用操作(如查看、分享、应用详情)。在隐式 Want 中,可定义该字段,配合 uri 或 parameters 来表示对数据要执行的操作(如打开并查看该 uri 数据)。例如,当uri为一段网址,action 为 ohos.want.action.viewData 则表示匹配可查看该网址的Ability
entities 只读 Array<string> 否 表示目标 Ability 额外的类别信息(如浏览器、视频播放器),在隐式 Want 中是对 action 的补充。在隐式 Want 中可定义该字段,用来过滤匹配 Ability 类别,如必须是浏览器。例如,在 action 字段的举例中,可存在多个应用声明了支持查看网址的操作,其中有应用为普通社交应用,有的为浏览器应用,可通过 entity.system.browsable 过滤掉非浏览器的其他应用
flags 只读 number 否 表示处理 Want 的方式。例如通过 wantConstant.Flags.FLAG_ABILITY_CONTINUATION 表示是否以设备间迁移方式启动 Ability
parameters 只读 {[key: string]: any} 否 此参数用于传递自定义数据,通过用户自定义的值对进行数据填充,具体支持的数据类型如 Want API 所示

Want实例

接下来通过显式 Want 启动应用内一个指定的 Ability 组件。

打开 DevEco Studio,选择一个 Empty Ability 工程模板,创建一个名为“ArkTSWantStartAbility”的工程为演示示例。

1) 新建Ability内页面。初始化工程之后,在原有的代码基础上,需要新建一个页面。在 src/main/ets/pages 目录下,通过右击“New→Page→Empty Page”来新建一个页面,并命名为 Second。

对 Second.ets 文件中的 message 变量值进行修改,最终文件内容如下:
@Entry
@Component
struct Second {
    // 修改变量值为Second
    @State message: string = 'Second';

    build() {
        RelativeContainer() {
            Text(this.message)
                .id('SecondHelloWorld')
                .fontSize(50)
                .fontWeight(FontWeight.Bold)
                .alignRules({
                    center: { anchor: '_container_', align: VerticalAlign.Center },
                    middle: { anchor: '_container_', align: HorizontalAlign.Center }
                })
        }
        .height('100%')
        .width('100%')
    }
}

2) 新建Ability

在原有的代码基础上,需要新建一个 Ability。在 src/main/ets 目录下,右击“New→Ability”新建一个名为“SecondAbility”的 Ability。

创建完成之后,会自动在 module.json5 文件中添加该 Ability 的信息:
{
    "name": "SecondAbility",
    "srcEntry": "./ets/secondability/SecondAbility.ets",
    "description": "$string:SecondAbility_desc",
    "icon": "$media:layered_image",
    "label": "$string:SecondAbility_label",
    "startWindowIcon": "$media:startIcon",
    "startWindowBackground": "$color:start_window_background"
}

此时,在 src/main/ets 目录下会初始化一个 secondability 目录,并在 secondability 目录下生成一个 SecondAbility.ts 文件。修改该文件,将 'pages/Index' 改为 'pages/Second',最终文件内容如下:
onWindowStageCreate(windowStage: window.WindowStage): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

    // 加载second页面
    windowStage.loadContent('pages/Second', (err) => {
        if (err.code) {
            hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
            return;
        }
        hilog.info(0x000, 'testTag', 'Succeeded in loading the content.');
    });
}
上述修改主要是为了当启动 SecondAbility 时,Second 页面能够展示。

3) 使用显式 Want 启动 Ability。在 Index.ets 文件中的 Text 组件上,添加单击事件触发执行启动 Ability。Index.ets 代码修改如下:
// 导入common, Want 从 '@kit.AbilityKit';
import { common, Want } from '@kit.AbilityKit';

@Entry
@Component
struct Index {
    @State message: string = 'Hello World';

    build() {
        RelativeContainer() {
            Text(this.message)
                .id('HelloWorld')
                .fontSize(50)
                .fontWeight(FontWeight.Bold)
                .alignRules({
                    center: { anchor: '_container_', align: VerticalAlign.Center },
                    middle: { anchor: '_container_', align: HorizontalAlign.Center }
                })
                .onClick(this.explicitStartAbility) // 设置单击事件,显示启动Ability
        }
        .height('100%')
        .width('100%')
    }

    // 显示启动Ability
    explicitStartAbility() {
        try {
            // 在启动Ability时指定了abilityName和bundleName
            let want: Want = {
                deviceId: "",
                bundleName: "com.waylau.hmos.arkuwantstartability",
                abilityName: "SecondAbility"
            };

            // 获取UIAbility的上下文信息
            let context = getContext(this) as common.UIAbilityContext;

            // 启动UIAbility实例
            context.startAbility(want);
            console.info('explicit start ability succeed');
        } catch(error) {
            console.info('explicit start ability failed with ${error.code}');
        }
    }
}

4) 运行项目后,初始化界面如下图所示:


图 2 初始化界面

在 Index 页面中,单击“Hello World”文本后,此时启动了 SecondAbility,并展示了 Second 页面,界面效果如下图所示。


图 3 Second页面