summaryrefslogtreecommitdiffstats
path: root/docs/html/training/auto/messaging/index.jd
blob: c51ad7ee4318253aced1cc11e9ab845c3322a867 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
page.title=Providing Messaging for Auto
page.tags="auto", "car", "automotive", "messaging"
page.article=true

@jd:body

<div id="tb-wrapper">
<div id="tb">
  <h2>Dependencies and Prerequisites</h2>
  <ul>
    <li>Android 5.0 (API level 21) or higher</li>
  </ul>

    <h2>This class teaches you to:</h2>

    <ul>
      <li><a href="#overview">Provide Messaging Services</a></li>
      <li><a href="#manifest">Configure Your Manifest</a></li>
      <li><a href="#support-lib">Import Support Library for Messaging</a></li>
      <li><a href="#messaging">Notify Users of Messages</a></li>
      <li><a href="#handle_actions">Handle User Actions</a></li>
    </ul>

    <h2>Related Samples</h2>

    <ul>
      <li><a href="{@docRoot}samples/MessagingService/index.html">
        MessagingService</a></li>
    </ul>

    <h2>See Also</h2>

    <ul>
      <li><a href="{@docRoot}shareables/auto/AndroidAuto-messaging-apps.pdf">
        User Experience Guidelines: Messaging Apps</a></li>
      <li><a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">
        Notifications</a></li>
    </ul>
</div>
</div>

<a class="notice-developers-video wide"
    href="https://www.youtube.com/watch?v=gSVLuaOTIPk">
<div>
    <h3>Video</h3>
    <p>DevBytes: Android Auto Messaging</p>
</div>
</a>

<p>
  Staying connected through text messages is important to many drivers. Chat apps can let users
  know if a child need to be picked up, or if a dinner location has been changed. Apps that provide
  sports information might tell the user who just won the big game, and let the user ask questions
  about other games being played. The Android framework enables messaging apps to extend their
  services into car dashboards using a standard user interface that lets drivers keep their eyes
  on the road.
</p>

<p>
  Apps that support messaging can be extended to pass messaging notifications to Auto
  dashboard systems, alerting them to new messages and allowing them to respond. You can configure
  your messaging app to provide these services when an Android mobile device with your app
  installed is connected to an Auto dashboard. Once connected, your app can provide text
  information to users and allow them to respond. The Auto dashboard system handles displaying the
  notification and the interface for replies.
</p>

<p>
  This lesson assumes that you have built an app that displays messages to the user and receive the
  user's replies, such as a chat app. It shows you how to extend your app to hand those messages
  off to an Auto device for display and replies.
</p>


<h2 id="overview">Provide Messaging Services</h2>

<p>
  Messaging apps do not run directly on the Android dashboard hardware. They are installed on
  separate, Android mobile device. When the mobile device is plugged into a dashboard,
  the installed messaging apps can offer services for viewing and responding to messages
  through the Auto user interface.
</p>

<p>To enable your app to provide messaging services for Auto devices:</p>

<ul>
  <li>Configure your app manifest to indicate that your app provides messaging services which are
  compatible with Android Auto dashboard devices.
  </li>
  <li>Build and send a specific type of <a href=
  "{@docRoot}guide/topics/ui/notifiers/notifications.html">notification</a> for display on Auto
  devices.
  </li>
  <li>Configure your app to receive {@link android.content.Intent} objects that indicate a user
    has read or replied to a message.
</ul>


<h2 id="#manifest">Configure Your Manifest</h2>

<p>
  You configure your app <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a>
  to indicate that it supports messaging services for Auto devices and handle message actions. This
  section describes what changes to make to your manifest to support messaging for Auto devices.
</p>


<h3 id="manifest-messaging">Declare Auto messaging support</h3>

<p>
  When a user connects a Android mobile device to a dashboard running Android, the dashboard
  device looks for apps that declare support for vehicle services, such as messaging. You indicate
  that your app supports cars capabilities using the following manifest entry:
</p>

<pre>
&lt;application&gt;
    ...
    &lt;meta-data android:name="com.google.android.gms.car.application"
        android:resource="@xml/automotive_app_desc" /&gt;
    ...
&lt;application&gt;
</pre>

<p>
  This manifest entry refers to a secondary xml file, where you declare what Auto capabilities your
  app supports. For an app that supports messaging for Auto devices, add an xml file to the {@code
  res/xml/} your app's development project directory as {@code automotive_app_desc.xml}, with the
  following content:
</p>

