App Actions deployment requirements

To ensure that users enjoy a seamless experience when using App Actions, you must meet these requirements before activating App Actions for your app:

  • Log contextual content: To create a better experience when users invoke App Actions from the Assistant while in the app, your Activity should call the onProvideAssistContent() method.
  • Report App Action interaction results: To help Google proactively suggest your App Actions to users, use the Firebase App Indexing API to let the Assistant know whether your app has successfully handled a built-in request.
  • Handle the SEARCH_ACTION Android intent: If your app has a search function, you must support the SEARCH_ACTION common intent. This lets Google provide a fallback mechanism if we are unable to resolve the user's query to a built-in intent.

These requirements are described in more detail below.

Log contextual content

By implementing onProvideAssistContent(), you provide the Assistant with structured information about the current foreground content. This contextual information enables the Assistant to continue being helpful after the user enters your app.

You only need to implement onProvideAssistContent() for the final app activity in the user's task flow after invoking the App Action. For example, in a CREATE_MONEY_TRANSFER flow, you would implement the method in the final screen showing the receipt; you would not need to implement it for any in-progress or preview screens.

You must provide this data as a JSON-LD object in the structuredData field. The following code snippet shows how you might implement the contextual content logging:

Java

@Override
public void onProvideAssistContent(AssistantContent outContent) {
  super.onProvideAssistContent(outContent);

  // JSON-LD object based on Schema.org structured data
  outContent.structuredData = new JSONObject()
    .put("@type", "MenuItem")
    .put("name", "Blueberry Crisp Iced Signature Latte")
    .put("url", "https://mysite.com/menuitems/12345a")
    .toString();
}

Kotlin

override fun onProvideAssistContent(outContent: AssistContent) {
 super.onProvideAssistContent(outContent)

 // JSON-LD object based on Schema.org structured data
 outContent.structuredData = JSONObject()
         .put("@type", "MenuItem")
         .put("name", "Blueberry Crisp Iced Signature Latte")
         .put("url", "https://mysite.com/menuitems/12345a")
         .toString()
}

We recommend that you implement onProvideAssistContent() for any sharable entity in your app. However, onProvideAssistContent() is required in the activities that are triggered by the following built-in intents for App Actions:

Category Built-in intent Required entity type
Finance CREATE_MONEY_TRANSFER @MoneyTransfer
Fitness STOP_EXERCISE @Exercise
GET_EXERCISE_OBSERVATION @ExerciseObservation
GET_FOOD_OBSERVATION @FoodObservation
Food ordering ORDER_MENU_ITEM @MenuItem, @Restaurant
GET_ORDER @Order
Ride sharing CREATE_TAXI_RESERVATION @TaxiReservation
GET_TAXI_RESERVATION @TaxiReservation

Similarly, while we recommend providing as much data as possible about each entity, we require the following fields:

  • @type
  • .name
  • .url (only required if the content is URL-addressable)

To learn more about using onProvideAssistContent(), see the Optimizing Contextual Content for the Assistant guide in the Android developer documentation.

Report interaction results

Google monitors the health of your App Actions to know when they aren't working as intended. You must let Google know using Firebase whether your app successfully handled a built-in intent with App Actions.

To satisfy this requirement, take these steps in your Android app:

  1. Add Firebase and the App Indexing library to your Android Studio project.
  2. For deep-linked activities launched via App Actions, use the FirebaseUserActions class to report either that the intended action completed successfully or that it did not. (A user cancelling an order that they started via App Actions counts as a failure.)

You can tell that an activity was launched via App Actions if the incoming deep link matches the format of a URL template defined in your actions.xml file. Because you define both the URL template and how an activity handles deep links, you can flag and recognize deep links from App Actions in a way that best suits your app.

For example, in your actions.xml file, you can add a query string parameter to the URL template of the element. In the corresponding activity, you can then look for that parameter to determine whether a user triggered the deep link via App Actions.

The following code snippet shows how to use the FirebaseUserActions class to report status when users invoke your App Actions:

Java

private static final String ACTION_TOKEN_EXTRA =
        "actions.fulfillment.extra.ACTION_TOKEN";

void notifyActionStatus(String status) {
    String actionToken = getIntent().getStringExtra(ACTION_TOKEN_EXTRA);
    final Action action = new AssistActionBuilder()
            .setActionToken(actionToken)
            .setActionStatus(status)
            .build();
    FirebaseUserActions.getInstance().end(action);
}

// On Action success
notifyActionStatus(Action.Builder.STATUS_TYPE_COMPLETED);

// On Action failed
notifyActionStatus(Action.Builder.STATUS_TYPE_FAILED);

Kotlin

private val actionTokenExtra = "actions.fulfillment.extra.ACTION_TOKEN"

fun notifyActionStatus(status: String) {
     val actionToken = intent.getStringExtra(actionTokenExtra)
     val action = AssistActionBuilder()
             .setActionToken(actionToken)
             .setActionStatus(status)
             .build()
     FirebaseUserActions.getInstance().end(action)
 }

 // On Action success
 notifyActionStatus(Action.Builder.STATUS_TYPE_COMPLETED)

 // On Action failed
 notifyActionStatus(Action.Builder.STATUS_TYPE_FAILED)

Make sure that you're uploading the action data to Google servers (default behavior) by not setting setUpload(false).

To see how to implement this deployment requirement in an Android app, check out the App Actions fitness sample on GitHub.

In the event where the Assistant is confident that the user wishes to access your app via the Assistant, but is unable to resolve the query to a built-in intent, it’s important to provide a fallback mechanism. If your app already has a search function, you must handle the SEARCH_ACTION Android intent, so that Google can pass the user query into your app, if needed.

The following snippet shows how to add an intent filter to an Activity with the SEARCH_ACTION common intent in the AndroidManifest.xml file:

<activity android:name=".SearchActivity">
   <intent-filter>
      <action android:name="com.google.android.gms.actions.SEARCH_ACTION"/>
      <category android:name="android.intent.category.DEFAULT"/>
   </intent-filter>
</activity>

In your search activity, you should check the for the SEARCH_ACTION intent and extract the query. Then, do something with the query like running a search and displaying the results in the UI. For example, you could make a query to the Assistant like this: "Hey Google, show me cats on myvideoapp".

The following code snippet shows an example implementation.

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
  ...
  Intent intent = getIntent();
  if (intent.getAction().equals(SearchIntents.ACTION_SEARCH)) {
    String query = intent.getStringExtra(SearchIntents.EXTRA_QUERY);
    //TODO: user query value to run search
  }
}

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
  ...
  if (intent?.action == SearchIntents.ACTION_SEARCH) {
    val query = intent?.getStringExtra(SearchIntents.EXTRA_QUERY)
    // TODO: use query value to run search
  }
  ...
}

To learn more about handling this common intent, see the Search using a specific app guide in the Android documentation.