dcsimg
December 7, 2016
Hot Topics:

Getting Notifications from Android Wearables

  • October 23, 2015
  • By Chunyen Liu
  • Send Email »
  • More Articles »

In the previous introductory tutorials on Android Wear, we mainly covered one of the most popular features in watch faces and configurations. Before we continue to dive into another equally important functionality in notifications, here is the starting article for that series: "Programming Android Wear Watch Faces."

This tutorial will focus on notification messages that you have probably been swamped with on your handheld's status bar every day if you own any mobile devices. Through this introduction, you will get a better understanding of how to create, deliver, organize, and respond to notifications and then incorporate the piece of notification software code into your app to give users better mobile experiences.

Creating Basic Notifications

After your wearables are paired up with your mobile device through the companion app, all the notifications are automatically synced up between them unless you specify what to share through settings or what not. These notifications are displayed on the wearables as a series of cards.

NotificationCompat.Builder is provided to create a notification and NotificationManagerCompat is called to issue it. To use these APIs, some supporting packages need to be imported, as in the example under import .... Once you have the software code pasted in your Android Studio, you can use the shortcut key Alt+Enter to automatically pull in these packages. After you press the basic example button, results will be shown as in Figures 1 and 2 on actual mobile and wearable devices.

import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
...
public class AWNotify extends Activity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_awnotify);

      Button button_basic = (Button)findViewById(R.id.button_basic);
      button_basic.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
            int notifyId = 1001;

            NotificationCompat.Builder notificationBuilder =
               new NotificationCompat.Builder(AWNotify.this)
                  .setSmallIcon(R.mipmap.ic_launcher)
                  .setContentTitle("AWN-1: Basic - Title")
                  .setContentText("AWN-1: Basic - Text")
                  .setLargeIcon(BitmapFactory.decodeResource(
                     getResources(), R.drawable.cb7));

            NotificationManagerCompat notificationManager =
               NotificationManagerCompat.from(AWNotify.this);
            notificationManager.notify(notifyId,
               notificationBuilder.build());
            }
      });
   }
}

Wear1
Figure 1: Basic Notification on Mobile

Wear2
Figure 2: Basic Notification on Wear

We can make some features specific only for the wearables. Very often, owning to the constrained space on screen, you may want to consider arranging the user interface in a compact way for easier interaction. For wearable-only features, NotificationCompat.WearableExtender is what you can do to enforce them. The creation process is almost like any regular notifications. In the following example, the line .extend(new NotificationCompat.WearableExtender().addAction(a)); means that this action button is only displayed on the wearable device, but not on mobile. Once it is pressed, it will search for the string "University of Kansas" on the Web. Figure 3 demonstrates what it looks like on a wearable device.

Button button_wearonly = (Button)findViewById(R.id.button_wearonly);
button_wearonly.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
      int notifyId = 1002;

      Intent i = new Intent(Intent.ACTION_WEB_SEARCH);
      i.putExtra(SearchManager.QUERY, "University of Kansas");
      PendingIntent pi =
         PendingIntent.getActivity(AWNotify.this, 0, i, 0);

      NotificationCompat.Action a =
         new NotificationCompat.Action.Builder(R.drawable.ic_media_play,
            "Search", pi).build();

      NotificationCompat.Builder notificationBuilder =
         new NotificationCompat.Builder(AWNotify.this)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle("AWN-2 Wear: Title")
            .setContentText("AWN-2 Wear: Text")
            .setContentIntent(pi)
            .setLargeIcon(BitmapFactory.decodeResource(getResources(),
               R.drawable.cb8))
            .extend(new NotificationCompat.WearableExtender()
               .addAction(a));

      NotificationManagerCompat notificationManager =
         NotificationManagerCompat.from(AWNotify.this);
      notificationManager.notify(notifyId,
         notificationBuilder.build());
   }
});

Wear3
Figure 3: Wear-Only Example

Building Multiple-Page Notifications

