From Wrist to Hand: Develop a Companion App for Your Wearable Application

Samiul Hossain

Engineer, Samsung Developer Program

Galaxy Watch applications can support many features and services on the watch hardware, but the watch's smaller size compared to a mobile device carries limitations, such as fewer hardware resources and smaller screen size.

To take advantage of mobile hardware, you can develop a companion mobile application for the wearable application. The companion application handles complex and resource-intensive tasks while the wearable application provides a seamless experience.

This tutorial uses Android Studio and Kotlin to demonstrate how to create a multi-module project and communicate between a companion mobile application and a wearable application using the Wearable Data Layer API.

To test the application, you need a Galaxy Watch running Wear OS powered by Samsung and a connected Galaxy mobile device.

Prerequisites

To develop a wearable application and its companion mobile application, create a multi-module project in Android Studio:

  1. Create a new mobile application project.
    Select File > New > New Project > Phone & Tablet > Empty Activity and define an appropriate name and application ID (package name) for the project.
  2. In the Android Studio environment, switch to Project view.
  3. To create the wearable module, right-click the project name and select New > Module > Wear OS > Blank Activity. Make sure the application ID for this module is identical to the mobile application.
  4. Switch the Android Studio environment back to Android view.

To use the Wearable Data Layer API to create a communication channel between the wearable and mobile applications, add the following dependency to the build.gradle file for both modules:

dependencies {
    ...
    implementation 'com.google.android.gms:play-services-wearable:xx.x.x'
  }

Launching the companion application

Launching the companion mobile application from the wearable application includes the following steps, which can be implemented using the MessageClient API:

  1. Send a message from the wearable application to the mobile application.
  2. Receive the message in the mobile application and launch an intent.

Send a message to the companion application

A coroutine is needed to send messages from the wearable application to the mobile application, because this task cannot be carried out on the main thread. The coroutine creates a separate background thread on which to complete the work.

To implement coroutines in the wearable application:

  1. Add the following dependencies to its build.gradle file:
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:x.x.x"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:x.x.x"
    implementation "androidx.lifecycle:lifecycle-extensions:x.x.x"
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:x.x.x"
    implementation "androidx.appcompat:appcompat:x.x.x"
    
  2. In the application code, modify the MainActivity class to inherit AppCompatActivity() instead of Activity().
  3. In the AndroidManifest.xml file, in the <application> element, change the android:theme attribute value to "@style/Theme.AppCompat.NoActionBar" or another custom theme.

Now that you've implemented coroutines, let's develop a way to send a message to the companion application.

In the XML file for the wearable module, define a UI with a button.

While a mobile device can be connected to multiple wearables, a watch is typically connected to only a single device. Therefore, send the message to the first node (connected device) on the watch using the MessageClient API.

To retrieve a list of the connected nodes, implement the following function:

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

In the MainActivity class of the wearable module, add a listener to the UI button that uses the sendMessage() function of the MessageClient API to send a message to the first node retrieved from the getNodes() function.

The sendMessage() function requires three parameters:

  • ID of the receiving node.
  • Message path (specific address) of the receiving node.
  • Byte array of the information to be sent to the node. The size must be less than 100 KB.

The message path is initialized in the companion object and is needed to receive the message on the mobile application.

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private var transcriptionNodeId: String? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.deployButton.setOnClickListener {
            lifecycleScope.launch(Dispatchers.IO){
                transcriptionNodeId = getNodes().first()?.also { nodeId->
                    val sendTask: Task<*> = Wearable.getMessageClient(applicationContext).sendMessage(
                        nodeId,
                        MESSAGE_PATH,
                        "deploy".toByteArray() //send your desired information here
                    ).apply {
                        addOnSuccessListener { Log.d(TAG, "OnSuccess") }
                        addOnFailureListener { Log.d(TAG, "OnFailure") }
                    }
                }
            }
        }
    }
}

companion object{
        private const val TAG = "MainWearActivity"
        private const val MESSAGE_PATH = "/deploy"
    }

Listen for messages in the companion application

A companion mobile application can be notified of incoming messages from the wearable application in two ways:

  • Extending the WearableListenerService class to create a service that listens for incoming messages even when the application is in the background
  • Implementing the MessageClient.OnMessageReceivedListener interface in the MainActivity class of the mobile application

Since we want to react to the message by launching the companion application even when it is not running in the foreground, create a separate class that extends the WearableListenerService class.

To receive messages from the wearable application, implement the following OnMessageReceived() function:

class PhoneListenerService: WearableListenerService() {

    override fun onMessageReceived(messageEvent: MessageEvent) {
        Log.d(TAG, "onMessageReceived(): $messageEvent")
        Log.d(TAG, String(messageEvent.data))
        if (messageEvent.path == MESSAGE_PATH) {
            val startIntent = Intent(this, MainActivity::class.java).apply {
                addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                putExtra("MessageData", messageEvent.data)
            }
            startActivity(startIntent)
        }
    }

    companion object{
        private const val TAG = "PhoneListenerService"
        private const val MESSAGE_PATH = "/deploy"
    }
}

In the AndroidManifest.xml file of the mobile application, add the service and an intent filter for the listener service:

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

To test the project, build both applications and run them on your Galaxy Watch and mobile device. When you tap the UI button on the watch, the companion application launches on the mobile device.

Conclusion

This tutorial has demonstrated how the Wearable Data Layer API enables you to implement seamless communication between a Galaxy Watch running Wear OS powered by Samsung and its connected mobile device. In addition to launching a companion application, the functions of the MessageClient API can also be used to delegate complex tasks to the mobile device, creating more seamless user experiences for wearable applications.

For more information about implementing communication between watch and mobile devices, see Send and receive messages on Wear.

If you have questions about or need help with the information in this tutorial, you can share your queries on the Samsung Developers Forum. For more specialized support, you can contact us through Samsung Developer Support.

Stay tuned for the next blog on wearable and mobile communication.