Actions.xml migration guide

This guide describes basic steps you can take to migrate your actions from actions.xml to shortcuts.xml. Use this guide alongside the App Actions actions.xml to shortcuts.xml conversion utility to simplify your migration to the shortcuts.xml format.

Differences between actions.xml and shortcuts.xml

There are several important differences between actions.xml and shortcuts.xml:

  • The file that you use to define the voice capabilities of your app (usually, res/xml/shortcuts.xml in your app project) is also used to define Android shortcuts. If you have previously implemented static Android shortcuts for your app, migrate your actions from actions.xml to that existing file.

  • Entity sets no longer exist. Instead, entities are defined using shortcut elements.

  • Deep links are still supported, but are not the core method of fulfillment. Instead, use explicit Android intents.

Prerequisites

To support the app namespace used by attributes in shortcuts.xml, you must include the Android Jetpack Core library version 1.6.0 or later with your app. Examples in this document demonstrate when it's necessary to use the app namespace.

Set up shortcuts.xml

If you have previously implemented Android shortcuts for your app, use that file to set up your capabilities.

If the shortcuts.xml file doesn't exist, follow these steps:

  1. In your app project's res/xml directory, create the shortcuts.xml file.

  2. In shortcuts.xml, define a shortcuts element.

    shortcuts.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
    
    </shortcuts>
    

Set up capabilities

When migrating your actions from actions.xml to shortcuts.xml, you must set up capability elements. A capability identifies the App Action intent that your app wants to recognize. To migrate, every action in actions.xml must be converted to a capability in shortcuts.xml.

If you have entity sets associated with your actions, complete this procedure to add the capabilities, and then set up shortcuts to represent the entity sets.

For more information about setting up capabilities, see Create shortcuts.xml.

To migrate an action to a capability, follow these steps:

  1. In shortcuts.xml, in the shortcuts element, define a capability element.

    shortcuts.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
      <capability>
    
      </capability>
    </shortcuts>
    
  2. Set the android:name attribute of the capability to the BII your action uses. In actions.xml, the value is found in the intentName attribute of your action element.

    If your action uses a custom intent, you must also include the app:queryPatterns attribute. In actions.xml, the value is found in the queryPatterns attribute of your action element.

    For example, suppose your action invokes the actions.intent.RECORD_FOOD_OBSERVATION intent.

    Built-in intent

    actions.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <actions>
      <action intentName="actions.intent.RECORD_FOOD_OBSERVATION">
        ...
      </action>
    </actions>
    

    In this example, for shortcuts.xml, you set the android:name attribute of your capability to actions.intent.RECORD_FOOD_OBSERVATION.

    shortcuts.xml:

    <shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
      <capability android:name="actions.intent.RECORD_FOOD_OBSERVATION">
    
      </capability>
    </shortcuts>
    

    Custom intent

    actions.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <actions>
      <action
        intentName="custom.actions.intent.RECORD_FOOD_OBSERVATION"
        queryPatterns="@array/foodObservationQueries">
        ...
      </action>
    </actions>
    

    In this example, for shortcuts.xml, you set the android:name attribute of your capability to actions.intent.RECORD_FOOD_OBSERVATION, and app:queryPatterns to @array/foodObservationQueries.

    shortcuts.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
      <capability
        android:name="custom.actions.intent.RECORD_FOOD_OBSERVATION"
        app:queryPatterns="@array/foodObservationQueries">
    
      </capability>
    </shortcuts>
    
  3. In the capability, for each fulfillment defined in your action, create an intent or slice. You need to add a slice element only if the fulfillmentMode attribute of a fulfillment is set to actions.fulfillment.SLICE. Otherwise, create an intent element.

    shortcuts.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
      <capability android:name="actions.intent.RECORD_FOOD_OBSERVATION">
        <intent>
    
        </intent>
      </capability>
    </shortcuts>
    

    Slice

    shortcuts.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
      <capability android:name="actions.intent.RECORD_FOOD_OBSERVATION">
        <slice>
    
        </slice>
      </capability>
    </shortcuts>
    
  4. For each element that you created in the previous step, define a url-template element and set the android:value attribute to the same value used for the url-template attribute of your fulfillment element.

    For example, suppose your action uses the following URL template.

    actions.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <actions>
      <action intentName="actions.intent.RECORD_FOOD_OBSERVATION">
        ...
        <fulfillment urlTemplate="myfoodapp://record{?food,meal}">
          ...
        </fulfillment>
      </action>
    </actions>
    

    In this example, for shortcuts.xml, you would set the android:value attribute of the url-template element to myfoodapp://record{?food,meal}.

    shortcuts.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
      <capability android:name="actions.intent.RECORD_FOOD_OBSERVATION">
        <intent>
          <url-template android:value="myfoodapp://record{?food,meal}" />
        </intent>
      </capability>
    </shortcuts>
    

    Slice

    shortcuts.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
      <capability android:name="actions.intent.RECORD_FOOD_OBSERVATION">
        <slice>
          <url-template android:value="myfoodapp://record{?food,meal}" />
        </slice>
      </capability>
    </shortcuts>
    
  5. For each parameter-mapping element for the URL template of your action, define a parameter element and set values for the android:name and android:key attributes.

    • Set android:name to the same value as the intentParameter attribute of your parameter-mapping element.

    • Set android:key to the same value as the urlParameter attribute of your parameter-mapping element.

    If one or more of your parameters are required, set the android:required attribute of the parameter to true.

    For example, suppose your action includes the following parameter mappings for your URL template.

    actions.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <actions>
      <action intentName="actions.intent.RECORD_FOOD_OBSERVATION">
        ...
        <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>
    </actions>
    

    In this example, for shortcuts.xml, you would create the following parameter elements.

    shortcuts.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <shortcuts
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">
      <capability android:name="actions.intent.RECORD_FOOD_OBSERVATION">
        <intent>
          <url-template android:value="myfoodapp://record{?food,meal}" />
          <parameter
            android:name="foodObservation.forMeal"
            android:key="meal"
            android:required="true"
            app:shortcutMatchRequired="true" />
          <parameter
            android:name="foodObservation.aboutFood.name"
            android:key="food" />
        </intent>
      </capability>
    </shortcuts>
    

    Slice

    shortcuts.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <shortcuts
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">
      <capability android:name="actions.intent.RECORD_FOOD_OBSERVATION">
        <slice>
          <url-template android:value="myfoodapp://record{?food,meal}" />
          <parameter
            android:name="foodObservation.forMeal"
            android:key="meal"
            android:required="true" />
          <parameter
            android:name="foodObservation.aboutFood.name"
            android:key="food" />
        </slice>
      </capability>
    </shortcuts>
    

