RatherBeSailing
RatherBeSailing

Reputation: 311

How do you start a Wear App from a connected Mobile

I am trying to get a mobile app to show a companion app on a connected Wear device.

Goal

When a simple countdown timer is started a message is sent to connected wear device(s) and they show the same countdown as the mobile

Problem

When the Wear device is in Ambient Mode startActivity() does not result in the Wear Device exiting Ambient Mode and the count down is not shown

Code which receives message but does not show App ...

For the Wear App to receive messages from the mobile it is implemented as a service

class DataLayerListenerService : WearableListenerService() {
    private lateinit var messageClient : MessageClient
    private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)

    override fun onCreate() {
        messageClient = Wearable.getMessageClient(this)
        messageClient.addListener {
            Log.d(TAG, "service OnMessageReceived ${it.path}")
            if (it.path.equals(START_ACTIVITY_PATH, true)) {
                Log.d(TAG, "service OnMessageReceived -> startActivity()")
                startActivity(
                    Intent(this, MainWearActivity::class.java)
                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)
                )
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        messageClient.removeListener { }
        scope.cancel()
    }

    companion object {
        private const val TAG = "MainWearActivity"
        private const val START_ACTIVITY_PATH = "/start-activity"
    }
}

The WearableListenerService is then included in the Wear Manifest file

<service
    android:name=".DataLayerListenerService"
    android:exported="true">
    <intent-filter>
        <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
        <data
            android:host="*"
            android:pathPrefix="/start-activity"
            android:scheme="wear" />
    </intent-filter>
</service>

So the code works perfectly provided the Wear device is not in Ambient mode. When the message is received the specified App is brought to the foreground (it does not even need to have been run previously)

Unfortunately if the Wear device is in Ambient mode then while the log shows the message being received, the device does not exit Ambient mode and the specified app is not shown

I have tried different Intents but so far none have brought the Wear device out of Ambient Mode

Intent(this, MainWearActivity::class.java)
      .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)

For completeness the code on the mobile device:

private fun startWearableActivity() {
    lifecycleScope.launch {
        try {
            val connectedNodes = nodeClient.connectedNodes.await()
            writeToLog("startWearableActivity() found ${connectedNodes.count()} connected nodes")
            connectedNodes.map { node ->
                writeToLog("startWearableActivity() - Trying to sendMessage to node ${node.displayName}")
                async {
                    // TODO : add countdown value to the byteArrayOf()
                    messageClient.sendMessage(node.id, START_ACTIVITY_PATH, byteArrayOf()).await()
                }
            }.awaitAll()

            writeToLog("startWearableActivity() - All activity start requests sent successfully")
        } catch (cancellationException: CancellationException) {
            writeToLog("startWearableActivity() - Start requests cancelled normally")
        } catch (exception: Exception) {
            writeToLog("startWearableActivity() - Activity start requests failed!!! Exception : $exception")
        }
    }
}

When run the log shows "All activity start requests sent successfully"

It appears the only work around is to stop the Wear App going into Ambient Mode

    window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

So is it possible for the mobile to send a message to the Wear device and have it exit Ambient Mode?

Upvotes: 1

Views: 312

Answers (1)

Yuri Schimke
Yuri Schimke

Reputation: 13488

It's documented here.

I think you'll need to use WearableListenerService.

abstract class WearDataService : WearableListenerService() {

    override fun onMessageReceived(p0: MessageEvent) {
        //
    }
}
        <service
            android:name="my.WearDataService"
            android:exported="true">
            <intent-filter>
                <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
                <data
                    android:host="*"
                    android:pathPrefix="/proto/"
                    android:scheme="wear" />
            </intent-filter>
        </service>

Upvotes: 0

Related Questions