<pre>
&lt;automotiveApp&gt;
    &lt;uses name="notification"/&gt;
&lt;/automotiveApp&gt;
</pre>

<p>
  For more information about declaring capabilities for Auto devices, see <a href=
  "{@docRoot}training/auto/start/index.html#auto-metadata">Getting Started with Auto</a>.
</p>


<h3 id="manifest-intent">Define read and reply intent filters</h3>

<p>
  Auto devices use {@link android.content.Intent} objects that indicate a user has read or replied
  to a message provided by your app. Your app defines intent types for reading and replying to
  messages and adds this information to messaging notifications for Auto devices, so that the
  dashboard system can notify your app when a user takes one of these actions.
</p>

<p>
  You define the read action and reply action intents types for your app and the {@code
  android.content.BroadcastReceiver} classes that handle them in the manifest. The following code
  example demonstrates how to declare these intents and thier associated receivers.
</p>

<pre>
&lt;application&gt;
    ...
    &lt;receiver android:name="<em>.MyMessageReadReceiver</em>"&gt;
        &lt;intent-filter&gt;
          &lt;action android:name="<em>com.myapp.messagingservice.ACTION_MESSAGE_HEARD</em>"/&gt;
        &lt;/intent-filter&gt;
    &lt;/receiver&gt;

    &lt;receiver android:name="<em>.MyMessageReplyReceiver</em>"&gt;
        &lt;intent-filter&gt;
          &lt;action android:name="<em>com.myapp.messagingservice.ACTION_MESSAGE_REPLY</em>"/&gt;
        &lt;/intent-filter&gt;
    &lt;/receiver&gt;
    ...
&lt;/application&gt;
</pre>

<p>
  The definition of the {@code android.content.BroadcastReceiver} classes shown in this example
  is discussed in <a href="#handle_actions">Handle User Actions</a>.
</p>


<h2 id="support-lib">Import Support Library for Messaging</h3>

<p>
  Building notifications for use with Auto devices requires classes from the
  <a href="{@docRoot}tools/support-library/features.html#v4">v4 support library</a>. Use the
  <a href="{@docRoot}tools/help/sdk-manager.html">Android SDK Manager</a> to update the
  <em>Extras > Android Support Repository</em> to version 9 or higher and the
  <em>Extras > Android Support Library</em> to version 21.1.0 or higher.
</p>

<p>
  After you have updated the support libraries, import them into your Android Studio development
  project by adding this dependency to your
  <a href="{@docRoot}sdk/installing/studio-build.html#configBuild">build.gradle</a> file:
</p>

<pre>
dependencies {
    ...
    compile 'com.android.support:support-v4:21.1.+'
}
</pre>

<p>
  For information about importing the support library into development projects for other
  development environments, see <a href="{@docRoot}tools/support-library/setup.html">Support
  Library Setup</a>.
</p>



<h2 id="messaging">Notify Users of Messages</h2>

<p>
  A messaging app provides messages to a connected Auto dashboard using the <a href=
  "{@docRoot}guide/topics/ui/notifiers/notifications.html">notifications</a> framework. When your
  messaging app has a message for a user, you build a specially configured notification that is
  received by the dashboard system and presented to the user. The Auto device manages the
  presentation on the dashboard screen and may play the message via text-to-speech. The dashboard
  system also handles voice interaction if the user replies to a message using verbal input.
</p>

<p>
  The messaging user interface for Auto presents users with two levels of information about
  messages. The first level of notification tells users what <em>conversations</em> are
  available, and who they are with, but not the content of the messages. Typically, a
  conversation is one or more messages from another user to the Auto user.
</p>

<p>
  The second level of the notification is the actual content of messages in the conversation. If a
  user indicates they want to hear the messages in a conversation, the Auto user interface plays
  the messages using text-to-speech.
</p>

<p>
  This section describes how to notify Auto users that conversations are available and
  provide the content of messages in those conversations.
</p>


<h3 id="build_conversation">Build message conversations</h4>

<p>
  Messaging notifications for Auto organize messages into conversations using the {@code
  NotificationCompat.CarExtender.UnreadConversation} class, that represents an unread or new
  portion of a conversation from a particular sender. It contains a list of messages from the
  sender.
</p>

<p>
  Use the {@code UnreadConversation.Builder} class to create an unread conversation object,
  as shown in the following example code:
</p>

<pre>
// Build a RemoteInput for receiving voice input in a Car Notification
RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
        .setLabel(getApplicationContext().getString(R.string.notification_reply))
        .build();

