---
title: "Build Wear OS Apps and Connect with Android"
summary: "Create Wear OS app and integrate them with Android, covering setup, permissions, and data sync."
---

## Initial Setup

Start by creating an android app using your preferred framework:

- Flutter <span className="text-gray-400">(the supreme)</span>
- React Native <span className="text-gray-400">(soydevs)</span>
- Kotlin <span className="text-gray-400">(chad)</span>
- Android Views <span className="text-gray-400">(mentally ill)</span>
- Any other <span className="text-gray-400">(idk)</span>

Open your android project in Android Studio (open the `android` folder if using cross-platform frameworks).

## Phone App Setup

First we need to create a service which will listen to messages from the watch and then we need to tell our phone about the service.

### Adding Dependencies

Add the following to your app level gradle file (`app/build.gradle`):

```kotlin
implementation("com.google.android.gms:play-services-wearable:19.0.0")
```

The dependency is needed to create the service.

### Permissions Setup

Add the following code in the `manifest` block of `AndroidManifest.xml`:

```xml
<uses-permission android:name="com.google.android.wearable.permission.BIND_WEARABLE_LISTENER" />
```

We need `BIND_WEARABLE_LISTENER` permission to bind a service. We don't need to prompt user to allow this permission.

### Creating Message Receiver

Create a new file `WearMessageReceiver.kt`:

```kotlin
package com.your.package

import android.content.Intent
import com.google.android.gms.wearable.MessageEvent
import com.google.android.gms.wearable.WearableListenerService

class WearMessageReceiver : WearableListenerService() {
    override fun onMessageReceived(event: MessageEvent) {
        when (event.path) {
            "/open" -> {
                val intent = packageManager.getLaunchIntentForPackage(packageName)?.apply {
                    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                    addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
                }
                startActivity(intent)
            }
        }
    }
}
```

This service will run in background(even when the app is killed) and listen to `/open` from your watch. When it receives the message, it will open the app.

### Registering the Service

Now we need to tell android about this service. Add the following code in the `application` block of `AndroidManifest.xml`:

```xml
<service
    android:name="[package name].WearMessageReceiver"
    android:exported="true">
    <intent-filter>
        <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
        <category android:name="android.intent.category.DEFAULT" />
        <data
            android:host="*"
            android:pathPattern=".*"
            android:scheme="wear" />
    </intent-filter>
</service>
```

This code tells android when to invoke the `WearMessageReceiver` service. Make sure `[package name]` is replaced with your package name.

### Message Sending Function

Now we need a function to send messages from the phone to the watch.

Add this function to `MainActivity.kt` and in `MainActivity` class:

```kotlin
suspend fun sendMessageToWatch(
        context: Context,
        path: String,
        data: ByteArray = ByteArray(0)
    ) {
        withContext(Dispatchers.IO) {
            try {
                val nodes = Tasks.await(Wearable.getNodeClient(context).connectedNodes)
                nodes.forEach { node ->
                    Tasks.await(
                        Wearable.getMessageClient(context).sendMessage(
                            node.id,
                            path,
                            data,
                        )
                    )
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }
```

this function is a suspend function which means you need to invoke it inside a coroutine to avoid blocking the main thread. Read more about suspend functions [here](https://kotlinlang.org/docs/composing-suspending-functions.html).

## Watch App Setup

### Creating the Watch Project

1. Go to `Android Studio > File > New > New Project > Wear OS > Empty Wear App`
2. Keep the bundle identifier same as your phone app
3. Connect a Wear OS device or create an emulator

### Adding Permissions

Add to the `manifest` block in `AndroidManifest.xml`:

```xml
<uses-permission android:name="com.google.android.wearable.permission.BIND_WEARABLE_LISTENER" />
```

This permission is also a [`normal` permission](https://developer.android.com/guide/topics/permissions/overview#normal) hence you don't need to prompt the user to allow it.

### Creating Message Listener

Create `MessageListenerService.kt`:

```kotlin
class MessageListenerService : WearableListenerService() {
    override fun onMessageReceived(event: MessageEvent) {
        super.onMessageReceived(event)
        when (event.path) {
            "/open" -> {
                val intent = Intent(this, MainActivity::class.java).apply {
                    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                }
                startActivity(intent)
            }
        }
    }
}
```

This service will run in background(even when the app is killed) and listen to `/open` from your phone. When it receives the message, it will open the app.

### Registering Watch Service

Add to the `application` block in `AndroidManifest.xml`:

```xml
<service
    android:name=".MessageListenerService"
    android:exported="true">
    <intent-filter>
        <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
            <data
                    android:host="*"
                    android:pathPattern=".*"
                    android:scheme="wear" />
        </intent-filter>
</service>
```

Similar to the phone app, we need to tell android about this service.

### Message Sending Function

Add to `MainActivity.kt`:

```kotlin
private suspend fun sendMessageToPhone(path: String, data: ByteArray) {
    val connectedNodes = Wearable.getNodeClient(this).connectedNodes.await()
    println("Connected nodes: $connectedNodes")
    for (node in connectedNodes) {
        try {
            messageClient.sendMessage(node.id, path, data).await()
        } catch (e: Exception) {
            println("Failed to send message to node ${node.id}: ${e.message}")
        }
    }
}
```

This function is a suspend function which means you need to invoke it inside a coroutine to avoid blocking the main thread. Read more about suspend functions [here](https://kotlinlang.org/docs/composing-suspending-functions.html).

Now, the setup is done. You can now send messages from the watch to the phone and vice versa.

This is very minimal setup and you can extend it using [`JSONObject`](https://developer.android.com/reference/org/json/JSONObject) or [`gson`](https://github.com/google/gson) to send complex objects between devices.

## Final Notes

- Messages are transferred in `ByteArray` format - remember to encode the data in sender device and decode the data in target device
- For cross-platform frameworks, call `sendMessageToWatch` using [MethodChannel](https://api.flutter.dev/flutter/services/MethodChannel-class.html) or equivalent
- Name of services should match the name specified in `AndroidManifest.xml`
