Sunday, January 18, 2015

Push Notifications for Phone Gap App using GCM and Mobile Service

Push Notifications are part of our lives everyday. We get alerted about new emails, news updates, What's app, Facebook Twitter messages so on every hour (or every minute for some :D ). When an app is running, it could request for data and present it on the screen.Push Notifications alert user with information even when the app is NOT open. For example email alert appearing even when the email app is not running on the mobile device.

Windows Azure Mobile Services (integrated with Notification Hub) simplifies sending notifications to multiple mobile platforms, Android, iOS, Windows Phone 8 etc. In this blog, I'm writing about Android Notifications. Will be writing about other mobile platforms (using mobile services) in upcoming blogs.

Here is the agenda for this blog,
  1. GCM (Google Cloud Messaging)
  2. Azure Mobile Services for sending Push Notifications
  3. Phone Gap App registering and receiving notifications

GCM for Android:

For an app installed on your Android device, GCM can send messages over the internet even when the app is not open. It has the ability to queue messages when the device is offline and send it when connected (if message doesn't expire). These messages popup in the notification area. App can be launched when user taps on a notification.

Refer to the image depicting steps involved in sending push notification using GCM. This is one of the ways to use GCM. For the case I'm describing in the blog, with Azure Mobile service, this design fits.

In the five step process described in the image, i) each phone registering with GCM for notification will get a reg id. App will store Sender Id/Project number and send it in the request to get reg id. ii) Developer need to generate API key through Google Developer Console and use it while sending Push Notifications. This way GCM is sure sender of the message is owner of the app.

Azure Mobile Service

Azure Notification Hub allows sending Push Notification to cross platform devices and apps. Mobile Service is integrated with Notification Hub allowing easy notifications. It acts as the server in above architecture. It automates most part of action 4 i) Saving reg Ids, ii) Storing API key and verifying with GCM and iii) Provides easy API for sending notifications. It also provides ready made client libraries for making GCM calls and registration with notification hub.

Let's get the app ready!

  1. Setup in Google Developer Console.
  2. Setup Mobile Services 
  3. Add Push Notifications to Hybrid Mobile App.

Setup in Google Developer Console.

  1. Log into Google Developer Console http://console.developers.google.com
  2. Click Create New Project, provide Project Name and click Create.
  3. Make a note of Project Number, that is the Sender Id.
  4. Click on the project to get into details view.
  5. In the left navigation panel, select Credentials under API & Auth.
  6. Click Create New Key. In the popup window, select server key.
  7. Make note of generated API Key.
  8. Click on APIs under APIs and Auth and make sure Google Cloud Messaging for Android is "ON"

Setup Mobile Service:

Log into Windows Azure Management Portal.
Enable Push Notifications on Mobile Services for GCM.
  1. Select the Mobile Service providing Push Notification functionality.
  2. Click on Push tab.
  3. Under Google Cloud Messaging Settings, specify API Key noted from Google Developer Console.
Update script that triggers Push Notification
  1. Select Data tab and click on table that need to trigger Push Notification.
  2. Click on Script tab.
  3. Select appropriate action among Insert, Update, Delete or Read. And update following code. (read descriptions in the comments)
// add additional behavior to request.execute for Push Notification.
request.execute({
       success: function() {
           // template for the payload
           var pn= '{ "message" : "Sample push notification" }';
// push.send notifies all configured mobile platforms (iOS, Android, WP8) etc. Using push.gcm.send for GCM only.
// first parameter of send specifies all tags. 

           push.gcm.send(null, pn, {
               success: function(response){
                   console.log("Sent push:", response);
                   request.respond();
               },
               error: function (error) {
                   console.log("Failed to send PN", error);
                   request.respond(500, { error: pushResponse });
               }
            });
       }
   });

Enable Phone Gap mobile app to send Push Notifications:

Add push plugin-
cordova plugin add https://github.com/phonegap-build/PushPlugin.git

Device plugin
cordova plugins add https://github.com/apache/cordova-plugin-device.git

Note: include scripts for Mobile Service and Notifications Hub MobileServices.Web-1.2.5.js and NotificationHub.js. They are downloadable from Mobile Service HTML/JS template project.
// set up Push Notification as the app is launched and deviceReady event is fired

 var pushNotification = window.plugins.pushNotification;

// Mobile Client object is created at script file level.
 mobileClient = new WindowsAzure .MobileServiceClient("https://my.mobile.service.url/", "my-mobile-service-key");

  if(pushNotification){
// Phone Gap App and Mobile Service could be used for non Android platforms as well. So check this condition. Else conditions on other mobile platforms shall be added.
if ( device.platform == 'android' || device.platform == 'Android' ){
       pushNotification.register(
           app.successHandler, app.errorHandler,
               "senderID": GCM_SENDER_ID, // it's the project number
               "ecb": "gcmCallback" // function to be called by GCM Service for completing registration.
              });
            } 
         }


