Integrate App Actions with Android Slices

For many intents, the best response from an app is a quick inline answer or a simple confirmation that an action was taken. For these intents, we recommend that you handle them with an Android Slice, rather than a deep link.

Figure 1. Launching a Slice using GET_INVOICE

A user can tap on the Slice to follow a deep link into the app if more information or additional interaction is needed.

For example, using the actions.intent.GET_INVOICE built-in intent, your banking app can implement a custom Slice that the Assistant displays when the user utters the invocation phrase “Check my upcoming bills”. In the Slice, you can show real time data for the user’s bill.

For a list of built-in intents we strongly recommend that you use for launching Android Slices, see Implement built-in intents for App Actions.

Implement Slices

To integrate App Actions with your Slices, follow these steps:

  1. Implement an Android Slice by following the steps described in the Slices Getting Started guide.
  2. In the actions.xml file, in the <fulfillment> element, specify fulfillmentMode=”actions.fulfillment.SLICE” to indicate that a user intent can be fulfilled using a Slice in your app.

When a Slice is used for fulfillment, the urlTemplate refers to the Slice URI as described in the SliceProvider. The urlTemplate must be of the type content://{slice_authority}/... where slice_authority is the authority defined in the AndroidManifest.xml file.

The following snippet shows an example of how you might specify a Slice as the fulfillment for the GET_ACCOUNT built-in intent, in your actions.xml file.

<action intentName="actions.intent.GET_ACCOUNT">
  <fulfillment
      fulfillmentMode="actions.fulfillment.SLICE"
      urlTemplate="content://com.example/balance{?accountName}">
    <parameter-mapping
          urlParameter="accountName"
          intentParameter="account.name"
          required="true"/>
  </fulfillment>
  <fulfillment urlTemplate="https://www.bank.example/account/balance" />
</action>

In your actions.xml, you can specify two <fulfillment> elements for the same intent, each with a different fulfillmentMode attribute value (that is, actions.fulfillment.SLICE or actions.fulfillment.DEEPLINK). This lets you provide a seamless experience if the user doesn’t supply a required parameter for the Slice. For example, if the user doesn’t specify an account name, you can deep link them to an activity in your app which shows all their accounts.

Slice permissions

You need to grant Slice access permission to the Assistant on startup. Since Slice permissions are hierarchical, the Assistant would get permission to all Slice URIs as long as you grant permission to the Assistant on a top level URI (for example: content://com.foo.slice.provider/).

The following code snippet shows how you might implement this:

public class MyApplication extends Application {

 private static final String SLICE_AUTHORITY = "...";

 @Override
 public void onCreate() {
   super.onCreate();
   grantSlicePermissions();
 }

 private void grantSlicePermissions() {
   Context context = getApplicationContext();
   Uri sliceProviderUri =
       new Uri.Builder()
           .scheme(ContentResolver.SCHEME_CONTENT)
           .authority(SLICE_AUTHORITY)
           .build();

   String assistantPackage = getAssistantPackage(context);
   if (assistantPackage == null) {
     return;
   }
   SliceManager.getInstance(context)
       .grantSlicePermission(assistantPackage, sliceProviderUri);
 }

 private String getAssistantPackage(Context context) {
   PackageManager packageManager = context.getPackageManager();
   List<ResolveInfo> resolveInfoList = packageManager.queryIntentServices(
       new Intent(VoiceInteractionService.SERVICE_INTERFACE), 0);
   if (resolveInfoList.isEmpty()) {
     return null;
   }
   return resolveInfoList.get(0).serviceInfo.packageName;
 }
}

Slice logging

In order to trigger App Actions, Google logs the following data about your Slice (specifically from the SliceMetadata object).

We will explicitly not log the following information:

Quality guidelines for Slices integration

This section highlights key requirements and best practices when you integrate App Actions with Slices.

General requirements

  • Make sure you define a primary action for each Slice.
  • While loading the content of the Slice, make sure to set the isLoading field in the Slices API to true if the Slice being returned is a loading Slice (and false otherwise).
  • To indicate error conditions, use the setIsError() method to let Google know that Slice content was not loaded successfully or that the user’s request could not be handled.

Content in Slices

  • (Required) Do not show ads in your Slices.
  • (Required) Do not add header or footer information in your Slices; Google automatically provides this.
  • Slice content should be completely focused on fulfilling the intent—don't try to fulfill multiple intents with one Slice or add irrelevant content.

Handling authentication

  • (Required) Where user authentication is needed to complete a user flow, return a Slice that explains that the user needs to continue in the app. In-line user authentication in the Assistant is not supported for App Actions.
  • If users are permitting your app to show data via Slices, you can return an Error Slice at runtime for unauthorized users.

Deep linking

  • (Required) Deep-link the user to the correct screen in your app, not the home screen.
  • (Required) In your actions.xml, you should always provide fallback deeplink fulfillment in addition to Slice fulfillment for a given built-in intent.
  • When to use a Slice versus when to deep link into your app:
    • Use a Slice when a user asks for a small piece of information that can be displayed in a line or two of text.
    • Use deep linking when the user wants to perform a task in your app or start a task that requires further interaction.