Actions.xml migration guide

This guide describes basic steps you can take to migrate your actions from an actions.xml file to a shortcuts.xml file. 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 the actions.xml and shortcuts.xml files:

  • You use the same file that you use to define the voice capabilities of your app (usually res/xml/shortcuts.xml in your app project) to define Android shortcuts. If you 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 on this page demonstrate when it's necessary to use the app namespace.

Set up shortcuts.xml

If you 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. Remove the <meta-data> tag referencing actions.xml in the AndroidManifest.xml file.

  3. Add a reference to shortcuts.xml in AndroidManifest.xml using a <meta-data> tag in the activity that has intent filters for both MAIN and LAUNCHER. The details for this process can be seen in the creating shortcuts overview

  4. In shortcuts.xml, define a shortcuts element as shown in the following example:

    <?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 an actions.xml file to a shortcuts.xml file, 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:

    <?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, as shown in the following sample actions.xml:

    Built-in intent

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

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

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

    Custom intent

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

    In this example, you set the android:name attribute of your capability to actions.intent.RECORD_FOOD_OBSERVATION and set app:queryPatterns to @array/foodObservationQueries in 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. This is shown in the following example 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

    <?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 in 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, you set the android:value attribute of the url-template element to myfoodapp://record{?food,meal} in 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

    <?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 is 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 in 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, you create the following parameter elements in 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

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

The following examples demonstrate the migration steps. Suppose your original action in actions.xml looks like this:

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

<?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, as shown in the following sample 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:

    ...
    <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:

    ...
    <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:

    ...
    <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 are now ready for testing.

Examples: actions.xml to shortcuts.xml

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

actions.xml - Finance

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

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

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

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

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

<?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">
    <intent android:data="myfoodapp://browse/italian/pizza"/>
    <capability-binding android:key="actions.intent.ORDER_MENU_ITEM">
      <parameter-binding
        android:key="menuItem.name"
        android:value="@string/pizza" />
    </capability-binding>
  </shortcut>

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

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

actions.xml - Transportation

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

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

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

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