Push Notifications With Cordova & Icenium

Overview

What are push notifications?

Push notifications are messages sent from an application server to a specific device using the vendor infrastructure. Typically, push notifications are used to notify an application to update its data. For example, push notifications are sent when a feed has been updated, a message has been received, or a new appointment has been made. For more information about push notifications, see Push technology.

Why do we need push notifications?

Push notifications are designed to preserve phone resources. If an app queries the server every 10 seconds, this uses up precious battery life and bandwidth. In fact, an iOS app cannot poll a server continuously because there is no true multitasking. Instead, the user needs to actually start the application to update it.

General overview

There are three components in the life cycle of a push notification: the actual application, the OS vendor servers (or a third-party mediator), and the application server. Here's how it works:

The application registers for push notifications with the OS. (Under the hood, the OS contacts the vendor push servers and requests a token.)

The OS returns the token to the application.

The token is sent to the application server.

The application server uses the token to send push notifications to the device.

Let's Bring Push Notifications to Life

With the Cordova-based PushPlugin plugin, we will develop the push notification module of a promotional app. The sample app is designed to run on iOS and Android, and to display promotional text in a single paragraph. To run and test the app, we will also create a simple application server and a web form that sends verbatim promotional text to the application. We will be using the Apple Push-Notification Service (APN) for iOS, and Google Cloud Messaging (GCM) for Android.

Bear this in mind – because push notifications are unreliable, you should avoid using them to transport data. Instead, use them to let your app know that an update is needed.

Application Server

Let's start our project by creating an application server with Node.js. (Node.js is becoming more and more popular and you can check out why here.) This sample application server was tested on Windows 7 64-bit and Mac OS 10.7 with the latest stable Node.js installed – but you should be able to run it on any OS that supports Node.js.

Here are the requirements for our server:

Accept token from device and store it for later use.

Host and run a very simple web form to send messages. (NOTE: To keep the code as simple and clear as possible, we will not add any security features.)

Send push notifications for new promotions to all registered devices.

Store promotional text submitted with the web form.

Our simplified HTTP server will listen on port 80 and answer requests with status code 200 and an empty body. (Just browse to localhost in your favorite browser and look at the node process console output.)

NOTE:

Turn off IIS, if running.

Running Node.js is as simple as running node server.js in the command line.

Running on ports below 1024 may require admin/root privileges, so you can alter the port as needed, or use sudo, etc. to run the server.js module below.

Next, we need to configure how our server handles the form. In our project, the server sends the form when called without a path. When the server is called with the "/setPromotion" path, the server responds with the promotional text that is currently stored in the form:

In your browser, you can test to see if the form appears and if using it correctly persists the message to the promotionText variable on the server. To track errors, you can add console.log anywhere you need it in the code.
The next step is to implement adding and removing devices, and querying for promotional text.

In the code below, we add routes for device registration and for retrieving promotional text. We also register the "/getPromotion" route that serves our promotion in JSON format.
To register, devices send their device token and platform in JSON format to the server.

Now let's start developing some of the device-side functionality, so that we can check if our application server is implemented correctly.

App code

Let's begin by creating a new jQuery project in Graphite. From Project Properties, we'll add PushPlugin to the project and include a reference to PushNotification.js in index.html.
Then, we create a file named push.js in the js folder and include a reference to it in index.html.
Here is how the script tags in your index.html should look:

Now if you run the application on your device or in the simulator, you should get something similar to this:

This occurs when the application is not signed with an AppID with enabled push notifications.

In our case, we do need to create a brand new AppID for the application. (For more information, click here).

Here, we can add a new AppID with com.icenium.PromotionalApp as a bundle identifier (or you can use whatever bundle identifier you like). We are not done with the AppID yet – we need to enable push notifications for it. Find it in the list and click "Configure". Enable push notifications and click "Configure" for Development Push SSL Certificate.

To set the newly created AppID for the sample application in Graphite, go to Project Properties and modify Application Identifier.