GCM Callback below.
    function gcmCallback (e) {
     switch (e.event) {
//This function is called in two scenarios, while registering device with GCM and while receiving Push Notifications
     case 'registered':
          if (e.regid.length > 0) { // regId will be sent back to Notification Hub/ Mobile Service.
              if (mobileClient) {
// Client library for notification hub -that allows multi-platform Push Notifications. Of course, Here we are focusing on GCM/Android.
             var notificationHub= new NotificationHub(mobileClient);

 // Set template for data to be sent by Mobile Service
            var template = "{ \"rootObject\" :{\"message\":\"$(message)\"}}";

// Send regId to Notification Hub, so that mobile service uses it when sending Push Message.
             notificationHub.gcm.register(e.regid, null, "any-template-name", template).done(function () {
// This is my function for updating status on view. You can use console.log or any other method.
              app.updateStatus("Registered for new notifications, through Notification Hub");
                        }).fail(function (error) {
               app.updateStatus("error);
                        });
                    }
                }
                break;
// This is handling Push Message
            case 'message':
            // if app is open when notification arrives
                if (e.foreground)
// Perform target action when notification arrives. Again, this my function update view. You can handle it diferently.
                    app.updateStatus(e.payload.message);

                }
                break;

            case 'error':
                app.updateStatus('GCM error: ' + e.message);
                break;

            default:
                app.updateStatus('An unknown GCM event has occurred');
                break;
        }
    }

Tuesday, January 6, 2015

Windows Azure Mobile Services for Connected Mobile Apps

In previous blogs (1, 2 and 3) I've set context by exploring Phone Gap and Ionic Framework for Hybrid mobile app development. This blog is taking a little step forward by integrating a sample mobile app with a cloud service.

Most mobile apps need to be connected, use a centralized data store and services. Attached is a sample mobile app that maintains laundry list of items. Sample allows users to add items (let's say groceries) over a period of time, review the list, mark one or more purchased or delete some items. This sample app stores data on a cloud service instead of saving on phone.

Laundry List - Sample App Demo on browser emulator: 



Download sample project here - Link

Below is the tech stack chosen
  • Windows Azure mobile service to address data needs of the app.
  • Hybrid Mobile App using Ionic Framework

Why Windows Azure Mobile Services?

1. Ease of development.

Most services are entities and their CRUD operations. Using mobile services, an entity or a database table is created with in no time. In Windows Azure Management Portal select New, under Compute select Mobile Service click Create. Make your choices on the following screen. As you click Next, database selections need to be made and the new mobile service is created.
In Visual Studio Server Explorer under Azure section right click on the new mobile service and click create table. The Mobile Service is ready. Service for Create, Retrieve, Update and Delete operations on the database table is automatically created.
1. Create Mobile Service
2. Create Table


To design the table (associated with mobile service) with column names, data types etc., open the database in "SQL Server Object Explorer" in Visual Studio. Right click on the newly created table and click design. Use the designer window and define columns and other aspects of a database table.

2. Ready made code templates for mobile apps.

You can download boilerplate code for most mobile platforms, namely Android, iOS, Windows Phone and Phone Gap (Hybrid). This helps reduce setup time. In the code sample, I used "mobile services" JS file that takes care of communication with the mobile service. This file acts as a proxy to mobile service. This means developer can focus on mobile app UI development and use the ready made data service communication library.

3. Push Notifications across mobile platforms. 

Implement push notifications easily across platforms iOS, Android, Windows Phone.

4. Deploy your service to a near location of users.

The Mobile Service could be deployed closer to target users in the available geological locations provided by Windows Azure.

I will not dwell into "why Ionic framework" as it's described already in my previous blog.

Ionic App

1. To download Ionic Framework's tabs template run
ionic start laundryList tabs

2. Include library from Windows Azure Mobile Service. Download project from the Windows Azure portal for Phone Gap and copy the lib to Ionic project. At the time of writing this blog, I happen to have version 1.2.5 (MobileServices.Web-1.2.5.js)

3. Create a AngularJS Service to perform CRUD operations.

Initialize the service for communication with Azure Mobile Service,
//create mobile service client object
var client = new WindowsAzure.MobileServiceClient('https:/my-mobile-service.azure-mobile.net/', 'my-app-key');
// get reference of the laundry list table.
var laundryList = client.getTable('laundrylist');

Code to get a list of active laundry list items is below,
var deferred = $q.defer();
// Where clause here restricts results to active items.
var query = laundryList.where({ isAvailable: true, isPurchased: false });
// query.read is async 
   query.read().then(function(pLaundryList) {
        deferred.resolve(pLaundryList);            
   }, function(error){
       deferred.reject(error);
   });
// as this code is in one of the service functions, it returns a promise
return deferred.promise;

Code to get a list of completed laundry list items is below,
var deferred = $q.defer();
// where clause here restricts results to purchased items.
var query = laundryList.where({isPurchased: true });
       query.read().then(function(pLaundryList) {
            deferred.resolve(pLaundryList);            
        }, function(error){
        deferred.reject(error);
        });
return deferred.promise;

Code to create a new laundry list item
// It returns a promise (Async) depicting status of http call to the mobile service.
laundryList.insert(item)

/*
Sample JSON object for Laundry List here

{
title: 'value from text box',
isAvailable: true,
isPurchased:false,
details: '',
price: 0,
quantity: 0

}
*/

Code to mark a laundry list item complete is below. This is an update call.
// It returns a promise (Async)
// id is primary key on the table, server side.
// value being updated is isPurchased.
return laundryList.update({id: id, isPurchased: true});

Code to delete a laundry list item is below.
// It returns a promise (Async)
return laundryList.del({id: id});

Mobile Service Logs.

Last but not least; While debugging API calls, mobile service errors could be reviewed on Management Portal. This will help reduce heart burn by giving specific information on why a mobile service call failed. Refer to logs tab under the mobile service for similar information depicted in the screenshot.



Download complete code here - Link to sample app