You send messages using the
[MessageClient](https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageClient) API and attach the following items to the message:

- An optional arbitrary payload
- A path that uniquely identifies the message's action

Unlike in the case of data items, no syncing occurs between the
handheld and wearable apps.
Messages are a one-way communication mechanism useful 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, send the message to a node with the processing power and battery
capacity to handle the request, such as a handheld device.

**Note:**
When you specify the details of your message, consider the possibility of multiple
connected nodes. Make sure the message is delivered to the intended devices or nodes.  

Refer to the following sample app for usage examples:
[DataLayer](https://github.com/android/wear-os-samples/tree/main/DataLayer)

## Send a message

A wearable app can provide functionality for users, such as voice
transcription. Users can speak into their wearable device's microphone and have a transcript
saved to a note. Since a wearable device typically doesn't have the processing power and battery
capacity required to handle the voice transcription activity, the app needs to 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
[MessageClient](https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageClient) 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, do the following:

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

**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`:  

```xml
<resources xmlns:tools="http://schemas.android.com/tools"
           tools:keep="@array/android_wear_capabilities">
    <string-array name="android_wear_capabilities">
        <item>voice_transcription</item>
    </string-array>
</resources>
```

### Retrieve nodes with the required capabilities

Initially, you can detect the capable nodes by calling the
`getCapability` method of the
[CapabilityClient](https://developers.google.com/android/reference/com/google/android/gms/wearable/CapabilityClient) class. To use this method, your Wear OS app and phone app
must have the same application ID. The following example
shows how to manually retrieve the results of reachable nodes with the
`voice_transcription` capability:

### Kotlin

```kotlin
private const val VOICE_TRANSCRIPTION_CAPABILITY_NAME = "voice_transcription"
...
private fun setupVoiceTranscription() {
    val capabilityInfo: CapabilityInfo = Tasks.await(
            Wearable.getCapabilityClient(context)
                    .getCapability(
                            VOICE_TRANSCRIPTION_CAPABILITY_NAME,
                            CapabilityClient.FILTER_REACHABLE
                    )
    )
    // capabilityInfo has the reachable nodes with the transcription capability
    updateTranscriptionCapability(capabilityInfo)
}
```

### Java

```java
private static final String
    VOICE_TRANSCRIPTION_CAPABILITY_NAME = "voice_transcription";
    ...
private void setupVoiceTranscription() {
    CapabilityInfo capabilityInfo = Tasks.await(
        Wearable.getCapabilityClient(context).getCapability(
            VOICE_TRANSCRIPTION_CAPABILITY_NAME, CapabilityClient.FILTER_REACHABLE));
    // capabilityInfo has the reachable nodes with the transcription capability
    updateTranscriptionCapability(capabilityInfo);
}
```


To detect capable nodes as they connect to the wearable device, register an
instance of a listener, specifically an `OnCapabilityChangedListener`
of a `CapabilityClient` object. The following example shows how to
register the listener and retrieve a result with reachable nodes that have the
`voice_transcription` capability:

### Kotlin

```kotlin
private fun setupVoiceTranscription() {
    updateTranscriptionCapability(capabilityInfo).also { capabilityListener ->
        Wearable.getCapabilityClient(context).addListener(
                capabilityListener,
                VOICE_TRANSCRIPTION_CAPABILITY_NAME
        )
    }
}
```

### Java

```java
private void setupVoiceTranscription() {
    ...
    // This example uses a Java 8 Lambda. You can use named or anonymous classes.
    CapabilityClient.OnCapabilityChangedListener capabilityListener =
        capabilityInfo -> { updateTranscriptionCapability(capabilityInfo); };
    Wearable.getCapabilityClient(context).addListener(
        capabilityListener,
        VOICE_TRANSCRIPTION_CAPABILITY_NAME);
}
```

After detecting the capable nodes, determine where to send the message. Choose 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 whether a node is nearby such as connected via Bluetooth, call the
[`Node.isNearby()`](https://developers.google.com/android/reference/com/google/android/gms/wearable/Node#isNearby()) method. If more than one node is nearby, choose one arbitrarily;
similarly, if no capable node is nearby, then choose a capable node arbitrarily.

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

### Kotlin

```kotlin
private var transcriptionNodeId: String? = null

private fun updateTranscriptionCapability(capabilityInfo: CapabilityInfo) {
    transcriptionNodeId = pickBestNodeId(capabilityInfo.nodes)
}

private fun pickBestNodeId(nodes: Set<Node>): String? {
    // Find a nearby node or pick one arbitrarily.
    return nodes.firstOrNull { it.isNearby }?.id ?: nodes.firstOrNull()?.id
}
```

### Java

```java
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 a node to use, send the message using the [MessageClient](https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageClient) class.


The following example shows how to send a message to the transcription-capable node
from a wearable device. This call is synchronous and blocks processing until the
system queues the message for delivery.


**Note:** A successful result code doesn't guarantee delivery of
the message. If your app requires data reliability, consider using [DataItem](https://developers.google.com/android/reference/com/google/android/gms/wearable/DataItem)
objects or the [ChannelClient](https://developers.google.com/android/reference/com/google/android/gms/wearable/ChannelClient)
class to send data between devices.  

### Kotlin

```kotlin
const val VOICE_TRANSCRIPTION_MESSAGE_PATH = "/voice_transcription"
...
private fun requestTranscription(voiceData: ByteArray) {
    transcriptionNodeId?.also { nodeId ->
        val sendTask: Task<*> = Wearable.getMessageClient(context).sendMessage(
                nodeId,
                VOICE_TRANSCRIPTION_MESSAGE_PATH,
                voiceData
        ).apply {
            addOnSuccessListener { ... }
            addOnFailureListener { ... }
        }
    }
}
```

### Java

```java
public static final String VOICE_TRANSCRIPTION_MESSAGE_PATH = "/voice_transcription";
private void requestTranscription(byte[] voiceData) {
    if (transcriptionNodeId != null) {
        Task<Integer> sendTask =
            Wearable.getMessageClient(context).sendMessage(
              transcriptionNodeId, VOICE_TRANSCRIPTION_MESSAGE_PATH, voiceData);
         // You can add success and/or failure listeners,
         // Or you can call Tasks.await() and catch ExecutionException
         sendTask.addOnSuccessListener(...);
         sendTask.addOnFailureListener(...);
    } else {
        // Unable to retrieve node with transcription capability
    }
}
```

**Note:** To learn more about asynchronous and synchronous calls to
Google Play services, and when to use each, see the [Tasks API](https://developers.google.com/android/guides/tasks).

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

### Kotlin

```kotlin
private fun getNodes(): Collection<String> {
    return Tasks.await(Wearable.getNodeClient(context).connectedNodes).map { it.id }
}
```

### Java

```java
private Collection<String> getNodes() {
    HashSet <String>results = new HashSet<String>();
    List<Node> nodes =
        Tasks.await(Wearable.getNodeClient(context).getConnectedNodes());
    for (Node node : nodes.getNodes()) {
        results.add(node.getId());
    }
    return results;
}
```

## Receive a message


To be notified of received messages, implement the
[MessageClient.OnMessageReceivedListener](https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageClient.OnMessageReceivedListener)
interface to provide a listener for message events. Then, register the listener
with the `addListener`
method. The following 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.  

### Kotlin

```kotlin
fun onMessageReceived(messageEvent: MessageEvent) {
    if (messageEvent.path == VOICE_TRANSCRIPTION_MESSAGE_PATH) {
        val startIntent = Intent(this, MainActivity::class.java).apply {
            addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            putExtra("VOICE_DATA", messageEvent.data)
        }
        startActivity(this, startIntent)
    }
}
```

### Java

```java
@Override
public void onMessageReceived(MessageEvent messageEvent) {
    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(this, startIntent);
    }
}
```


This code requires more implementation details. Learn about
how to implement a full listener service or activity in
[Listen for data layer events](https://developer.android.com/training/wearables/data-layer/events#Listen).