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&lt;resources>
90    &lt;string-array name="android_wear_capabilities">
91        &lt;item>voice_transcription&lt;/item>
92    &lt;/string-array>
93&lt;/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                &#64;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&lt;Node> connectedNodes = capabilityInfo.getNodes();
174
175    transcriptionNodeId = pickBestNodeId(connectedNodes);
176}
177
178private String pickBestNodeId(Set&lt;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                      &#64;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&lt;String&gt; getNodes() {
244    HashSet &lt;String&gt;results = new HashSet&lt;String&gt;();
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&#64;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>