创建 actions.xml(已废弃)

确定要实现的应用内功能和内置 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>

intentName

queryPatterns(仅适用于自定义 intent

<parameter> <action> name
<entity-set-reference> <parameter>

entitySetId

urlFilter

<fulfillment> <action>

urlTemplate

fulfillmentMode(可选)

requiredForegroundActivity(可选)

<parameter-mapping> <fulfillment>

urlParameter

intentParameter

required(可选)

entityMatchRequired(可选)

<entity-set> <actions> entitySetId
<entity> <entity-set>

name(以及可选的 alternateName)或

sameAs

identifierurl

标记说明

本部分将介绍 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

以下是网址模板值的一些示例:

模板 展开值
https://example.com/test{?someValue,anotherValue} "someValue": "123"

"anotherValue": "456"

https://example.com/test?someValue=123&anotherValue=456
https://example.com/test?utm_campaign=appactions{&someValue,anotherValue} "someValue": "123"

"anotherValue": "456"

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"

"S.extra2": "456"

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> 中必须有参数 latlong 的键。

  • 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 集。

属性:

  • entitySetIdactions.xml<entity-set> 的唯一标识符(例如 "myInlineEntitySet1"),该值是必需的。此外,该值还必须与 <entity-set-reference> 标记中的 <entitySetId> 值相对应。

    entitySetId 的值最多只能包含 30 个字母数字字符(不能包含 -_ 等特殊字符),并且必须以字母开头。

<entity>

actions.xml 中内嵌的一组 entity 中的一个。包含一部分 schema.org/Thing 字段。

urlidentifiersameAs 字段的字符串值可以硬编码,也可以使用 APK 的字符串资源进行引用。提供同义词时,请为 alternateName 字段使用引用 APK 的字符串数组资源的字符串值。

属性:

  • name:entity 的名称,除非指定了 sameAs 字段,否则必须提供该值。对于给定的 <entity-set>(例如,“toothpaste”),entity 的 namealternateName 字段的值必须不同。

  • alternateName:(可选)entity 的备用名称。必须先指定 name 字段,再指定 alternateName 字段。对于给定的 <entity-set>,entity 的 namealternateName 字段的值必须不同。只要用户的查询与这些字符串之一匹配,就会选择该 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)。

必须提供 identifierurl。给定 entity 集中的所有 entity 都必须使用相同的属性(identifierurl)。

与应用有关的 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

  1. 在要使用网站目录的 <action> 标记中,添加 <fulfillment> 标记并将其 urlTemplate 属性设为 {@url}

  2. 在同一 <action> 标记中,添加一个 <parameter> 标记,并将其 name 属性设为与您的网页所描述的 entity 最贴近的内置 intent 参数。例如,在为 ORDER_MENU_ITEM 提供网站目录时,将菜单页面链接到 menuItem.name,并将餐厅位置页面链接到 menuItem.inMenuSection.inMenu.forRestaurant.name

  3. 在新的 <parameter> 标记中,添加一个 <entity-set-reference> 标记,并将其 urlFilter 属性设为要用于网站目录的网址路径。

执行上述步骤后,Google 助理即可在 urlFilter 属性中提供的网址路径中执行网页搜索。然后,Google 助理会使用搜索结果向您的执行方式提供 {@url} 值,以便深层链接处理程序可以根据 Google 助理针对该执行方式返回的深层链接跳转用户。

例如,假设您的网站包含的产品详情使用以 https://www.example.com/items/ 开头的路径。如果您使用 urlFilterhttps://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{&amp;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 会选择其 namealternateName 值与用户查询匹配的 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>