How to make WearableListenerService working in Android 13?

214 Views Asked by At

WearableListenerService stopped working in API 33 leading to a situation when WearOS devices are not able to send message to a phone. Google was aware about the issue and stated that it's fixed, but it's not. I could confirm that the service in question works with API 30, 31, and 32, but not with 33. Is there a way around to make it working with 33?

The code for the service is very much standard and I just took it from some Google example a few years ago. If I need to change it, please let me know how.

Once again Google did a "great job" on breaking working apps with new API releases.

class WearService : WearableListenerService() {

var mApp : App? = null
var mCtx : Context? = null

override fun onCreate() {
    super.onCreate()
    App.d(TAG, "ON CREATE")
    mApp = application as App
    mCtx = applicationContext
}

companion object {
    const val TAG = "GAC-WEARS"
}


override fun onMessageReceived(messageEvent: MessageEvent) {

    App.d(TAG, "RCV ${String(messageEvent.data)}")
    val root = App.app?.myAct
    val model = root?.model

    if (App.NO_WEAR) {
        return
    }


    if (messageEvent.path == RootActivity.BROADCAST_PATH) {

        val message = String(messageEvent.data)

        if (model?.connected?.value != null && model?.connected?.value != R.drawable.wear) {

            if (message.startsWith("start"))
                mApp!!.showToast("Can't connect to Wear. Connected to another watch already", App.MTYPE.ERROR)
            return
        }
        App.d(TAG, message)

        root?.handler?.post {
            root.onNotify(RootActivity.NOTIFICATIONS.Ping, R.drawable.wear)
        }


        if (message.startsWith("start")) {
            root?.handler?.post {
                root.onNotify(RootActivity.NOTIFICATIONS.Ping, R.drawable.wear)
            }
        }
        else {
            val messageIntent = Intent()
            messageIntent.action = Intent.ACTION_SEND
            messageIntent.putExtra("message", message)
            messageIntent.putExtra("device", App.DEV_WEAR)
            LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent)
        }

    } else {
        super.onMessageReceived(messageEvent)
    }
}

}

1

There are 1 best solutions below

2
Oleg Gryb On

After writing to Google about the bug and not getting any answer I had to rewrite the code to get rid of WearableListenerService. Instead of that I derived my activity class from CapabilityClient.OnCapabilityChangedListener and MessageClient.OnMessageReceivedListener, and overridden some methods:

 override fun onCapabilityChanged(ci: CapabilityInfo) {

        mNode = pickBestNodeId(ci.nodes)
        if (mNode != null) {
            sendMessage("start")
        }

    } 
 override fun onMessageReceived(ev: MessageEvent) {
    Util.d(TAG, "got message from node: ${ev.path} ${String(ev.data)}")

    if (ev.path == "/gacw/message") {

        //...retrieve the message//

        val msg: String = String(ev.data)

        when {
            msg.startsWith(...) -> [Process Specific Message Type]
            ...
        }
    }
}

This is how I derive my main activity class in the watch app:

class MainActivity() : ComponentActivity(),

 CapabilityClient.OnCapabilityChangedListener, MessageClient.OnMessageReceivedListener {

And this is the main activity class in the phone app:

open class RootActivity : FragmentActivity(), MessageClient.OnMessageReceivedListener {

Note that this approach works on both watch and phone sides, and most importantly - it works in all current Android API versions.

Once again, shame on Google for breaking working code with new API releases, but at least we have a solution that works now