1 page.title=Receiving Voice Input in a Notification 2 page.tags=notifications 3 helpoutsWidget=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, 21 such as reply to an email, it should normally launch an activity 22 on the handheld device to input the text. However, when your notification appears on a wearable, 23 there is no keyboard input, so you can let users dictate a reply or provide pre-defined text messages 24 using {@link android.support.v4.app.RemoteInput}. 25 </p> 26 27 <p>When users reply with voice or select one of the available 28 messages, the system attaches the text response to the {@link android.content.Intent} you specified 29 for 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" 32 style="float:right;margin:0 0 20px 40px;clear:right" /> 33 <img src="{@docRoot}wear/images/03_actions.png" height="200" width="169" 34 style="float:right;margin:0 0 20px 40px" /> 35 36 <p class="note"><strong>Note:</strong> The Android emulator does not support voice input. When 37 using the emulator for a wearable device, enable <b>Hardware keyboard present</b> in the AVD settings 38 so 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 50 label for the voice input prompt:</p> 51 52 <pre class="prettyprint"> 53 // Key for the string that's delivered in the action's intent 54 private static final String EXTRA_VOICE_REPLY = "extra_voice_reply"; 55 56 String replyLabel = getResources().getString(R.string.reply_label); 57 58 RemoteInput 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" 67 style="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 <?xml version="1.0" encoding="utf-8"?> 78 <resources> 79 <string-array name="reply_choices"> 80 <item>Yes</item> 81 <item>No</item> 82 <item>Maybe</item> 83 </string-array> 84 </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> 91 public static final String EXTRA_VOICE_REPLY = "extra_voice_reply"; 92 ... 93 String replyLabel = getResources().getString(R.string.reply_label); 94 String[] replyChoices = getResources().getStringArray(R.array.reply_choices); 95 96 RemoteInput 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> 105 To 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()}. 108 You can then apply the action to the notification. For example: 109 </p> 110 111 <pre> 112 // Create an intent for the reply action 113 Intent replyIntent = new Intent(this, ReplyActivity.class); 114 PendingIntent replyPendingIntent = 115 PendingIntent.getActivity(this, 0, replyIntent, 116 PendingIntent.FLAG_UPDATE_CURRENT); 117 118 // Create the reply action and add the remote input 119 NotificationCompat.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 126 Notification 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 135 NotificationManagerCompat notificationManager = 136 NotificationManagerCompat.from(mContext); 137 notificationManager.notify(notificationId, notification); 138 </pre> 139 <p> 140 When 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> 145 To receive the user's transcribed message in the activity you declared in the reply action's intent, 146 call {@link android.support.v4.app.RemoteInput#getResultsFromIntent getResultsFromIntent()}, 147 passing in the "Reply" action's intent. This method returns a {@link android.os.Bundle} that 148 contains 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()} 151 to obtain the voice result, because the voice input is stored as 152 {@link android.content.ClipData}. The {@link android.support.v4.app.RemoteInput#getResultsFromIntent 153 getResultsFromIntent()} method provides a convenient way to receive a character sequence without 154 having to process the {@link android.content.ClipData} yourself. 155 </p> 156 157 <p> 158 The following code shows a method that accepts an intent and returns the voice response, 159 which 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 169 private 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