// Create an unread conversation object to organize a group of messages
// from a particular sender.
UnreadConversation.Builder unreadConvBuilder =
    new UnreadConversation.Builder(participantName)
        .setReadPendingIntent(msgHeardPendingIntent)
        .setReplyAction(replyPendingIntent, remoteInput);
</pre>

<p>
  This conversation object includes a {@link android.app.PendingIntent}, which allows the Auto
  device to signal your app that the conversation has been read by the Auto user. The construction
  of this intent is discussed in the <a href="#conversation-intents">Creating conversation read and
  reply intents</a> section.
</p>

<p>
  If your app supports replying to a conversation, you must call the {@code setReplyAction()}
  method and provide a pending intent to pass that user action back to your app. The {@code
  UnreadConversation} object you create must also include a {@link
  android.support.v4.app.RemoteInput} object. This object is required because the Auto user
  receiving this conversation speaks a reply, a the remote input objects lets your app get a text
  version of the voice reply.
</p>


<h4 id="conversation-messages">Associate messages with conversations</h4>

<p>
  Messages provided for Auto must be associated with a conversation using the {@code
  NotificationCompat.CarExtender.UnreadConversation} class. The following code example shows how
  to associate individual messages with a conversation object.
</p>

<pre>
// Note: Add messages from oldest to newest to the UnreadConversation.Builder
for (Iterator&lt;String&gt; messages = conversation.getMessages().iterator();
     messages.hasNext(); ) {
    String message = messages.next();
    unreadConvBuilder.addMessage(message);
}
</pre>

<p>
  When a new message arrives in a particular conversation, your app should check if there is
  already a conversation object for that particular conversation. If there is, associate the new
  message with the existing conversation instead of building a new one.
</p>


<h4 id="conversation-intents">Create conversation read and reply intents</h4>

<p>
  Unread conversation objects contain intents for reading and replying to a conversation. You
  create a {@link android.app.PendingIntent} object for each of these actions, so the Auto device
  can notify your app of action taken by the Auto user on a particular conversation.
</p>

<p>
  The following example code demonstrates how to define a {@link android.app.PendingIntent} to let
  your app know if a conversation was listened to by the Auto user:
</p>

<pre>
Intent msgHeardIntent = new Intent()
    .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
    .setAction(<em>com.myapp.messagingservice.ACTION_MESSAGE_HEARD</em>)
    .putExtra("conversation_id", conversationId);

PendingIntent msgHeardPendingIntent =
    PendingIntent.getBroadcast(getApplicationContext(),
        conversationId,
        msgHeardIntent,
        PendingIntent.FLAG_UPDATE_CURRENT);
</pre>

<p>
  In this example, {@code conversationId} is an integer that identifies the current conversation.
  The value of {@code setAction()} is an intent filter identifier for heard messages which is
  defined in your app manifest, as shown in <a href="#manifest-intent">Define read and reply intent
  filters</a>.
</p>

<p>
  If your app supports replying to conversations, you also create a {@link
  android.app.PendingIntent} for each conversation to notify your app that the user has replied.
  The following code example shows you how to build this intent for use with a particular
  conversation:
</p>

<pre>
Intent msgReplyIntent = new Intent()
    .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
    .setAction(<em>com.myapp.messagingservice.ACTION_MESSAGE_REPLY</em>)
    .putExtra("conversation_id", <em>conversationId</em>);

PendingIntent msgReplyPendingIntent = PendingIntent.getBroadcast(
    getApplicationContext(),
    <em>conversationId</em>,
    msgReplyIntent,
    PendingIntent.FLAG_UPDATE_CURRENT);
</pre>

<p>
  Once again, {@code conversationId} is an integer that uniquely identifies this conversation. The
  value of {@code setAction()} is an intent filter identifier for replies which is defined in your
  app manifest, as shown in <a href="#manifest-intent">Define read and reply intent filters</a>.
</p>


<h3 id="sending_messages">Sending Messages</h4>

<p>
  When a message arrives for a conversation, you take the following steps to dispatch it as a
  notification to Auto.
</p>

<p>First, add the message to the <code>UnreadConversation.Builder</code> for
this conversation, and update its timestamp:</p>

<pre>
unreadConvBuilder.addMessage(<em>messageString</em>)
    .setLatestTimestamp(<em>currentTimestamp</em>);
</pre>

<p>Then create a {@link android.support.v4.app.NotificationCompat.Builder}
object that you'll use to build the actual notification. You'll need to use the
pending intents you created in the previous step.</p>

