1page.title=Receiving Voice Input in a Notification
2page.tags=notifications
3helpoutsWidget=true
4
5@jd:body
6
7<div id="tb-wrapper">
8<div id="tb">
9
10<h2>This lesson teaches you to</h2>
11<ol>
12  <li><a href="#VoiceInput">Define the Voice Input</a></li>
13  <li><a href="#AddAction">Add the Voice Input as a Notification Action</li>
14  <li><a href="#ReceiveInput">Receiving the Voice Input as a String</a>
15</ol>
16
17</div>
18</div>
19
20<p>If you have handheld notifications that include an action to input text,
21such as reply to an email, it should normally launch an activity
22on the handheld device to input the text. However, when your notification appears on a wearable,
23there is no keyboard input, so you can let users dictate a reply or provide pre-defined text messages
24using {@link android.support.v4.app.RemoteInput}.
25</p>
26
27<p>When users reply with voice or select one of the available
28messages, the system attaches the text response to the {@link android.content.Intent} you specified
29for the notification action and sends that intent to your handheld app.</p>
30
31<img src="{@docRoot}wear/images/13_voicereply.png" height="200" width="169"
32style="float:right;margin:0 0 20px 40px;clear:right" />
33<img src="{@docRoot}wear/images/03_actions.png" height="200" width="169"
34style="float:right;margin:0 0 20px 40px" />
35
36<p class="note"><strong>Note:</strong> The Android emulator does not support voice input. When
37using the emulator for a wearable device, enable <b>Hardware keyboard present</b> in the AVD settings
38so you can type replies instead.</p>
39
40<h2 id="VoiceInput">Define the Voice Input</h2>
41
42<p>To create an action that supports voice input, create an instance of
43  {@link android.support.v4.app.RemoteInput.Builder} that you can add to your notification action.
44  This class's constructor accepts a string that the system uses as
45  the key for the voice input, which you'll later use to retrieve the text of the
46  input in your handheld app.</p>
47
48<p>For example, here's how to create a
49{@link android.support.v4.app.RemoteInput} object that provides a custom
50label for the voice input prompt:</p>
51
52<pre class="prettyprint">
53// Key for the string that's delivered in the action's intent
54private static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
55
56String replyLabel = getResources().getString(R.string.reply_label);
57
58RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
59        .setLabel(replyLabel)
60        .build();
61</pre>
62
63
64<h3>Add Pre-defined Text Responses</h3>
65
66<img src="{@docRoot}wear/images/12_voicereply.png" height="200"
67style="float:right;margin:0 0 20px 40px" />
68
69<p>In addition to allowing voice input, you can
70    provide up to five text responses that the user can select for quick replies. Call
71 {@link android.support.v4.app.RemoteInput.Builder#setChoices setChoices()} and pass it a string array.</p>
72
73<p>For example, you can define some responses in a resource array:</p>
74
75<p class="code-caption">res/values/strings.xml</code>
76<pre class="prettyprint">
77&lt;?xml version="1.0" encoding="utf-8"?>
78&lt;resources>
79    &lt;string-array name="reply_choices">
80        &lt;item>Yes&lt;/item>
81        &lt;item>No&lt;/item>
82        &lt;item>Maybe&lt;/item>
83    &lt;/string-array>
84&lt;/resources>
85</pre>
86
87<p>Then, inflate the string array and add it to the
88 {@link android.support.v4.app.RemoteInput}:</p>
89
90<pre>
91public static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
92...
93String replyLabel = getResources().getString(R.string.reply_label);
94String[] replyChoices = getResources().getStringArray(R.array.reply_choices);
95
96RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
97        .setLabel(replyLabel)
98        .setChoices(replyChoices)
99        .build();
100</pre>
101
102<h2 id="AddAction">Add the Voice Input as a Notification Action</h2>
103
104<p>
105To set the voice input, attach your
106{@link android.support.v4.app.RemoteInput} object to an action using
107{@link android.support.v4.app.NotificationCompat.Action.Builder#addRemoteInput addRemoteInput()}.
108You can then apply the action to the notification. For example:
109</p>
110
111<pre>
112// Create an intent for the reply action
113Intent replyIntent = new Intent(this, ReplyActivity.class);
114PendingIntent replyPendingIntent =
115        PendingIntent.getActivity(this, 0, replyIntent,
116                PendingIntent.FLAG_UPDATE_CURRENT);
117
118// Create the reply action and add the remote input
119NotificationCompat.Action action =
120        new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
121                getString(R.string.label), replyPendingIntent)
122                .addRemoteInput(remoteInput)
123                .build();
124
125// Build the notification and add the action via WearableExtender
126Notification notification =
127        new NotificationCompat.Builder(mContext)
128                .setSmallIcon(R.drawable.ic_message)
129                .setContentTitle(getString(R.string.title))
130                .setContentText(getString(R.string.content))
131                .extend(new WearableExtender().addAction(action))
132                .build();
133
134// Issue the notification
135NotificationManagerCompat notificationManager =
136        NotificationManagerCompat.from(mContext);
137notificationManager.notify(notificationId, notification);
138</pre>
139<p>
140When you issue this notification, users can swipe to the left to see the "Reply" action button.
141</p>
142
143<h2 id="ReceiveInput">Receiving the Voice Input as a String</h2>
144<p>
145To receive the user's transcribed message in the activity you declared in the reply action's intent,
146call {@link android.support.v4.app.RemoteInput#getResultsFromIntent getResultsFromIntent()},
147passing in the "Reply" action's intent. This method returns a {@link android.os.Bundle} that
148contains the text response. You can then query the {@link android.os.Bundle} to obtain the response.
149
150<p class="note"><b>Note:</b> Do not use {@link android.content.Intent#getExtras Intent.getExtras()}
151to obtain the voice result, because the voice input is stored as
152{@link android.content.ClipData}. The {@link android.support.v4.app.RemoteInput#getResultsFromIntent
153getResultsFromIntent()} method provides a convenient way to receive a character sequence without
154having to process the {@link android.content.ClipData} yourself.
155</p>
156
157<p>
158The following code shows a method that accepts an intent and returns the voice response,
159which is referenced by the <code>EXTRA_VOICE_REPLY</code> key that is used in the previous examples:
160</p>
161
162<pre>
163/**
164 * Obtain the intent that started this activity by calling
165 * Activity.getIntent() and pass it into this method to
166 * get the associated voice input string.
167 */
168
169private CharSequence getMessageText(Intent intent) {
170    Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
171    if (remoteInput != null) {
172        return remoteInput.getCharSequence(EXTRA_VOICE_REPLY);
173    }
174    return null;
175}
176</pre>
177