On the wearable devices, we also can add more pages to a notification if more information needs to be presented to the user. Use NotificationCompat.Builder to construct the notifications as before and in the main starting notification, use addPages() or addPage() to append the additional pages for the wearable device. Again, NotificationCompat.WearableExtender is used for this wearable-specific feature. Figure 4 shows the result on a wearable device.

Button button_multipages =
   (Button)findViewById(R.id.button_multipages);
button_multipages.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
      int notifyId = 1003;

      Intent i = new Intent(Intent.ACTION_VIEW);
      i.setData(Uri.parse("geo:0,0?q=" +
         Uri.encode("Stanford University")));
      PendingIntent pi =
         PendingIntent.getActivity(AWNotify.this, 0, i, 0);

      NotificationCompat.Action a =
        new NotificationCompat.Action.Builder(R.drawable.ic_media_play,
           "Map", pi).build();

      Notification p2 =
         new NotificationCompat.Builder(AWNotify.this)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle("AWN-3 MPages: Page 2 Title")
            .setContentText("AWN-3 MPages: Page 2 Text")
            .setLargeIcon(BitmapFactory.decodeResource(
               getResources(), R.drawable.cb7))
            .build();

      Notification p3 =
        new NotificationCompat.Builder(AWNotify.this)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle("AWN-3 MPages: Page 3 Title")
            .setContentText("AWN-3 MPages: Page 3 Text")
            .setLargeIcon(BitmapFactory.decodeResource(
               getResources(), R.drawable.cb7))
            .build();

      List<Notification> pages = new ArrayList<Notification>();
      pages.add(p2);
      pages.add(p3);

      NotificationCompat.Builder notificationBuilder =
        new NotificationCompat.Builder(AWNotify.this)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle("AWN-3 MPages: Page 1 Title")
            .setContentText("AWN-3 MPages: Page 1 Text")
            .setContentIntent(pi)
            .setLargeIcon(BitmapFactory.decodeResource(
                getResources(), R.drawable.cb7))
            .extend(new NotificationCompat.WearableExtender().addAction(a))
            .extend(new NotificationCompat.WearableExtender().addPages(pages));

      NotificationManagerCompat notificationManager =
            NotificationManagerCompat.from(AWNotify.this);
      notificationManager.notify(notifyId, notificationBuilder.build());
   }
});

Wear4
Figure 4: Multiple-Page Notification

Aggregating Similar Notifications

If we need to deliver many similar notifications from our mobile app, grouping them or even providing summaries is a great way to improve user experiences on the wearables. The key is to designate a unique string to identify a specific group. In our example, GROUP_KEY_MY_APP is used in each notification creation as in .setGroup(GROUP_KEY_MY_APP). Figure 5 shows the example on a wearable device.

Button button_group = (Button)findViewById(R.id.button_group);
button_group.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
      int notifyId = 1004;

      Intent i = new Intent(Intent.ACTION_VIEW);
      i.setData(Uri.parse("geo:0,0?q=" + 
         ri.encode("Princeton University")));
      PendingIntent pi =
         PendingIntent.getActivity(AWNotify.this, 0, i, 0);

      NotificationCompat.Action a =
         new NotificationCompat.Action.Builder(R.drawable.ic_media_play,
            "Map", pi).build();

      NotificationManagerCompat notificationManager =
         NotificationManagerCompat.from(AWNotify.this);

      final String GROUP_KEY_MY_APP = "group_key_my_app";

      Notification n1 =
         new NotificationCompat.Builder(AWNotify.this)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle("AWN-4 Group: Title 1")
            .setContentText("AWN-4 Group: Text 1")
            .setContentIntent(pi)
            .setLargeIcon(BitmapFactory.decodeResource(
               getResources(), R.drawable.cb7))
            .setGroup(GROUP_KEY_MY_APP)
            .build();
      notificationManager.notify(notifyId, n1);

      Notification n2 =
         new NotificationCompat.Builder(AWNotify.this)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle("AWN-4 Group: Title 2")
            .setContentText("AWN-4 Group: Text 2")
            .setContentIntent(pi)
            .setLargeIcon(BitmapFactory.decodeResource(
               getResources(), R.drawable.cb8))
            .setGroup(GROUP_KEY_MY_APP)
            .build();
      notificationManager.notify(notifyId + 1, n2);

      Notification n3 =
         new NotificationCompat.Builder(AWNotify.this)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle("AWN-4 Group: Title 3")
            .setContentText("AWN-4 Group: Text 3")
            .setContentIntent(pi)
            .setLargeIcon(BitmapFactory.decodeResource(
               	getResources(), R.drawable.cb9))
            .setGroup(GROUP_KEY_MY_APP)
            .build();
      notificationManager.notify(notifyId + 2, n3);
   }
});

