【学习目标】
- 理解 Want 本质:掌握 Want 作为组件间信息传递载体的核心作用,明确显式/隐式 Want 的划分与适用场景;
- 掌握显式启动:精通跨应用通过
bundleName+abilityName精准启动组件; - 掌握隐式启动:吃透
linkFeature、action、entities、uri、type的完整层级匹配规则; - 数据传递与校验:规范使用
parameters传递数据,合理运用功能标识实现精准匹配。
【内容铺垫】
在 HarmonyOS 中,Want 是组件(Ability/Extension)间交互的标准信息载体,核心用于描述"操作目标""操作意图"和"附加数据",是应用内/跨应用组件通信的核心桥梁。无论是应用内页面跳转、跨应用功能调用(如打开文档、分享内容),本质都是通过传递 Want 对象实现的。
在之前的章节中,我们已多次使用 Want 实现 Ability 拉起操作,本节将所有 Want 核心能力直接在 Index 页演示,无需额外跳转页面。
核心规范提示:从 API 12 开始,已不再推荐三方应用使用指定 Ability 方式(即显式 Want)拉起其他应用,推荐使用指定应用链接方式(下一节讲),但作为开发者,我们仍需掌握显式/隐式 Want 的核心原理,以便应对各类组件通信场景。
示意图如下:
一、Want 核心概念与结构
Want 是对象类型,核心字段决定组件匹配与启动逻辑,关键字段及约束如下:
1. 核心字段解析
| 字段名 | 类型 | 核心作用 | 必选性 | 核心说明 |
|---|---|---|---|---|
deviceId |
string | 目标设备ID | 否 | 空字符串表示本机,跨设备场景需指定设备标识;隐式 Want 暂不支持跨设备调用 |
bundleName |
string | 目标应用包名 | 显式必选 | 显式 Want 必须指定 |
abilityName |
string | 目标组件名称 | 显式必选 | 显式 Want 核心字段;API 12+ 跨应用场景不推荐使用 |
moduleName |
string | 目标模块名称 | 否 | 同一应用多模块存在重名组件时,需指定,否则默认匹配第一个模块 |
uri |
string | 统一资源标识符 | 隐式可选 | 格式为 scheme://host:port/path;自定义 scheme 不可与系统应用重复(如 ohos 前缀) |
action |
string | 操作意图 | 隐式核心 | 常用值:ohos.want.action.viewData(查看数据)、ohos.want.action.share(分享)、ohos.want.action.search(搜索) |
entities |
Array | 组件类别约束 | 隐式可选 | 常用值:entity.system.browsable(浏览器类组件)、entity.system.home(桌面应用) |
type |
string | 数据MIME类型 | 隐式可选 | 如 text/plain(纯文本)、image/png(PNG图片),需与 uri 协同匹配 |
parameters |
Object | 自定义附加数据 | 否 | 支持基础数据类型(字符串、数字、布尔值等);可通过 linkFeature 字段标记功能类型(隐式匹配最高优先级) |
flags |
number | 启动模式标记 | 否 | 仅 FLAG_START_WITHOUT_TIPS 支持隐式 Want 取消"暂无可用打开方式"弹框;无法取消"是否允许跳转"系统弹框 |
2. Want 的两种核心类型
- 显式 Want :同时指定
bundleName和abilityName,直接定位目标组件,无需系统遍历匹配,匹配效率高、无系统开销。 - 隐式 Want :不指定
abilityName,通过linkFeature、action、entities、uri、type描述操作意图,由系统匹配声明对应skills的组件,适用于跨应用通用功能调用(如调用系统分享、打开浏览器)。
3. 隐式 Want 匹配规则(核心重点)
(1)匹配基础前提
隐式 Want 匹配的基础前提:若 action/entities/uri/type/parameters(linkFeature) 五个属性均未配置,系统直接判定匹配失败,无需后续校验。
(2)匹配优先级(从高到低)
linkFeature(parameters 内置字段) → action → entities → uri + type
linkFeature是 HarmonyOS API 11+ 新增的最高优先级匹配字段,通过parameters传递,专门解决传统隐式匹配范围过宽的问题,适用于跨应用固定功能的精准隐式调用。
(3)分步详细规则
表格中 action 值如 abc 仅为表达匹配,工程中取值要规范。
① linkFeature 匹配(最高优先级)
核心匹配字段及校验逻辑(精准匹配为唯一规则)
| 校验字段 | 触发校验条件 | 匹配规则 | 失败判定 |
|---|---|---|---|
| linkFeature | 调用方传该参数则必校验 | 需与 skills 配置值完全一致 | 配置值≠调用方值(如 link≠errLink) |
| scheme(URI) | 调用方传 uri 则必校验 scheme | 需与 uri 的 scheme 完全一致 | scheme≠uri 的 scheme(如 https≠file) |
| type | 调用方传 type 则必校验 | 需与调用方 type 完全一致 | type≠调用方值(如 text/plain≠image/png) |
分场景匹配规则
- 场景1(仅传 linkFeature):仅校验 linkFeature,scheme/type 不参与,一致则成功,否则失败;
- 场景2(传 uri+linkFeature):需同时满足 scheme 匹配 + linkFeature 匹配,任一不满足则失败;
- 场景3(传 type+linkFeature):需同时满足 type 匹配 + linkFeature 匹配,任一不满足则失败;
- 场景4(传 uri+type+linkFeature):需同时满足 scheme 匹配 + type 匹配 + linkFeature 匹配,任一不满足则失败。
补充说明
- 无通配符、前缀匹配等宽松规则,所有参与校验的字段均为精准完全匹配;
- 调用方未传的字段(如 uri/type),skills 中对应字段不参与校验;
- 无"部分匹配""降级匹配"逻辑,任一需校验字段不匹配则整体失败。
② action 匹配规则
调用方 want 的 action |
目标方 skills.actions |
匹配结果 | 核心说明 |
|---|---|---|---|
空值 action:"" |
空值 actions: [] |
失败 | 双方均未声明操作意图,系统无法匹配 |
空值 action:"" |
非空值 actions: ["abc"] |
成功 | 调用方未指定意图,目标方声明了能力,默认匹配 |
非空值 action:"abc" |
空值 actions: [] |
失败 | 调用方指定了意图,目标方未声明对应能力 |
非空值 action:"abc" |
包含调用方 actions: ["abc"] |
成功 | 目标方声明的能力包含调用方意图 |
非空值 action:"abc" |
不包含调用方 actions: ["bcd"] |
失败 | 目标方未声明调用方所需能力 |
③ entities 匹配规则
调用方 entities |
目标方 skills.entities |
匹配结果 | 核心说明 |
|---|---|---|---|
空(entities: []) |
非空(entities: ["a","b"]) |
成功 | 调用方未限定组件类别,目标方无论是否声明类别均匹配 |
空(entities: []) |
空(entities: []) |
成功 | 调用方未限定组件类别,目标方无论是否声明类别均匹配 |
非空(entities: ["a"]) |
空(entities: []) |
失败 | 调用方限定了组件类别,目标方未声明任何类别 |
非空(entities: ["a","b"]) |
包含所有调用方(entities: ["a","b","c"]) |
成功 | 目标方声明的类别完全包含调用方需求 |
非空(entities: ["a","b"]) |
未包含所有调用方(entities: ["a","c"]) |
失败 | 目标方声明的类别缺失调用方所需类别(如调用方要 browsable,目标方仅声明 home) |
④ uri + type 匹配规则(协同校验)
| 场景 | 调用方配置 | 匹配规则 |
|---|---|---|
| 场景1 | uri 空 + type 空 | 1. 目标方 skills.uris 为空 → 成功; 2. 目标方 skills.uris 存在「scheme 和 type 均空」的元素 → 成功; 3. 其他情况 → 失败 |
| 场景2 | uri 非空 + type 空 | 1. 目标方 skills.uris 为空 → 失败; 2. 目标方 skills.uris 存在「uri 匹配 + type 空」的元素 → 成功; 3. 前两步失败且 uri 为文件路径 → 按后缀推导 MIME 类型,匹配目标方 type → 成功/失败 |
| 场景3 | uri 空 + type 非空 | 1. 目标方 skills.uris 为空 → 失败; 2. 目标方 skills.uris 存在「scheme 空 + type 匹配」的元素 → 成功; 3. 其他情况 → 失败 |
| 场景4 | uri 非空 + type 非空 | 1. 目标方 skills.uris 为空 → 失败; 2. 目标方 skills.uris 存在「uri 匹配 + type 匹配」的元素 → 成功; 3. 其他情况 → 失败 |
Type 单独匹配规则(仅调用方 type 非空时生效)
Type 匹配核心为 MIME 媒体类型匹配,遵循 HarmonyOS 官方规范,无降级匹配逻辑,规则如下:
- 精准匹配(最高优先级) :调用方
type与目标方skills.uris中type完全一致 → 匹配成功; - 通配符匹配 :仅支持「主类型/*」格式,目标方
type为此格式且调用方type属于该主类型范畴 → 成功;不支持*/子类型格式; - 匹配失败场景 :
- 目标方
type为具体值但与调用方type不一致; - 目标方
type通配符格式不规范; - 调用方
type为复合 MIME 类型,目标方无对应配置。
- 目标方
补充说明:Type 匹配仅在「调用方传递 type」且「进入 uri+type 协同校验环节」时触发;若目标方
type为空,仅当调用方type也为空时匹配成功。
uri 匹配规则
URI 匹配以 scheme → host → port → 路径 为核心层级,仅当前一级匹配通过时触发下一级校验,任一层级失败则整体 URI 匹配失败,具体规则:
- scheme 层级(首验层级) :
- 目标 URI 项
scheme为空 → 仅调用方uri为空时匹配成功,否则失败; - 目标 URI 项
scheme非空 → 调用方uri的scheme需与其完全一致(大小写敏感,官方建议全小写),否则失败。
- 目标 URI 项
- host 层级(仅 scheme 匹配成功后触发) :
- 目标 URI 项
host为空 → 直接匹配成功; - 目标 URI 项
host非空 → 调用方uri的host需与其完全一致,否则失败。
- 目标 URI 项
- port 层级(仅 scheme+host 匹配成功后触发) :
- 目标 URI 项
port为空 → 直接匹配成功; - 目标 URI 项
port非空 → 调用方uri的port需与其完全一致(数字格式),否则失败。
- 目标 URI 项
- 路径层级(仅 scheme+host+port 匹配成功后触发) :
按path → pathStartWith → pathRegex优先级校验,任一规则匹配成功则终止校验,全部失败则 URI 匹配失败:- path 精准匹配 :目标 URI 项
path非空 → 调用方uri全路径与其完全一致 → 成功,否则进入下一级; - pathStartWith 前缀匹配 :目标 URI 项
pathStartWith非空 → 调用方uri路径包含该前缀 → 成功,否则进入下一级; - pathRegex 正则匹配 :目标 URI 项
pathRegex非空 → 调用方uri路径符合该正则表达式 → 成功,否则 URI 匹配失败; - 路径字段均为空 :目标 URI 项
path、pathStartWith、pathRegex均为空 → 直接匹配成功。
- path 精准匹配 :目标 URI 项
补充说明:
- 最左 URI 匹配:仅当目标 URI 项仅配置
scheme/scheme+host/scheme+host+port(路径字段均为空)时生效,调用方uri需以目标配置为前缀;- 文件 URI 解析:
file://开头的 URI,系统自动解析文件后缀推导 MIME 类型,用于补充场景2的 type 匹配;- URI 格式规范:自定义
scheme不可与系统内置(ohos/http/https/file)重复。
(4)匹配结果说明
根据系统中待匹配应用组件的匹配情况不同,使用隐式 Want 启动应用组件时会出现以下三种情况:
- 未匹配到满足条件的应用组件:启动失败。
- 匹配到一个满足条件的应用组件:直接启动该应用组件。
- 匹配到多个满足条件的应用组件(UIAbility):弹出选择框让用户选择。
二、本节工程
(一)工程创建
1. 调用方工程:WantAndLinkingDemo
- 基础配置:HarmonyOS 5.0+、API 18+、Stage 模型;
- 核心用途:演示显式/隐式 Want 启动;
- 包名:
com.example.wantandlinkingdemo。
2. 接收方工程:ImplicitReceiverDemo
- 基础配置:HarmonyOS 5.0+、API 18+、Stage 模型;
- 核心用途:作为跨应用显式/隐式启动的目标应用,接收并展示传递的参数;
- 包名:
com.example.implicitreceiverdemo。
(二)调用方工程核心目录结构
WantAndLinkingDemo/ # 项目根目录(Want实战Demo)
├─ AppScope/ # 应用全局配置目录(多模块应用共享)
│ ├─ resources/ # 应用全局资源文件(如全局样式、多语言字符串)
│ └─ app.json5 # 应用级配置文件(应用名称、版本号等)
├─ entry/ # 主模块目录(核心代码所在)
│ ├─ src/
│ │ ├─ main/ # 主代码目录(应用运行的核心代码)
│ │ │ ├─ ets/ # ArkTS代码目录(逻辑实现核心)
│ │ │ │ ├─ entryability/ # 主Ability目录(应用入口)
│ │ │ │ │ └─ EntryAbility.ets # 应用入口Ability(处理启动初始化)
│ │ │ │ └─ pages/ # 主Ability对应的页面目录
│ │ │ │ └─ Index.ets # 核心功能页(整合显式/隐式Want启动所有案例)
│ │ │ ├─ resources/ # 模块级资源目录(页面布局、图片、局部样式)
│ │ │ └─ module.json5 # 模块配置文件(核心!配置skills、exported等)
│ ├─ build-profile.json5 # 模块构建配置文件(编译、打包参数)
│ ├─ hvigorfile.ts # 模块构建脚本(hvigor构建任务配置)
│ ├─ obfuscation-rules.txt # 代码混淆规则文件(发布时加密代码,可选)
│ └─ oh-package.json5 # 模块依赖配置文件(第三方库、工具依赖)
(三)隐式/显示拉起应用传参示例
调用方:WantAndLinkingDemo Index.ets
构造Want数据,演示显式/隐式不同模式拉起应用,通过不同匹配规则。
javascript
import { BusinessError } from '@ohos.base';
import { common, Want, wantConstant } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { promptAction } from '@kit.ArkUI';
const DOMAIN = 0xFF00;
const TAG = 'WantAndLinkingDemo';
@Entry
@Component
struct Index {
// 获取UIAbility上下文
private context = this.getUIContext().getHostContext() as common.UIAbilityContext;
build() {
Column({ space: 15 }) {
// 页面标题
Text('Want 显式/隐式启动实战(匹配规则修正版)')
.fontSize(30)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 30 })
// 1. 显式Want(精准匹配,无规则问题)
Button('1. 显式Want跨应用拉起传参')
.width('80%')
.height(50)
.fontSize(18)
.backgroundColor('#1890ff')
.fontColor('#ffffff')
.onClick(() => {
this.crossAppExplicitStart();
})
// 2. 隐式Want - linkFeature(最高优先级,需精准匹配)
Button('2. 隐式Want-linkFeature匹配(最高优先级)')
.width('80%')
.height(50)
.fontSize(18)
.backgroundColor('#1890ff')
.fontColor('#ffffff')
.onClick(() => {
this.implicitStartShare();
})
// 3. 隐式Want - action单独匹配(核心:仅传action,无其他干扰字段)
Button('3. 隐式Want-action单独匹配')
.width('80%')
.height(50)
.fontSize(18)
.backgroundColor('#1890ff')
.fontColor('#ffffff')
.onClick(() => {
this.implicitStartActionMatch();
})
// 4. 隐式Want - entities单独匹配
Button('4. 隐式Want-entities单独匹配')
.width('80%')
.height(50)
.fontSize(18)
.backgroundColor('#1890ff')
.fontColor('#ffffff')
.onClick(() => {
this.implicitStartEntitiesMatch();
})
// 5. 隐式Want - uri+type协同匹配(核心:仅传uri+type,配通用action)
Button('5. 隐式Want-uri+type协同匹配')
.width('80%')
.height(50)
.fontSize(18)
.backgroundColor('#1890ff')
.fontColor('#ffffff')
.onClick(() => {
this.implicitStartUriTypeMatch();
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor('#f5f5f5')
}
/**
* 场景1:显式Want
* 规则:指定bundleName+abilityName,无需匹配skills,仅需接收方设置 exported=true
*/
private async crossAppExplicitStart() {
try {
const want: Want = {
bundleName: "com.example.implicitreceiverdemo", // 接收方包名(必须与实际一致)
abilityName: "EntryAbility", // 接收方组件名(必须与实际一致)
parameters: {
"shareContent": "显式Want测试:跨应用精准传递内容",
"linkFeature": "Explicit"
}
};
await this.context.startAbility(want);
hilog.info(DOMAIN, TAG, "显式Want跨应用拉起成功");
} catch (err) {
const businessErr = err as BusinessError;
promptAction.showToast({
message: `启动失败:${businessErr.message}`,
duration: 3000
});
}
}
/**
* 场景2:隐式Want - linkFeature(最高优先级)
* 规则:uri和type均为空时,仅校验linkFeature精准匹配
* 规则:uri或type不为空时,需同时满足linkFeature精准匹配 + uri的scheme匹配 + type精准匹配
*/
private async implicitStartShare() {
const want: Want = {
uri: "data://com.example.wantandlinkingdemo/share/text", // scheme/host需匹配
type: "text/plain", // 必须精准匹配
parameters: {
shareContent: "隐式Want测试:linkFeature匹配成功!",
linkFeature: "Share" // 最高优先级,接收方必须精准配置
},
};
try {
await this.context.startAbility(want);
hilog.info(DOMAIN, TAG, "隐式Want(linkFeature)跨应用拉起成功");
} catch (error) {
const businessErr = error as BusinessError;
hilog.error(DOMAIN, TAG, `linkFeature匹配失败:${businessErr.message}`);
promptAction.showToast({
message: '启动失败,未匹配到支持分享的应用',
duration: 3000
});
}
}
/**
* 场景3:隐式Want - action单独匹配
* 规则:调用方action需匹配接收方skills中的action配置
*/
private async implicitStartActionMatch() {
const want: Want = {
action: 'ohos.want.action.viewData',
parameters: {
"shareContent": "隐式Want测试:action匹配成功!",
}
};
try {
await this.context.startAbility(want);
hilog.info(DOMAIN, TAG, "隐式Want(action)跨应用拉起成功");
} catch (error) {
const businessErr = error as BusinessError;
hilog.error(DOMAIN, TAG, `action匹配失败:${businessErr.message}`);
promptAction.showToast({
message: '启动失败,未匹配到支持查看数据的应用',
duration: 3000
});
}
}
/**
* 场景4:隐式Want - entities匹配
* entities匹配规则:调用方传递的所有entities值,需被目标方skills.entities完全包含才匹配成功(本示例为"abc")
* 系统标准值参考:entity.system.browsable(浏览器类别,处理网页链接)、entity.system.home(应用主入口组件)
*/
private async implicitStartEntitiesMatch() {
const want: Want = {
action: 'ohos.want.action.viewData', // 查看数据
entities: ["abc"],
parameters: {
"shareContent": "隐式Want测试:entities匹配成功!",
}
};
try {
await this.context.startAbility(want);
hilog.info(DOMAIN, TAG, "隐式Want(entities)跨应用拉起成功");
} catch (error) {
const businessErr = error as BusinessError;
hilog.error(DOMAIN, TAG, `entities匹配失败:${businessErr.message}`);
promptAction.showToast({
message: '启动失败,未匹配到浏览器类应用',
duration: 3000
});
}
}
/**
* 场景5:隐式Want - uri+type协同匹配
* 核心:需同时满足uri层级匹配(scheme→host→port→路径) + type精准匹配
*/
private async implicitStartUriTypeMatch() {
const want: Want = {
action: 'ohos.want.action.viewData',
uri: "data://com.implicitreceiverdemo:8080/detail/page123",
type: "text/plain",
flags: wantConstant.Flags.FLAG_START_WITHOUT_TIPS // 取消失败弹窗提示
};
try {
await this.context.startAbility(want);
hilog.info(DOMAIN, TAG, "隐式Want(uri+type)跨应用拉起成功");
} catch (error) {
const businessErr = error as BusinessError;
hilog.error(DOMAIN, TAG, `uri+type匹配失败:${businessErr.message}`);
promptAction.showToast({
message: '启动失败,未匹配到符合uri+type规则的应用',
duration: 3000
});
}
}
}
(2)接收方:ImplicitReceiverDemo
跨应用接收调用方Want传递的参数(拉起组件内Ability接收参数同理,本节不做示例演示)
javascript
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { ConfigurationConstant } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
const DOMAIN = 0x0000;
const TAG = 'ImplicitReceiverDemo';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
hilog.info(DOMAIN, TAG, '%{public}s', 'ImplicitReceiverDemo onCreate 触发');
try {
// 解析 Want 中的参数(显式传递的 data + 隐式传递的 shareContent)
const parameters = want.parameters as Record<string, Object>;
// 存储参数到 AppStorage,供 UI 页面展示(默认值避免空显示)
AppStorage.setOrCreate("shareContent", parameters["shareContent"] || '未接收分享数据');
// 设置应用颜色模式(可选,保持系统默认)
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
} catch (err) {
hilog.error(DOMAIN, TAG, 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
}
}
/**
* 已启动时接收新的 Want 参数(如隐式启动多次触发)
*/
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
hilog.info(DOMAIN, TAG, '%{public}s', 'ImplicitReceiverDemo onNewWant 触发');
const parameters = want.parameters as Record<string, Object>;
// 更新参数(实时同步到 UI 页面)
AppStorage.setOrCreate("shareContent", parameters["shareContent"] || '未接收分享数据');
// 打印接收的参数
console.log(`ImplicitReceiverDemo 接收参数:${JSON.stringify(want.parameters)}`);
}
/**
* 加载 UI 页面
*/
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, TAG, 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
hilog.info(DOMAIN, TAG, 'Succeeded in loading the content: Index');
});
}
}
② 接收方:Index.ets(展示跨应用接收的参数)
javascript
@Entry
@Component
struct Index {
@StorageProp('shareContent') shareContent: string = '隐式/显式分享数据未接收';
build() {
Column({ space: 20 }) {
Text('ImplicitReceiverDemo(参数接收)')
.fontSize(25)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Text(`接收的内容:${this.shareContent}`)
.fontColor(Color.Red)
.fontSize(18)
.textWrap(true)
.padding(10)
}.justifyContent(FlexAlign.Center)
.height('100%')
.width('100%')
.padding(20)
}
}
③ 接收方:module.json5配置
json
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"phone"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true, // 必须开启:允许外部应用调用(显式/隐式均需)
"skills": [
{
// 基础技能:桌面应用(默认配置)
"entities": ["entity.system.home"],
"actions": ["ohos.want.action.home"]
},
// 场景2:linkFeature匹配规则
{
"uris": [
{
"scheme": "data",
"host": "com.example.wantandlinkingdemo",
"type": "text/plain",
"linkFeature": "Share"
}
]
},
// 场景3:action单独匹配规则
{
"actions": ["ohos.want.action.viewData"]
},
// 场景4:entities单独匹配规则
{
"actions": ["ohos.want.action.viewData"],
"entities": ["abc"]
},
// 场景5:uri+type协同匹配规则
{
"actions": ["ohos.want.action.viewData"],
"uris": [
{
"scheme": "data", // 协议必须完全一致
"host": "com.implicitreceiverdemo", // 域名需完整匹配
"port": "8080", // 端口不可省略
"path": "detail/page123", // 路径需完全一致或使用通配符
"type": "text/plain" // MIME类型需严格匹配
}
]
}
]
}
],
"extensionAbilities": [
{
"name": "EntryBackupAbility",
"srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
"type": "backup",
"exported": false,
"metadata": [
{
"name": "ohos.extension.backup",
"resource": "$profile:backup_config"
}
]
}
]
}
}
运行结果
四、开发核心规范与避坑指南
1. 核心约束
- 所有对外提供调用的 Ability(显式/隐式),必须在
module.json5中配置exported: true,否则无法被外部调用; - 自定义 scheme 不可与系统内置 scheme(如
ohos、http、https、file)重复,建议采用"应用标识+功能"命名(如harmonydemo); - 隐式 Want 若使用
linkFeature匹配,actions字段可忽略;使用action/entities/uri+type匹配时,对应字段不可为空。
2. 避坑指南
| 问题现象 | 排查/解决方法 |
|---|---|
| 隐式启动匹配失败 | 检查 linkFeature、action、entities、uri、type 是否与接收方配置一致,尤其是 scheme、host 大小写(建议全小写); |
| 参数传递失败 | 确保传递的参数为基础数据类型(避免传递复杂对象),接收方通过 want.parameters 解析时需做类型断言; |
| 跨应用显式启动失败 | 确认目标应用已安装、bundleName 和 abilityName 配置正确,且目标 Ability 已设置 exported: true; |
| uri 匹配失败 | 按 scheme→host→port→路径 层级逐一校验,路径匹配优先精准匹配,前缀/正则匹配需确保规则正确。 |
五、内容总结
- 核心载体:Want 是组件间通信的核心载体,显式 Want 用于跨应用精准启动,隐式 Want 用于跨应用通用功能调用;
- 隐式匹配规则:按
linkFeature→action→entities→uri+type优先级校验,前序字段匹配失败则整体失败,所有参与匹配的字段均为精准匹配(uri路径除外); - 配置关键:对外调用的 Ability 需设
exported: true,隐式启动需保证调用方 Want 字段与接收方skills配置完全一致; - 实践原则:按场景选择匹配规则,重视异常处理和用户体验,遵循 API 12+ 规范(优先使用应用链接替代显式 Want)。
六、代码仓库
- 调用方工程:WantAndLinkingDemo
- 接收方工程:ImplicitReceiverDemo
- 仓库地址:https://gitee.com/HarmonyOS-UI-Basics/harmony-os-ui-basics.git
七、下节预告
下一节我们将学习 Deep Linking 与 App Linking 应用链接 的完整配置与调用,重点包括:
- 掌握 Deep Linking 自定义 scheme 配置、
openLink调用及canOpenLink校验; - 掌握 App Linking HTTPS 域名配置、域名校验、参数解析及未安装应用的降级处理;
- 明晰 Deep Linking 与 App Linking 的安全性、适用场景核心差异,能按需选型;
- 掌握应用链接与 Want 结合的最佳实践,实现跨应用通信的解耦与高安全性。