The code downloads for this chapter are found at www.wrox.com/go/androidwearables on the Download Code tab. The code is in the Chapter 7 download and the filenames are those noted throughout the chapter.
Chapter 6 introduced the three APIs that handle all communication between your phone and your Wear device. This chapter is devoted to the Wearable Data Layer API. This set of methods and classes is part of Google Play services.
The API consists of a set of data objects and listeners that notify your apps of different events. Table 7.1 lists the available data objects.
Sets up shared data storage between the devices with automatic syncing.
MessageApi
Sends fire-and-forget-type commands, such as controlling and starting an intent on the wearable from the handheld or controlling a phone app from the wearable. Delivers an error when the devices are disconnected or the message if they are connected.
Asset
Sends binary blobs of data, such as images. Attached to data items, the system handles the transfer automatically. Minimizes Bluetooth bandwidth by caching large assets to avoid retransmission.
WearableListenerService
Used with services. Listens to data layer events.
DataListener
Used with foreground services. Listens to data layer events when the activity is in the foreground.
In this chapter you will experiment with different types of data transfers between devices. Doing so requires building a client to access the Google Play services. This client will provide a common entry point to all the services and will manage the network connection between the user’s device and each Google service.
CHECKING THE EXAMPLE
Start by taking a look at the example that comes with the Android SDK 20 called DataLayer. Most likely, this example will be replicated in later releases of the SDK, so you should have a version of it available no matter which version of the Wear-enabled SDK you’re using. It shows how different types of data can be moved back and forth between devices.
This example lets you take a picture with your phone’s camera and send the picture to the smartwatch. Figure 7.1 explains how this works in the form of a diagram.
I have refactored the example so that it is made in the same way as the examples in the rest of the book. In the Chapter 7 code downloads folder, decompress the file named chapter7_SimpleWearableData.zip and open it in Android Studio. Once you have it running on your handheld and either your emulator or your watch, you can take a picture with your phone and send it to the Wear device’s screen. You will also see a lot of information overlaid on top. Figure 7.2 shows the app running on a phone.
The interaction performed was to take a picture with the phone after pressing the button on the app’s UI and then to send it to the wearable device. Unlike other examples, such as those in Chapter 6, in this case we have a running wearable app that waits to receive data from the phone and then displays it onscreen. Figure 7.3 is the result on an emulator for a squared Wear device.
The Wearable Data Layer API is useful when a chunk of information (such as an image or sound) needs to be transferred from one device to another. You need to make your own app for your smartwatch, because the amount of data to be transferred starts to become significant. Notifications aren’t good for this. They offer a basic way to get simple information from one device to another and to gather an answer to a simple query. The default software on your Android Wear device won’t meet all your needs—or will it?
Since the whole codebase for this app is fairly large, we’ll look at some code snippets from this example to understand how it works. Later you will perform the inverse operation of building such a program from scratch, which will help you better understand the minimal setup needed to make a distributed application between your Wear device and your phone or tablet.
Phone’s MyActivityPhone.java
In this class you find a series of hints on what the application does. I have chosen a couple of code snippets and highlighted the most relevant aspects. Listing 7-1 shows that we are choosing to use the camera in the application and that when the class is created, the app builds a Google API client.
That Google API client implements listeners for all three APIs that are involved in the communication between devices: Data, Message, and Node. Listing 7-2 shows the override method that adds the listeners for all three APIs at once.
The application, as mentioned earlier, takes a picture with the camera. It calls whatever camera applications you have installed, lets you choose one, and “intercepts” the result of that operation to include it in your app. It takes only a thumbnail, because the biggest image you can show on your Wear device is 320 by 320 pixels. Listing 7-3 shows the main methods responsible for this action. I have highlighted the lines that better describe this idea of launching the activity of taking a picture, resizing it, and sending it to the watch.
Even if the Node API is not the main aim of this chapter, it is worth showing the methods that deal with the connection between the smartwatch and the handheld. Thanks to this API, it’s easy to look for existing wearables and send remote requests to start the activity. Listing 7-4 displays the methods and asynchronous class that check whether the watch is connected and fire up the activity remotely.
Phone’s AndroidManifest.xml
Note the following in the phone’s manifest file which is shown in Listing 7-5.
➤ A uses-feature tag that specifies the use of the camera
➤ A meta-data tag that registers a key-value pair regarding the use of the Google Play services API
Wearable’s MyActivityWear.java
You will notice, when reading the Android Wear application in depth, that the program structure is very similar to the one for the handheld. A whole series of methods handle communication between both devices, initializing the three APIs, and so on.
In essence, the application on the smartwatch does three things:
➤ It shows a simple text when the phone’s app hasn’t been launched yet and/or the devices aren’t connected to each other.
➤ When the phone captures a new image and sends it to the wearable, the application shows this image as a background picture.
➤ The application displays a series of status messages over the image. These messages come from the Node API or the Message API.
Listing 7-6 is an excerpt of the whole class. It focuses on the code that handles the arrival of the asset—the image in this case—the code that handles the shared data storage, and the code that handles how the wearable app displays it onscreen.
Wearable’s AndroidManifest.xml
The manifest file for the wearable contains a couple of relevant things, as shown in Listing 7-7. First, you see how the Google Play services API has been declared in the same way as in the manifest file for the phone’s app.
Second, a class is launched as a service in parallel to the main class. This class, called DataLayerListenerService, waits for events coming from the handheld. There is a better description of that class in the following section.
Finally, the intent-filter named com.wiley.wrox.chapter7.simplewearabledata.EXAMPLE launches the app remotely.
Wearable’s Listener
This example separates the wearable code into two classes—for clarity and because they perform two different tasks. The main activity changes the UI upon arrival of new background images or data that is worth pushing to the screen. The DataLayerListenerService is just that—a service running in the background that waits for events coming from the handheld app that it can report to the main class.
Listing 7-8 shows the two main methods in the service: onDataChanged and onMessageReceived. Note that the second one can launch the main class, as highlighted in the code.
MAKING YOUR GOOGLE API CLIENT FROM SCRATCH
After you have checked the basic example from the Android Wear developers on how to get the phone app and the one on the watch to talk to each other, you will wonder how to make this from scratch. Let’s build the scaffolding for a minimal application that you could expand for whatever use you’re interested in.
A good implementation of a client to Google’s API should be able to connect to one or more Google Play services synchronously or asynchronously and handle connection failures.
Next you will build two apps that will be connected through Google Play services. You will do the equivalent of having two sockets open between the phone and the watch. One will send a value to change the color of the watch’s screen. The other will tell the handheld about the coordinates of the last touch on the watch’s screen.
Consider the following points when dealing with such a scenario:
➤ How will you handle communication between devices? In this case we are using the Data API. You might consider it not to be optimal in this situation. Because we will send small amounts of data, the Message API probably would have been more suitable for this example. But because the aim is to show an example that is easy to expand, the Data API is more versatile and therefore is the one I chose.
➤ How will you update the information on the devices’ screens? This was covered in Chapter 6, where we used BroadcastReceiver to listen to the arrival of digitized voice from the watch and a LocalBroadcastManager to capture the data into the UI. This time you will apply that same technique to the wearable and not only to the phone.
When it comes to the code’s structure, you will have two classes for each device. One will be dedicated to the UI, and the other will run as a service, to listen to the changes in the data storage. When a change occurs, the service on the phone will tell the UI which new values it can use. The process will be the same for the wearable.
Start with a Clean Project
The first step is to create the API client by starting from a clean Android Wear project with code for both the handheld and the Wear device. In this case, a couple objects of the class DataItem are shared between both devices. One field represents the watch’s background color, and the other represents the coordinates of the last location where the user touched the screen.
This is probably one of the shortest examples you can find on how to establish bidirectional communication between the handheld and the watch. It has many anchor points where you can easily add your own code.
The following sections examine each program that is part of this example. The code files can be downloaded from the Chapter 7 download folder.
The Phone’s MyActivityPhone.java
On MyActivityPhone.java, as I have uploaded it to the Wrox server, you will find some interesting things:
➤ The declaration of a Google API client to start sharing data between devices, with overrides to control the possibility of the connectivity’s being lost or not even started.
➤ A local broadcast manager that will be registered at the onCreate()method. It refreshes the text on the UI’s label upon data arrival.
➤ The method syncDataItem(), which sends a new random color using the filter PHONE2WEAR to the watch every time someone presses the button on the UI. I used two different types of data within the Data API: an int for the color and a String to send a simple text indicating how many times the button has been pressed.
Listing 7-9 shows how to implement the Google API client from scratch.
The Phone’s AndroidManifest.xml
Listing 7-10 shows the manifest file for the phone. I’ve highlighted the service declaration. Together with the metadata tag declaring the use of the Google Play services API, these are the two changes needed for the service to boot when the app launches and for the combo to use the Google API to talk to the other device.
The Phone’s DataLayerListenerService
DataLayerListenerService is launched on the phone after the app launches. When the phone registers an event of any of the shared data objects changing, the listener is triggered. In this case it filters by WEAR2PHONE. This object, as defined in MyActivityWear.java (check the source code later in the chapter), carries two float numbers—the x-coordinate and the y-coordinate of the last time the screen was touched.
In Listing 7-11 you can see the listener service in the phone that will be waiting for the wearable device to make changes on the shared data object.
MyActivityWear.java
The activity on the watch is very similar to the one on the phone. Just take a look at Listing 7-12, a snippet of the main class running on the phone. You will see that it is more or less the same application as on the phone, with these differences:
➤ In this case the data is sent as WEAR2PHONE.
➤ The property we are changing in this case is the background color—a combo of the setActivityBackgroundColor() and setBackgroundColor() methods.
➤ touchListener is implemented within the method dedicated to the layout. Because the listener is responsible for detecting touches and sending them, all the needed code is added there, inline.
Wear’s Android Manifest File
Listing 7-13 shows that there is almost no difference between the manifest file for the wearable and the one for the handheld.
The Listener on the Wearable’s Side
Listing 7-14 shows the last piece of the puzzle.
The Final Result
I haven’t focused on showing the layout for either of the applications. I recommend you check the full example on the book’s downloads under chapter7_WearableDataFromScratch.zip. There you will find all the code used here, ready for you to copy and start experimenting with in your own applications.
The expected result on your side should be something like what is shown in the next two figures. Figure 7.4 is a screenshot of the activity on my phone. Figure 7.5 is a screenshot of the watch after the button on the phone’s UI is pressed and the watch’s screen is touched.
SUMMARY
This chapter has shown you how to run the basic Wearable API communication example provided by Google in the Android Wear SDK. You have learned how to make your own simple, bidirectional app ecosystem so that you can share data records between apps on different devices.
Remember that the way to communicate between your handheld and your watch is Google Play services.
In the next chapter you’ll explore how to stream audio over Bluetooth.
RECOMMENDED READING
Visit the following documentation sites from the Android Wear project for further reference: