Advertisement
  1. Code
  2. Android SDK
Code

Get Wear OS and Android Talking: Exchanging Information via the Wearable Data Layer

When it comes to performing quick, simple tasks, wearable apps have the advantage, as a smartwatch that’s right there on your wrist is always going to be more accessible than a smartphone or tablet that’s floating around somewhere in your bag.

But there’s no such thing as the perfect gadget, and no-one’s raving about their smartwatch’s battery life or claiming that it’s every bit as quick and powerful as their smartphone or tablet.

To deliver the best possible user experience, you need to play to a device’s strengths. If you’re developing for Wear OS (the operating-system-formerly-known-as-Android-Wear), then you’re in a unique position to cherry-pick the best features from two very different devices.

Basically, you can have the best of both worlds!

In this article, I’ll show you how to make the most out of everything Android OS and Wear OS have to offer, by opening a channel of communication between the two. Once your handheld app and its wearable counterpart are chatting, you can delegate tasks based on the device it’s best suited for—whether that’s offloading battery-intensive tasks to the handheld, or making sure your app’s most important information is always easily accessible by displaying it on the user’s wrist.

By the end of this article, you’ll have created a handheld and a wearable application that can exchange information via the Wearable Data Layer and the MessageClient API.

What Is the Wearable Data Layer?

The Wearable Data Layer provides access to various client classes that you can use to store and retrieve data, without having to get your hands dirty with technical details such as data serialization. Once this information is on the Data Layer, it’s accessible to both the handheld and the wearable device.

In this article, we’ll be focusing on the MessageClient API, which is a one-way communication mechanism that you can use to send information to the Wearable Data Layer. This API is particularly handy for executing remote procedure calls (RPC), such as launching an Activity remotely on the paired handheld or wearable device.

Let’s look at an example: imagine you’ve created a navigation app. This app needs to a) retrieve location updates, and b) give the user directions.

Monitoring the device’s location is an intensive task that can quickly drain the limited battery available to your typical wearable. Using the MessageClient API, your wearable app can instruct its handheld counterpart to perform this work instead. Once the handheld has performed this heavy lifting, it can send the resulting information back to the wearable via the Data Layer, so your app gets the information it needs without taking a chunk out of the wearable’s remaining battery.

As a general rule, if your wearable app needs to perform a task that requires significant battery or processing power, or complex user interactions, then you should consider offloading this work to the corresponding handheld app. By contrast, if your app deals with particularly time-sensitive information, or content that the user is likely to access on the go, then you should display this information on the wearable app. 

In our navigation app example, pushing each set of directions from the handheld to the wearable makes this information more easily accessible, especially for someone who’s out and about, and hopelessly lost!

Out of the box, the MessageClient API is a one-way communication mechanism, but you can implement bidirectional messaging by creating a sender and a receiver in both your project’s handheld and wearable module—which is exactly what we’re going to do.

Creating a Wearable and a Handheld Module

In this article, we’re going to create a wearable app that’ll recognise when its handheld counterpart sends a new message to the Data Layer. This wearable app will then respond by retrieving this message and displaying it as part of its UI.

Then, we’ll rinse and repeat, creating a handheld app that monitors the Data Layer for messages sent from its wearable counterpart.

Information sent via the MessageClient API is only accessible to the application that created it. If the system is going to identify your wearable and handheld as belonging to the same application, then they’ll need to have the same package name, version code, and signing certificate. The easiest way to tick all these boxes is to create a project that consists of both a wearable and a handheld module:

  • Create a new project called DataLayer.
  • On the Target Android Device screen, select Phone and Tablet and Wear. Click Next.
  • For your phone and tablet module, select the Empty Activity template, and then click Next.
  • For your wearable module, select the Blank Wear Activity template, and then click Next, followed by Finish.

Creating Your Handheld App

Since we’re implementing bidirectional communication, both our handheld and our mobile modules need their own listener and sender. Let’s start by implementing this functionality in our handheld application.

I’m going to keep things simple and create a UI consisting of a TextView that’ll display the various messages retrieved from the Data Layer and a button that, when tapped, will send its own message to the Data Layer.  

Open your mobile module’s activity_main.xml file, and add the following:

Since we referenced a few dimens.xml values, we need to provide definitions for these values:

  • Control-click the mobile module’s res/values directory.
  • Select New > Values resource file.
  • Name this file dimens.xml and then click OK.
  • Add the following:

This gives us the following user interface:

Create the user interface for your projects handheld component

Add Your Dependencies

Open the mobile module’s build.gradle file and add the following dependencies:

Displaying and Sending Messages in MainActivity

In MainActivity, we need to perform the following:

  1. Keep the user in the loop!