Set up shortcuts

In shortcuts.xml, entities are represented as shortcuts. If you haven't yet migrated your actions to capabilities, you must first set up a capability for each action. When migrating from actions.xml to shortcuts.xml, if your action has an entity set, you must create a shortcut for each entity.

This procedure uses the following example to demonstrate the migration steps. Suppose your original action looks like this:

actions.xml:

<?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>

In this example, assume that you have already defined the capability in shortcuts.xml, including the intent and parameters.

shortcuts.xml:

<?xml version="1.0" encoding="utf-8"?>
<shortcuts
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto">
  <capability android:name="actions.intent.RECORD_FOOD_OBSERVATION">
    <intent>
      <url-template android:value="myfoodapp://record{?food,meal}" />
      <parameter
        android:name="foodObservation.forMeal"
        android:key="meal"
        android:required="true" />
      <parameter
        android:name="foodObservation.aboutFood.name"
        android:key="food" />
    </intent>
  </capability>
</shortcuts>

To set up shortcuts for your entities, follow these steps:

  1. In the shortcuts element, for each parameter and entity, define a shortcut element and set a value for the android:shortcutId attribute. The value of android:shortcutId must be the same as the identifier attribute of the corresponding entity.

    In this example, you create a shortcut for each entity in the MealEntitySet entity set.

    shortcuts.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <shortcuts>
      <capability android:name="actions.intent.RECORD_FOOD_OBSERVATION">
        ...
      </capability>
    
      <shortcut android:shortcutId="1">
    
      </shortcut>
    
      <shortcut android:shortcutId="2">
    
      </shortcut>
    
      <shortcut android:shortcutId="3">
    
      </shortcut>
    </shortcuts>
    
  2. For each shortcut, define a capability-binding element. Set the android:key attribute to the built-in intent or custom intent in your capability.

    shortcuts.xml:

    ...
    <shortcut android:shortcutId="1">
      <capability-binding android:key="actions.intent.RECORD_FOOD_OBSERVATION">
    
      </capability-binding>
    </shortcut>
    
    <shortcut android:shortcutId="2">
      <capability-binding android:key="actions.intent.RECORD_FOOD_OBSERVATION">
    
      </capability-binding>
    </shortcut>
    
    <shortcut android:shortcutId="3">
      <capability-binding android:key="actions.intent.RECORD_FOOD_OBSERVATION">
    
      </capability-binding>
    </shortcut>
    ...
    
  3. In each capability-binding, define a parameter-binding. Set the android:key attribute to the name of the corresponding parameter in the intent.

    shortcuts.xml:

    ...
    <shortcut android:shortcutId="1">
      <capability-binding android:key="actions.intent.RECORD_FOOD_OBSERVATION">
        <parameter-binding android:key="foodObservation.forMeal" />
      </capability-binding>
    </shortcut>
    
    <shortcut android:shortcutId="2">
      <capability-binding android:key="actions.intent.RECORD_FOOD_OBSERVATION">
        <parameter-binding android:key="foodObservation.forMeal" />
      </capability-binding>
    </shortcut>
    
    <shortcut android:shortcutId="3">
      <capability-binding android:key="actions.intent.RECORD_FOOD_OBSERVATION">
        <parameter-binding android:key="foodObservation.forMeal" />
      </capability-binding>
    </shortcut>
    ...
    
  4. Add the android:value attribute to your parameter-binding, and then define an extra element.

    Using the example, to support the entities, you update your capability-bindings for meal_breakfast, meal_lunch, and meal_dinner, and add the corresponding extra elements.

    shortcuts.xml:

    ...
    <shortcut android:shortcutId="1">
      <capability-binding android:key="actions.intent.RECORD_FOOD_OBSERVATION">
        <parameter-binding android:key="foodObservation.forMeal" />
      </capability-binding>
      <extra
        android:key="sameAs"
        android:value="http://schema.googleapis.com/MealTypeBreakfast" />
    </shortcut>
    
    <shortcut android:shortcutId="2">
      <capability-binding android:key="actions.intent.RECORD_FOOD_OBSERVATION">
        <parameter-binding android:key="foodObservation.forMeal" />
      </capability-binding>
      <extra
        android:key="sameAs"
        android:value="http://schema.googleapis.com/MealTypeLunch" />
    </shortcut>
    
    <shortcut android:shortcutId="3">
      <capability-binding android:key="actions.intent.RECORD_FOOD_OBSERVATION">
        <parameter-binding android:key="foodObservation.forMeal" />
      </capability-binding>
      <extra
        android:key="sameAs"
        android:value="http://schema.googleapis.com/MealTypeDinner" />
    </shortcut>
    ...
    

