Landing on Wearables (part 2)

In Introduction to Wearables we had a look at some of the concepts those are the foundations of Android Wear. In this part we are going to skip completely any considerations on that and we’ll have a look at how things work underneath. In particular, we’ll have a look at how to extend existing application’s notifications and how to debug on wearables(this second part will be used for the following tutorials). In order to achieve this, we’ll start with a sample application that runs just on a handheld device and we’ll try step by step to extend it, trying to create a beautiful user experience even on a device running Android Wear.

The Android app that we want to extend and enrich allows users to buy and sell elements from a predefined set of IT books. The user can then navigate between all available items and his own purchased books.

Clicking on any list item opens the details screen for the selected book, allowing the user to understand more about his new or next purchase. At every device start-up a delayed alarm is scheduled in order to suggest the user a new reading in the form of notification that will appear in the status bar. For debugging purposes, this functionality can be forced to happen through an ad hoc action item provided in the application Actionbar’s menu.

The app’s code is completely open-source and can be accessed as a reference on GitHub at http://goo.gl/LKggXp.

A video demonstration of the handheld app that shows how the screens interacts together is available on YouTube at http://youtu.be/WHu6SJn9-kc.

Identifying portable features

When we want to extend and enrich an existing Android application aiming to supply wearable functionalities, one of the first things that we need to do is understanding what we can and want to expose. Another thing to keep in mind is that we are going to develop features on devices those are limited in term of resources and those are meant to do powerful things with the quickest user interaction. We are not going to create an application that’ll try to replace our handheld one but we are going to expose some of the already available features in the app, trying to simplify the user’s life.

Looking at our notification displayed on a wearable device, a book suggestion seems a good candidate to achieve this result. The user might want to do something more with it, possibly with zero or low interaction.

Rather than just showing passive content, we are going to supply interactive functionalities through the following elements:

  • the book’s description
  • the capability of purchasing/selling a book
  • optional voice notes

In this way, the user will be able to perform powerful actions, having the complete control on what’s going on, even without having to interact with the handheld device. Providing an instant and constant feedback for every user action is going to be one of the key elements to ensure a consistent flow.

The component that allows us to add the expected wearable functionalities to the existing notification is a concrete implementation of NotificationCompat.Extender. This interface offers the capability to add custom and ad-hoc features to a notification. The implementation that suits for wearable notifications is called WearableExtender and it provides support for custom backgrounds, icons, pages, actions, content control and alignments. Through the WearableExteneder, it is then possible to add custom Actions with an associated PendingIntent that will be handled by the handheld device in a background Service.

Looking at the SuggestionService.java class:

// Notification Builder used to compose the notification(s)
NotificationCompat.Builder builder = new NotificationCompat.Builder(this); 

… (default notification elements) 

// Creating the Wearable Extender 
NotificationCompat.WearableExtender extender = new NotificationCompat
    .WearableExtender(); 

// Adding the book description as a new page 
extender.addPage(new NotificationCompat.Builder(context)
    .setContentTitle(“Description”).setStyle(new NotificationCompat
        .BigTextStyle().bigText(book.getDescrition())).build()); 
// Adding a custom background 
// (400x400px non scrollable & 640x400px scrollable content) 
extender.setBackground(BitmapFactory
             .decodeResource(getResources(), R.drawable.background)); 

// Action to purchase the book 
PendingIntent purchase = … ; 
extender.addAction(new NotificationCompat.Action.Builder(
     R.drawable.ic_action_buy, “Buy”, purchase).build()); 

// Action to add notes via voice recognition 
RemoteInput voice = new RemoteInput.Builder(EXTRA_NOTE)
    .setLabel(“Add a Note”) .setChoices(getResources()
        .getStringArray(options)).build(); 
PendingIntent notes = … ; 
extender.addAction(new NotificationCompat.Action
    .Builder(R.drawable.ic_action_notes, “Notes”, notes)
    .addRemoteInput(voice).build()); 

// Extending the builder’s notification 
builder.extend(wearableExtender); 

… (space for other extenders) 

// USE the NotificationManagerCompat from the Support Library
NotificationManagerCompat.from(context).notify(ID_SUGGESTION, builder.build());

When an action is then selected by the user, the BookActionService receives the incoming Intent and in a worker thread performs:

  1. the cancellation of the current notification (AndroidWear doesn’t remove by default the current notification for custom actions).
  2. the execution of the incoming action if valid and associated with a valid book id
  3. the creation of a new feedback notification (if required)

 

Having only extended the default notification through the WearableExtender does not mutate its behaviour on the handheld device. On the other hand, the wearable displays the same content but decorated with the given extensions like in the following screenshots.

1. The wearable book suggestion:

2. ACK when a book is successfully purchased:

The video that demonstrates the entire flow is available at http://youtu.be/e8AEcNo-ZSw.

In the case of the Voice note, the content can be retrieved using the supplied extra key using the following util:

// Getting the voice input as a CharSequence
// N.B.: use this instead of trying to get it from intent.getExtras()
RemoteInput.getResultsFromIntent(intent).getCharSequence(EXTRA_NOTE);

Even if this set of tutorials is not about extending a ContentProvider or any other kind of Android element, following standards and using platform tools definitely help and facilitate the development. If you try to install the app on a device coupled with an Android Wear one, you’ll be able to notice that the content is updated instantly on the handheld’s screen even if the update comes from your watch. This is done for free by the Cursor that the ContentProvider behind has returned when the app queried for the content currently shown. Moreover, this feature does not depend on the caller that asks to modify the data but on the way in which the update is implemented. Because of that this behaviour is consistent even if the update comes from a source different from the smartwatch.

Debugging Wearables

Even if the wearable device is paired with the handheld one, when it comes to debugging there are few things that we need to do in order to access the device running Android Wear. In fact, presuming that the handheld device has the USB debugging enabled, if we connect it to our machine and run the ADB command to look up the available devices, it’ll be the only option available. In order to see the wearable device we have to forward the debug output to the handheld device. After having enabled the ADB debugging via Bluetooth on the wearable and in the companion app(settings), we have to route the output in the following way:

adb forward tcp:<port*> localabstract:adb/hub
adb connect localhost:<port*>

*any available port but the same in both commands

The settings in the companion app will then be updated with both the host and the target labeled as connected. Listing now all the available devices on our development machine will show both the devices and will allow us to execute ADB commands and/or even connect the watch to tools like Android Studio.

Finally, I would like to thank you for having spent some time reading this post 🙂
I’m sorry if this one took more than the previous one but I had to prepare the sample app on GitHub.

If you have appreciated this post I invite you to share it to friends, colleagues …even aliens!

See you soon,
Simone

Advertisements

About alchemiasoft

Android Developer at Bloomberg LP. Algorithms and performance passionate. Curious. Eager to learn.

Posted on January 6, 2015, in Android, Java and tagged , , , , , , , , , , , , , , , , , , , , , , . Bookmark the permalink. 2 Comments.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: