From 33ac358a5a4199549d11ba1931243e7dc8a7ab85 Mon Sep 17 00:00:00 2001
From: Luan Nguyen
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.
+ +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. +
+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. +
+ +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. +
res/values/ directory of your project and
+ name it wear.xml.
+ android_wear_capabilities to wear.xml.
+ 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> ++ +
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;
+}
+
+
+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