1page.title=Sending and Receiving Messages 2 3@jd:body 4 5<div id="tb-wrapper"> 6<div id="tb"> 7 8<h2>This lesson teaches you to</h2> 9<ol> 10 <li><a href="#SendMessage">Send a Message</a></li> 11 <li><a href="#ReceiveMessage">Receive a Message</a></li> 12</ol> 13<h2>Try it out</h2> 14<ul> 15 <li> 16 <a href="https://github.com/googlesamples/android-FindMyPhone/" class="external-link">FindMyPhone</a> 17 </li> 18</ul> 19</div> 20</div> 21 22<p>You send messages using the 23<a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.html"><code>MessageApi</code></a> 24and attach the following items to the message:</p> 25 26<ul> 27 <li>An arbitrary payload (optional)</li> 28 <li>A path that uniquely identifies the message's action</li> 29</ul> 30<p> 31Unlike with data items, there is no syncing between the handheld and wearable apps. 32Messages are a one-way communication mechanism that's good for remote procedure calls (RPC), 33such as sending a message to the wearable to start an activity.</p> 34 35<p>Multiple wearable devices can be connected to a user’s handheld device. Each connected device in 36the network is considered a <em>node</em>. With multiple connected devices, you must consider which 37nodes receive the messages. For example, in a voice transcription app that receives voice data on 38the wearable device, you should send the message to a node with the processing power and battery 39capacity to handle the request, such as a handheld device.</p> 40 41<p class="note"><strong>Note:</strong> 42With versions of Google Play services prior to 7.3.0, only one wearable device could be connected to 43a handheld device at a time. You may need to update your existing code to take the multiple 44connected nodes feature into consideration. If you don’t implement the changes, your messages may 45not get delivered to intended devices. 46</p> 47 48<h2 id="SendMessage">Send a Message</h2> 49 50<p>A wearable app can provide functionality for users such as voice 51transcription. Users can speak into their wearable device's microphone, and have a transcription 52saved to a note. Since a wearable device typically does not have the processing power and battery 53capacity required to handle the voice transcription activity, the app should offload this work to a 54more capable, connected device.</p> 55 56<p>The following sections show you how to advertise device nodes that can process activity 57requests, discover the nodes capable of fulfilling a requested need, and send messages to those 58nodes. 59</p> 60 61<h3 id="AdvertiseCapabilities">Advertise capabilities</h3> 62 63<p>To launch an activity on a handheld device from a wearable device, use the 64<a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.html"><code>MessageApi</code></a> 65class to send the request. Since multiple wearables can be connected to the handheld device, the 66wearable app needs to determine that a connected node is capable of launching the activity. In your 67handheld app, advertise that the node it runs on provides specific capabilities.</p> 68 69<p>To advertise the capabilities of your handheld app:</p> 70 71<ol> 72 <li>Create an XML configuration file in the <code>res/values/</code> directory of your project and 73 name it <code>wear.xml</code>. 74 </li> 75 <li>Add a resource named <code>android_wear_capabilities</code> to <code>wear.xml</code>. 76 </li> 77 <li>Define capabilities that the device provides. 78 </li> 79</ol> 80 81<p class="note"><strong>Note:</strong> 82Capabilities are custom strings that you define and must be unique within your app. 83</p> 84 85<p>The following example shows how to add a capability named <code>voice_transcription</code> to 86<code>wear.xml</code>:</p> 87 88<pre> 89<resources> 90 <string-array name="android_wear_capabilities"> 91 <item>voice_transcription</item> 92 </string-array> 93</resources> 94</pre> 95 96<h3 id="RetrieveCapabilities">Retrieve the nodes with the required capabilities</h3> 97 98<p>Initially, you can detect the capable nodes by calling the <a 99href="{@docRoot}reference/com/google/android/gms/wearable/CapabilityApi.html#getCapability(com.google.android.gms.common.api.GoogleApiClient, java.lang.String, int)"><code>CapabilityApi.getCapability()</code></a> 100method. 101The following example shows how to manually retrieve the results of reachable nodes with the 102<code>voice_transcription</code> capability:</p> 103 104<pre> 105private static final String 106 VOICE_TRANSCRIPTION_CAPABILITY_NAME = "voice_transcription"; 107 108private GoogleApiClient mGoogleApiClient; 109 110... 111 112private void setupVoiceTranscription() { 113 CapabilityApi.GetCapabilityResult result = 114 Wearable.CapabilityApi.getCapability( 115 mGoogleApiClient, VOICE_TRANSCRIPTION_CAPABILITY_NAME, 116 CapabilityApi.FILTER_REACHABLE).await(); 117 118 updateTranscriptionCapability(result.getCapability()); 119} 120</pre> 121 122<p>To detect capable nodes as they connect to the wearable device, register a <a 123href="{@docRoot}reference/com/google/android/gms/wearable/CapabilityApi.CapabilityListener.html"><code>CapabilityApi.CapabilityListener()</code></a> 124instance to your <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html"><code>GoogleApiClient</code></a>. 125The following example shows how to register the listener and retrieve the results of reachable nodes 126with the <code>voice_transcription</code> capability:</p> 127 128<pre> 129private void setupVoiceTranscription() { 130 ... 131 132 CapabilityApi.CapabilityListener capabilityListener = 133 new CapabilityApi.CapabilityListener() { 134 @Override 135 public void onCapabilityChanged(CapabilityInfo capabilityInfo) { 136 updateTranscriptionCapability(capabilityInfo); 137 } 138 }; 139 140 Wearable.CapabilityApi.addCapabilityListener( 141 mGoogleApiClient, 142 capabilityListener, 143 VOICE_TRANSCRIPTION_CAPABILITY_NAME); 144} 145</pre> 146 147<p class="note"><strong>Note:</strong> 148If you create a service that extends 149<a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a> 150to detect capability changes, you may want to override the 151<a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html#onConnectedNodes(java.util.List<com.google.android.gms.wearable.Node>)"><code>onConnectedNodes()</code></a> 152method to listen to finer-grained connectivity details, such as when a wearable device switches 153from Wi-Fi to a Bluetooth connection to the handset. For an example implementation, see the 154<code>DisconnectListenerService</code> class in the 155<a href="https://github.com/googlesamples/android-FindMyPhone/" class="external-link">FindMyPhone</a> 156sample. For more information on how to listen for important events, see 157<a href="{@docRoot}training/wearables/data-layer/events.html#Listen">Listen for Data Layer Events</a>. 158</p> 159 160<p>After detecting the capable nodes, determine where to send the message. You should pick a node 161that is in close proximity to your wearable device to 162minimize message routing through multiple nodes. A nearby node is defined as one that is directly 163connected to the device. To determine if a node is nearby, call the <a 164href="{@docRoot}reference/com/google/android/gms/wearable/Node.html#isNearby()"><code>Node.isNearby()</code></a> 165method.</p> 166 167<p>The following example shows how you might determine the best node to use:</p> 168 169<pre> 170private String transcriptionNodeId = null; 171 172private void updateTranscriptionCapability(CapabilityInfo capabilityInfo) { 173 Set<Node> connectedNodes = capabilityInfo.getNodes(); 174 175 transcriptionNodeId = pickBestNodeId(connectedNodes); 176} 177 178private String pickBestNodeId(Set<Node> nodes) { 179 String bestNodeId = null; 180 // Find a nearby node or pick one arbitrarily 181 for (Node node : nodes) { 182 if (node.isNearby()) { 183 return node.getId(); 184 } 185 bestNodeId = node.getId(); 186 } 187 return bestNodeId; 188} 189</pre> 190 191<h3 id="DeliverMessage">Deliver the message</h3> 192 193<p>Once you’ve identified the best node to use, send the message using the 194<a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.html"><code>MessageApi</code></a> 195class.</p> 196 197<p>The following example shows how to send a message to the transcription-capable node from a 198wearable device. Verify that the node is available before you attempt to send the message. This call 199is synchronous and blocks processing until the system queues the message for delivery. 200</p> 201 202<p class="note"><strong>Note:</strong> A successful result code does not guarantee delivery of the 203message. If your app requires data reliability, use 204<a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a> 205objects or the 206<a href="{@docRoot}reference/com/google/android/gms/wearable/ChannelApi.html"><code>ChannelApi</code></a> 207class to send data between devices. 208</p> 209 210<pre> 211 212public static final String VOICE_TRANSCRIPTION_MESSAGE_PATH = "/voice_transcription"; 213 214private void requestTranscription(byte[] voiceData) { 215 if (transcriptionNodeId != null) { 216 Wearable.MessageApi.sendMessage(googleApiClient, transcriptionNodeId, 217 VOICE_TRANSCRIPTION_MESSAGE_PATH, voiceData).setResultCallback( 218 new ResultCallback<SendMessageResult>() { 219 @Override 220 public void onResult(SendMessageResult sendMessageResult) { 221 if (!sendMessageResult.getStatus().isSuccess()) { 222 // Failed to send message 223 } 224 } 225 } 226 ); 227 } else { 228 // Unable to retrieve node with transcription capability 229 } 230} 231</pre> 232 233<p class="note"><strong>Note:</strong> To learn more about asynchronous and synchronous calls 234to Google Play services and when to use each, see 235<a href="{@docRoot}google/auth/api-client.html#Communicating">Communicate with Google Play 236Services</a>. 237</p> 238 239<p>You can also broadcast messages to all connected nodes. To retrieve all of the 240connected nodes that you can send messages to, implement the following code:</p> 241 242<pre> 243private Collection<String> getNodes() { 244 HashSet <String>results = new HashSet<String>(); 245 NodeApi.GetConnectedNodesResult nodes = 246 Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await(); 247 for (Node node : nodes.getNodes()) { 248 results.add(node.getId()); 249 } 250 return results; 251} 252</pre> 253 254<h2 id="ReceiveMessage">Receive a Message</h2> 255 256<p> 257To be notified of received messages, implement the 258<a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.MessageListener.html"> 259<code>MessageListener</code></a> interface to provide a listener for message events. Then, 260register the listener with the 261<a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.html#addListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.MessageApi.MessageListener)"> 262<code>MessageApi.addListener()</code></a> method. This example shows how you might implement the 263listener to check the <code>VOICE_TRANSCRIPTION_MESSAGE_PATH</code>. If this condition is 264<code>true</code>, start an activity to process the voice 265data. 266</p> 267 268<pre> 269@Override 270public void onMessageReceived(MessageEvent messageEvent) { 271 if (messageEvent.getPath().equals(VOICE_TRANSCRIPTION_MESSAGE_PATH)) { 272 Intent startIntent = new Intent(this, MainActivity.class); 273 startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 274 startIntent.putExtra("VOICE_DATA", messageEvent.getData()); 275 startActivity(startIntent); 276 } 277} 278</pre> 279 280<p> 281This is just a snippet that requires more implementation details. Learn about 282how to implement a full listener service or activity in 283<a href="{@docRoot}training/wearables/data-layer/events.html#Listen">Listening for Data Layer 284Events</a>. 285</p>