Swifty
Swifty

Reputation: 25

How to connect to a WearOS companion watch app using Kotlin?

For days now I have been trying to connect a Jetpack Compose app to an WearOS watch (simulator), and I just can't figure it out. I have successfully paired the simulators (Wear OS app shows Connected to emulator), but I can't get them to connect in my app. I have looked at examples, documentation, concurred with chatGPT but nothing I seem to do works. So I am wondering if I am missing a step somewhere.

In the end I want to be able to send data from my bluetooth class to the watch (probably using the message client).

 class MyCapabilityListener(private val context: Context) :
    DataClient.OnDataChangedListener,
    MessageClient.OnMessageReceivedListener,
    CapabilityClient.OnCapabilityChangedListener {

    private val capabilityClient: CapabilityClient = Wearable.getCapabilityClient(context)
    private val dataClient: DataClient = Wearable.getDataClient(context)

    fun sendData(data: String) {
        val dataItem = PutDataMapRequest.create("/data/path").run {
            dataMap.putString("data", data)
            asPutDataRequest()
        }
        dataClient.putDataItem(dataItem)
    }

    override fun onCapabilityChanged(capabilityInfo: CapabilityInfo) {
        // Check if the wearable device is available
        val nodes = capabilityInfo.nodes
        if (nodes.isNotEmpty()) {
            Log.v("Connected", "Connected to the watch")
            // Do something with the connected wearable device
        } else {
            Log.v("Not connected", "Not connected to the watch")
        }
    }

    fun addListener() {
        // Connect to the capability client
        Wearable.getCapabilityClient(context)
        Wearable.getDataClient(context)
        capabilityClient.addListener(this, Uri.parse("wear://"), CapabilityClient.FILTER_REACHABLE)
        // Check the current capability status
        capabilityClient.getCapability("wear://", CapabilityClient.FILTER_REACHABLE)
            .addOnSuccessListener { capabilityInfo ->
                onCapabilityChanged(capabilityInfo) // Call onCapabilityChanged manually
            }
            .addOnFailureListener { e ->
                Log.e("Capability", "Failed to get capability: ${e.message}")
            }
    }

}

On the watch side I have just have a WearableListenerService() class with an override fun for data that gets received.

I am expecting an onCapabilityChanged callback, but that never happens and when manually checking with capabilityClient.getCapability I always get the "Not connected", "Not connected to the watch", log statement back. I call MyCapabilityListener(context).addListener in the onCreate fun.

Upvotes: 0

Views: 978

Answers (1)

Code Poet
Code Poet

Reputation: 8003

Are you using the wear-os samples? You might find your answer for sending data to your watch here and checking remote connection here.

What I think you might be missing is the res/values/wear.xml on both sides.

So on the mobile side you would need to add this in the values folder:

<resources>
    <string-array name="android_wear_capabilities">
   <!-- IMPORTANT NOTE: Should be different than capability in Wear res/values/wear.xml. -->
        <item>verify_remote_example_phone_app</item>
    </string-array>
</resources>

And on the wearable side:

<resources>
    <string-array name="android_wear_capabilities">
   <!-- IMPORTANT NOTE: Should be different than capability in App res/values/wear.xml. -->
        <item>verify_remote_example_wear_app</item>
    </string-array>
</resources>

Then instead of using getCapability("wear://", CapabilityClient.FILTER_REACHABLE) you can refer to your wear.xml. Like this:

private const val CAPABILITY_PHONE_APP = "verify_remote_phone_app"

and

val capabilityInfo = capabilityClient
            .getCapability(CAPABILITY_PHONE_APP, CapabilityClient.FILTER_ALL)
            .await()

Upvotes: 2

Related Questions