When the user taps the Talk to the Wearable button, two things need to happen:

  • The handheld sends a message to the wearable. I’m going to use "I received a message from the handheld."
  • The handheld provides visual confirmation that the message has been sent successfully. I’m going to use "I sent a message to the wearable."

When the user taps the handheld’s Talk to the Wearable button, the handheld will attempt to send a message to the Data Layer. The system only considers this message successfully sent once it’s queued for delivery to a specific device, which means at least one paired device needs to be available.

In the best case scenario, the user taps Talk to the Wearable, the message gets queued for delivery, and our handheld triumphantly declares that: "I just sent a message to the wearable."

However, if no wearable devices are available then the message isn’t queued, and by default the user gets no confirmation that our app has even tried to send a message. This could lead the user to wonder whether the app is broken, so I’m also going to display a Sending message…. notification, regardless of whether the message is successfully queued or not.

When testing this app, you may also want to trigger multiple messages in quick succession. To make it clear when each message has been queued for delivery, I’m adding a counter to each message, so our handheld will display I just sent a message to the wearable 2, I just sent a message to the wearable 3, and so on. On the other side of the connection, our wearable will display I just received a message from the handheld 2, I just received a message from the handheld 3, and so on.

2. Display received messages

In the next section, we’ll be creating a MessageService that monitors the Data Layer and retrieves messages. Since our service will be performing its work on a different thread, it’ll broadcast this information to our MainActivity, which will then be responsible for updating the UI.

3. Define the path

Every message you transmit via the MessageClient API must contain a path, which is a string that uniquely identifies the message and allows your app to access it from the other side of the connection.

This path always starts with a forward slash (I’m using /my_path) and can also contain an optional payload, in the form of a byte array.

4. Check your nodes!

In Google Play services 7.3.0 and higher, you can connect multiple wearables to a single handheld device—for example, a user might splash out on multiple wearables that they switch between or use simultaneously. A Wear OS device may also be connected to multiple handheld devices during its lifetime, for example if the user owns an Android smartphone and a tablet, or they replace their old smartphone with a shiny new one. Note that any device that's capable of connecting to the Data Layer is referred to as a node in the application code.

In this article, I’m going to assume there will only ever be a single available wearable. Alternatively, you can get selective about which devices you send messages to, using GetConnectedNodes or getLocalNode.

Let’s implement all this in our MainActivity:

Create a Listening Service

At this point, our handheld is capable of pushing messages to the Data Layer, but since we want to implement bidirectional communication, it also needs to listen for messages arriving on the Data Layer.

In this section, we’re going to create a service that performs the following:

  1. Monitor the Data Layer for events

You can monitor the Data Layer either by implementing the DataClient.OnDataChangedListener interface or by extending WearableListenerService. I’m opting for the latter, as there are a few benefits to extending WearableListenerService. Firstly, WearableListenerService does its work on a background thread, so you don’t have to worry about blocking the main UI thread. Secondly, the system manages the WearableListenerService lifecycle to ensure it doesn’t consume unnecessary resources, binding and unbinding the service as required.

The drawback is that WearableListenerService will listen for events even when your application isn’t running, and it will launch your app if it detects a relevant event. If your app only needs to respond to events when it’s already running, then WearableListenerService can drain the device’s battery unnecessarily.

2. Override the relevant data callbacks

WearableListenerService can listen for a range of Data Layer events, so you’ll need to override the data event callback methods for the events you’re interested in handling. In our service, I’m implementing onMessageReceived, which will be triggered when a message is sent from the remote node.

3. Check the path

Every time a message is sent to the Data Layer, our app needs to check whether it has the correct my_path identifier.

4. Broadcast messages to MainActivity

Since WearableListenerService runs on a different thread, it can’t update the UI directly. To display a message in our application, we need to forward it to MainActivity, using a LocalBroadcastManager.

To create the service:

  • Make sure you have the mobile module selected.
  • Select New > Service from the Android Studio toolbar.
  • Name this service MessageService.
  • Add the following:

Finally, open the Manifest and add some information to the MessageService entry:

As already mentioned, the system only considers a message successfully sent once it’s queued for delivery, which can only occur if one or more wearable devices are available.

You can see this in action by installing the mobile module on a compatible smartphone or tablet, or an Android Virtual Device (AVD). Click the Talk to the Wearable button and the app will display the Sending message… text only. The I just sent the wearable… text won't make an appearance. 

If our message is ever going to be queued for delivery, then we need to implement another set of sender and receiver components in our project’s wearable module.

Creating Your Wearable App

Our wearable app is going to have similar functionality as its handheld counterpart, so I’ll be skipping over all the code that we’ve already covered.

Once again, let’s start by creating the app’s user interface. Open the wear module’s activity_main.xml file and add the following:

