Home | History | Annotate | Download | only in data-layer
      1 page.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>
     24 and 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>
     31 Unlike with data items, there is no syncing between the handheld and wearable apps.
     32 Messages are a one-way communication mechanism that's good for remote procedure calls (RPC),
     33 such as sending a message to the wearable to start an activity.</p>
     34 
     35 <p>Multiple wearable devices can be connected to a users handheld device. Each connected device in
     36 the network is considered a <em>node</em>. With multiple connected devices, you must consider which
     37 nodes receive the messages. For example, in a voice transcription app that receives voice data on
     38 the wearable device, you should send the message to a node with the processing power and battery
     39 capacity to handle the request, such as a handheld device.</p>
     40 
     41 <p class="note"><strong>Note:</strong>
     42 With versions of Google Play services prior to 7.3.0, only one wearable device could be connected to
     43 a handheld device at a time. You may need to update your existing code to take the multiple
     44 connected nodes feature into consideration. If you dont implement the changes, your messages may
     45 not 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
     51 transcription. Users can speak into their wearable device's microphone, and have a transcription
     52 saved to a note. Since a wearable device typically does not have the processing power and battery
     53 capacity required to handle the voice transcription activity, the app should offload this work to a
     54 more capable, connected device.</p>
     55 
     56 <p>The following sections show you how to advertise device nodes that can process activity
     57 requests, discover the nodes capable of fulfilling a requested need, and send messages to those
     58 nodes.
     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>
     65 class to send the request. Since multiple wearables can be connected to the handheld device, the
     66 wearable app needs to determine that a connected node is capable of launching the activity. In your
     67 handheld 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>
     82 Capabilities 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
     99 href="{@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>
    100 method.
    101 The following example shows how to manually retrieve the results of reachable nodes with the
    102 <code>voice_transcription</code> capability:</p>
    103 
    104 <pre>
    105 private static final String
    106         VOICE_TRANSCRIPTION_CAPABILITY_NAME = "voice_transcription";
    107 
    108 private GoogleApiClient mGoogleApiClient;
    109 
    110 ...
    111 
    112 private 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
    123 href="{@docRoot}reference/com/google/android/gms/wearable/CapabilityApi.CapabilityListener.html"><code>CapabilityApi.CapabilityListener()</code></a>
    124 instance to your <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html"><code>GoogleApiClient</code></a>.
    125 The following example shows how to register the listener and retrieve the results of reachable nodes
    126 with the <code>voice_transcription</code> capability:</p>
    127 
    128 <pre>
    129 private 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>
    148 If you create a service that extends
    149 <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>
    150 to 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>
    152 method to listen to finer-grained connectivity details, such as when a wearable device switches
    153 from 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>
    156 sample. 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
    161 that is in close proximity to your wearable device to
    162 minimize message routing through multiple nodes. A nearby node is defined as one that is directly
    163 connected to the device. To determine if a node is nearby, call the <a
    164 href="{@docRoot}reference/com/google/android/gms/wearable/Node.html#isNearby()"><code>Node.isNearby()</code></a>
    165 method.</p>
    166 
    167 <p>The following example shows how you might determine the best node to use:</p>
    168 
    169 <pre>
    170 private String transcriptionNodeId = null;
    171 
    172 private void updateTranscriptionCapability(CapabilityInfo capabilityInfo) {
    173     Set&lt;Node> connectedNodes = capabilityInfo.getNodes();
    174 
    175     transcriptionNodeId = pickBestNodeId(connectedNodes);
    176 }
    177 
    178 private 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 youve 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>
    195 class.</p>
    196 
    197 <p>The following example shows how to send a message to the transcription-capable node from a
    198 wearable device. Verify that the node is available before you attempt to send the message. This call
    199 is 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
    203 message. If your app requires data reliability, use
    204 <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a>
    205 objects or the
    206 <a href="{@docRoot}reference/com/google/android/gms/wearable/ChannelApi.html"><code>ChannelApi</code></a>
    207 class to send data between devices.
    208 </p>
    209 
    210 <pre>
    211 
    212 public static final String VOICE_TRANSCRIPTION_MESSAGE_PATH = "/voice_transcription";
    213 
    214 private 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
    234 to Google Play services and when to use each, see
    235 <a href="{@docRoot}google/auth/api-client.html#Communicating">Communicate with Google Play
    236 Services</a>.
    237 </p>
    238 
    239 <p>You can also broadcast messages to all connected nodes. To retrieve all of the
    240 connected nodes that you can send messages to, implement the following code:</p>
    241 
    242 <pre>
    243 private 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>
    257 To 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,
    260 register 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
    263 listener to check the <code>VOICE_TRANSCRIPTION_MESSAGE_PATH</code>. If this condition is
    264 <code>true</code>, start an activity to process the voice
    265 data.
    266 </p>
    267 
    268 <pre>
    269 &#64;Override
    270 public 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>
    281 This is just a snippet that requires more implementation details. Learn about
    282 how to implement a full listener service or activity in
    283 <a href="{@docRoot}training/wearables/data-layer/events.html#Listen">Listening for Data Layer
    284 Events</a>.
    285 </p>