Your migrated capabilities should now be ready for testing.

Examples: actions.xml to shortcuts.xml

The following examples demonstrate implementations of App Actions using actions.xml and shortcuts.xml.

Actions.xml - Finance

actions.xml

<?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>

Shortcuts.xml - Finance

shortcuts.xml

<?xml version="1.0" encoding="utf-8"?>
<shortcuts>
  <capability android:name="actions.intent.CREATE_MONEY_TRANSFER">
    <intent>
      <url-template android:value="mybankapp://transfer{?amount,currency,recipientBankAccountType,senderBankAccountType,mode}" />
      <parameter
        android:name="moneyTransfer.amount.value"
        android:key="amount"
        android:required="true" />
      <parameter
        android:name="moneyTransfer.amount.currency"
        android:key="currency" />
      <parameter
        android:name="moneyTransfer.moneyTransferDestination.name"
        android:key="recipientBankAccountType" />
      <parameter
        android:name="moneyTransfer.moneyTransferOrigin.name"
        android:key="senderBankAccountType" />
      <parameter
        android:name="moneyTransfer.transferMode"
        android:key="mode" />
    </intent>
  </capability>
</shortcuts>

Actions.xml - Fitness and nutrition

actions.xml

<?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>

Shortcuts.xml - Fitness and Nutrition

shortcuts.xml

<?xml version="1.0" encoding="utf-8"?>
<shortcuts>
  <capability android:name="actions.intent.RECORD_FOOD_OBSERVATION">
    <intent>
      <url-template android:value="myfoodapp://record{?food,meal}" />
      <parameter
        android:name="foodObservation.forMeal"
        android:key="meal"
        android:required="true" />
      <parameter
        android:name="foodObservation.aboutFood.name"
        android:key="food" />
    </intent>
  </capability>

  <shortcut android:shortcutId="1">
    <capability-binding android:key="actions.intent.RECORD_FOOD_OBSERVATION">
      <parameter-binding android:key="foodObservation.forMeal" />
    </capability-binding>
    <extra
      android:key="sameAs"
      android:value="http://schema.googleapis.com/MealTypeBreakfast" />
  </shortcut>

  <shortcut android:shortcutId="2">
    <capability-binding android:key="actions.intent.RECORD_FOOD_OBSERVATION">
      <parameter-binding android:key="foodObservation.forMeal" />
    </capability-binding>
    <extra
      android:key="sameAs"
      android:value="http://schema.googleapis.com/MealTypeLunch" />
  </shortcut>

  <shortcut android:shortcutId="3">
    <capability-binding android:key="actions.intent.RECORD_FOOD_OBSERVATION">
      <parameter-binding android:key="foodObservation.forMeal" />
    </capability-binding>
    <extra
      android:key="sameAs"
      android:value="http://schema.googleapis.com/MealTypeDinner" />
  </shortcut>
