This is a sample from the book.

Sample 1 Sample 2 Sample 3 Sample 4 Sample 5


Creating a Custom Notification with Timer

If you’ve been reading the Android Wear Design guide, then you’ve probably noticed Google’s familiar fitness app shown above.

How do you determine if the example above is a notification or a standalone app using a custom card? Simple. Just look at the small icon on the right hand side (i.e. the bicep icon). If it overlaps the dotted lines, then it’s a notification. If it’s bounded inside the dotted lines, then it’s a card. 

Notifications allow users to keep informed about relevant and timely events such as incoming mail, the arrival of a new chat message, or a calendar event. Notifications make up a very important part of any Android App, but they are even more relevant on wearables. And since they are worn so close to your body, wearable notifications aren’t just immediate, they’re intimate and impactful. Your understanding of Android Wear is not rigorous until you master the architecture of Android’s notification framework.

In Android Wear, there are five types of notifications that are supported by the notification framework:

  • Basic Notification: This is the most common notification. At the bare minimum, it requires an icon, a title and a description.
  • Rich Notification: Starting with Android JellyBean (API Level 16), Google has made the notification system more versatile by introducing rich notifications that can display a large text block, images and action buttons. Rich notifications are comprised of the following styles:  1) Big View Style, 2) Big Picture Style and 3) Inbox Style.
  • Notification Extra Pages: This notification allows you to show content using additional notification pages.
  • Stacked Notifications: This notification groups a set of related notifications in a card stack. When the user taps on the stack, each card is progressively expanded in the stream allow each notification to be viewed separately.
  • Custom Notifications: This type of notification uses a custom layout to display a notification that better supports your brand. You create a custom notification by defining the notification’s appearance in an XML layout file.

In the following exercise, you will learn how to create a custom notification with a working circular progress timer as shown in the figure above.

Let’s get started!

Note: For brevity, the following images: ic_bicep.png  and pushup_background.png are not supplied as part of this exercise.  You will need to substitute them with your own set of images. 

1. Using Android Studio, create a new Android project for the Wear platform and name it CustomNotification.

2. Add a new Class file and name it CircularProgressDrawable. Populate it with the following content:

3. Add a new XML file in the res/layout folder and name it activity_workout. Key in LinearLayout in the Root Tag field. Populate it as follows:

4. Add a new Class file and name it NotificationBuilder. Populate it with the following content:

5. Add a new Class file and name it WorkoutViewActivity. Populate it with the following content:

6. Add a new Class file and name it WorkoutActivity. Populate it with the following content:

7. In the AndroidManifest.xml, set the default theme to Light and add the following the content enclosed in the <activity></activity> XML nodes:

8. That’s it! Now press Shift+F9 to debug the project on a wearable device or emulator.

Understanding the Code

In the preceding example, you implemented a 2D circular progress timer to display the remaining time left for a workout exercise. To render your own 2D custom graphics, you used the Android Drawable abstraction layer. The Drawable abstract class provides generic APIs to manage a variety of visual elements that are intended for display. These elements are often used by widgets and can include buttons, background images, or progress indicators, as in our case. The Drawable API provides a rich and diverse framework for handling graphics. You may also want to check out the following link to find out more about this API:

To display a circular progress timer, you first defined a class that extends Drawable:

You also implemented the Animatable interface to provide your class with two basic methods to support animation: start() and stop().

You created a constructor with three parameters. The first parameter, currentValue sets the initial start time and the second parameter, maxValue sets the target time. The last parameter, order, is used to set the direction toward which the progress timer fills. For example, setting a currentValue of 20, a maxValue of 30 and a DESCENDING order will draw a circular timer with 30 increments and will start a countdown from 20 to zero:

Next, you overrode the draw() method so that you can draw your custom shapes on a canvas (the latter is used to set the content for the ImageView):

To avoid blocking the UI, you created a Runnable block to perform periodic tasks that will be executed in a separate thread. The following block of code is used to compute values to draw our shapes, to check for boundaries and to refresh the image via a callback:

Finally, you implemented the following Animatable interfaces:

In the preceding code snippet, calling the start() method will schedule a call to the mRefreshRunnable() method every second, and the invalidateSelf() method forces the image to be redrawn. Calling the stop() method will unscheduled the runnable, thus stopping the animation.

To display a custom notification, you first created the activity_workout.xml file to contain the custom layout for your notification. The ImageView will be used to display the circular progress timer and two TextViews are used to show the workout details.

In the WorkoutViewActivity class, you set the activity_workout layout as the content view for the activity that you want to display in your notification:

In the preceding code, you also created an instance of the CircularProgressDrawable with a 30-second countdown. The mPieDrawableCallback() method is a callback for redrawing the circular progress timer image that is managed by the Drawable API. To set a drawable as the content for the ImageView, you passed the mCircularProgressBar instance to the ImageView’s setImageDrawable() method. Finally, when you call the start() method, the countdown will begin and the mPieDrawableCallback() method will be periodically invoked by a thread.

In the class, you built your notification by creating an instance of NotificationCompat.Builder and setting a title, a text, and a small icon.

To display a custom notification, you created an intent object to point to the WorkoutViewActivity class:

You also need to create a PendingIntent object. In this case, a PendingIntent object is used by the Notification Manager to launch an activity on your application’s behalf. You initialized it as follows:

To add wearable-specific options to your existing notification, you used the NotificationCompat.WearableExtender class to specify a background and a notification size (SIZE_XSMALL). Note that the default size for a notification is SIZE_LARGE. To set the custom content view for the activity you want to display, you passed the workoutPendingIntent object to the setDisplayIntent() method:

To display the notification, you obtained an instance of NotificationManagerCompat:

Finally, you issued the notification by specifying the notification ID and calling the build() method to combine all the options and return a new notification object:

That’s it! I hope you enjoyed this sample tutorial. The source code for this tutorial will be posted shortly.

Alex Ho • Email Me ©2015

Go to previous sample


Enjoyed the samples?


Signup to receive additional content for free.

(Don't forget to check your email and confirm your subscription)

We won't send you spam. Unsubscribe at any time.