Receiving Voice Input from a Notification

If your notification includes an action to respond with text, such as to reply to an email, it should normally launch an activity on the handheld device. However, when your notification appears on an Android wearable, you can allow users to dictate a reply with voice input. You can also provide pre-defined text messages for the user to select.

When the user replies with voice or selects one of the available messages, the system sends the message to your app on the connected handheld device. The message is attached as an extra in the Intent you specified to be used for the notification action.

Note: When developing with the Android emulator, you must type text replies into the voice input field, so be sure you have enabled Hardware keyboard present in the AVD settings.

Define the Remote Input

To create an action that supports voice input, first create an instance of RemoteInput using the RemoteInput.Builder APIs. The RemoteInput.Builder constructor takes a string that the system will use as a key for the Intent extra that carries the reply message to your app on the handheld.

For example, here's how to create a new RemoteInput object that provides a custom label for the voice input prompt:

// Key for the string that's delivered in the action's intent
private static final String EXTRA_VOICE_REPLY = "extra_voice_reply";

String replyLabel = getResources().getString(R.string.reply_label);

RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
        .setLabel(replyLabel)
        .build();

Add Pre-defined Text Responses

In addition to allowing voice input, you can provide up to five text responses that the user can select for quick replies. Call setChoices() and pass it a string array.

For example, you may define some responses in a resource array:

res/values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="reply_choices">
        <item>Yes</item>
        <item>No</item>
        <item>Maybe</item>
    </string-array>
</resources>

Then, inflate the string array and add it to the RemoteInput:

String replyLabel = getResources().getString(R.string.reply_label);
String[] replyChoices = getResources().getStringArray(R.array.reply_choices);

RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
        .setLabel(replyLabel)
        .setChoices(replyChoices)
        .build();

Receive Voice Input for the Primary Action

If "Reply" is your notification's primary action (defined by the setContentIntent() method), then you should attach the RemoteInput to the main action using addRemoteInputForContentIntent(). For example:

// Create intent for reply action
Intent replyIntent = new Intent(this, ReplyActivity.class);
PendingIntent replyPendingIntent =
        PendingIntent.getActivity(this, 0, replyIntent, 0);

// Build the notification
NotificationCompat.Builder replyNotificationBuilder =
        new NotificationCompat.Builder(this)
        .setSmallIcon(R.drawable.ic_new_message)
        .setContentTitle("Message from Travis")
        .setContentText("I love key lime pie!")
        .setContentIntent(replyPendingIntent);

// Create the remote input
RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
        .setLabel(replyLabel)
        .build();

// Add remote input to wearable options and apply to notification
Notification replyNotification =
        new WearableNotificationOptions.Builder()
        .addRemoteInputForContentIntent(remoteInput)
        .build()
        .applyTo(replyNotificationBuilder)
        .build();

By using addRemoteInputForContentIntent() to add the RemoteInput object to the notification's primary action, the button that normally appears as an "Open" action becomes the "Reply" action and starts the voice input UI when users select it on Android Wear.

Receive Voice Input for a Secondary Action

If the "Reply" action is not your notification's primary action and you want to enable voice input for a secondary action, add the RemoteInput to a new action button defined by an Action object.

You should instantiate the WearableAction with the WearableAction.Builder() constructor, which takes an icon and text label for the action button, plus the PendingIntent the system should use to invoke your app when the user selects the action. For example:

// Create the pending intent to fire when the user selects the action
Intent replyIntent = new Intent(this, ReplyActivity.class);
PendingIntent pendingReplyIntent =
        PendingIntent.getActivity(this, 0, replyIntent, 0);

// Create the remote input
RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
        .setLabel(replyLabel)
        .build();

// Create the notification action
WearableAction replyAction = new WearableAction.Builder(R.drawable.ic_message,
        "Reply", pendingIntent)
        .addRemoteInput(remoteInput)
        .build();

After you add the RemoteInput to the Wearablection, set the WearableAction on the WearableNotifications.Builder using addAction(). For example:

// Create basic notification builder
NotificationCompat.Builder replyNotificationBuilder =
        new NotificationCompat.Builder(this)
                .setContentTitle("New message");

// Create the notification action and add remote input
WearableAction replyAction = new WearableAction.Builder(R.drawable.ic_message,
        "Reply", pendingIntent)
        .addRemoteInput(remoteInput)
        .build();

// Create wearable notification and add action
Notification replyNotification =
        new WearableNotificationOptions.Builder()
                .addAction(replyAction)
                .build()
                .applyTo(replyNotificationBuilder)
                .build();

Now, when the user selects "Reply" from an Android wearable, the system prompts the user for voice input (and shows the list of pre-defined replies, if provided). Once the user completes a response, the system invokes the Intent attached to the action and adds the EXTRA_VOICE_REPLY extra (the string you passed to the RemoteInput.Builder constructor) with the user's message as the string value.

Obtaining the Voice Input as a String

To obtain the user's voice input, call getResultsFromIntent(), passing in the "Reply" action's intent. This method returns a Bundle that represents the intent's extras. You can then query the Bundle to obtain the user's voice input string.

The following code shows a method that accepts an intent and returns the voice input string, which is referenced by the EXTRA_VOICE_REPLY key that is used in the previous examples:

/**
 * Obtain the intent that started this activity by calling
 * Activity.getIntent() and pass it into this method to
 * get the associated voice input string.
 */
private String getMessageText(Intent intent) {
    Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
        if (remoteInput != null) {
            return remoteInput.getString(Intent.EXTRA_VOICE_REPLY);
        }
    }
    return null;
}