Next, we need to create a certificate signing request (CSR) for a SSL certificate. This will be used to connect our application server to the Apple server. Let's head back to Graphite and create a CSR from Options > General > Certification Management. To generate a certificate signing request (CSR), click the Create button and select Certification Request. Next, save the CSR file on the disk, upload it to the Apple web site, and download the certificate that Apple generates. Back in Graphite, we can now complete the pending request in Options > General > Certification Management by uploading the newly created certificate. The certificate is used to connect to the Apple Push Notification Service (APN).

Now, we will create a specific provision for our application with the new AppID. We will go here and create a new developer provision with our newly created AppID. You might need to hit Refresh a couple of times before the provision becomes active.

Once we have a new developer provision, we need to download it, and in Graphite, import it from Options > Mobile > iOS.
In Project Properties > iOS, we can set the codesigning identity to our newly created provision.

The next step is to finally get the device token:

In our project, we send this token to the application server, get registered for notifications, and POST an AJAX request to the server with the token. We also implement the onNotificationAPN callback which is called when a push notification is received.
In the example, the IP address belongs to my local machine. To get your IP, type ipconfig in the command line if you are running Windows, or use ifconfig if you are running Mac OS.

If everything has worked, in your node.js console, you should see output confirmation for the registered device.

Android

For the Android implementation, we will start by creating a Google API project. You can find the tutorial for that part here. Once we have created our API project, we use its project number to request a token. In our application code, we need to add a function to get the actual promotional text when we receive a push notification. Once we have the promotional text, we will add it to a paragraph on the landing page of our jQuery starting project. Here is how we enhance push.js with the described functionality:

Application server

To send our push notifications, we will use two open source modules for Node.js: node-apn and node-gcm. Again, we will add the code separately for iOS and for Android.
Let's start by installing the two open source modules. Go to the folder where your server js file is. In the command line, type npm install apn and npm install gcm. If everything is OK, you should see two folders in the folder where your server js file is: ./node_modules/apn and ./node_modules/gcm.

Our application server needs to establish an SSL connection with the push notificaion servers of Apple. For this, we will use the private key and certificate that we created earlier for our AppID. We need to create PEM files for the certificate and the private key. You can read more here. Go to Options > General > Certification Management, select the cryptographic identity that we created earlier and export it. For the next part we will need to do some format conversion with OpenSSL.

Creating PEM files from certificate and p12 file

If you're running Windows, download OpenSSL for Windows from here. Note that Microsoft Visual Studio 2008 C++ Distributable is required for OpenSSL under Windows. Mac OS should have OpenSSL out of the box.
To create the required PEM files, follow the instructions found here.

Now copy the PEM files you created to the folder where your server js file is. In our example, we have named them cert.pem and key.pem. Here's what we need to add to our server code:

NOTE: Make sure that port 2195 is not filtered by your system administrator.

Now, iOS devices should display the promotional text in the landing page paragraph. We just need to add the code for Android devices to our project, and we are done.

To send messages to GCM (Google Cloud Messaging), we use the API key for the Google API project we created earlier. You can find your own API key here, in the API Access tab. The final touches to our server code look like this:

Conclusion

It was a long road but if you are reading this you are ready to create some amazing apps using push notifications. Keep in mind that the implementation here is very basic and you can do a lot more to make it production ready. For example, you can use the APN feedback service to keep track of undelivered messages and identify unreachable devices. A few more ideas: fetch promotions when app starts, unsubscribe from promotions, and so on.

About the AuthorEvgeni Petrov is one of the mobile guys at Icenium. He has been involved in numerous mobile project throughout his career. He's passionate about UX and Developer Tools. When he's not looking at the computer monitor, he loves to play drum solos. Evgeni works as a Software Developer @ Telerik.

Progress, Telerik, and certain product names used herein are trademarks or registered trademarks of Progress Software Corporation and/or one of its subsidiaries or affiliates in the U.S. and/or other countries. See Trademarks or appropriate markings.