确定要实现的应用内功能和内置 intent (BII) 后,需要在 Android 应用中创建将 BII 映射到应用功能的 actions.xml
资源。actions.xml
中定义的与应用有关的 Action 说明了每个 BII 如何解析其执行方式,以及提取的并提供给应用的参数。
概览
如需集成 Android 应用和与应用有关的 Action,必须在应用项目的 res/xml
目录中放置一个 actions.xml
文件。
使用 <meta-data>
标记在 AndroidManifest.xml
文件中添加对 actions.xml
文件的引用。例如:
<application> <!-- ... --> <meta-data android:name="com.google.android.actions" android:resource="@xml/actions" /> </application>
这会为 APK 中的 xml/actions.xml
文件声明一个 XML 资源。如需详细了解如何在 Android 中指定资源,请参阅 Android 开发者文档中的应用资源概览。
架构
下表列出了 actions.xml
的架构。添加标记时,需要提供除标记为可选的属性之外的所有属性。
标记 | 包含于 | 属性 |
---|---|---|
<actions> |
顶层 | |
<action> |
<actions> |
|
<parameter> |
<action> |
name |
<entity-set-reference> |
<parameter> |
|
<fulfillment> |
<action> |
|
<parameter-mapping> |
<fulfillment> |
|
<entity-set> |
<actions> |
entitySetId |
<entity> |
<entity-set> |
|
标记说明
本部分将介绍 actions.xml
的各种架构标记。
<action>
应用支持的与应用有关的 Action。对于 actions.xml
文件中的每个 <action>
标记,必须至少提供一个 <fulfillment>
。
属性:
intentName
:与应用有关的 Action 的内置 intent(例如actions.intent.CREATE_TAXI_RESERVATION
)。如需查看受支持的内置 intent 的列表,请参阅内置 intent 参考文档。queryPatterns
:用户预期会对此 intent 执行的一系列查询。此属性仅适用于自定义 intent,因为 BII 已包含用户表达尝试执行的任务或尝试搜索的信息的常见方式模型。
<parameter>
与应用有关的 Action 的一个参数,该参数具有一个名称和一系列关联的 entity。
属性:
name
:要与此参数关联的名称(例如“destination”)。该名称可以是该参数的叶级字段(例如tradeOrder.assetOrdered.assetIssuedBy.name
)。如果该参数是基元类型(例如字符串),那么该名称就是该参数的名称本身。
<entity-set-reference>
引用开发者提供的 schema.org Feed。必须使用 <entity-set>
标记直接在 actions.xml
文件中提供 Feed。
属性:
entitySetId
:对特定 entity 集合的引用。此属性必须对应于<entity-set>
标记中的一个entitySetId
。urlFilter
:为执行方式提供网站目录时使用的网址路径。此属性支持两种通配符:*
:星号匹配由前面紧挨字符的零到多个重复项所组成的序列。.*
:英文句点后跟星号匹配由零到多个字符构成的任意序列。只有文字
*
和\
才需要转义字符,它们可以分别转义为\\*
和\\\\
。
<fulfillment>
有关如何使用 Android 应用执行用户 intent 的信息。开发者可以在 actions.xml
中提供多个 <fulfillment>
标记,为每个 intent 提供一组不同的必需参数。
Google 会使用第一个 <fulfillment>
,该 <fulfillment> 的所有必需参数都可用于执行用户查询。您必须提供一个不带任何必需参数的 <fulfillment>
作为回退执行方式。
属性:
urlTemplate
:用于构建要在设备上打开的深层链接或 Slice URI 的模板。如果提供了该模板的所有必需参数,则可使用用户 intent 的参数展开该模板。如需查看 HTTP 网址模板示例,请参阅关于网址模板的维基百科文章。模板格式遵循 RFC 6570 URI 模板规范。fulfillmentMode
:(可选)用于服务的执行方式模式。有效值包括:actions.fulfillment.DEEPLINK
:通过使用深层链接打开 Android 应用来执行用户操作。这是默认值。actions.fulfillment.SLICE
:通过嵌入 Android 应用提供的 Slice 来执行用户操作。
requiredForegroundActivity
:(可选)对于要通过前台应用调用触发的与应用有关的 Action,这表示必须在前台运行的 activity。- 请按以下方式指定不带任何类缩写的 activity:使用应用软件包名称后跟正斜杠 (
/
) 和 activity 名称:APP_PACKAGE_NAME/ACTIVITY_NAME
- 请按以下方式指定不带任何类缩写的 activity:使用应用软件包名称后跟正斜杠 (
以下是网址模板值的一些示例:
模板 | 值 | 展开值 |
---|---|---|
https://example.com/test{?someValue,anotherValue} |
"someValue": "123"
|
https://example.com/test?someValue=123&anotherValue=456 |
https://example.com/test?utm_campaign=appactions{&someValue,anotherValue} |
"someValue": "123"
|
https://example.com/test?utm_campaign=appactions&someValue=123&anotherValue=456 |
https://example.com/test?utm_campaign=appactions{#someValue} |
"someValue": "123" |
https://example.com/test?utm_campaign=appactions#someValue=123 |
myapp://example/{someValue} |
"someValue": "123" |
myapp://example/123 |
intent://example#Intent;scheme=my-scheme{;S.extra1,S.extra2};end |
"S.extra1": "123"
|
intent://example#Intent;scheme=my-scheme;S.extra1=123;S.extra2=456;end |
如需详细了解如何配置网址模板,请参阅执行方式中的网址模板。
<parameter-mapping>
从 intent 参数映射到网址模板中的变量。此映射中的键表示网址模板参数或“变量”(如 RFC 6570 中所述)。
对于未包含在 intent 中的参数,相应的变量在网址模板展开时保持未定义状态。如需了解未定义变量的处理方式,请参阅 RFC 6570 第 3.2.1 节。
请注意,required="true"
和 entityMatchRequired="true"
是不同的。
属性:
urlParameter
:网址模板中提及的每个变量都必须在<parameter-mapping>
中有对应的urlParameter
。例如,如果 uri_template 为http://spysatellite.com/show{?lat,long}
,则<parameter-mapping>
中必须有参数lat
和long
的键。intentParameter
:该属性的值引用 intent 参数。如果 intent 参数是结构化类型,请使用点表示法来引用嵌套字段。例如,如果存在类型为schema.org/TaxiReservation
的参数taxiReservation
,则可以使用taxiReservation.pickupLocation.geo.latitude
来引用纬度值。如果为该参数提供 entity 集,则
intentParameter
必须与对应的<parameter>
标记的名称完全匹配(例如,taxiReservation.pickupLocation.geo.latitude
)。如果 intent 参数具有复杂类型,则其值会与参数的对象引用相对应(例如,
taxiReservation
)。如果 intent 参数具有基元类型,则其值为参数名称本身。required
:(可选)表示必须存在给定intentParameter
,此网址模板才能有效。如果用户查询不包含给定intentParameter
的值,网址模板会被丢弃。entityMatchRequired
:(可选)表示必须存在给定intentParameter
的目录匹配项。默认为false
。当此属性设为
true
时,如果存在目录匹配项,系统会将该匹配项的标识符传递给网址模板。否则,如果没有匹配项,Google 助理会跳过该执行方式。当此属性设为
false
时,如果存在目录匹配项,系统会将该匹配项的标识符传递给网址模板。否则,Google 助理会提供从用户查询中提取的 BII 参数值。
<entity-set>
actions.xml
中的内嵌 entity 集。
属性:
entitySetId
:actions.xml
中<entity-set>
的唯一标识符(例如"myInlineEntitySet1"
),该值是必需的。此外,该值还必须与<entity-set-reference>
标记中的<entitySetId>
值相对应。entitySetId
的值最多只能包含 30 个字母数字字符(不能包含-
或_
等特殊字符),并且必须以字母开头。
<entity>
actions.xml
中内嵌的一组 entity 中的一个。包含一部分 schema.org/Thing
字段。
url
、identifier
和 sameAs
字段的字符串值可以硬编码,也可以使用 APK 的字符串资源进行引用。提供同义词时,请为 alternateName
字段使用引用 APK 的字符串数组资源的字符串值。
属性:
name
:entity 的名称,除非指定了sameAs
字段,否则必须提供该值。对于给定的<entity-set>
(例如,“toothpaste”),entity 的name
和alternateName
字段的值必须不同。alternateName
:(可选)entity 的备用名称。必须先指定name
字段,再指定alternateName
字段。对于给定的<entity-set>
,entity 的name
和alternateName
字段的值必须不同。只要用户的查询与这些字符串之一匹配,就会选择该 entity。sameAs
:明确标识 entity 的参考网页的网址。当且仅当 intent 参数类型是schema.org/Enumeration
的子类型时,才用于指定枚举值。对于类型为
schema.org/Enumeration
的子类型的参数字段(例如MealTypeBreakfast
),必需提供该属性。identifier
:entity 的标识符。对于给定的<entity-set>
,其中各个 entity 的标识符必须不同(例如CAPPUCCINO_ID
)。url
:要在 Android 设备上打开的 RFC 3986 网址。该网址可能无法由 HTTP 客户端解析。例如,在 Android 上,该网址可以是链接应用的“http://”网址或设备专用网址,例如“intent://”网址或自定义网址架构中的网址。您可以通过以下方式将
url
字段与<fulfillment>
的urlTemplate
属性结合使用:在内嵌目录中提供
url
值,而在<fulfillment>
中省略urlTemplate
。在内嵌目录中提供
url
值,并在urlTemplate
值中使用这些值(例如{@url}?extra_param=ExampleValue
)。
必须提供 identifier
或 url
。给定 entity 集中的所有 entity 都必须使用相同的属性(identifier
或 url
)。
与应用有关的 Action 的内嵌目录
对于某些内置 intent,可以选择性地将 entity 提取引导到 actions.xml
中指定的一组受支持 entity(称为内嵌目录)。当用户调用您的与应用有关的 Action 时,Google 助理会将用户查询参数与指定为内嵌目录的 entity 进行匹配。然后,Google 助理就可以使用与目录项对应的标识符来为执行方式生成深层链接。
您将主要使用 <entity-set>
和 <entity>
元素定义内嵌目录。内嵌目录可让您的应用仅处理来自与应用有关的 Action 调用的标识符或网址,而无需识别字符串或 Google 枚举值,从而可以简化开发。
例如,您的应用提供用户可以订购的不同饮料,您希望用户针对同种类型的饮料发出以下请求:
Hey Google, order a Blueberry Crisp Iced Signature Latte from Example App.
Hey Google, order a Blueberry Iced Coffee from Example App.
在内嵌目录中,将“Blueberry Crisp Iced Signature Latte”指定为与标识符 12345a
对应的 entity。此外,还将“Blueberry Iced Coffee”指定为与同一标识符对应的 entity。现在,当用户通过上述查询触发与应用有关的 Action 时,Google 助理就可以使用标识符 12345a
为执行方式生成深层链接。
可以为每个应用的所有 entity 集指定最多 1000 个 entity。每个 <entity>
最多可以定义 20 个 alternateName
同义词值。
与应用有关的 Action 的网站目录
对于某些内置 intent,可以使用网站目录为执行方式生成网址。网站目录会使用您的网站为与应用有关的 Action 执行方式发现网址。当您的网上曝光度较高且应用内深层链接围绕公开提供的网页内容整理结构时,此功能最为有用。
如需使用网站目录,请更新您的 actions.xml
:
在要使用网站目录的
<action>
标记中,添加<fulfillment>
标记并将其urlTemplate
属性设为{@url}
。在同一
<action>
标记中,添加一个<parameter>
标记,并将其name
属性设为与您的网页所描述的 entity 最贴近的内置 intent 参数。例如,在为ORDER_MENU_ITEM
提供网站目录时,将菜单页面链接到menuItem.name
,并将餐厅位置页面链接到menuItem.inMenuSection.inMenu.forRestaurant.name
。在新的
<parameter>
标记中,添加一个<entity-set-reference>
标记,并将其urlFilter
属性设为要用于网站目录的网址路径。
执行上述步骤后,Google 助理即可在 urlFilter
属性中提供的网址路径中执行网页搜索。然后,Google 助理会使用搜索结果向您的执行方式提供 {@url}
值,以便深层链接处理程序可以根据 Google 助理针对该执行方式返回的深层链接跳转用户。
例如,假设您的网站包含的产品详情使用以 https://www.example.com/items/
开头的路径。如果您使用 urlFilter
值 https://www.example.com/items/.*
,Google 助理稍后就会返回 https://www.example.com/items/item123
之类的执行方式网址。如需了解 urlFilter
属性,请参阅 <entity-set-reference>
。
执行方式中的网址模板
在 <fulfillment>
标记中,您可以声明包含动态参数占位符的网址模板。此模板使用应用链接网址、自定义架构或基于 intent 的网址映射到您的其中一个 Android activity。
配置网址模板
应用链接网址示例:
<action intentName="actions.intent.CREATE_TAXI_RESERVATION"> <fulfillment urlTemplate="http://my-taxi.com/order{?dropoffLocation}"> <parameter-mapping intentParameter="taxiReservation.dropoffLocation.name" urlParameter="dropoffLocation"/> </fulfillment> </action>
自定义架构示例:
<action intentName="actions.intent.CREATE_TAXI_RESERVATION"> <fulfillment urlTemplate="mytaxi://reserve{?dropoffLocation}"> <parameter-mapping intentParameter="taxiReservation.dropoffLocation.name" urlParameter="dropoffLocation"/> </fulfillment> </action>
基于 intent 的网址示例:
<action intentName="actions.intent.CREATE_TAXI_RESERVATION"> <fulfillment urlTemplate="intent:#Intent;package=com.example.myapp;action=com.example.myapp.MY_ACTION{;S.dropoff};end"> <parameter-mapping intentParameter="taxiReservation.dropoffLocation.name" urlParameter="S.dropoff"/> </fulfillment> </action>
为执行方式指定 <parameter-mapping>
标记时,intentParameter
属性表示用户提供的内置 intent 参数。在上述示例中,该参数为下车点名称 (taxiReservation.dropoffLocation.name
)。您可以在内置 intent 参考文档中找到任何给定内置 intent 的可用参数。
如需将内置 intent 参数映射到网址中的某个位置,请使用 <parameter-mapping>
标记的 urlParameter
属性。此属性对应于网址模板中您想使用用户信息替换的占位值。该占位值必须存在于您的 urlTemplate
中并用大括号 ({}
) 括起来。
应用链接网址
如果您使用的是应用链接网址,urlTemplate
会指向可以触发您的 Activity
的常规 HTTP 网址。参数会以网址参数的形式传递给应用链接网址。urlTemplate
中的参数必须用大括号 ({}
) 括起来,并且前面带一个问号 (?
)。对于未设置的参数,结果中会省略该参数(包括大括号)。
例如,如果用户通过请求预订一辆前往“San Francisco”的出租车触发了与应用有关的 Action,则触发的最终 URI(参数替换后)将如下所示:
https://mydomain.com/order?action=com.example.myapp.MY_ACTION&dropoff=San+Francisco
基于 intent 的网址
如果您使用的是基于 intent 的网址,则 urlTemplate
值中会包含软件包名称、intent 操作和一个名为 dropoff 的 extra intent。该 extra 带有“S.”前缀,表示这是一个 String
intent extra(由 Intent.toUri()
定义),并用大括号括起来表示参数替代。
需要一个额外的前置分号来将 intent 操作与 intent extra 分隔开(只有在设置了相应参数时才需要这么做)。
在以下示例中,urlParameter
值设为 S.dropoff
;您可以在 urlTemplate
中查找此值,了解它在网址中出现的位置。
例如,如果用户通过请求叫车前往“San Francisco”触发了与应用有关的 Action,则触发的最终 URI(参数替换后)将是:
intent:#Intent;package=com.example.myapp;action=com.example.myapp.MY_ACTION;S.dropoff=San+Francisco;end
如需详细了解 intent,请参阅 Android intent 文档。
在网址模板中使用来自 entity 的网址值
默认情况下,如果 <entity>
与用户的查询匹配,系统会将 identifier
属性的值传递给网址模板。如需引用 <entity>
的 url
属性,请在网址模板中使用 {@url}
,而不要使用 <parameter-mapping>
标记。请注意,标识符值会进行网址转义,但 url
属性值会保持不变。
如果执行方式在网址模板中使用了 {@url}
,则执行方式会尝试从网站目录和内嵌目录等来源派生 {@url}
。当网站目录和内嵌目录都是派生 {@url}
的潜在来源时,网站目录优先。
具体可见以下示例:
<fulfillment urlTemplate="{@url}"> <!-- No parameter-mapping is needed --> </fulfillment> <entity-set entitySetId="..."> <entity name="..." url="https://my.url.fulfillment/1"/> <entity name="..." url="https://my.url.fulfillment/2"/> </entity-set>
{@url}
参数可以与其他参数结合使用。
<fulfillment urlTemplate="{@url}?referrer=actions_on_google{&other_param}"> <parameter-mapping intentParameter="otherParam.name" urlParameter="other_param"/> </fulfillment> <entity-set entitySetId="..."> <entity name="..." url="https://my.url.fulfillment/1"/> <entity name="..." url="https://my.url.fulfillment/2"/> </entity-set>
参数匹配
Google 将用户话语中的参数与您指定的 entity 进行匹配的方式取决于参数的类型:
- 枚举:Google 将用户的查询(“Monday”)与关联的枚举网址(“http://schema.org/Monday”)匹配,然后选择其
sameAs
值与该枚举网址匹配的 entity。 - 字符串:Google 会选择其
name
或alternateName
值与用户查询匹配的 entity。
示例
本部分举例说明了如何在 actions.xml
中使用内置 intent。
财务 - 帐号和付款
以下 actions.xml
示例使用 actions.intent.CREATE_MONEY_TRANSFER
内置 intent:
<?xml version="1.0" encoding="utf-8"?> <actions> <action intentName="actions.intent.CREATE_MONEY_TRANSFER"> <fulfillment urlTemplate="mybankapp://transfer{?amount,currency,recipientBankAccountType,senderBankAccountType,mode}"> <parameter-mapping intentParameter="moneyTransfer.amount.value" urlParameter="amount" /> <parameter-mapping intentParameter="moneyTransfer.amount.currency" urlParameter="currency" /> <parameter-mapping intentParameter="moneyTransfer.moneyTransferDestination.name" urlParameter="recipientBankAccountType" /> <parameter-mapping intentParameter="moneyTransfer.moneyTransferOrigin.name" urlParameter="senderBankAccountType" /> <parameter-mapping intentParameter="moneyTransfer.transferMode" urlParameter="mode" /> </fulfillment> </action> </actions>
健身 - 营养
以下 actions.xml
示例使用 actions.intent.RECORD_FOOD_OBSERVATION
内置 intent:
<?xml version="1.0" encoding="utf-8"?> <actions> <action intentName="actions.intent.RECORD_FOOD_OBSERVATION"> <parameter name="foodObservation.forMeal"> <entity-set-reference entitySetId="MealEntitySet"/> </parameter> <fulfillment urlTemplate="myfoodapp://record{?food,meal}"> <parameter-mapping intentParameter="foodObservation.forMeal" urlParameter="meal" entityMatchRequired="true" /> <parameter-mapping intentParameter="foodObservation.aboutFood.name" urlParameter="food" /> </fulfillment> </action> <entity-set entitySetId="MealEntitySet"> <entity sameAs="http://schema.googleapis.com/MealTypeBreakfast" identifier="1" /> <entity sameAs="http://schema.googleapis.com/MealTypeLunch" identifier="2" /> <entity sameAs="http://schema.googleapis.com/MealTypeDinner" identifier="3" /> </entity-set> </actions>
点餐
以下 actions.xml
示例使用 actions.intent.ORDER_MENU_ITEM
内置 intent:
<?xml version="1.0" encoding="utf-8"?> <actions> <action intentName="actions.intent.ORDER_MENU_ITEM"> <parameter name="menuItem.inMenuSection.inMenu.forRestaurant.servesCuisine"> <entity-set-reference entitySetId="CuisineEntitySet"/> </parameter> <fulfillment urlTemplate="myfoodapp://order{?restaurant}"> <parameter-mapping intentParameter="menuItem.inMenuSection.inMenu.forRestaurant.name" urlParameter="restaurant" required="true" /> </fulfillment> <!-- URL values are derived from a matched entity from the CuisineEntity Set. This is not a fallback fulfillment because {@url} is a required parameter. --> <fulfillment urlTemplate="{@url}" /> <!-- Fallback fulfillment with no required parameters --> <fulfillment urlTemplate="myfoodapp://browse{?food}"> <parameter-mapping intentParameter="menuItem.name" urlParameter="food" /> </fulfillment> </action> <entity-set entitySetId="CuisineEntitySet"> <entity url="myfoodapp://browse/italian/pizza" name="@string/pizza" alternateName="@array/pizzaSynonyms" /> <entity url="myfoodapp://browse/american/hamburger" name="@string/hamburger" alternateName="@array/hamburgerSynonyms" /> <entity url="myfoodapp://browse/mediterranean" name="@string/mediterranean" alternateName="@array/mediterraneanSynonyms" /> </entity-set> </actions>
交通
以下 actions.xml
文件使用 actions.intent.CREATE_TAXI_RESERVATION
内置 intent:
<actions> <action intentName="actions.intent.CREATE_TAXI_RESERVATION"> <fulfillment urlTemplate="https://taxi-actions.firebaseapp.com/order{?dropoffAddress}"> <!-- Dropoff location as an address --> <parameter-mapping intentParameter="taxiReservation.dropoffLocation.name" urlParameter="dropoffAddress"/> </fulfillment> </action> </actions>
其他
以下 actions.xml
示例使用 actions.intent.OPEN_APP_FEATURE
内置 intent。
<?xml version="1.0" encoding="utf-8"?> <actions> <action intentName="actions.intent.OPEN_APP_FEATURE"> <!-- Each parameter can reference an entity set using a custom ID. --> <parameter name="feature"> <entity-set-reference entitySetId="FeatureEntitySet"/> </parameter> <fulfillment urlTemplate="myexampleapp://pathto{?appFeature}"> <parameter-mapping intentParameter="feature" urlParameter="appFeature" /> </fulfillment> </action> <entity-set entitySetId="FeatureEntitySet"> <entity identifier="FEATUREONE" name="first feature" /> <entity identifier="FEATURETWO" name="second feature" /> </entity-set> </actions>