</shortcuts>

Actions.xml - Food ordering

actions.xml

<?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>
    <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>

Shortcuts.xml - Food ordering

shortcuts.xml

<?xml version="1.0" encoding="utf-8"?>
<shortcuts
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto">
  <capability android:name="actions.intent.ORDER_MENU_ITEM">
    <intent>
      <url-template android:value="myfoodapp://order{?restaurant}" />
      <parameter
        android:name="menuItem.inMenuSection.inMenu.forRestaurant.name"
        android:key="restaurant"
        android:required="true" />
    </intent>
    <intent>
      <url-template android:value="myfoodapp://browse{?food}" />
      <parameter
        android:name="menuItem.name"
        android:key="food"
        android:required="true" />
    </intent>
  </capability>

  <shortcut android:shortcutId="food_pizza">
    <capability-binding android:key="actions.intent.ORDER_MENU_ITEM">
      <parameter-binding
        android:key="menuItem.name"
        android:value="@string/pizza" />
    </capability-binding>
    <extra
      android:key="sameAs"
      android:value="myfoodapp://browse/italian/pizza" />
  </shortcut>

  <shortcut android:shortcutId="food_hamburger">
    <capability-binding android:key="actions.intent.ORDER_MENU_ITEM">
      <parameter-binding
        android:key="menuItem.name"
        android:value="@string/hamburger" />
    </capability-binding>
    <extra
      android:key="sameAs"
      android:value="myfoodapp://browse/american/hamburger" />
  </shortcut>

  <shortcut android:shortcutId="food_mediterranean">
    <capability-binding android:key="actions.intent.ORDER_MENU_ITEM">
      <parameter-binding
        android:key="menuItem.name"
        android:value="@string/mediterranean" />
    </capability-binding>
    <extra
      android:key="sameAs"
      android:value="myfoodapp://browse/mediterranean" />
  </shortcut>
</shortcuts>

Actions.xml - Transportation

actions.xml

<?xml version="1.0" encoding="utf-8"?>
<actions>
  <action intentName="actions.intent.CREATE_TAXI_RESERVATION">
    <fulfillment urlTemplate="https://taxi-actions.firebaseapp.com/order{?dropoffAddress}">
      <parameter-mapping
        intentParameter="taxiReservation.dropoffLocation.name"
        urlParameter="dropoffAddress"/>
    </fulfillment>
  </action>
</actions>

Shortcuts.xml - Transportation

shortcuts.xml

<?xml version="1.0" encoding="utf-8"?>
<shortcuts
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto">
  <capability android:name="actions.intent.CREATE_TAXI_RESERVATION">
    <intent>
      <url-template android:value="https://taxi-actions.firebaseapp.com/order{?dropoffAddress}" />
      <parameter
        android:name="taxiReservation.dropoffLocation.name"
        android:key="dropoffAddress" />
    </intent>
  </capability>
</shortcuts>

Actions.xml - Other

actions.xml

<?xml version="1.0" encoding="utf-8"?>
<actions>
  <action intentName="actions.intent.OPEN_APP_FEATURE">
    <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>

Shortcuts.xml - Other

shortcuts.xml

<?xml version="1.0" encoding="utf-8"?>
<shortcuts
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto">
  <capability android:name="actions.intent.OPEN_APP_FEATURE">
    <intent>
      <url-template android:value="myexampleapp://pathto{?appFeature}" />
      <parameter android:name="feature" android:key="appFeature" />
    </intent>
  </capability>

  <shortcut android:shortcutId="FEATUREONE">
    <capability-binding android:key="actions.intent.OPEN_APP_FEATURE">
      <parameter-binding
        android:key="feature"
        android:value="@string/featureOne" />
    </capability-binding>
   </shortcut>

  <shortcut android:shortcutId="FEATURETWO">
    <capability-binding android:key="actions.intent.OPEN_APP_FEATURE">
      <parameter-binding
        android:key="feature"
        android:value="@string/featureTwo" />
    </capability-binding>
  </shortcut>
</shortcuts>