This post looks at notification systems on Android, Chrome and Android Wear and provides a simple way to insert your own notifications in to the stream with Pushbullet. I presented this at the Google Developers Group in Brisbane this week, the post is a longer form of the presentation. The slide deck I used is available here, I've enabled commenting on the document so please feel free to leave your feedback.
What are Notifications?
Before we look at specific implementations we need to describe what a notification actually is, or more specifically what an idealised version of a notification is. An ideal notification has four key features - it must be concise, subtle, contextual and ignorable.
The purpose of a notification is to let you know about an event that you 'might' be interested in. How this notification is presented varies greatly - it might be a simple LED indicator, an icon present in a toolbar or small popup in the corner of a screen. In any case there is not a lot of ways to show complex information so the notification should only provide the minimum required to allow you to make the decision to follow up on it or not.
Notifications are personal things - they only affect you and should be tuned to what you need to know so they should be subtle and non-intrusive. The whole world doesn’t need to know that your eBay purchase was just shipped so a vibration or a blinking light should be enough to get your attention.
A notification system should take your current context - time of day, location and the activities you are performing - into account as a filter to determine what notifications are pertinent. Google Now is a good example of a service that uses context to filter notifications - your location, the current time and recent activity determines what cards are presented.
Notifications, alerts and alarms are different things with different purposes. Ignoring a notification should have no negative consequences - if the information or event being reported requires immediate action you should not be using a notification.
Notifications on Android
The Android notification system is simple, they are announced with a sound or vibration and an icon will be placed in the status bar for events that have not been dealt with yet.
The image above shows the UI for Lollipop, the KitKat version is very similar. Simply slide the status bar down to see the pending notifications, tap to get more details or swipe right to discard it. If none of the notifications are of interest you can clear all of them with a single tap.
Unfortunately the nature of the phone doesn't make this a particularly useful system. There are several steps required to see even the basic information contained in the notification - pull out your phone, unlock it and swipe down the notification list.
The common pattern with a phone is polling - check the device periodically to see what notifications have come in. Unfortunately this interferes with the timeliness of notifications, they may no longer be relevant by the time you read them.
Notifications on Chrome
The presentation is similar to desktop notifications for native applications and Google have done a good job integrating it into the major desktop platforms. An icon indicates if there are any pending notifications and a small popup will appear with the content. All of the Google services use this system in the browser and many third party extensions make good use of it as well. You can even have notifications from your phone mirrored on the desktop through an extension as well.
If you are in front of a computer most of the day this is a more effective way of getting notifications than a phone. Relevant information is presented in the corner of the screen as it happens and you have the opportunity to respond to it as it becomes available without the need to poll for updates.
Android Wear are one of the first devices to appear whose primary, if not sole, function is to display notifications. They have been on the market for nearly a year now and the software has matured to do the job very effectively.
The Android Wear system comes close to the ideal notifications I spoke about at the start of the post - the notifications are concise (presented with a card based UI), subtle (notifications are announced with a simple vibration), and ignorable.
The UI is very intuitive - notifications form a stack as they come in and you can simply swipe right to dismiss the current one, swipe left to respond to it and swipe up or down to navigate through the list. Some notifications on Wear allow you to respond to them immediately directly on the device itself - for a message you can reply via voice, a reminder can be postponed or the sending app can be opened on the phone.
I reviewed the Galaxy Gear Live shortly after they first came out and it has become an integral part of my day to day life since then. Wearable devices seem to be a very partisan item - you either find them indispensable or you just don't see the point. Unfortunately only using one will determine which camp you live in.
Now that we've seen how notifications are handled on a range of Google platforms it's time to consider where these notifications are coming from.
All the usual suspects are present - email, social media, calendar reminders and Google Now which is all fine and good. What about the events we want to know about but aren’t supported or generated by these apps? There are a lot of domain specific events that it would be nice to hear about when they happen that aren't being pushed to the notification queue displayed on your phone or watch.
It would be nice to know if a long running task such as a build script has finished (and if it finished without error). Monitoring values would be useful as well - I don’t really need to know how many hits my site has had every hour but if that value was significantly above or below what was expected that is a useful piece of information to have. There are also events you do want to know about whenever they happen; a server restarting or a UPS kicking in.
How do we get those sort of things into our notification queue?
The best tool I have found for this is a service called Pushbullet. Pushbullet allows you to send ‘pushes’ (which are notifications with benefits) between all devices it is installed on. Even if you are not interested in sending out custom notifications the service is pretty damn useful all by itself and I highly recommend you take a look at it.
It’s available as an app for Android and iOS, a browser extension for Chrome, Safari, Firefox and Opera and as a desktop application for Mac and Windows. If you are using Chrome you don’t need a separate desktop app - the Chrome extension provides all the functionality (as long as you are allowing Chrome to run background services). There is of course a web app as well - so you can send out pushes from any browser on any machine.
It will mirror notifications that appear on your phone to your desktop and, in some cases, let you directly respond to notifications from the desktop as well (you can reply to an SMS message without going to your phone for example). You can easily send files between devices which is a simpler experience than using Dropbox or Google Drive if you just want to transfer a single file. You can also share your clipboard across devices as well.
The full set of functionality is only supported on Google platforms, other platforms have some limitations - you can’t mirror notifications from iOS for example.
What we are mostly interested in though is the API that Pushbullet presents that we can use to send our own notifications to devices and Chrome. It is a very simple REST based API - simply POST a JSON request to the correct endpoint and process the JSON result. The API lets you generate new pushes, read the list of pushes that have already been sent and manage your device list.
A ‘device’ is not necessarily a device - it’s simply a named target for pushes. New devices will be created for everything you install Pushbullet on so you can send pushes directly to it as well as to all devices in your list. You can create a new 'virtual' device if you like and use that for a specific set of notifications. In this way you can get it to act more like a message queue - the pushes don’t actually get displayed on anything they are just generated and consumed by software.
Bindings exist for C#, Java and Python and there are a lot of other bindings are available on GitHub - just do a search. If your language of choice is not supported it is very simple to write your own - as long as you can do a HTTP request you can write a binding. For the examples here I’m going to use the Python bindings.
The Python bindings for Pushbullet are available on PyPI, simply install the 'pushbullet.py' package ...
pip install pushbullet.py
The simplest example to send out a notification to all of your connected devices looks like this ...
from pushbullet import Pushbullet # Get from account settings page # https://www.pushbullet.com/account API_KEY = "your_api_key" pb = Pushbullet(API_KEY) push = pb.push_note("My title", "My message")
As you can see adding support for sending out notifications is very simple. If we extend the basic example with error checking and support for command line arguments we can build up a tool that you can invoke from a batch file or shell script and use to add notifications to notifications and long running tasks. Here is the code ...
#!/usr/bin/env python #---------------------------------------------------------------------------- # 15-Jun-2015 ShaneG # # Simple command line tool to send a Pushbullet notification #---------------------------------------------------------------------------- from pushbullet import Pushbullet from optparse import OptionParser from sys import argv # Either set a default key here or pass on command line API_KEY = "" # Usage information USAGE = """ %s Usage: %s [-k|--key api_key] [-t|--title message_title] message_body Where: -k|--key api_key Specifies the API key to use for this push. -t|--title title Specifies the title of the notification. """ def showUsage(message): """ Display usage information and exit """ global USAGE print (USAGE % (message, argv)).strip() exit(1) if __name__ == "__main__": # Process args parser = OptionParser() parser.add_option("-k", "--key", action="store", type="string", dest="key", default=API_KEY) parser.add_option("-t", "--title", action="store", type="string", dest="title", default="New Notification") options, args = parser.parse_args() # Make sure we have a key if len(options.key) == 0: showUsage("You must provide an API key.") # And we want a message. message = " ".join(args).strip() if len(message) == 0: showUsage("No message provided.") # Do the push try: pb = Pushbullet(options.key) pb.push_note(options.title, message) except Exception, ex: print "Error: Unable to send notification - %s" % ex
Even this is simplistic, you could extend it further to add support for files and URLs as well as simple text notifications. As it stands it is good enough for a range of purposes. Simply add it to your /etc/rc.local file to get notified of server restarts or at the end of a build script to let you know it has finished.
A More Complex Example
As I mentioned before Pushbullet supports a rich set of notification types and all of these are exported by the API. You can build up some complex integration scripts to get information from sources that were never designed to present it in that fashion.
I have an old digital oscilliscope from the 1990's, it's a nice piece of equipment but hardly what you would call modern. The only way to get a copy of the trace on the screen was to send it to a printer and the oscilliscope has a centronics and a serial port to facilitate this.
One of the output options in a raw monochrome PCX file (the other is Epson Esc/P printer control codes but that's a little bit too old school - even for me).
I wrote a simple Python script to monitor the serial port and save any data coming in as a PCX file. It then converts the PCX image into PNG (so it can be understood by modern applications) and send it out using Pushbullet.
When I press the 'Print' button on the oscilliscope the trace image pops up as a notification in Chrome and I can embed it into my lab notebook, a blog post or Hangout conversation. It automatically stores it in Google Photos as well so I have a time and date stamped archive of measurements I've made.
A well behaved notification system can dramatically improve your day to day activities if it stays close to the key features (concise, subtle, contextual and ignorable) and allows you to insert your own notifications into the queue to meet your specific requirements. Hopefully I have pointed you to tools that can help you with the latter.