1page.title=Providing Messaging for Auto
2page.tags="auto", "car", "automotive", "messaging"
3page.article=true
4
5@jd:body
6
7<div id="tb-wrapper">
8<div id="tb">
9  <h2>Dependencies and Prerequisites</h2>
10  <ul>
11    <li>Android 5.0 (API level 21) or higher</li>
12  </ul>
13
14    <h2>This class teaches you to:</h2>
15
16    <ul>
17      <li><a href="#overview">Provide Messaging Services</a></li>
18      <li><a href="#manifest">Configure Your Manifest</a></li>
19      <li><a href="#support-lib">Import Support Library for Messaging</a></li>
20      <li><a href="#messaging">Notify Users of Messages</a></li>
21      <li><a href="#handle_actions">Handle User Actions</a></li>
22    </ul>
23
24    <h2>Related Samples</h2>
25
26    <ul>
27      <li><a href="{@docRoot}samples/MessagingService/index.html">
28        MessagingService</a></li>
29    </ul>
30
31    <h2>See Also</h2>
32
33    <ul>
34      <li><a href="{@docRoot}shareables/auto/AndroidAuto-messaging-apps.pdf">
35        User Experience Guidelines: Messaging Apps</a></li>
36      <li><a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">
37        Notifications</a></li>
38    </ul>
39</div>
40</div>
41
42<a class="notice-developers-video wide"
43    href="https://www.youtube.com/watch?v=gSVLuaOTIPk">
44<div>
45    <h3>Video</h3>
46    <p>DevBytes: Android Auto Messaging</p>
47</div>
48</a>
49
50<p>
51  Staying connected through text messages is important to many drivers. Chat apps can let users
52  know if a child need to be picked up, or if a dinner location has been changed. Apps that provide
53  sports information might tell the user who just won the big game, and let the user ask questions
54  about other games being played. The Android framework enables messaging apps to extend their
55  services into car dashboards using a standard user interface that lets drivers keep their eyes
56  on the road.
57</p>
58
59<p>
60  Apps that support messaging can be extended to pass messaging notifications to Auto
61  dashboard systems, alerting them to new messages and allowing them to respond. You can configure
62  your messaging app to provide these services when an Android mobile device with your app
63  installed is connected to an Auto dashboard. Once connected, your app can provide text
64  information to users and allow them to respond. The Auto dashboard system handles displaying the
65  notification and the interface for replies.
66</p>
67
68<p>
69  This lesson assumes that you have built an app that displays messages to the user and receive the
70  user's replies, such as a chat app. It shows you how to extend your app to hand those messages
71  off to an Auto device for display and replies.
72</p>
73
74
75<h2 id="overview">Provide Messaging Services</h2>
76
77<p>
78  Messaging apps do not run directly on the Android dashboard hardware. They are installed on
79  separate, Android mobile device. When the mobile device is plugged into a dashboard,
80  the installed messaging apps can offer services for viewing and responding to messages
81  through the Auto user interface.
82</p>
83
84<p>To enable your app to provide messaging services for Auto devices:</p>
85
86<ul>
87  <li>Configure your app manifest to indicate that your app provides messaging services which are
88  compatible with Android Auto dashboard devices.
89  </li>
90  <li>Build and send a specific type of <a href=
91  "{@docRoot}guide/topics/ui/notifiers/notifications.html">notification</a> for display on Auto
92  devices.
93  </li>
94  <li>Configure your app to receive {@link android.content.Intent} objects that indicate a user
95    has read or replied to a message.
96</ul>
97
98
99<h2 id="#manifest">Configure Your Manifest</h2>
100
101<p>
102  You configure your app <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a>
103  to indicate that it supports messaging services for Auto devices and handle message actions. This
104  section describes what changes to make to your manifest to support messaging for Auto devices.
105</p>
106
107
108<h3 id="manifest-messaging">Declare Auto messaging support</h3>
109
110<p>
111  When a user connects a Android mobile device to a dashboard running Android, the dashboard
112  device looks for apps that declare support for vehicle services, such as messaging. You indicate
113  that your app supports cars capabilities using the following manifest entry:
114</p>
115
116<pre>
117&lt;application&gt;
118    ...
119    &lt;meta-data android:name="com.google.android.gms.car.application"
120        android:resource="@xml/automotive_app_desc" /&gt;
121    ...
122&lt;application&gt;
123</pre>
124
125<p>
126  This manifest entry refers to a secondary xml file, where you declare what Auto capabilities your
127  app supports. For an app that supports messaging for Auto devices, add an xml file to the {@code
128  res/xml/} your app's development project directory as {@code automotive_app_desc.xml}, with the
129  following content:
130</p>
131
132<pre>
133&lt;automotiveApp&gt;
134    &lt;uses name="notification"/&gt;
135&lt;/automotiveApp&gt;
136</pre>
137
138<p>
139  For more information about declaring capabilities for Auto devices, see <a href=
140  "{@docRoot}training/auto/start/index.html#auto-metadata">Getting Started with Auto</a>.
141</p>
142
143
144<h3 id="manifest-intent">Define read and reply intent filters</h3>
145
146<p>
147  Auto devices use {@link android.content.Intent} objects that indicate a user has read or replied
148  to a message provided by your app. Your app defines intent types for reading and replying to
149  messages and adds this information to messaging notifications for Auto devices, so that the
150  dashboard system can notify your app when a user takes one of these actions.
151</p>
152
153<p>
154  You define the read action and reply action intents types for your app and the {@link
155  android.content.BroadcastReceiver} classes that handle them in the manifest. The following code
156  example demonstrates how to declare these intents and their associated receivers.
157</p>
158
159<pre>
160&lt;application&gt;
161    ...
162    &lt;receiver android:name="<em>.MyMessageReadReceiver</em>"&gt;
163        &lt;intent-filter&gt;
164          &lt;action android:name="<em>com.myapp.messagingservice.ACTION_MESSAGE_HEARD</em>"/&gt;
165        &lt;/intent-filter&gt;
166    &lt;/receiver&gt;
167
168    &lt;receiver android:name="<em>.MyMessageReplyReceiver</em>"&gt;
169        &lt;intent-filter&gt;
170          &lt;action android:name="<em>com.myapp.messagingservice.ACTION_MESSAGE_REPLY</em>"/&gt;
171        &lt;/intent-filter&gt;
172    &lt;/receiver&gt;
173    ...
174&lt;/application&gt;
175</pre>
176
177<p>
178  The definition of the {@link android.content.BroadcastReceiver} classes shown in this example
179  is discussed in <a href="#handle_actions">Handle User Actions</a>.
180</p>
181
182
183<h2 id="support-lib">Import Support Library for Messaging</h3>
184
185<p>
186  Building notifications for use with Auto devices requires classes from the
187  <a href="{@docRoot}tools/support-library/features.html#v4">v4 support library</a>. Use the
188  <a href="{@docRoot}tools/help/sdk-manager.html">Android SDK Manager</a> to update the
189  <em>Extras > Android Support Repository</em> to version 9 or higher and the
190  <em>Extras > Android Support Library</em> to version 21.0.2 or higher.
191</p>
192
193<p>
194  After you have updated the support libraries, import them into your Android Studio development
195  project by adding this dependency to your
196  <a href="{@docRoot}sdk/installing/studio-build.html#configBuild">build.gradle</a> file:
197</p>
198
199<pre>
200dependencies {
201    ...
202    compile 'com.android.support:support-v4:21.0.+'
203}
204</pre>
205
206<p>
207  For information about importing the support library into development projects for other
208  development environments, see <a href="{@docRoot}tools/support-library/setup.html">Support
209  Library Setup</a>.
210</p>
211
212
213
214<h2 id="messaging">Notify Users of Messages</h2>
215
216<p>
217  A messaging app provides messages to a connected Auto dashboard using the <a href=
218  "{@docRoot}guide/topics/ui/notifiers/notifications.html">notifications</a> framework. When your
219  messaging app has a message for a user, you build a specially configured notification that is
220  received by the dashboard system and presented to the user. The Auto device manages the
221  presentation on the dashboard screen and may play the message via text-to-speech. The dashboard
222  system also handles voice interaction if the user replies to a message using verbal input.
223</p>
224
225<p>
226  The messaging user interface for Auto presents users with two levels of information about
227  messages. The first level of notification tells users what <em>conversations</em> are
228  available, and who they are with, but not the content of the messages. Typically, a
229  conversation is one or more messages from another user to the Auto user.
230</p>
231
232<p>
233  The second level of the notification is the actual content of messages in the conversation. If a
234  user indicates they want to hear the messages in a conversation, the Auto user interface plays
235  the messages using text-to-speech.
236</p>
237
238<p>
239  This section describes how to notify Auto users that conversations are available and
240  provide the content of messages in those conversations.
241</p>
242
243
244<h3 id="build_conversation">Build message conversations</h4>
245
246<p>
247  Messaging notifications for Auto organize messages into conversations using the {@link
248  android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation} class,
249  that represents an unread or new
250  portion of a conversation from a particular sender. It contains a list of messages from the
251  sender.
252</p>
253
254<p>
255  Use the {@link android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation.Builder} class to create an unread conversation object,
256  as shown in the following example code:
257</p>
258
259<pre>
260// Build a RemoteInput for receiving voice input in a Car Notification
261RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
262        .setLabel(getApplicationContext().getString(R.string.notification_reply))
263        .build();
264
265// Create an unread conversation object to organize a group of messages
266// from a particular sender.
267UnreadConversation.Builder unreadConvBuilder =
268    new UnreadConversation.Builder(participantName)
269        .setReadPendingIntent(msgHeardPendingIntent)
270        .setReplyAction(replyPendingIntent, remoteInput);
271</pre>
272
273<p>
274  This conversation object includes a {@link android.app.PendingIntent}, which allows the Auto
275  device to signal your app that the conversation has been read by the Auto user. The construction
276  of this intent is discussed in the <a href="#conversation-intents">Creating conversation read and
277  reply intents</a> section.
278</p>
279
280<p>
281  If your app supports replying to a conversation, you must call the {@link android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation.Builder#setReplyAction setReplyAction()}
282  method and provide a pending intent to pass that user action back to your app. The
283  {@link android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation}
284  object you create must also include a {@link
285  android.support.v4.app.RemoteInput} object. When the Auto user
286  receiving this conversation speaks a reply, the remote input objects lets your app get a text
287  version of the voice reply.
288</p>
289
290
291<h4 id="conversation-messages">Associate messages with conversations</h4>
292
293<p>
294  Messages provided for Auto must be associated with a conversation using the
295  {@link android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation}
296  class. The following code example shows how
297  to associate individual messages with a conversation object.
298</p>
299
300<pre>
301// Note: Add messages from oldest to newest to the UnreadConversation.Builder
302for (Iterator&lt;String&gt; messages = conversation.getMessages().iterator();
303     messages.hasNext(); ) {
304    String message = messages.next();
305    unreadConvBuilder.addMessage(message);
306}
307</pre>
308
309<p>
310  When a new message arrives in a particular conversation, your app should check if there is
311  already a conversation object for that particular conversation. If there is, associate the new
312  message with the existing conversation instead of building a new one.
313</p>
314
315
316<h4 id="conversation-intents">Create conversation read and reply intents</h4>
317
318<p>
319  Unread conversation objects contain intents for reading and replying to a conversation. You
320  create a {@link android.app.PendingIntent} object for each of these actions, so the Auto device
321  can notify your app of action taken by the Auto user on a particular conversation.
322</p>
323
324<p>
325  The following example code demonstrates how to define a {@link android.app.PendingIntent} to let
326  your app know if a conversation was listened to by the Auto user:
327</p>
328
329<pre>
330Intent msgHeardIntent = new Intent()
331    .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
332    .setAction(<em>com.myapp.messagingservice.ACTION_MESSAGE_HEARD</em>)
333    .putExtra("conversation_id", <em>conversationId</em>);
334
335PendingIntent msgHeardPendingIntent =
336    PendingIntent.getBroadcast(getApplicationContext(),
337        <em>conversationId</em>,
338        msgHeardIntent,
339        PendingIntent.FLAG_UPDATE_CURRENT);
340</pre>
341
342<p>
343  In this example, {@code conversationId} is an integer that identifies the current conversation.
344  The value of {@link android.content.Intent#setAction setAction()} is an intent filter identifier for heard messages which is
345  defined in your app manifest, as shown in <a href="#manifest-intent">Define read and reply intent
346  filters</a>.
347</p>
348
349<p>
350  If your app supports replying to conversations, you also create a {@link
351  android.app.PendingIntent} for each conversation to notify your app that the user has replied.
352  The following code example shows you how to build this intent for use with a particular
353  conversation:
354</p>
355
356<pre>
357Intent msgReplyIntent = new Intent()
358    .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
359    .setAction(<em>com.myapp.messagingservice.ACTION_MESSAGE_REPLY</em>)
360    .putExtra("conversation_id", <em>conversationId</em>);
361
362PendingIntent msgReplyPendingIntent = PendingIntent.getBroadcast(
363    getApplicationContext(),
364    <em>conversationId</em>,
365    msgReplyIntent,
366    PendingIntent.FLAG_UPDATE_CURRENT);
367</pre>
368
369<p>
370  Once again, {@code conversationId} is an integer that uniquely identifies this conversation. The
371  value of {@link android.content.Intent#setAction setAction()} is an intent filter identifier for replies which is defined in your
372  app manifest, as shown in <a href="#manifest-intent">Define read and reply intent filters</a>.
373</p>
374
375
376<h3 id="sending_messages">Sending Messages</h4>
377
378<p>
379  When a message arrives for a conversation, you take the following steps to dispatch it as a
380  notification to Auto.
381</p>
382
383<p>First, add the message to the {@link
384android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation.Builder}
385for this conversation, and update its timestamp:</p>
386
387<pre>
388unreadConvBuilder.addMessage(<em>messageString</em>)
389    .setLatestTimestamp(<em>currentTimestamp</em>);
390</pre>
391
392<p>Then create a {@link android.support.v4.app.NotificationCompat.Builder}
393object that you'll use to build the actual notification. You'll need to use the
394pending intents you created in the previous step.</p>
395
396<pre>
397NotificationCompat.Builder notificationBuilder =
398    new NotificationCompat.Builder(getApplicationContext())
399        .setSmallIcon(R.drawable.<em>notification_icon</em>)
400        .setLargeIcon(<em>icon_bitmap</em>)
401        .setContentText(<em>messageString</em>)
402        .setWhen(<em>currentTimestamp</em>)
403        .setContentTitle(<em>participant_name</em>)
404        .setContentIntent(msgHeardPendingIntent);
405
406</pre>
407
408<p>You'll also need to extend the  {@link
409android.support.v4.app.NotificationCompat.Builder} with the {@link
410android.support.v4.app.NotificationCompat.CarExtender}. This is where you
411actually create the {@link android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation} object using the builder you
412just created, and attach it to the {@link
413android.support.v4.app.NotificationCompat.CarExtender}:</p>
414
415<pre>
416notificationBuilder.extend(new CarExtender()
417    .setUnreadConversation(unreadConvBuilder.build());
418</pre>
419
420<p>Once you've done all this, you use your app's {@link
421android.support.v4.app.NotificationManagerCompat} to send the notification:</p>
422
423<pre>
424NotificationManagerCompat msgNotificationManager =
425    NotificationManagerCompat.from(context);
426msgNotificationManager.notify(<em>notificationId</em>, notificationBuilder.build());
427</pre>
428
429<h2 id="handle_actions">Handle User Actions</h2>
430
431<p>
432  When your create and dispatch a notification for messaging, you specify intents to be triggered
433  when the Auto user hears the message and when the user dictates a reply. Your app indicates to
434  the Android framework that it handles these intends by registering them through it's manifest, as
435  discussed in <a href="#manifest-intent">Define read and reply intent filters</a>.
436</p>
437
438<p>
439  In addition to registering these intent filters, your app must provide code to handle these
440  actions. Your app can do this by providing a service or {@link android.content.BroadcastReceiver}
441  objects that handle these intents.</p>
442
443<p>
444  For more information about intents, see <a href=
445  "{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a>.
446</p>
447
448
449<h3 id="handling_msg_heard">Handling a message heard action</h3>
450
451<p>
452  When a user listens to a messaging conversation through the Auto user interface, the dashboard
453  device sends a read intent based on how your app defined the messaging notification. Your app
454  catches that intent and invokes the broadcast receiver class associated with it, or the service
455  method set up to handle that action.
456</p>
457
458<p>
459  The following code example shows how to define a {@link android.content.BroadcastReceiver} class
460  to handle a received message heard intent:
461</p>
462
463<pre>
464public class MessageHeardReceiver extends BroadcastReceiver {
465
466    &#64;Override
467    public void onReceive(Context context, Intent intent) {
468
469        // If you set up the intent as described in
470        // "Create conversation read and reply intents",
471        // you can get the conversation ID by calling:
472        int conversationId = intent.getIntExtra("conversation_id", -1);
473
474        // Remove the notification to indicate it has been read
475        // and update the list of unread conversations in your app.
476    }
477}
478</pre>
479
480<p>
481  Once a notification is read, your app can remove it by calling
482  {@link android.support.v4.app.NotificationManagerCompat#cancel} with the notification ID.
483  Within your app, you should mark the messages provided in the notification as read.
484</p>
485
486
487<p class="note">
488  <strong>Note:</strong> An alternative to this implementation is to use a service in a
489  {@link android.app.PendingIntent}.
490</p>
491
492
493<h3 id="handling_reply">Handling a reply action</h3>
494
495<p>
496  When a user replies to a messaging conversation through the Auto user interface, the dashboard
497  system sends a reply intent based on how your app defined the messaging notification. Your app
498  catches that intent and invokes the broadcast receiver class associated with it, or the service
499  method set up to handle that action.
500</p>
501
502<p>
503  The following code example shows how to define a {@link android.content.BroadcastReceiver} class
504  to handle a received message reply intent:
505</p>
506
507<pre>
508  public class MessageReplyReceiver extends BroadcastReceiver {
509
510
511    &#64;Override
512    public void onReceive(Context context, Intent intent) {
513        // If you set up the intent as described in
514        // "Create conversation read and reply intents",
515        // you can get the conversation ID by calling:
516        int conversationId = intent.getIntExtra("conversation_id", -1).
517
518    }
519
520    /**
521     * Get the message text from the intent.
522     * Note that you should call
523     * RemoteInput.getResultsFromIntent() to process
524     * the RemoteInput.
525     */
526    private CharSequence getMessageText(Intent intent) {
527        Bundle remoteInput =
528            RemoteInput.getResultsFromIntent(intent);
529        if (remoteInput != null) {
530            return remoteInput.getCharSequence("extra_voice_reply");
531        }
532        return null;
533    }
534
535}</pre>
536