From 33ac358a5a4199549d11ba1931243e7dc8a7ab85 Mon Sep 17 00:00:00 2001 From: Luan Nguyen Date: Tue, 14 Apr 2015 08:54:22 -0700 Subject: docs: Add Wear Capability training bug: 20088602 Change-Id: I52ede5d91936c5eab3d6ee8be8108004cce1f0e0 --- docs/html/training/wearables/data-layer/index.jd | 11 ++ .../html/training/wearables/data-layer/messages.jd | 213 ++++++++++++++++++--- 2 files changed, 193 insertions(+), 31 deletions(-) (limited to 'docs/html/training') diff --git a/docs/html/training/wearables/data-layer/index.jd b/docs/html/training/wearables/data-layer/index.jd index b49ea4d..df7c216 100644 --- a/docs/html/training/wearables/data-layer/index.jd +++ b/docs/html/training/wearables/data-layer/index.jd @@ -91,6 +91,17 @@ devices. For instance, don't try to open low-level sockets to create a communica channel.

+

Android Wear supports multiple wearables connected to a handheld device. For example, when the +user saves a note on a handheld, it automatically appears on both of the user's Wear devices. To +synchronize data between devices, Google’s servers host a cloud node in the network of devices. The +system synchronizes data to directly connected devices, the cloud node, and to wearable devices +connected to the cloud node via Wi-Fi.

+ + +

Figure 1. A sample network of nodes with +handheld and wearable devices.

+ +

Lessons

Accessing the Wearable Data Layer
diff --git a/docs/html/training/wearables/data-layer/messages.jd b/docs/html/training/wearables/data-layer/messages.jd index 0ca55ba..0826e6b 100644 --- a/docs/html/training/wearables/data-layer/messages.jd +++ b/docs/html/training/wearables/data-layer/messages.jd @@ -26,42 +26,191 @@ Unlike with data items, there is no syncing between the handheld and wearable ap Messages are a one-way communication mechanism that's good for remote procedure calls (RPC), such as sending a message to the wearable to start an activity.

+

Multiple wearable devices can be connected to a user’s handheld device. Each connected device in +the network is considered a node. With multiple connected devices, you must consider which +nodes receive the messages. For example, In a voice transcription app that receives voice data on +the wearable device, you should send the message to a node with the processing power and battery +capacity to handle the request, such as a handheld device.

+ +

Note: +With versions of Google Play services prior to 7.3.0, only one wearable device could be connected to +a handheld device at a time. You may need to update your existing code to take the multiple +connected nodes feature into consideration. If you don’t implement the changes, your messages may +not get delivered to intended devices. +

+

Send a Message

-

The following example shows how to send a message that indicates to the other -side of the connection to start an activity. -This call is synchronous and blocks processing until the message is received or until the request -times out:

+

A wearable app can provide functionality for users such as voice +transcription. Users can speak into their wearable device's microphone, and have a transcription +saved to a note. Since a wearable device typically does not have the processing power and battery +capacity required to handle the voice transcription activity, the app should offload this work to a +more capable, connected device.

+ +

The following sections show you how to advertise device nodes that can process activity +requests, discover the nodes capable of fulfilling a requested need, and send messages to those +nodes. +

+ +

Advertise capabilities

+ +

To launch an activity on a handheld device from a wearable device, use the +MessageApi +class to send the request. Since multiple wearables can be connected to the handheld device, the +wearable app needs to determine that a connected node is capable of launching the activity. In your +handheld app, advertise that the node it runs on provides specific capabilities.

+ +

To advertise the capabilities of your handheld app:

-

Note: Read more about asynchronous and synchronous calls -to Google Play services and when to use each in -Communicate with Google Play Services. +

    +
  1. Create an XML configuration file in the res/values/ directory of your project and + name it wear.xml. +
  2. +
  3. Add a resource named android_wear_capabilities to wear.xml. +
  4. +
  5. Define capabilities that the device provides. +
  6. +
+ +

Note: +Capabilities are custom strings that you define and must be unique within your app.

+

The following example shows how to add a capability named voice_transcription to +wear.xml:

+
-GoogleApiClient mGoogleApiClient;
-public static final String START_ACTIVITY_PATH = "/start/MainActivity";
+<resources>
+    <string-array name="android_wear_capabilities">
+        <item>voice_transcription</item>
+    </string-array>
+</resources>
+
+ +

Retrieve the nodes with the required capabilities

+ +

Initially, you can detect the capable nodes by calling the CapabilityApi.getCapability() +method. +The following example shows how to manually retrieve the results of reachable nodes with the +voice_transcription capability:

+ +
+private static final String
+        VOICE_TRANSCRIPTION_CAPABILITY_NAME = "voice_transcription";
+
+private GoogleApiClient mGoogleApiClient;
+
 ...
 
