1page.title=Providing Messaging for Auto
2page.tags="auto", "car", "automotive", "messaging"
3page.article=true
4
5page.metaDescription=Learn how to extend your messaging app for use in Android Auto devices.
6page.image=auto/images/assets/icons/messaging_app_notifications.png
7
8@jd:body
9
10<div id="tb-wrapper">
11<div id="tb">
12  <h2>Dependencies and Prerequisites</h2>
13  <ul>
14    <li>Android 5.0 (API level 21) or higher</li>
15  </ul>
16
17    <h2>This class teaches you to:</h2>
18
19    <ul>
20      <li><a href="#overview">Provide Messaging Services</a></li>
21      <li><a href="#manifest">Configure Your Manifest</a></li>
22      <li><a href="#support-lib">Import Support Library for Messaging</a></li>
23      <li><a href="#messaging">Notify Users of Messages</a></li>
24      <li><a href="#handle_actions">Handle User Actions</a></li>
25    </ul>
26
27    <h2>Related Samples</h2>
28
29    <ul>
30      <li><a href="{@docRoot}samples/MessagingService/index.html">
31        MessagingService</a></li>
32    </ul>
33
34    <h2>See Also</h2>
35
36    <ul>
37      <li><a href="{@docRoot}shareables/auto/AndroidAuto-messaging-apps.pdf">
38        User Experience Guidelines: Messaging Apps</a></li>
39      <li><a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">
40        Notifications</a></li>
41    </ul>
42</div>
43</div>
44
45<a class="notice-developers-video wide"
46    href="https://www.youtube.com/watch?v=gSVLuaOTIPk">
47<div>
48    <h3>Video</h3>
49    <p>DevBytes: Android Auto Messaging</p>
50</div>
51</a>
52
53<p>
54  Staying connected through messages is important to many drivers. Chat apps can let users
55  know if a child need to be picked up, or if a dinner location has been changed.
56  The Android framework enables messaging apps to extend their
57  services into car dashboards using a standard user interface that lets drivers keep their eyes
58  on the road.
59</p>
60
61<p>
62  Apps that support messaging can be extended to pass messaging notifications to Auto
63  dashboard systems, alerting them to new messages and allowing them to respond. You can configure
64  your messaging app to provide these services when an Android mobile device with your app
65  installed is connected to an Auto dashboard. Once connected, your app can provide text
66  information to users and allow them to respond. The Auto dashboard system handles displaying the
67  notification and the interface for replies.
68</p>
69
70<p>
71  This lesson assumes that you have built an app that displays messages to the user and receive the
72  user's replies, such as a chat app. It shows you how to extend your app to hand those messages
73  off to an Auto device for display and replies.
74</p>
75
76
77<h2 id="overview">Provide Messaging Services</h2>
78
79<p>
80  Messaging apps do not run directly on the Android dashboard hardware. They are installed on
81  a separate Android mobile device. When the mobile device is plugged into a dashboard,
82  the installed messaging apps can offer services for viewing and responding to messages
83  through the Auto user interface.
84</p>
85
86<p>To enable your app to provide messaging services for Auto devices:</p>
87
88<ul>
89  <li>Configure your app manifest to indicate that your app provides messaging services which are
90  compatible with Android Auto dashboard devices.
91  </li>
92  <li>Build and send a specific type of <a href=
93  "{@docRoot}guide/topics/ui/notifiers/notifications.html">notification</a> for display on Auto
94  devices.
95  </li>
96  <li>Configure your app to receive {@link android.content.Intent} objects that indicate a user
97    has read or replied to a message.
98</ul>
99
100<h3 id="concepts">Concepts and objects</h3>
101
102<p>Before you start designing your app, it's helpful to understand how Auto
103handles messaging.</p>
104
105<p>Each individual chunk of communication is a <em>message</em>. A message is a
106short length of text, suitable for the Auto device to read aloud. In a chat app,
107this might be a single message from one person to another: <code>"Fitzy -- Jane
108can't come to the ball, her youngest has the croup. :-( --Liz"</code>.</p>
109
110<p>A <em>conversation</em> is a group of messages that are all grouped together
111in some way. Auto uses the conversation information to group the messages
112together when presenting them to the user. In a chat app, a conversation might
113be all the messages between the user and another person (for example, all
114the messages back and forth between Darcy and Elizabeth). Every message
115belongs to a conversation, even if it's the only message in that conversation.
116Each conversation has a <em>conversation name</em>.
117The conversation name is used by Android Auto to
118present the messages; it's up to your app to choose an appropriate conversation
119name. In a chat app, the conversation name is usually the person your user is
120talking to.</p>
121
122<p>The v4 support library defines an {@link
123android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation
124UnreadConversation} object. This object holds all messages in a conversation
125which have not yet been heard by the user. To give those messages to the user,
126you attach that {@link
127android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation
128UnreadConversation} to a notification. However, you do not attach messages to
129the {@link
130android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation
131UnreadConversation} directly. Instead, you must first set up an {@link
132android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation.Builder
133UnreadConversation.Builder} object for the conversation. The messages are added to the builder,
134then when you are ready to send the messages, you use the builder to create the
135actual {@link
136android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation
137UnreadConversation} and attach the {@link
138android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation
139UnreadConversation} to the notification.</p>
140
141<p class="note"><strong>Note:</strong> When Auto presents messages to the
142user, it uses the notification <em>tag</em> and <em>ID</em> to determine which conversation the
143messages belong to. It is important to use the same tag and ID for all messages in
144a conversation, and to not use that tag for other conversations.</p>
145
146<h3 id="#workflow">Workflow</h3>
147
148<p>This section describes how the mobile device interacts with Auto to present
149messages to the user.</p>
150
151<ol>
152
153<li>The app receives a message that it wants to pass on to the user. It attaches
154the message to an  {@link
155android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation
156UnreadConversation} object and attaches it to a notification. That notification
157is associated with a {@link
158android.support.v4.app.NotificationCompat.CarExtender CarExtender} object, which
159indicates that the notification can be handled by Android Auto.</li>
160
161<li>The app posts the notification. The Android notification framework passes the
162message to Auto. Auto uses the notification tag and ID to determine which conversation
163the message belongs to, and presents the message to the user in an appropriate
164way.</li>
165
166<li>When the user listens to the message, Auto triggers the app's message heard
167pending intent. The app should discard the {@link
168android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation
169UnreadConversation} object and its builder at this time, since the messages
170contained in those objects have been heard by the user.</li>
171
172<li>If the user sends a reply, Auto triggers the app's "message reply" intent and
173attaches a transcript of the user's response.  The app can take appropriate
174action, based on the app's logic. For example, a chat app might interpret the
175reply as a message to go to the other conversation participants.</li>
176
177</ol>
178
179<h2 id="#manifest">Configure Your Manifest</h2>
180
181<p>
182  You configure your app <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a>
183  to indicate that it supports messaging services for Auto devices and handle message actions. This
184  section describes what changes to make to your manifest to support messaging for Auto devices.
185</p>
186
187<h3 id="manifest-messaging">Declare Auto messaging support</h3>
188
189<p>
190  When a user connects a Android mobile device to a dashboard running Android, the dashboard
191  device looks for apps that declare support for vehicle services, such as messaging. You indicate
192  that your app supports cars capabilities using the following manifest entry:
193</p>
194
195<pre>
196&lt;application&gt;
197    ...
198    &lt;meta-data android:name="com.google.android.gms.car.application"
199        android:resource="@xml/automotive_app_desc" /&gt;
200    ...
201&lt;application&gt;
202</pre>
203
204<p>
205  This manifest entry refers to a secondary xml file, where you declare what Auto capabilities your
206  app supports. For an app that supports messaging for Auto devices, add an xml file to the {@code
207  res/xml/} your app's development project directory as {@code automotive_app_desc.xml}, with the
208  following content:
209</p>
210
211<pre>
212&lt;automotiveApp&gt;
213    &lt;uses name="notification"/&gt;
214&lt;/automotiveApp&gt;
215</pre>
216
217<p>
218  For more information about declaring capabilities for Auto devices, see <a href=
219  "{@docRoot}training/auto/start/index.html#auto-metadata">Getting Started with Auto</a>.
220</p>
221
222
223<h3 id="manifest-intent">Define read and reply intent filters</h3>
224
225<p>
226  Auto devices use {@link android.content.Intent} objects that indicate a user has read or replied
227  to a message provided by your app. Your app defines intent types for reading and replying to
228  messages and adds this information to messaging notifications for Auto devices, so that the
229  dashboard system can notify your app when a user takes one of these actions.
230</p>
231
232<p>
233  You define the read action and reply action intents types for your app and the {@link
234  android.content.BroadcastReceiver} classes that handle them in the manifest. The following code
235  example demonstrates how to declare these intents and their associated receivers.
236</p>
237
238<pre>
239&lt;application&gt;
240    ...
241    &lt;receiver android:name=".MyMessageHeardReceiver"&gt;
242        &lt;intent-filter&gt;
243          &lt;action android:name="com.myapp.messagingservice.MY_ACTION_MESSAGE_HEARD"/&gt;
244        &lt;/intent-filter&gt;
245    &lt;/receiver&gt;
246
247    &lt;receiver android:name=".MyMessageReplyReceiver"&gt;
248        &lt;intent-filter&gt;
249          &lt;action android:name="com.myapp.messagingservice.MY_ACTION_MESSAGE_REPLY"/&gt;
250        &lt;/intent-filter&gt;
251    &lt;/receiver&gt;
252    ...
253&lt;/application&gt;
254</pre>
255
256<p>   In this example, <code>"MyMessageReadReceiver"</code> and
257<code>"MyMessageReplyReceiver"</code> are the names of the {@link
258android.content.BroadcastReceiver} subclasses you define to handle the
259intents. You can choose whatever you like   as the action names, but it's best
260to prepend your package name to ensure that   the action names are unique. For
261more information about handling actions, see <a href="#handle_actions">Handle
262User Actions</a>. </p>
263
264<h2 id="support-lib">Import Support Library for Messaging</h3>
265
266<p>
267  Building notifications for use with Auto devices requires classes from the
268  <a href="{@docRoot}tools/support-library/features.html#v4">v4 support library</a>. Use the
269  <a href="{@docRoot}tools/help/sdk-manager.html">Android SDK Manager</a> to update the
270  <em>Extras > Android Support Repository</em> to version 9 or higher and the
271  <em>Extras > Android Support Library</em> to version 21.0.2 or higher.
272</p>
273
274<p>
275  After you have updated the support libraries, import them into your Android Studio development
276  project by adding this dependency to your
277  <a href="{@docRoot}sdk/installing/studio-build.html#configBuild">build.gradle</a> file:
278</p>
279
280<pre>
281dependencies {
282    ...
283    compile 'com.android.support:support-v4:21.0.2'
284}
285</pre>
286
287<p>
288  For information about importing the support library into development projects for other
289  development environments, see <a href="{@docRoot}tools/support-library/setup.html">Support
290  Library Setup</a>.
291</p>
292
293
294
295<h2 id="messaging">Notify Users of Messages</h2>
296
297<p>
298  A messaging app provides messages to a connected Auto dashboard using the <a href=
299  "{@docRoot}guide/topics/ui/notifiers/notifications.html">notifications</a> framework. When your
300  messaging app has a message for a user, you build a specially configured notification that is
301  received by the dashboard system and presented to the user. The Auto device manages the
302  presentation on the dashboard screen and may play the message via text-to-speech. The dashboard
303  system also handles voice interaction if the user replies to a message using verbal input.
304</p>
305
306<p>
307  The messaging user interface for Auto presents users with two levels of information about
308  messages. The first level of notification tells users what <em>conversations</em> are
309  available, and who they are with, but not the content of the messages. Typically, a
310  conversation is one or more messages from another user to the Auto user.
311</p>
312
313<p>
314  The second level of the notification is the actual content of messages in the conversation. If a
315  user indicates they want to hear the messages in a conversation, the Auto user interface plays
316  the messages using text-to-speech.
317</p>
318
319<p>
320  This section describes how to notify Auto users that conversations are available and
321  provide the content of messages in those conversations.
322</p>
323
324<h4 id="conversation-intents">Create conversation read and reply intents</h4>
325
326<p>
327  Unread conversation objects contain intents for reading and replying to a conversation. You
328  create a {@link android.app.PendingIntent} object for each of these actions, so the Auto device
329  can notify your app of action taken by the Auto user on a particular conversation.
330</p>
331
332<p>
333  The following example code demonstrates how to define a {@link android.app.PendingIntent} to let
334  your app know if a conversation was read to the Auto user:
335</p>
336
337<pre>
338Intent msgHeardIntent = new Intent()
339    .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
340    .setAction("com.myapp.messagingservice.MY_ACTION_MESSAGE_HEARD")
341    .putExtra("conversation_id", thisConversationId);
342
343PendingIntent msgHeardPendingIntent =
344    PendingIntent.getBroadcast(getApplicationContext(),
345        thisConversationId,
346        msgHeardIntent,
347        PendingIntent.FLAG_UPDATE_CURRENT);
348</pre>
349
350<p>In this example, {@code thisConversationId} is an integer that identifies the
351current conversation.   The value of {@link android.content.Intent#setAction
352Intent.setAction()} is the intent filter identifier for heard messages which you
353defined in your app manifest, as shown in <a href="#manifest-intent">Define read
354and reply intent filters</a>. </p>
355
356<p>
357  If your app supports replying to conversations, you also create a {@link
358  android.app.PendingIntent} for each conversation to notify your app that the user has replied.
359  The following code example shows you how to build this intent for use with a particular
360  conversation:
361</p>
362
363<pre>
364Intent msgReplyIntent = new Intent()
365    .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
366    .setAction("com.myapp.messagingservice.MY_ACTION_MESSAGE_REPLY")
367    .putExtra("conversation_id", thisConversationId);
368
369PendingIntent msgReplyPendingIntent = PendingIntent.getBroadcast(
370    getApplicationContext(),
371    thisConversationId,
372    msgReplyIntent,
373    PendingIntent.FLAG_UPDATE_CURRENT);
374</pre>
375
376<p>   Once again, {@code thisConversationId} is an integer that uniquely identifies
377this conversation, and    the value you pass to {@link
378android.content.Intent#setAction Intent.setAction()} is the intent filter
379identifier you defined for replies in your   app manifest. </p>
380
381<h3 id="build_conversation">Set up the conversation builder</h4>
382
383<p>
384  Messaging notifications for Auto organize messages into conversations using the {@link
385  android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation} class,
386  that represents an unread or new
387  portion of a conversation from a particular sender. It contains a list of messages from the
388  sender.
389</p>
390
391<p>
392  You generally do not configure the {@link
393  android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation UnreadConversation}
394  directly. Instead, you configure an
395  {@link android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation.Builder
396  UnreadConversation.Builder} with the information about the conversation,
397  as shown in the following example code.
398</p>
399
400<pre>
401// Build a RemoteInput for receiving voice input in a Car Notification
402RemoteInput remoteInput = new RemoteInput.Builder(MY_VOICE_REPLY_KEY)
403        .setLabel(getApplicationContext().getString(R.string.notification_reply))
404        .build();
405
406// Create an unread conversation object to organize a group of messages
407// from a particular sender.
408UnreadConversation.Builder unreadConvBuilder =
409    new UnreadConversation.Builder(conversationName)
410        .setReadPendingIntent(msgHeardPendingIntent)
411        .setReplyAction(msgReplyPendingIntent, remoteInput);
412</pre>
413
414<p class="note">
415  <strong>Note:</strong> You won't actually create the {@link
416  android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation
417  UnreadConversation} until you are almost ready to send the message.
418</p>
419
420<p>
421  This conversation object includes a {@link android.app.PendingIntent}, which allows the Auto
422  device to signal your app that the conversation has been read by the Auto user. The construction
423  of this intent is discussed in the <a href="#conversation-intents">Creating conversation read and
424  reply intents</a> section.
425</p>
426
427<p>
428  If your app supports replying to a conversation, you must call the
429  {@link android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation.Builder#setReplyAction
430  UnreadConversation.Builder.setReplyAction()}
431  method and provide a pending intent to pass that user action back to your app. The
432  {@link android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation
433  UnreadConversation}
434  object you create must also include a {@link
435  android.support.v4.app.RemoteInput} object. When the Auto user
436  receiving this conversation speaks a reply, the remote input objects lets your app get a text
437  version of the voice reply.
438</p>
439
440<h3 id="sending_messages">Sending Messages</h4>
441
442<p>
443  When a message arrives for a conversation, you take the following steps to dispatch it as a
444  notification to Auto.
445</p>
446
447<p>First, add the message to the {@link
448android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation.Builder
449UnreadConversation.Builder} for this conversation, and update its timestamp:</p>
450
451<pre>
452unreadConvBuilder.addMessage(messageString)
453    .setLatestTimestamp(currentTimestamp);
454</pre>
455
456<p class="note"><strong>Note:</strong> If you are sending several messages at
457once, add them to the {@link
458android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation.Builder
459UnreadConversation.Builder} in order, from oldest to newest.</p>
460
461<p>Then create the {@link android.support.v4.app.NotificationCompat.Builder
462NotificationCompat.Builder}
463object that builds the actual notification. You need to use the
464pending intents you created in the previous step.</p>
465
466<pre>
467NotificationCompat.Builder notificationBuilder =
468    new NotificationCompat.Builder(getApplicationContext())
469        .setSmallIcon(smallIconResourceID)
470        .setLargeIcon(largeIconBitmap);
471</pre>
472
473<dl>
474  <dt><code>smallIconResourceID</code></dt>
475  <dd>The resource ID of a small icon to use for the conversation. This is
476    typically a generic icon for the messaging app.</dd>
477
478  <dt><code>largeIconBitmap</code></dt>
479  <dd>A {@link android.graphics.Bitmap} of a large version of the icon. This
480    is typically a conversation-specific graphic. For example, if this is a
481    chat app, the large icon would be a picture of the person the user is
482    chatting with.</dd>
483
484  <dt><code>messageString</code></dt>
485  <dd>The text of the message you want to send. (If you are sending several
486    messages at once, concatenate them into a single string, with the oldest
487    message first.)</dd>
488
489  <dt><code>currentTimestamp</code></dt>
490  <dd>The message timestamp. (If you are sending several messages at once,
491    use the timestamp of the most recent message.)</dd>
492
493  <dt><code>conversationName</code></dt>
494
495  <dd>The name you chose for this conversation (for example, the name of the
496    person the user is chatting with). This should be the same conversation
497    name you used when you created the {@link
498android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation.Builder
499    UnreadConversation.Builder}.</dd>
500
501  <dt><code>msgHeardPendingIntent</code></dt>
502  <dd>The pending intent object you created in
503    <a href="#conversation-intents">Create conversation read and reply
504      intents</a>.</dd>
505</dl>
506
507
508<p>You'll also need to extend the  {@link
509android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} with the {@link
510android.support.v4.app.NotificationCompat.CarExtender CarExtender}. This is where you
511actually create the
512{@link android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation
513UnreadConversation} object using the builder you
514just created, and attach it to the {@link
515android.support.v4.app.NotificationCompat.CarExtender CarExtender}:</p>
516
517<pre>
518notificationBuilder.extend(new CarExtender()
519    .setUnreadConversation(unreadConvBuilder.build());
520</pre>
521
522<p class="note"><strong>Note:</strong> If you wish, you can set an override icon
523or color for the {@link android.support.v4.app.NotificationCompat.CarExtender
524CarExtender} by calling {@link
525android.support.v4.app.NotificationCompat.CarExtender#setLargeIcon
526setLargeIcon()} or {@link
527android.support.v4.app.NotificationCompat.CarExtender#setColor setColor()}. The
528override icon or color is used when the notification is handled by a car, and
529has no effect if the notification is handled on the Android device. This is
530useful if the notification's default icon or color are not suitable for the
531car's display.</p>
532
533<p>Once you've done all this, you use your app's {@link
534android.support.v4.app.NotificationManagerCompat} to send the notification:</p>
535
536<pre>
537NotificationManagerCompat msgNotificationManager =
538    NotificationManagerCompat.from(context);
539msgNotificationManager.notify(notificationTag,
540    notificationId, notificationBuilder.build());
541</pre>
542
543<h2 id="handle_actions">Handle User Actions</h2>
544
545<p>
546  When your create and dispatch a notification for messaging, you specify intents to be triggered
547  when the Auto user hears the message and when the user dictates a reply. Your app indicates to
548  the Android framework that it handles these intends by registering them through its manifest, as
549  discussed in <a href="#manifest-intent">Define read and reply intent filters</a>.
550</p>
551
552<p>
553  In addition to registering these intent filters, your app must provide code to handle these
554  actions. Your app can do this by providing a service or {@link android.content.BroadcastReceiver}
555  objects that handle these intents.</p>
556
557<p>
558  For more information about intents, see <a href=
559  "{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a>.
560</p>
561
562
563<h3 id="handling_msg_heard">Handling a message heard action</h3>
564
565<p>
566  When a user listens to a messaging conversation through the Auto user interface, the dashboard
567  device sends a read intent based on how your app defined the messaging notification. Your app
568  catches that intent and invokes the broadcast receiver class associated with it, or the service
569  method set up to handle that action.
570</p>
571
572<p>
573  The following code example shows how to define a {@link android.content.BroadcastReceiver} class
574  to handle a received message heard intent:
575</p>
576
577<pre>
578public class MyMessageHeardReceiver extends BroadcastReceiver {
579
580    &#64;Override
581    public void onReceive(Context context, Intent intent) {
582
583        // If you set up the intent as described in
584        // "Create conversation read and reply intents",
585        // you can get the conversation ID by calling:
586        int thisConversationId = intent.getIntExtra("conversation_id", -1);
587
588        // Remove the notification to indicate it has been read
589        // and update the list of unread conversations in your app.
590    }
591}
592</pre>
593
594<p>
595  Once a notification is read, your app can remove it by calling
596  {@link android.support.v4.app.NotificationManagerCompat#cancel
597  NotificationManagerCompat.cancel()} with the notification ID.
598  Within your app, you should mark the messages provided in the notification as read.
599</p>
600
601
602<p class="note">
603  <strong>Note:</strong> An alternative to this implementation is to use a service in a
604  {@link android.app.PendingIntent}.
605</p>
606
607
608<h3 id="handling_reply">Handling a reply action</h3>
609
610<p>
611  When a user replies to a messaging conversation through the Auto user interface, the dashboard
612  system sends a reply intent based on how your app defined the messaging notification. Your app
613  catches that intent and invokes the broadcast receiver class associated with it, or the service
614  method set up to handle that action.
615</p>
616
617<p>
618  The following code example shows how to define a {@link android.content.BroadcastReceiver} class
619  to handle a received message reply intent:
620</p>
621
622<pre>
623  public class MyMessageReplyReceiver extends BroadcastReceiver {
624
625
626    &#64;Override
627    public void onReceive(Context context, Intent intent) {
628        // If you set up the intent as described in
629        // "Create conversation read and reply intents",
630        // you can get the conversation ID by calling:
631        int thisConversationId = intent.getIntExtra("conversation_id", -1).
632
633    }
634
635    /**
636     * Get the message text from the intent.
637     * Note that you should call
638     * RemoteInput.getResultsFromIntent() to process
639     * the RemoteInput.
640     */
641    private CharSequence getMessageText(Intent intent) {
642        Bundle remoteInput =
643            RemoteInput.getResultsFromIntent(intent);
644        if (remoteInput != null) {
645            return remoteInput.getCharSequence(MY_VOICE_REPLY_KEY);
646        }
647        return null;
648    }
649
650}</pre>
651