<pre>
NotificationCompat.Builder notificationBuilder =
    new NotificationCompat.Builder(getApplicationContext())
        .setSmallIcon(R.drawable.<em>notification_icon</em>)
        .setLargeIcon(<em>icon_bitmap</em>)
        .setContentText(<em>messageString</em>)
        .setWhen(<em>currentTimestamp</em>)
        .setContentTitle(<em>participant_name</em>)
        .setContentIntent(msgHeardPendingIntent);

</pre>

<p>You'll also need to extend the  {@link
android.support.v4.app.NotificationCompat.Builder} with the
<code>CarExtender</code>. This is where you actually create the
<code>UnreadConversation</code> object using the builder you just
created, and attach it to the <code>CarExtender</code>:</p>

<pre>
notificationBuilder.extend(new CarExtender()
    .setUnreadConversation(unreadConvBuilder.build());
</pre>

<p>Once you've done all this, you use your app's {@link
android.support.v4.app.NotificationManagerCompat} to send the notification:</p>

<pre>
mNotificationManager = NotificationManagerCompat.from(context);
mNotificationManager.notify(<em>notificationId</em>, notificationBuilder.build());
</pre>

<p>In this example, <em>msgNotificationManager</em> is a
{@link android.support.v4.app.NotificationManagerCompat} you created for your app.</p>


<h2 id="handle_actions">Handle User Actions</h2>

<p>
  When your create and dispatch a notification for messaging, you specify intents to be triggered
  when the Auto user hears the message and when the user dictates a reply. Your app indicates to
  the Android framework that it handles these intends by registering them through it's manifest, as
  discussed in <a href="#manifest-intent">Define read and reply intent filters</a>.
</p>

<p>
  In addition to registering these intent filters, your app must provide code to handle these
  actions. Your app can do this by providing a service or {@link android.content.BroadcastReceiver}
  objects that handle these intents.</p>

<p>
  For more information about intents, see <a href=
  "{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a>.
</p>


<h3 id="handling_msg_heard">Handling a message heard action</h3>

<p>
  When a user listens to a messaging conversation through the Auto user interface, the dashboard
  device sends a read intent based on how your app defined the messaging notification. Your app
  catches that intent and invokes the broadcast receiver class associated with it, or the service
  method set up to handle that action.
</p>

<p>
  The following code example shows how to define a {@link android.content.BroadcastReceiver} class
  to handle a received message heard intent:
</p>

<pre>
public class MessageHeardReceiver extends BroadcastReceiver {

    &#64;Override
    public void onReceive(Context context, Intent intent) {

        // If you set up the intent as described in
        // "Create conversation read and reply intents",
        // you can get the conversation ID by calling:
        int conversationId = intent.getIntExtra("conversation_id", -1);

        // Remove the notification to indicate it has been read
        // and update the list of unread conversations in your app.
    }
}
</pre>

<p>
  Once a notification is read, your app can remove it by calling
  {@link android.support.v4.app.NotificationManagerCompat#cancel} with the notification ID.
  Within your app, you should mark the messages provided in the notification as read.
</p>


<p class="note">
  <strong>Note:</strong> An alternative to this implementation is to use a service in a
  {@link android.app.PendingIntent}.
</p>


<h3 id="handling_reply">Handling a reply action</h3>

<p>
  When a user replies to a messaging conversation through the Auto user interface, the dashboard
  system sends a reply intent based on how your app defined the messaging notification. Your app
  catches that intent and invokes the broadcast receiver class associated with it, or the service
  method set up to handle that action.
</p>

<p>
  The following code example shows how to define a {@link android.content.BroadcastReceiver} class
  to handle a received message reply intent:
</p>

<pre>
  public class MessageReplyReceiver extends BroadcastReceiver {


    &#64;Override
    public void onReceive(Context context, Intent intent) {
        // If you set up the intent as described in
        // "Create conversation read and reply intents",
        // you can get the conversation ID by calling:
        int conversationId = intent.getIntExtra("conversation_id", -1).

    }

    /**
     * Get the message text from the intent.
     * Note that you should call
     * RemoteInput.getResultsFromIntent() to process
     * the RemoteInput.
     */
    private CharSequence getMessageText(Intent intent) {
        Bundle remoteInput =
            RemoteInput.getResultsFromIntent(intent);
        if (remoteInput != null) {
            return remoteInput.getCharSequence("extra_voice_reply");
        }
        return null;
    }

}</pre>