Wear5
Figure 5: Aggregating Notifications

Expecting Responses Through Action Buttons and Voice Input

If you want users to respond to the notification, you can create action buttons with choices. Becaise wearable devices usually do not have a large screen or a keyboard, you should always provide easy choices with reasonably sized buttons or simply provide the voice input option whenever possible. Fortunately, doing this is easy through RemoteInput.Builder. You also can specify predetermined choices and a unique string for identification later; for example, retrieving the text from voice input. In the following example, VOICE_RESPONSE_MY_APP is for this purpose. Then, add this instance of RemoteInput to the action button with addRemoteInput. Figure 6 demonstrates this on a wearable device.

Button button_respond = (Button)findViewById(R.id.button_respond);
button_respond.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
      int notifyId = 1005;

      final String VOICE_RESPONSE_MY_APP = "voice_reply_my_app";
      RemoteInput ri = new RemoteInput.Builder(VOICE_RESPONSE_MY_APP)
         .setLabel("Android rocks?")
         .setChoices(new String[]{"Yes", "No"})
         .build();

      Intent i = new Intent(Intent.ACTION_VIEW);
      i.setData(Uri.parse("geo:0,0?q=" +
         Uri.encode("Google Headquarters")));
      PendingIntent pi = PendingIntent.getActivity(AWNotify.this, 0, i, 0);

      NotificationCompat.Action a =
         new NotificationCompat.Action.Builder(R.drawable.ic_media_play,
            "Respond", pi)
            .addRemoteInput(ri)
            .build();

      NotificationCompat.Builder notificationBuilder =
         new NotificationCompat.Builder(AWNotify.this)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle("AWN-5 Respond: Title")
            .setContentText("AWN-5 Respond: Text")
            .setContentIntent(pi)
            .setLargeIcon(BitmapFactory.decodeResource(
               getResources(), R.drawable.cb9))
            .extend(new NotificationCompat.WearableExtender().addAction(a));

      NotificationManagerCompat notificationManager =
         NotificationManagerCompat.from(AWNotify.this);
      notificationManager.notify(notifyId, notificationBuilder.build());
   }
});

Wear6
Figure 6: Reply Action with Voice Input

Conclusion

The notification feature is likely the most practical function on wearable devices. We cover the fundamental topics in notification creation, delivery, organization, and response. There is an excellent sample project called "Wearable Notifications" directly downloadable through Android Studio. It covers several advanced features you might be interested in. Lastly, the photos used here are my talented friend Chris Blunt's creations and he certainly should get all the credit. His link can be found in the References section.

References

  1. Download example source codes from the link at the end of this article.
  2. Android Developers at: http://www.android.com/developers/
  3. Androidlet at http://www.androidlet.com
  4. Chris Blunt Photography at: https://www.facebook.com/Chris.Blunt.Photography

About the Author

Chunyen Liu has been a software professional in Taiwan and the United States. He is a published author of 40+ articles and 100+ tiny apps, software patentee, technical reviewer, and programming contest winner by ACM/IBM/SUN. He holds advanced degrees in Computer Science, trained in 20+ graduate-level courses. On the non-technical side, he is a certified coach, certified umpire, rated player of USA Table Tennis, and categorized medalist at State Championships and US Open.


Tags: Android, APIs, android studio, Android Wear, Android wearable services APIs, handheld devices, notifications, action button




Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date
Rocket Fuel