Posted on: 9/5/2014 4:35:00 PM by Chris
A while back (a year ago counts as awhile back, right?), I posted about the General Availability of Azure Notification Hubs. Since then, I’ve given a few presentations at different conferences (TechEd, AnDevCon, CocoaConf, 360iDev, etc) on how you can make use of Notification Hubs to power your push notifications. However, I haven’t really posted about it or released sample code demonstrating how it works on the different platforms. Technically, I did release a very comprehensive app, named LensRocket, that uses Notification Hubs, however, that is a huge sample so if you’re just looking for “how do i do push?” it might be confusing. Today I’m going to start fixing that by releasing a fairly comprehensive explanation of push focusing on Android clients. I actually just posted the same walkthrough for iOS a few days ago. For clarity sake, and so you don’t have to hop between the two posts, I’m going to reexplain all of the things which both Android and iOS have in common here. Note that if you want to pull down the completed app, you can access all of the source code here in GitHub.
For those who may not already know, I’ll give a quick overview of what Azure Notification Hubs are and why they exist. When building client applications (whether they’re iPhone, Android, WinPhone, or WinStore apps) one of the capabilities apps have is to receive Push Notifications. Push Notifications are a way of delivering information to your app without your app having to go out and request it. These pushes could inform the user / app of many many different things and just a few examples of them include: you’ve received an email (including increasing a badge number), play a sound, display a message, download some data from a server. What’s really key here is that you can send this information down to a device without your app needing to request it first, or without your app even running! This means that push notifications end up being used a LOT. Fortunately, when you’re building an app (regardless of the platform) it’s pretty simple for you to take advantage of push notifications.
For each client platform, there is a Push Notification Service (PNS) provided by the vendor primarily responsible for the OS. So:
- iOS has Apple Push Notification Service (APNS)
- Android has Google Cloud Messaging (GCM) and Amazon Device Messaging (ADM) for Google Android and Amazon Android, respectively
- WinPhone has Microsoft Push Notification Service (MPNS)
- Windows Store has Windows Notification Service (WNS)
- Other OSes provide their own services but are more bit players
Each of these PNS will provide to your application some identifier that identifies your app and device to the PNS. Once you get this identifier, you can then use it to talk to the PNS and ask it to deliver a push notification to the device / app. While you COULD request a push from the same device that you’re running the app on, what is common practice is to have a backend somewhere that you send the identifier to. This backend can then talk to the PNS and request a push. This backend could be a website running somewhere, a web service, a virtual machine, a client application, or really anything else capable of making an HTTP request to the PNS.
So far we have a client app, we have a PNS, and we have a backend. Let’s talk about how Notification Hubs fits into this. Notification Hubs is basically built to be a pseudo backend / service that will handle talking with the PNSes. That’s a pretty big simplification though because there is a lot behind that. First, when your backend asks a PNS to deliver a push notification, every request has to be signed with either an API key or a certificate (depending on which PNS it is). So not only does NH need to be able to handle taking in the keys / certs and using them for each request, it needs to be capable of updating to new versions as the certs do expire! While that’s more of administrative details, NH also enables easy targeting of push notifications using Tags (more on this below) as well as enabling single line of code cross-platform push via templates (more on this also below). Let’s start seeing some code so we understand how this works.
Setting up GCM and Starting on the Client
Today we’re going to be focusing on using GCM to push to Google Android devices. On the client side, setting up your app for push notifications is probably more complicated for Android than any of the other platforms. The first step you need to follow is to go to the Google API Console and generate a new project, enable the Google Cloud Messaging API, and then create a Public API Access key. You can follow along with step by step instructions for doing so here. Once you’ve done that, you’re ready to proceed with client changes. Before we edit any files, we need to put the Notification Hubs jar into our libs folder. You can download the libraries from here. Make sure to copy over the notification-hubs-X.jar and the notifications-X.jar into your libs folder and then refresh that folder in your IDE.
Next, open the AndroidManifest.xml file in your Android project. We first need to add the necessary permissions inside the manifest element:
Make sure you replace the PACKAGE in the bottom two lines with the package of your actual application. The last step in our manifest is to specify the receiver:
Again here we need to replace PACKAGE with the package of the application. The com.microsoft.windowsazure.notifications.NotificationsBroadcastReceiver is a helper we get from the Notification Hubs library. Up next we’ll set up our Notification Hub on the server side before we switch back to the client.
Setting up Notification Hubs and your Project
Head over to the Azure Portal and create a new Notification Hub. If you haven’t done that before, it’s documented here. Once you’re done with that, go to your Hub in the portal and go to the CONFIGURE tab. Find the area for google cloud messaging settings. Copy the server API Key you got from the Google API Console into this and save the changes. Next, go to the DASHBOARD tab for your service and click on the CONNECTION INFORMATION button at the bottom. You’ll want to copy the Listen and Full Shared Access Signature’s for later. Now we can head back to the client.
Registering with GCM
We’ll do two things now. First we’ll handle getting an instance of a GoogleCloudMessaging object and then we’ll set up our Notification Hub for later:
In the demo app, this code is in my fragment’s onCreateView method but you may want it elsewhere. You’ll need to replace the NotificationHubName and NotificationHubListenSharedAccessSignature with the values from your Notification Hub (that you just got a second ago). Next we’ll add a method that will go out to GCM and register. In the demo app, I’m triggering this from a button tap, but you might want to do it right after you create the GCM object above:
Here we’re starting a background async task (to not block the main thread) and telling it to go and register with GCM. We’re passing in a SENDER_ID which should be the Project Number of your project in the Google API Console (note that this is the Project Number and NOT the Project ID). The last thing we need to do before moving on to talking with our Hub is create something to handle receiving push notifications.
If you’re adding the code to your own project (as opposed to using the referenced demo code), you’ll want to add a new class to your project named MyHandler which inherits from NotificationsHandler. Here’s the code for our class:
The NotificationsHandler base already handles a few things for us . All we need to do is override the onReceive method and dictate what we want to happen when we receive a notification. Here we’re calling into a sendNotification method which will first use the NotificiationManager to display a notification in the status bar at the top of the device. Then it will also display a toast on the screen of the app. Now that we’re able to display our notifications when we receive them, we’re ready to start registering with our hub and then sending out push notifications.
Broadcast push is a way of doing untargeted push notifications. In other words, push to all of the Androiddevices that have registered with my hub. Let’s look at the client side code first:
Here we’re calling register on the hub we created earlier and we’re just passing in the registration ID we received from GCM. When this runs it will contact our hub and basically say “I’m an Android device that is registered with GCM, here’s my registration ID.” Now let’s look at the server side code to trigger a push.
Here you’ll replace the strings in call to createNotificationHubService with your hub’s name and the FULL Access Signature. We then use the notificationHubService object to call gcm.send where we specify the payload we want to send. Running this script will trigger our hub to push that payload to any Android / GCM device that has connected to the hub. One other thing to note is that these scripts were created to be run as Mobile Service Custom APIs in order to ease testing out (with the permissions set to Everyone, I can trigger this script by going to the endpoint for it in a browser). I’ll talk more about connecting to Notification Hubs to trigger pushes later, but for now just know that this same Node.JS Script could run anywhere you can run Node. You’d just need to pull down the Azure Node Package.
Pushing to Tags
Up next we’ll talk about targeted pushes. So instead of “Broadcast to everyone” we’ll be able to say “Push to user X” or “Push to this group of users”. The first step in doing this is registering from the client:
This is identical to the code we had on our client before except now we’re passing in additional parameters which are tags. In this case, my array has three tags: MyTag, AllUsers, and AndroidUser. When we run this it basically says, “I’m an Android device that is registered with GCM, here’s my push token. Also, tie it to these three tags.” What’s great about this is then from our backend, we can tell our hub to only push to devices that are tied to a specific tag, like this:
Here we’re doing the same thing on the server, EXCEPT we’re passing in a first parameter (previously it was null). In this case we’re passing in the tag MyTag so only devices registered with my hub, with GCM, will receive the push notification.
Pushing based off of tags is pretty cool. You could use tags for lots of different things (sports teams, stock ticker labels, zipcode (i.e. geopush), etc). You could even set the user’s username (if they were logged in) as a tag and then you’d have the ability to say “push to all of Chris’ devices” if you wanted. Another powerful feature of hubs is called Tag Expressions. This basically enables you to trigger pushes based off logical expressions of tags. So for example, if I was registering with the username and a group I’m in, I could say “Push to GROUPNAME except ME”. So push to everyone in the group I’m in but not my devices. The actual tag string I would use would probably look something like this “Group:ID && !User:ID” where the tags I register with might be “Group:ID” and “User:ID”.
So far we’ve looked at broadcast and targeted based push. However, all of the pushing we’ve done has been constrained to GCM devices. If I’m building a cross-platform app, I need to be able to handle pushing to other platforms as well. Now I could have the same code to do a push to iOS and WinPhone and WinStore right after my gcm.send code everywhere I want to do a push, but that’s a decent amount of code. Especially if I am pushing in many different places. The alternative to that is using Templates. When you register with your hub, in addition to sending the push identifier and the tags you want to be tied to, you can also specify a template that indicates the format of the payload you want to receive. Let’s take a look:
Here we’re creating a template string that contains the data JSON format that we previously saw in our server script. Inside of that payload is the important bit $(message). From the server side, when we push, it will use that message bit to figure out how to format the payload with the data we want to inject. The other difference here is that we’re now calling registerTemplateWithDeviceToken. Let’s take a look at the Node script to push to our client now:
Now we’re creating a payload object which is a JSON object with a message field in it. We can then use notificationHubService.send (notice there is no gcm in the middle anymore) and set the payload as the second parameter (we’re not using a tag to do a targeted push here but we could). When this runs, it will cause the hub to find any device registration that has a payload with the message field in it and format the payload with the data from the payload we’re sending in. So effectively, when we send to our Android device, we’ll use the gcm payload format specified on the client. If i was doing something for iOS, we’d send it in the iOS specific format, and so on. So we now have a single line that is capable of handling pushing to any device type!
Talking to Notification Hubs from Your Backend
The idea here is that Notification Hubs can effectively handle all the aspects of Push Notifications for you. I can have a backend (website or web service) running somewhere, whether its on Azure or not or it’s in .NET or not doesn’t matter at all, and just talk to my Notification Hub whenever I need to trigger a push. Now in the samples above, I’m trigger my pushes from Node.js scripts which make use of the Node.js Azure module. These could be running anywhere but to make things easy, I usually run them from Azure Mobile Services (super quick to get them up and running). You can also use the .NET SDK for triggering push notifications, and their are guides for doing so from Java as well as from PHP. Everything in Notification Hubs is also exposed over a REST API so even if there isn’t an SDK or a guide for talking to your hub from your platform of choice to trigger pushes, you can always fall back on the REST API.
I hope this post proves helpful for anyone looking at using Notification Hubs to handle Android push notifications. If you also look at the iOS walkthrough, you’ll see that the majority of the code is either the same or very similar. Notification Hubs are a super easy way to get into doing push notifications for your apps and make it super simple to make them working on different platforms. Add to all these features the fact that you get 1 million push notifications for FREE every month (as of Sept. 1, 2014) and it’s a pretty sweet deal! You can grab both the client and server source code for the app seen above here.