diff --git "a/Want\345\274\200\345\217\221\346\214\207\345\215\227.md" "b/Want\345\274\200\345\217\221\346\214\207\345\215\227.md" index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3ee6e7aca0b5efac889cb8bc275d54a165277d91 100644 --- "a/Want\345\274\200\345\217\221\346\214\207\345\215\227.md" +++ "b/Want\345\274\200\345\217\221\346\214\207\345\215\227.md" @@ -0,0 +1,372 @@ +# Want + +## Want的简介 +### Want的定义 + +* Want是对象间传递信息的载体,包含一个请求的内容。 Want最常见使用场景便是用于[Ability](#)间的信息传递。当Ability(A)启动Ability(B)并需要传入一些数据给Ability(B)时,Want可以作为一个数据载体将数据封装传给Ability(B)。Want内含有自定义参数字段,因此Want同样可在需要传递数据信息时使用,如作为函数传参的数据结构体。 + +### Want的用途 + +* Want最重要的使用场景之一便是[startAbility](#),其包含了指定的启动目标,以及启动时需携带的相关数据。如`bundleName`和`abilityName`字段分别指明目标Ability所在应用的**包名**,以及对应包内Ability名称。 + +### Want的类型 + +* **显式Want:** + **指定`abilityName`和`bundleName`的Want称为显式Want**。当有明确处理请求的对象时,通过提供目标Ability所在应用的包名信息,并在Want内提供`abilityName`便可启动目标Ability。显式Want通常在启动当前应用开发中某个已知Ability时被用到。 + +* **隐式Want:** + **当Want未设置`abilityName`时,则为隐式**。当请求处理的对象不明确时,如开发者希望在当前应用中使用其他应用提供的能力,而不关心提供该能力的具体应用,可以使用隐式Want。例如使用隐式Want描述需要打开一个链接的请求,而不关心通过具体哪个应用打开,系统将匹配声明支持该请求的所有应用,当未匹配到时支持的应用时,系统将提示;当存在一个时,系统将自动拉起对应应用;当存在多个时,系统将弹出候选列表,由用户选择。 + +> 显式与隐式Want等更多详细信息可参考[Want匹配规则](#want匹配规则)。 + +## 约束与限制 + +> 由于通过隐式Want启动[Extension](#)存在安全风险,因为开发者无法确定哪些Extension将相应Want,且用户无法看到Extension的启动,因此普通应用不支持通过隐式Want启动Extension。 + + +### 属性说明 + +**系统能力**:以下各项对应的系统能力均为SystemCapability.Ability.AbilityBase + +| 名称 | 读写属性 | 类型 | 必填 | 描述 | +| ----------- | -------- | -------------------- | ---- | ------------------------------------------------------------ | +| deviceId | 只读 | string | 否 | 表示目标Ability所在设备ID。如果未设置该字段,则表明本设备。 | +| bundleName | 只读 | string | 否 | 表示目标Ability所在应用名称。如果在Want中同时指定了bundleName,moduleName和abilityName,则Want可以直接匹配到指定的Ability。 | +| abilityName | 只读 | string | 否 | 表示目标Ability名称。如果未设置该字段,则该Want为隐式。 | +| uri | 只读 | string | 否 | 表示携带的数据,一般配合type使用,指明待处理的数据类型。如果在Want中指定了Uri,则Want将匹配指定的Uri信息,包括[scheme, schemeSpecificPart, authority和path](#)信息。 | +| type | 只读 | string | 否 | 表示携带数据类型,使用[MIME类型](#)规范。比如:"text/plain" 、 "image/*"等。 | +| action | 只读 | string | 否 | 表示要执行的通用操作(如:*查看、分享、应用详情*)。在隐式Want中,您可定义该字段,配合Uri来表示对数据要执行的操作,如*打开*,*查看*该Uri数据。例如,当uri为一段网址,action为`ohos.want.action.viewData`则表示匹配可**查看**该网址的Ability。更多详情可参考[wantConstant.Action](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-ability-wantConstant.md#wantconstantaction)。| +| entities | 只读 | Array\ | 否 | 表示目标Ability额外的类别信息(如:*浏览器,视频播放器*),在隐式Wan中是对action的补充。在隐式Want中,您可定义该字段,来过滤匹配Ability类别,如必须是*浏览器*。例如,在action字段的举例中,可存在多个应用声明了支持查看网址的操作,其中有应用为普通社交应用,有的为浏览器应用,您可通过`entity.system.browsable`过滤掉非浏览器的其他应用。更多详情可参考[wantConstant.Entity](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-ability-wantConstant.md#wantconstantentity)。 | +| flags | 只读 | number | 否 | 表示处理Want的方式。使用时通过[wantConstant.Flags](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-ability-wantConstant.md#wantconstantflags)获取,例如通过`wantConstant.Flags.FLAG_ABILITY_CONTINUATION`表示是否以设备间迁移方式启动Ability。 | +| parameters | 只读 | {[key: string]: any} | 否 | 表示WantParams描述,是一种自定义的数据结构,由开发者自行决定传入的键值对,来传入所需的额外信息。 | +| moduleName9+ | 只读 | string | 否 | 表示目标Ability所属的模块(module)。 | + +以上属性中,`entities,action,uri,type`四个属性主要用于[隐式Want](#want的类型),这些属性通俗的讲定义了**支持对数据类型为`type`的数据`uri`执行`action`操作,且类型为`entities`的Ability**。因以上属性均不是必选参数,每个单独匹配规则可参考[隐式Want匹配原理详解](#隐式want匹配原理详解)。 + +## Want匹配规则 + +#### 显式Want匹配逻辑 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称类型匹配项是否设置规则
deviceIdstringNA可选字段,留空将仅匹配本设备内Ability。
bundleNamestring必选字段,如果指定abilityName,而不指定bundleName,则匹配失败。
moduleNamestringNA可选字段,留空时当同一个应用内存在多个模块且模块间存在重名Ability,将默认匹配第一个。
abilityNamestring必选字段。
uristringNA系统匹配时将忽略该参数,但仍可作为参数传递给目标Ability。
typestringNA
actionstringNA
entitiesArray<string>NA
flagsnumberNA不参与匹配,直接传递给系统处理,一般用来设置运行态信息,比如URI数据授权等。
parameters{[key: string]: any}NA不参与匹配,应用自定义数据将直接传递给目标Ability。
+ +#### 隐式Want匹配逻辑 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称类型匹配项是否设置规则
deviceIdstringNA跨设备目前不支持隐式调用。
abilityNamestringNA 该字段必须留空表示隐式匹配。
bundleNamestringNA 这些字段将用来隐式匹配,系统将匹配出所有支持对的uri进行action操作的应用,并仅保留属于entities内应用类别的应用。 详情可参考 隐式Want匹配原理详解。
moduleNamestringNA
uristringNA
typestringNA
actionstringNA
entitiesArray<string>NA
flagsnumberNA不参与匹配,直接传递给系统处理,一般用来设置运行态信息,比如URI数据授权等。
parameters{[key: string]: any}NA不参与匹配,应用自定义数据将直接传递给目标Ability。
+ +#### 隐式Want匹配原理详解 + +从[隐式Want的定义](#want的类型),可得知: +* 调用方需要表明自己执行的操作,并提供相关数据以及其他应用类型限制。 +* 其他应用需要声明自己具备的能力([skills字段](#))。 + +系统将调用应用传入的Want(包含action,entities,uri和type属性)与其他应用的skills(包含action,entities和uris属性)进行匹配。**当以下四个属性匹配均通过**,则此应用才会被应用选择器展示给用户进行选择。 + +##### action匹配规则: +将其他应用skills信息中的`actions`与调用方want内的`action`进行匹配。 +* 如果skills信息中的actions为空,则匹配失败。 +* 如果skills信息中的actions不为空,且其包含want信息中的action(*不可以为空*),匹配成功;否则匹配失败。 + +##### entities匹配规则: +将其他应用skills信息中的`entities`与调用方want内的`entities`进行匹配。 +* 如果skills信息中的entities为空,则只有当want信息中的entities为空时才匹配通过;否则匹配失败。 +* 如果skills信息中的entities不为空,且其包含want信息中**全部**entities(*可以为空*),匹配成功;否则匹配失败。 + +##### uri匹配规则: +将其他应用skills信息的`uris`中`scheme`,`host`,`port`,`path`,`pathStartWith`和`pathRegex`属性拼接成`uri(scheme://host:port/(path;pathStartWith;pathRegex))`, 将此uri与调用方应用的want信息中的uri进行匹配。其中`path`为*完全路径匹配*,`pathStartWith`为*前缀匹配*,`pathRegex`为*正则匹配*。当存在多个路径声明时,仅一个路径匹配被使用,匹配的优先级为:*完全路径匹配* > *前缀匹配* > *正则匹配*。 + +* 如果skills信息拼接成的uri为空,则只有当want中的uri也为空时才匹配成功;否则匹配失败。 +* 如果skills信息拼接成的uri不为空,且其涵盖want信息中的uri(*不可以为空*),则匹配成功;否则匹配失败。 + +##### type匹配规则: +将其他应用skills信息中`uris`中的`type`与调用方的want中的`type`进行匹配,支持`*`通配符匹配。 + +* 如果skills信息中的type为空,则只有当want信息中的type同样为空时才匹配成功;否则匹配失败。 +* 如果skills信息中的type不为空,其包含want信息中的type(*不可以为空*),则匹配成功;否则匹配失败。 +> 注意:因为`type`是skill信息中`uris`的成员字段,因此需配合uri匹配规则。 + + +## 相关用例 + +### Stage模型下通过按钮使用显式Want启动本应用一个Ability + +* 在应用使用场景中,当用户点击某个按钮时,应用拉起特定组件即Ability来完成某些特定任务是一个非常常见的操作,在本用例中,您将通过显式Want拉起应用内一个指定Ability的操作。注意:*该用例内不存在模块间重名Ability,当您的开发存在此情况,请确保补充want内`moduleName`字段。* + +#### 前提条件 + +1. Stage模型工程内,创建`callerAbility`,与一个页面, 并在`callerAbility`文件内的[onWindowStageCreate](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-application-abilityLifecycleCallback.md#abilitylifecyclecallbackonwindowstageactive)内通过`windowStage.setUIContent`方法将两者绑定。 + ```js + // callerAbility.ts + onWindowStageCreate(windowStage) { + // Main window is created, set main page for this ability + console.log("[Demo] MainAbility onWindowStageCreate") + // Bind callerAbility with a paged named index + windowStage.setUIContent(this.context, "pages/index", null) + } + ``` +2. 同上方法创建`calleeAbility`,与页面,并将其关联。 + +#### 实现 {#Stage模型下通过按钮使用显式Want启动本应用一个Ability实现} + +1. 在`index`页面内新增一个按钮。 + ```js + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + // A new button with will call explicitStartAbility() when clicked. + Button("CLICKME") + .onClick(explicitStartAbility) + .... + ``` + +2. 补充相对应的onClick方法,并使用显式Want在方法内启动`calleeAbility`。在Stage模型下,`bundleName`字段可在工程`AppScope>app.json5`文件内获取;`abilityName`可在对应模块内的`yourModuleName>src>main>module.json5`文件查看。 + ```js + async function explicitStartAbility() { + try { + // Explicit want with abilityName specified. + let want = { + deviceId: "", + bundleName: "com.example.wantdemo", + abilityName: "calleeAbility" + } + await globalThis.context.startAbility(want) + console.info(`explicit start ability succeed`) + } catch (error) { + console.info(`explicit start ability failed with ${error.code}`) + } + } + ``` + > 注意:在Stage模型下,[startAbility](#)为[Ability.context](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-ability-context.md)(上下文)的成员函数, 因此当在对应页面内使用startAbility时,需借助`globalThis`获取对应context。 + +3. 在callerAbility的`onCreate`生命周期函数内设定`globalThis.context`。 + ```js + // callerAbility.ts + onCreate(want, launchParam) { + console.log("[Demo] MainAbility onCreate") + globalThis.abilityWant = want; + globalThis.context = this.context; + } + ``` + +4. 至此,当您点击`CLICKME`按钮时,应看到页面的跳转。 +![startAbilityWithExplicitWant](./assets/startAbilityWtExplicitWant.PNG) + +### FA模型下通过按钮使用显式Want启动本应用一个Ability + +#### 前提条件 + +1. 创建`callerAbility`与`calleeAbility`, 在FA模型下,您无需关注页面的创建和页面与Ability的绑定,工程将自动为您完成。因此Stage模型下的页面绑定,在FA模型下可忽略。 + +2. FA模型下startAbility为[featureAbility](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-featureAbility.md)的成员函数, 因此您同样无需关注上文Stage模型下提及的`globalThis.context`。 + +#### 实现 + +1. 导入模块 + ```js + import featureAbility from '@ohos.ability.featureAbility' + ``` + +2. 与Stage模型下[实现.1](#Stage模型下通过按钮使用显式Want启动本应用一个Ability实现)相同,添加按钮。 + +3. 补充相对应的onClick方法,并使用显式Want在方法内启动`calleeAbility`。在FA模型下,`bundleName`字段可在对应模块文件夹下`yourModuleName>src>main>config.json`文件内获取;同文件下,我们可以找到对应`abilityName`,以及`abilityName`所在`module`字段下的`packageName`。 + > 在FA模型下,显式Want内的`abilityName`字段为`packageName` + `abilityName`。如当config.json内如下时,want内`abilityName`字段仅填写`.PageAbility`将报错。正确的是`com.example.entry.PageAbility`。注意:*packageName并不一定与bundleName相同。* + ```json + "module": { + "mainAbility": ".MainAbility", + "deviceType": [ + "phone", + "tablet" + ], + "abilities": [ + { + "orientation": "unspecified", + "srcPath": "PageAbility", + // abilityName + "name": ".PageAbility", + "srcLanguage": "ets", + ... + }, + ], + ..., + // packageName + "package": "com.example.entry", + ... + } + ``` + 实现`explicitStartAbility`方法。 + ```js + async function explicitStartAbility() { + try { + // Explicit want with abilityName specified. + let param = { + want: { + deviceId: "", + bundleName: "com.example.wantdemo", + // packageName doesn't have to be the same as bundleName. + abilityName: "com.example.entry.calleeAbility" + } + } + await featureAbility.startAbility(param) + console.info(`explicit start ability succeed`) + } catch (error) { + console.info(`explicit start ability failed with ${error.code}`) + } + } + ``` \ No newline at end of file diff --git a/assets/startAbilityWtExplicitWant.PNG b/assets/startAbilityWtExplicitWant.PNG new file mode 100644 index 0000000000000000000000000000000000000000..1d9e25f148d08a58a0ac45b703e08072f52fc300 Binary files /dev/null and b/assets/startAbilityWtExplicitWant.PNG differ