At this point, your user interface should look something like this:

Create the UI for your Android projects Wear OS module

Open your build.gradle and add the following dependencies:

Now, we need to send our message to the Data Layer:

Next, we need to create a listener that’ll monitor the Data Layer for incoming messages and notify MainActivity whenever a new message is received:

  • Make sure the wear module is selected.
  • Choose New > Service from the Android Studio toolbar.
  • Name this service MessageService and then add the following:

Open the module’s Manifest, and create an intent filter for the WearableListenerService:

You can download the complete project from GitHub.

Testing Your App

At this point you have two apps that can exchange messages over the Data Layer, but if you're going to put these communication skills to the test, you’ll need to install your project on a handheld and a wearable device.

If you’re an Android developer, then chances are you have at least one Android smartphone or tablet laying around, but wearables still feel like a relatively new and niche product, so you might not have invested in a smartwatch just yet.

If you do decide to pursue Wear OS development, then you should take the plunge and purchase a smartwatch at some point, as there’s no substitute for testing your app on a real Android device. However, if you’re just experimenting with Wear OS, then you can create an AVD that emulates a wearable, in exactly the same way you create an AVD that emulates a smartphone or tablet. You can then get your AVD and your physical Android device talking, using port forwarding.

The first step is to create a wearable AVD and install your wear module on this emulated device:

  • Select Tools > Android > AVD Manager from the Android Studio toolbar.
  • Click Create Virtual Device…
  • Select Wear from the left-hand menu.
  • Choose the wearable that you want to emulate, and then click Next.
  • Select your system image, and then click Next.
  • Give your AVD a name, and then click Finish.
  • Select Run > Run… from the Android Studio toolbar.
  • In the little popup that appears, select Wear…
  • Select the wearable AVD that you just created. After a few moments, the AVD will launch with your wearable component already installed.

Next, install the handheld module on your smartphone or tablet:

  • Connect your physical Android device to your development machine.
  • Select Run > Run… from the Android Studio toolbar.
  • Choose mobile when prompted.

Finally, we need to get our physical Android device and our AVD talking:

  • Make sure Bluetooth is enabled on your handheld (Settings > Bluetooth) and that it’s connected to your development machine via USB cable.
  • On your handheld device, open the Play Store and download the Wear OS by Google app (formerly Android Wear).
  • Launch the Wear OS application.
  • On your emulated wearable, click the Home button in the accompanying strip of buttons (where the cursor is positioned in the following screenshot) and then open the Settings app.

Testing your project by connecting your emulator and your Android smartphone or tablet

  • Select System > About and click the Build number repeatedly, until you see a You are now a developer message.
  • Return to the main Settings menu by clicking the Back button twice. You should notice a new Developer Options item; give it a click.
  • Select ADB Debugging.
  • On your development machine, open a new Command Prompt (Windows) or Terminal (Mac) and then change directory (cd) so it’s pointing at the Android SDK’s platform-tools folder. For example, my command looks like this:
  • Make sure ADB (Android Debug Bridge) is recognizing both the emulator and your attached smartphone or tablet, by running the /.adb devices command. It should return the codes for two separate devices.
  • Forward your AVD’s communication port to the attached smartphone or tablet, by running the following command in the Terminal/Command Prompt window:
  • On your handheld, launch the Wear OS app. Navigate through any introductory dialogues, until you reach the main Wear OS screen.
  • Open the dropdown in the upper-left corner and select Add a new watch.
  • Tap the dotted icon in the upper-right corner, and select Pair with emulator. After a few moments, the handheld should connect to your emulator.
Use the Wear OS app to pair your emulator with your Android smartphone or tablet

You’re now ready to test your app! Launch the Wear component on your emulator and the mobile component on your handheld, and experiment by tapping the different Talk... buttons.

When you tap Talk to the wearable on the handheld, the following messages should appear:

  • Handheld: “I just sent the handheld a message." 
  • Wearable: “I just received a message from the handheld.”
You can now exchange messages over the Data Layer using the MessageClient API

When you tap Talk to the handheld on the wearable, the following messages should appear:

  • Wearable: “I just sent the handheld a message."
  • Handheld: ‘I just received a message from the wearable.”

Conclusion

In this article, we looked at how to exchange messages between your handheld and your wearable app, over the Wearable Data Layer. 

In production, you’d probably use this technique to do something more interesting than simply exchanging the same few lines of text! For example, if you developed an app that plays music on the user’s smartphone, you could give them the ability to play, pause, and skip songs directly from their wearable, by sending these instructions from the wearable to the handheld, over the Data Layer.

You can learn more about the Wearable Data Layer, including how to sync more complex data, over at the official Android docs.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.