-private void sendStartActivityMessage(String nodeId) {
-    Wearable.MessageApi.sendMessage(
-      mGoogleApiClient, nodeId, START_ACTIVITY_PATH, new byte[0]).setResultCallback(
-          new ResultCallback<SendMessageResult>() {
-              @Override
-              public void onResult(SendMessageResult sendMessageResult) {
-                  if (!sendMessageResult.getStatus().isSuccess()) {
-                      Log.e(TAG, "Failed to send message with status code: "
-                              + sendMessageResult.getStatus().getStatusCode());
+private void setupVoiceTranscription() {
+    CapabilityApi.GetCapabilityResult result =
+            Wearable.CapabilityApi.getCapability(
+                    mGoogleApiClient, VOICE_TRANSCRIPTION_CAPABILITY_NAME,
+                    CapabilityApi.FILTER_REACHABLE).await();
+
+    updateTranscriptionCapability(result.getCapability());
+}
+
+ +

To detect capable nodes as they connect to the wearable device, register a CapabilityApi.CapabilityListener() +instance to your GoogleApiClient. +The following example shows how to register the listener and retrieve the results of reachable nodes +with the voice_transcription capability:

+ +
+private void setupVoiceTranscription() {
+    ...
+
+    CapabilityApi.CapabilityListener capabilityListener =
+            new CapabilityApi.CapabilityListener() {
+                @Override
+                public void onCapabilityChanged(CapabilityInfo capabilityInfo) {
+                    updateTranscriptionCapability(capabilityInfo);
+                }
+            };
+
+    Wearable.CapabilityApi.addCapabilityListener(
+            mGoogleApiClient,
+            capabilityListener,
+            VOICE_TRANSCRIPTION_CAPABILITY_NAME);
+}
+
+ +

After detecting the capable nodes, determine where to send the message. You should pick a node +that is in close proximity to your wearable device to +minimize message routing through multiple nodes. A nearby node is defined as one that is directly +connected to the device. To determine if a node is nearby, call the Node.isNearby() +method.

+ +

The following example shows how you might determine the best node to use:

+ +
+private String transcriptionNodeId = null;
+
+private void updateTranscriptionCapability(CapabilityInfo capabilityInfo) {
+    Set<Node> connectedNodes = capabilityInfo.getNodes();
+
+    transcriptionNodeId = pickBestNodeId(connectedNodes);
+}
+
+private String pickBestNodeId(Set<Node> nodes) {
+    String bestNodeId = null;
+    // Find a nearby node or pick one arbitrarily
+    for (Node node : nodes) {
+        if (node.isNearby()) {
+            return node.getId();
+         }
+         bestNodeId = node.getId();
+    }
+    return bestNodeId;
+}
+
+ +

Deliver the message

+ +

Once you’ve identified the best node to use, send the message using the +MessageApi +class.

+ +

The following example shows how to send a message to the transcription-capable node from a +wearable device. Verify that the node is available before you attempt to send the message. This call +is synchronous and blocks processing until the message is received or until the request times out. +

+ +
+
+public static final String VOICE_TRANSCRIPTION_MESSAGE_PATH = "/voice_transcription";
+
+private void requestTranscription(byte[] voiceData) {
+    if (transcriptionNodeId != null) {
+        Wearable.MessageApi.sendMessage(googleApiClient, transcriptionNodeId,
+            VOICE_TRANSCRIPTION_MESSAGE_PATH, voiceData).setResultCallback(
+                  new ResultCallback() {
+                      @Override
+                      public void onResult(SendMessageResult sendMessageResult) {
+                          if (!sendMessageResult.getStatus().isSuccess()) {
+                              // Failed to send message
+                          }
+                      }
                   }
-              }
-          }
-      );
+            );
+    } else {
+        // Unable to retrieve node with transcription capability
+    }
 }
 
-

-Here's a simple way to get a list of connected nodes that you can potentially -send messages to:

+

Note: To learn more about asynchronous and synchronous calls +to Google Play services and when to use each, see +Communicate with Google Play +Services. +

+ +

You can also broadcast messages to all connected nodes. To retrieve all of the +connected nodes that you can send messages to, implement the following code:

 private Collection<String> getNodes() {
@@ -78,22 +227,24 @@ private Collection<String> getNodes() {
 

Receive a Message

-To be notified of received messages, you implement the +To be notified of received messages, implement the -MessageListener interface to provide a listener for message events. Then you register your -listener with the +MessageListener interface to provide a listener for message events. Then, +register the listener with the -MessageApi.addListener() method. This example shows how you might implement the listener -to check the START_ACTIVITY_PATH that the previous example used to send the message. -If this condition is true, a specific activity is started. +MessageApi.addListener() method. This example shows how you might implement the +listener to check the VOICE_TRANSCRIPTION_MESSAGE_PATH. If this condition is +true, start an activity to process the voice +data.

 @Override
 public void onMessageReceived(MessageEvent messageEvent) {
-    if (messageEvent.getPath().equals(START_ACTIVITY_PATH)) {
+    if (messageEvent.getPath().equals(VOICE_TRANSCRIPTION_MESSAGE_PATH)) {
         Intent startIntent = new Intent(this, MainActivity.class);
         startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        startIntent.putExtra("VOICE_DATA", messageEvent.getData());
         startActivity(startIntent);
     }
 }
-- 
cgit v1.1