how to develop smart android notifications using google cloud … · 2013-09-08 · develop smart...

38
Software Engineering Competence Center TUTORIAL © Copyright Software Engineering Competence Center 2013 How To Develop Smart Android Notifications using Google Cloud Messaging Service Ahmed Mohamed Gamaleldin Senior R&D Engineer-SECC [email protected]

Upload: others

Post on 23-May-2020

16 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

Software Engineering

Competence Center

TUTORIAL

© Copyright Software Engineering Competence Center 2013

How To Develop Smart Android Notifications

using Google Cloud Messaging Service

Ahmed Mohamed Gamaleldin Senior R&D Engineer-SECC

[email protected]

Page 2: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 2

Abstract

Google Cloud Messaging for Android (GCM) is a service that helps developers to

send data from servers to their Android applications on Android devices. The

service was unveiled on June 27, 2012, at Google I/O 2012 held at the Moscone

Center in San Francisco [1]. The GCM service handles all aspects of queuing of

messages and delivery to the target Android application running on the target

device. It is completely free whatever your messaging needs are and it can be

used in some applications like smart notification systems.

This tutorial gives an overview about the Google GCM service and provides

hands-on experience on using this technology in a case study for energy-aware

smart home application developed at Software Engineering Competence Center

(SECC).

Keywords: Google Cloud Messaging (GCM), Cloud to Device Messaging (C2DM),

Android smart notifications.

Page 3: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 3

Table of Contents

1. Introduction 4

2. Getting started with the GCM service 4

3. How the GCM works? 10

3.1. GCM Lifecycle 12

4. Example of Android Application that Uses the GCM 12

5. Architecture of Android Application that uses GCM 14

5.1. GCM process flow 14

5.1.1. Enabling GCM 15

5.1.2. Sending a message 15

5.1.3. Receiving a message 16

5.2. Application server App 16

5.3 Android App 18

5.3.1 Creating the Manifest file 19

5.3.2 Android app structure 22

6. Invoker Application 34

6.1. Invoker example architecture 35

7. Summary 37

8. References 38

9. Abbreviations 38

Page 4: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 4

1. Introduction

Google Cloud Messaging for Android (GCM) is a service that allows you to send

data from your server to the users' Android-powered device. This could be a

lightweight message telling your app there is new data to be fetched from the

server like new version of apps or something like that [1].

The GCM service handles all aspects of storing, queuing and delivery of messages

to the target Android application running on the target device. It is a completely

free service whatever your messaging needs are.

Google Cloud Messaging technology is the new version of the C2DM (cloud to

device messaging) technology as the C2DM service has been officially deprecated

as of June 26, 2012 which means that C2DM has stopped accepting new users

and quota requests. The GCM could be considered as a more efficient

implementation of the C2DM technology.

The GCM service has many characteristics as described in [2]:

1. It allows 3rd-party application servers to send messages to their Android

applications. This is a key feature as you always need your server

application to be in direct contact with the mobile application such that

you can send messages to the mobile application about new versions for

instance.

2. An Android application on an Android device doesn't need to be running

to receive messages. The system will wake it up the Android application

via Intent broadcast when the message arrives. This is achieved if the

application is set up with the proper broadcast receiver and permissions

in the AndroidManifest.xml file.

3. The application has full control of how to handle the GCM messages

passed to it. For example, the application might post a notification when

receiving these messages.

4. It requires devices running Android 2.2 or higher that also have the

Google Play Store application installed.

2. Getting started with the GCM service

To start writing an Android application and the server-side application using the

client and server helper libraries provided by GCM, you must begin with the first

Page 5: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 5

step which is creating a Google API project. The following steps explain how the

Google API project is created [1]:

1. Open the Google API console page

https://code.google.com/apis/console/

2. If you haven't created an API project yet, this page will ask you to do so:

3. If you already have existing projects, the first page you see will be the

Dashboard page. From there you can create a new project by opening the

project drop-down menu (upper left corner) and choosing Other

projects > Create.

Page 6: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 6

4. After creating the project. Your browser URL will change to something

like: https://code.google.com/apis/console/#project:514132917049

You’ll need to keep the value after #project: (514132917049 in this

example). This is your project number, and it will be used later on as the

GCM sender ID.

5. It is required now to enable the GCM service through the following steps:

a. In the main Google APIs Console page, select Services.

b. Turn the Google Cloud Messaging toggle to ON.

Page 7: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 7

c. In the Terms of Service page, accept the terms.

6. After enabling the service, the API key is required. To obtain it:

In the main Google APIs Console page, select API Access. You will see a

screen as like:

Page 8: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 8

7. Click Create new Server key. Note that either a server key or a browser key should work. The advantage of using a server key is that it gives you more control on the IP addresses that can access your app (this feature is not used in our application below). The following screen appears, just click the Create button:

8. Take note with the API key that is shown after that:

Page 9: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 9

9. Up to this step, you have finished creation of the Google API proejct and toke a note with the project number and the API key. For development, you’ll need to install the helper libraries from the SDK manager as follow:

From the SDK Manager, install Extras > Google Cloud Messaging for Android Library. This creates a gcm directory under YOUR_SDK_ROOT/extras/google/ containing these subdirectories: gcm-

client, gcm-server, samples/gcm-demo-client, samples/gcm-demo-server, and samples/gcm-demo-appengine

Page 10: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 10

3. How the GCM works?

There are some key terms and concepts involved in the GCM service and it is

very important to have a good knowledge about them. The key terms and

concepts of the GCM are divided into two categories [2]:

Components — The physical items involved in GCM steps.

Credentials — The IDs that are used in different stages of GCM to achieve

the authentication, and to be sure that the message is going to the correct

application and the correct Android device.

Table 1 below explains the previous GCM concepts with clear examples

Page 11: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 11

Table 1 GCM concepts

Components

Mobile Devices

The device that is running an Android application that uses

GCM

3rd-party Application Server

The 3rd-party application server sends data to an Android

application on the device via the GCM server.

GCM Servers

The Google servers used in taking messages from the 3rd-

party application server and sending them to the device.

Credentials

Sender ID

A project number you acquire from the API console. The sender ID is

used in the registration process to identify an Android application that

is permitted to send messages to the device

Application ID

The Android application that is registering to receive messages. The

Android application is identified by the package name from the

manifest.xml file. This ensures that the messages are targeted to the

correct Android application

Registration ID

An ID issued by the GCM servers to the Android application that allows

it to receive messages. Once the Android application has the

registration ID, it sends it to the 3rd-party application server, which

uses it to identify each device that has registered to receive messages

for a given Android application. In other words, a registration ID is tied

to a particular Android application running on a particular device.

Page 12: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 12

Google User Account

For GCM to work, the mobile device must include at least one Google

account if the device is running a version lower than Android 4.0.4.

Sender Auth Token

An API key that is saved on the 3rd-party application server that gives

the application server authorized access to Google services. The API

key is included in the header of POST requests that send messages.

3.1. GCM Lifecycle

The usage of the GCM process requires the following phases:

1. Enabling GCM - An Android application running on a mobile device

registers itself to be able to receive messages.

2. Sending a message - A 3rd-party application server sends messages to

the device.

3. Receiving a message - An Android application receives a message from a

GCM server.

4. Example of Android Application that Uses the GCM

This section will explain an Android application used in the energy-aware smart

home project developed by SECC. This app was based on the GCM demo

application provided by Google [3]. We’ll cover the details of that application

with all of the code snapshots in the next section

The android application architecture is described in Error! Reference source not

ound.. It consists of three parts:

1. Application server App (Here called GCM server) 2. GCM client App (the Android App) 3. GCM cloud service

The following is an explanation for the scenario shown in Error! Reference

ource not found.

1. At the device start up, the installed Android app (GCM client) sends a

registration request to the GCM server asking for a registration id. This

registration request uses the Google API project ID to identify the

Android device that asks for the registration id.

Page 13: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13

2. The GCM server responds to the previous request and sends the

registration id to the Android device. The Android app sends this

registration id to server application which stores it in its internal storage.

Figure 1 GCM application example in smart home building application

3. The fault detector KP is subscribed for smart home devices faults. When it

detects any fault, it invokes the server application 4. The server application sends a message to the Android device, where it

sends a request to the GCM server via its helper classes APIs including the Google API project ID and the server API key.

5. When the GCM server finds the Android device online, it’ll pass the message to it through a broadcast intent. The broadcast receiver GCMIntentService intent in the Android device is responsible for receiving this broadcast message and invoking the notification manager

Page 14: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 14

to create a new notification.

First, we need to state the list of tools required to develop this App. Table 1

shows these tools

Tool

Eclipse Indigo or Eclipse Juno

Android ADT plugin

Apache Tomcat Application server v7.1or later

Apache Ant 1.8 or later

For the web server:

Ant 1.8, it is a project building tool and it is used for building the server-

side application as a .war file

A running web server compatible with Servlets API version 2.5, such as

Tomcat 7

Google account registered to use GCM.

The API key for that account.

For the Android application:

Eclipse with the ADT plugin

Emulator (or device) running Android 2.3 (Ginger-bread) or higher with

Google APIs.

The Google API project number of the account registered to use GCM.

5. Architecture of Android Application that uses GCM

In this section, we’ll cover in details the architecture of the Android app

that uses the GCM service and also we’ll cover the 3d party application

server app.

5.1. GCM process flow

As mentioned above the GCM service has three main steps:

Enabling GCM

Sending a message

Receiving a message

Page 15: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 15

5.1.1. Enabling GCM

This is the sequence of events that occurs when an Android application

running on a mobile device registers itself into the GCM server to receive

messages:

1. The first time the Android application needs to use the messaging

service, it sends registration intent to a GCM server.

This registration Intent (com.google.android.c2dm.intent.REGISTER)

includes the sender ID, and the Android application ID.

2. If the registration is successful, the GCM server broadcasts a

com.google.android.c2dm.intent.REGISTRATION intent which gives the

Android application a registration ID.

The Android application should store this ID for later use (for

instance, to check on onCreate() if it is already registered).

3. To complete the registration, the Android application sends the

registration ID to the application server. The application server stores

the registration ID in a database.

5.1.2. Sending a message

For an application server to send a message to an Android application,

the following things must be in place:

The Android application has a registration ID that allows it to

receive messages for a particular device.

The 3rd-party application server has stored the registration ID.

An API key. It is a key for the application on the application server

and it is previously set up in the api.key file that exists in the

application server app that will be explained later.

Here is the sequence of events that occurs when the application server

sends a message:

1. The application server sends a message to GCM servers.

2. GCM servers store the message in case the device is offline.

3. When the device is online, Google sends the message to the device.

Page 16: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 16

5.1.3. Receiving a message

This is the sequence of events that occurs when an Android

application installed on a mobile device receives a message:

1. The system receives the incoming message and extracts any data from

it, if any.

2. The system passes the key/value pairs to the targeted Android

application in a com.google.android.c2dm.intent.RECEIVE Intent as a

set of extras.

3. The Android application processes the message

5.2. Application server App

The application server used here is the Apache Tomcat v7.0 which is a servlet

container that can accept HTTP requests and send HTTP commands to the

GCM server. We don’t need to develop a new application server where the

GCM Demo server application provided by Google can be used directly. The

following steps explain how to use it:

1. From the SDK Manager, install Extras > Google Cloud Messaging for Android Library.

2. This creates a gcm directory under YOUR_SDK_ROOT/extras/google/ containing these subdirectories: gcm-client, gcm-server, samples/gcm-demo-client, samples/gcm-demo-server, and samples/gcm-demo-appengine.

3. You can create a web application from Eclipse and copy the gcm-demo-server app into it as shown below

4. In a text editor or from inside Eclipse, edit the samples/gcm-demo-server/WebContent/WEB-INF/classes/api.key and replace the existing text (if any) with the API key obtained above.

Page 17: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 17

$ ant war

Buildfile:build.xml

init:

[mkdir] Created dir: build/classes

[mkdir] Created dir: dist

compile:

[javac] Compiling 6 source files to build/classes

war:

[war] Building war: dist/gcm-demo.war

BUILD SUCCESSFUL

Total time: 0 seconds

5. In a shell window, go to the samples/gcm-demo-server directory. 6. Generate the server's WAR file by running ant war:

Now the .war file is ready to be deployed into your application server, For

instance, if you're using Tomcat as in our case, copy gcm-demo.war to the

${CATALINA_HOME}/webapps directory of the Tomcat installation. Starting

the Tomcat will make this application running waiting for inquires that will

be sent to it from the invoker app that will be explained later.

Page 18: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 18

For more information about how the 3rd party application server works, and

how it sends messages either in text or JSON format, you can refer to [2]

5.3 Android App

To write Android applications that use GCM, you must have an application

server described above. This section describes the steps you take to create a

client application that uses GCM.

Our client app is based on the gcm-demo-client app that exists in

YOUR_SDK_ROOT/extras/google/samples

You can follow these steps to use the gcm-demo-client app:

1- Create new Android project in Eclipse with the name gcm-demo-client

2- Copy the package com.google.android.gcm.demo.app from

YOUR_SDK_ROOT/extras/google/samples/gcm-demo-client and paste it

in the eclipse project

3- Add the gcm.jar file into your project’s libs1 directory (this is done by just

copying it into libs folder)

4- Open the AndroidManifest.xml from

YOUR_SDK_ROOT/extras/google/samples/gcm-demo-client and copy its

contents in the AndroidManifest.xml file in your local eclipse project

You must see now the following project structure:

1 The libs directory is by default existing in the project class path so if you don’t want to add gcm.jar in this directory, you’ll just need to add the path of it into your class path

Page 19: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 19

There are two primary steps involved in writing a client Android application:

Creating a manifest that contains the permissions the Android

application needs to use GCM.

Implementing your code. To use GCM, this implementation must

include:

o Code to start and stop the registration service.

o Receivers for the com.google.android.c2dm.intent.RECEIVE and

com.google.android.c2dm.intent.REGISTRATION intents.

5.3.1 Creating the Manifest file

Every Android application must have an AndroidManifest.xml file in its root

directory. The manifest presents essential information about the Android

application to the Android system. To use the GCM feature, the manifest must

include the following:

The com.google.android.c2dm.permission.RECEIVE permission so the

Android application can register itself and receive messages.

The android.permission.INTERNET permission so the Android

application can send the registration ID to the 3rd party server.

Page 20: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 20

The android.permission.GET_ACCOUNTS permission as GCM requires a

Google account (necessary only if the device is running a version

lower than Android ICS 4.0.4)

The android.permission.WAKE_LOCK permission so the application

can keep the processor from sleeping when a message is received.

An application package + ".permission.C2D_MESSAGE permission to

prevent other Android applications from registering and receiving the

Android application's messages. The permission name must exactly

match this pattern—otherwise the Android application will not

receive the messages.

A receiver for com.google.android.c2dm.intent.RECEIVE and

com.google.android.c2dm.intent.REGISTRATION, with the category set

as application package. The receiver should require the

com.google.android.c2dm.SEND permission, to ensure that only intents

sent by the GCM system framework are sent to the receiver (a regular

application cannot issue intents with that permission).

This broadcast receiver is responsible for handling the above 2 intents

that can be sent by GCM (com.google.android.c2dm.intent.RECEIVE and

com.google.android.c2dm.intent.REGISTRATION) and it is defined here

in the manifest file so that these intents can be received even if the

application is not running.

An intent service to handle the intents received by the broadcast

receiver. This intent service will be called by the

GCMBroadcastReceiver (which is provided by the GCM library). It

could be a subclass of com.google.android.gcm.GCMBaseIntentService,

and it must contain a public constructor, and should be named

my_app_package.GCMIntentService

Set android:minSdkVersion="8" in the manifest. This ensures that the

Android application cannot be installed in an environment in which it

could not run properly.

Here’s the AndroidManifest.xml file of the gcm-demo-client project

Page 21: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 21

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.google.android.gcm.demo.app" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16"/> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <permission android:name="com.google.android.gcm.demo.app.permission.C2D_MESSAGE" android:protectionLevel="signature" /> <uses-permission android:name="com.google.android.gcm.demo.app.permission.C2D_MESSAGE" /> <!-- This app has permission to register and receive data message. --> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> <!-- Main activity. --> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".DemoActivity" android:label="@string/app_name" android:screenOrientation="portrait" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name="com.google.android.gcm.GCMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" > <intent-filter> <!-- Receives the actual messages. --> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <!-- Receives the registration id. --> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> <category android:name="com.google.android.gcm.demo.app" /> </intent-filter> </receiver> <service android:name=".GCMIntentService" /> </application> </manifest>

Page 22: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 22

5.3.2 Android app structure

The client application is consisting of 4 files:

1. CommonUtilities.java

This file includes the definitions of two main variables

SERVER_URL , the server app url for e.g., http://10.130.201.80:8080/gcm-demo

SENDER_ID , Google API project ID

This file will look like this:

package com.google.android.gcm.demo.app; import android.content.Context; import android.content.Intent; /** * Helper class providing methods and constants common to other classes in the * app. */ public final class CommonUtilities { /** * Base URL of the Demo Server (such as http://my_host:8080/gcm-demo) */ static final String SERVER_URL = "http://10.130.201.80:8080/gcm-demo"; /** * Google API project id registered to use GCM. */ static final String SENDER_ID = "514132917049"; /** * Tag used on log messages. */ static final String TAG = "GCMDemo"; /** * Intent used to display a message in the screen. */ static final String DISPLAY_MESSAGE_ACTION = "com.google.android.gcm.demo.app.DISPLAY_MESSAGE"; /** * Notifies UI to display a message. * <p> * This method is defined in the common helper because it's used both by * the UI and the background service. * * @param context application's context. * @param message message to be displayed. */ static void displayMessage(Context context, String message) {

Page 23: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 23

2. GCMIntentService.java

This class extends GCMBaseIntentService and it represents the intent service responsible for handling GCM messages. In this class we are overriding the following callback methods (which are called by GCMBroadcastReceiver):

onRegistered(Context context, String regId): Called after a

registration intent is received, passes the registration ID

assigned by GCM to that device/application pair as parameter.

Typically, you should send the regid to your server so it can use

it to send messages to this device.

onUnregistered(Context context, String regId): Called after the

device has been unregistered from GCM. Typically, you should

send the regid to the server so it unregisters the device.

onMessage(Context context, Intent intent): Called when your

server sends a message to GCM, and GCM delivers it to the

device. If the message has a payload, its contents are available

as extras in the intent.

onError(Context context, String errorId): Called when the

device tries to register or unregister, but GCM returned an

error. Typically, there is nothing to be done other than

evaluating the error (returned by errorId) and trying to fix the

problem.

onRecoverableError(Context context, String errorId): Called

when the device tries to register or unregister, but the GCM

/** * Intent's extra that contains the message to be displayed. */ static final String EXTRA_MESSAGE = "message"; /** * Notifies UI to display a message. * <p> * This method is defined in the common helper because it's used both by * the UI and the background service. * * @param context application's context. * @param message message to be displayed. */ static void displayMessage(Context context, String message) { Intent intent = new Intent(DISPLAY_MESSAGE_ACTION); intent.putExtra(EXTRA_MESSAGE, message); context.sendBroadcast(intent); } }

Page 24: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 24

Log.i(TAG, "Ignoring unregister callback"); } } @Override protected void onMessage(Context context, Intent intent) { Log.i(TAG, "Received message"); String message = getString(R.string.gcm_message); displayMessage(context, message); // notifies user with the new messages generateNotification(context, message); } @Override protected void onDeletedMessages(Context context, int total) { Log.i(TAG, "Received deleted messages notification"); String message = getString(R.string.gcm_deleted, total); displayMessage(context, message); // notifies user generateNotification(context, message); } @Override public void onError(Context context, String errorId) { Log.i(TAG, "Received error: " + errorId); displayMessage(context, getString(R.string.gcm_error, errorId)); } @Override protected boolean onRecoverableError(Context context, String errorId) { // log message Log.i(TAG, "Received recoverable error: " + errorId); displayMessage(context, getString(R.string.gcm_recoverable_error, errorId)); return super.onRecoverableError(context, errorId); } /** * Issues a notification to inform the user that server has sent a message. */ private static void generateNotification(Context context, String message) { int icon = R.drawable.ic_stat_gcm; long when = System.currentTimeMillis(); NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); Notification notification = new Notification(icon, message, when); String title = context.getString(R.string.app_name); Intent notificationIntent = new Intent("android.intent.action.VIEW", Uri.parse("http://10.130.201.80:8080/ECWebSec/")); // set intent so it does not start a new activity notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent, 0); notification.setLatestEventInfo(context, title, message, intent); notification.flags |= Notification.FLAG_AUTO_CANCEL; notificationManager.notify(0, notification); } }

Page 25: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 25

servers are unavailable. The GCM library will retry the

operation using exponential backup, unless this method is

overridden and returns false. This method is optional and

should be overridden only if you want to display the message to

the user or cancel the retry attempts.

This file will look like this:

package com.google.android.gcm.demo.app; import static com.google.android.gcm.demo.app.CommonUtilities.SENDER_ID; import static com.google.android.gcm.demo.app.CommonUtilities.displayMessage; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.util.Log; import com.google.android.gcm.GCMBaseIntentService; import com.google.android.gcm.GCMRegistrar; /** * IntentService responsible for handling GCM messages. */ public class GCMIntentService extends GCMBaseIntentService { @SuppressWarnings("hiding") private static final String TAG = "GCMIntentService"; public GCMIntentService() { super(SENDER_ID); } @Override protected void onRegistered(Context context, String registrationId) { Log.i(TAG, "Device registered: regId = " + registrationId); displayMessage(context, getString(R.string.gcm_registered)); ServerUtilities.register(context, registrationId); } @Override protected void onUnregistered(Context context, String registrationId) { Log.i(TAG, "Device unregistered"); displayMessage(context, getString(R.string.gcm_unregistered)); if (GCMRegistrar.isRegisteredOnServer(context)) { ServerUtilities.unregister(context, registrationId); } else { // This callback results from the call to unregister made on // ServerUtilities when the registration to the server failed.

Page 26: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 26

3. ServerUtilities.java

This is a helper class used to enable the Android app to communicate with the application server. It contains three methods called:

register()

Posts the registration request to the register servlet

deployed at the application server, this servlet accepts the

request and stores the registration id in its database.

unregister()

Posts the unregister request to the unregister servlet

deployed at the application server, this servlet accepts the

request and removes the registration id from its database.

Post()

Posts the register or unregister request to the application

server

This file will look like this:

Page 27: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 27

package com.google.android.gcm.demo.app; import static com.google.android.gcm.demo.app.CommonUtilities.SERVER_URL; import static com.google.android.gcm.demo.app.CommonUtilities.TAG; import static com.google.android.gcm.demo.app.CommonUtilities.displayMessage; import com.google.android.gcm.GCMRegistrar; import android.content.Context; import android.util.Log; import java.io.IOException; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Random; /** * Helper class used to communicate with the demo server. */ public final class ServerUtilities { private static final int MAX_ATTEMPTS = 5; private static final int BACKOFF_MILLI_SECONDS = 2000; private static final Random random = new Random(); /** * Register this account/device pair within the server. * * @return whether the registration succeeded or not. */ static boolean register(final Context context, final String regId) { Log.i(TAG, "registering device (regId = " + regId + ")"); String serverUrl = SERVER_URL + "/register"; Map<String, String> params = new HashMap<String, String>(); params.put("regId", regId); long backoff = BACKOFF_MILLI_SECONDS + random.nextInt(1000); for (int i = 1; i <= MAX_ATTEMPTS; i++) { Log.d(TAG, "Attempt #" + i + " to register"); try { displayMessage(context, context.getString( R.string.server_registering, i, MAX_ATTEMPTS)); post(serverUrl, params); GCMRegistrar.setRegisteredOnServer(context, true); String message = context.getString(R.string.server_registered); CommonUtilities.displayMessage(context, message); return true; } catch (IOException e) { Log.e(TAG, "Failed to register on attempt " + i, e); if (i == MAX_ATTEMPTS) { break; } try { Log.d(TAG, "Sleeping for " + backoff + " ms before retry"); Thread.sleep(backoff); } catch (InterruptedException e1) { // Activity finished before we complete - exit. Log.d(TAG, "Thread interrupted: abort remaining retries!"); Thread.currentThread().interrupt(); return false; } // increase backoff exponentially backoff *= 2; } } String message = context.getString(R.string.server_register_error,

Page 28: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 28

Log.d(TAG, "Thread interrupted: abort remaining retries!"); Thread.currentThread().interrupt(); return false; } // increase backoff exponentially backoff *= 2; } } String message = context.getString(R.string.server_register_error, MAX_ATTEMPTS); CommonUtilities.displayMessage(context, message); return false; } /** * Unregister this account/device pair within the server. */ static void unregister(final Context context, final String regId) { Log.i(TAG, "unregistering device (regId = " + regId + ")"); String serverUrl = SERVER_URL + "/unregister"; Map<String, String> params = new HashMap<String, String>(); params.put("regId", regId); try { post(serverUrl, params); GCMRegistrar.setRegisteredOnServer(context, false); String message = context.getString(R.string.server_unregistered); CommonUtilities.displayMessage(context, message); } catch (IOException e) { // At this point the device is unregistered from GCM, but still // registered in the server. // We could try to unregister again, but it is not necessary: // if the server tries to send a message to the device, it will get // a "NotRegistered" error message and should unregister the device. String message = context.getString(R.string.server_unregister_error, e.getMessage()); CommonUtilities.displayMessage(context, message); } }

Page 29: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 29

1. DemoActivity.java

This class is the main UI of the application; it handles the registration of the Android device when the activity starts

/** * Issue a POST request to the server. * * @param endpoint POST address. * @param params request parameters. * * @throws IOException propagated from POST. */ private static void post(String endpoint, Map<String, String> params) throws IOException { URL url; try { url = new URL(endpoint); } catch (MalformedURLException e) { throw new IllegalArgumentException("invalid url: " + endpoint); } StringBuilder bodyBuilder = new StringBuilder(); Iterator<Entry<String, String>> iterator = params.entrySet().iterator(); // constructs the POST body using the parameters while (iterator.hasNext()) { Entry<String, String> param = iterator.next(); bodyBuilder.append(param.getKey()).append('=') .append(param.getValue()); if (iterator.hasNext()) { bodyBuilder.append('&'); } } String body = bodyBuilder.toString(); Log.v(TAG, "Posting '" + body + "' to " + url); byte[] bytes = body.getBytes(); HttpURLConnection conn = null; try { conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setUseCaches(false); conn.setFixedLengthStreamingMode(bytes.length); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); // post the request OutputStream out = conn.getOutputStream(); out.write(bytes); out.close(); // handle the response int status = conn.getResponseCode(); if (status != 200) { Log.d(TAG, "Post failed with error code"); throw new IOException("Post failed with error code " + status); } } finally { if (conn != null) { conn.disconnect(); } } } }

Page 30: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 30

4. DemoActivity.java

This class is the main UI of the application; it handles the registration of the Android device when the activity starts

4.1 Application registration:

An Android application needs to register with GCM servers before it can receive messages. To register, the application sends Intent (com.google.android.c2dm.intent.REGISTER), with 2 extra parameters:

o Sender is the project number of the account

authorized to send messages to the Android

application.

o App is the Android application's ID, set with a

PendingIntent to allow the registration service to

extract Android application information.

This registration can be done easily using the GCMRegstrar object

GCMRegistrar.register(this, SENDER_ID);

This intent will be asynchronously sent to the GCM server, and the

response will be delivered to the application as a

com.google.android.c2dm.intent.REGISTRATION intent containing

the registration ID assigned to the Android application running on

that particular device.

Registration is not complete until the Android application sends

the registration ID to the 3rd-party application server, which in

turn will use the registration ID to send messages to the

application. This is done by calling

ServerUtilities.register(context, regId);

4.2 Handling GCM intents:

The manifest defines a broadcast receiver for the

com.google.android.c2dm.intent.REGISTRATION and

com.google.android.c2dm.intent.RECEIVE intents. These intents are

sent by GCM to indicate that a device was registered (or

unregistered), or to deliver messages, respectively.

Page 31: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 31

Handling these intents might require I/O operations (such as

network calls to the 3rd party server), and such operations should

not be done in the receiver's onReceive() method. The

recommended way to handle the intents is to delegate them to a

service, such as a GCMIntentService explained above.

This file will look like this:

package com.google.android.gcm.demo.app; import static com.google.android.gcm.demo.app.CommonUtilities.DISPLAY_MESSAGE_ACTION; import static com.google.android.gcm.demo.app.CommonUtilities.EXTRA_MESSAGE; import static com.google.android.gcm.demo.app.CommonUtilities.SENDER_ID; import static com.google.android.gcm.demo.app.CommonUtilities.SERVER_URL; import com.google.android.gcm.GCMRegistrar; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Color; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.TextView; /** * Main UI for the demo app. */ public class DemoActivity extends Activity { TextView mDisplay; Button webSiteButton; AsyncTask<Void, Void, Void> mRegisterTask; private static final String TAG = "Activity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); checkNotNull(SERVER_URL, "SERVER_URL"); checkNotNull(SENDER_ID, "SENDER_ID"); // Make sure the device has the proper dependencies. GCMRegistrar.checkDevice(this); // Make sure the manifest was properly set - comment out this line // while developing the app, then uncomment it when it's ready. GCMRegistrar.checkManifest(this); setContentView(R.layout.main); webSiteButton=(Button)findViewById(R.id.WebSiteButton); webSiteButton.setOnClickListener(new View.OnClickListener(){ public void onClick(View v){

Page 32: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 32

// Make sure the device has the proper dependencies. GCMRegistrar.checkDevice(this); // Make sure the manifest was properly set - comment out this line GCMRegistrar.checkManifest(this); setContentView(R.layout.main); webSiteButton=(Button)findViewById(R.id.WebSiteButton); webSiteButton.setOnClickListener(new View.OnClickListener(){ public void onClick(View v){ Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.addCategory(Intent.CATEGORY_BROWSABLE); intent.setData(Uri.parse("http://10.130.201.80:8080/ECWebSec/")); startActivity(intent); } }); mDisplay = (TextView) findViewById(R.id.display); mDisplay.setText("\nSmart Home Notifier Application will send you a notifications in case of " + "faults occured with your home devices." + "The application is based on Google Cloud Messaging Service (GCM).\n" + "The scenario is as follow:\n" +" 1- In case of fault occured, a fault detector web service will be invoked. This web service sends the fault message to the GCM server via a web application deployed in the application server\n" + " 2- The GCM server receives the message and routes it to the target Application which is running on your device.\n" + "**Developed by: SECC R&D Team. www.secc.org.eg\n\n\n"); mDisplay.setTextColor(Color.WHITE); mDisplay.append("Log:"); registerReceiver(mHandleMessageReceiver, new IntentFilter(DISPLAY_MESSAGE_ACTION)); final String regId = GCMRegistrar.getRegistrationId(this); if (regId.equals("")) { // Automatically registers application on startup. GCMRegistrar.register(this, SENDER_ID); Log.d(TAG, "Registered to GCM !!! "); } else { // Device is already registered on GCM, check server. if (GCMRegistrar.isRegisteredOnServer(this)) { // Skips registration. mDisplay.append(getString(R.string.already_registered) + "\n"); } else { // Try to register again, but not in the UI thread. // It's also necessary to cancel the thread onDestroy(), // hence the use of AsyncTask instead of a raw thread. final Context context = this; mRegisterTask = new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { boolean registered = ServerUtilities.register(context, regId); if (!registered) { GCMRegistrar.unregister(context); } return null; } @Override protected void onPostExecute(Void result) { mRegisterTask = null;

Page 33: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 33

if (!registered) { GCMRegistrar.unregister(context); } return null; } @Override protected void onPostExecute(Void result) { mRegisterTask = null; } }; mRegisterTask.execute(null, null, null); } } } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.options_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()) { case R.id.options_clear: mDisplay.setText(null); return true; case R.id.options_exit: finish(); return true; default: return super.onOptionsItemSelected(item); } } @Override protected void onDestroy() { if (mRegisterTask != null) { mRegisterTask.cancel(true); } unregisterReceiver(mHandleMessageReceiver); GCMRegistrar.onDestroy(this); super.onDestroy(); }

Page 34: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 34

After developing the above application, you can now run the project to get the .apk file and install it in your Android-powered device. When running this application you will see a screen like this: N.B: You must make sure that the application server app (gc-demo-server.war) is deployed and running on tomcat

6. Invoker Application

Up till now, you have both Android and the Application server apps running. In

order to test the whole cycle you’ll need to develop an invoker application that

private void checkNotNull(Object reference, String name) { if (reference == null) { throw new NullPointerException( getString(R.string.error_config, name)); } } private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String newMessage = intent.getExtras().getString(EXTRA_MESSAGE); mDisplay.append(newMessage + "\n"); } }; }

Page 35: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 35

calls the application server app and asks it to send a message to the Android app.

Once this message is received, the Android app will fire a notification for the

user. In the practical cases, this invoker app is your end application that needs

based on some logic to send notifications to the Android-powered device.

6.1. Invoker example architecture

The invoker explained in this tutorial is composed of two files:

1. Definitions.java This file is simply contains the project ID, it will look as follow:

2. InvokeSendAllServlet.java

This file is the core invoker which calls the sendAll servlet of the application

server which is responsible for contacting the GCM server and asking it to send

messages to the Android application. This file could be like this:

package com.secc.SendNotificationViaGCMService; public final class Definitions { static final String SERVER_URL = "http://10.130.201.80:8080/gcm-demo"; /** * Google API project id registered to use GCM. */ static final String SENDER_ID = "514132917049"; }

Page 36: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 36

package com.secc.SendNotificationViaGCMService; import static com.secc.SendNotificationViaGCMService.Definitions.SERVER_URL; import java.io.IOException; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class InvokeSendAllServlet { public void invokeSendAllServlet() { String serverUrl = SERVER_URL + "/sendAll"; try { post(serverUrl); } catch (IOException e) { } } private static void post(String endpoint) throws IOException { URL url; try { url = new URL(endpoint); } catch (MalformedURLException e) { throw new IllegalArgumentException("invalid url: " + endpoint); } HttpURLConnection conn = null; try { conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setUseCaches(false); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); OutputStream out = conn.getOutputStream(); out.close(); int status = conn.getResponseCode(); if (status != 200) { throw new IOException("Post failed with error code " + status); } } finally { if (conn != null) { conn.disconnect(); } } } public static void main(String []args) { InvokeSendAllServlet invoke=new InvokeSendAllServlet(); invoke.invokeSendAllServlet(); } }

Page 37: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 37

By running the above invoker app you should see a notification appeared.

7. Summary

Google Cloud Messaging for Android (GCM) is a free and powerful service that

helps developers to send data from servers to their Android applications

running on Android-powered devices. This tutorial provides the basic concepts

of this service with a detailed explanation of the GCM demo application provided

by the Android SDK. The GCM service is very promising and it could be

Page 38: How To Develop Smart Android Notifications using Google Cloud … · 2013-09-08 · Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 13 2

How To Develop Smart Android Notifications using Google Cloud Messaging Service | Tutorial Page 38

considered the most optimized and powerful method for sending messages from

servers to the Android devices without the need to have the Android application

listens to the server in an endless loop.

8. References

[1] http://developer.android.com/google/gcm/gs.html

[2] http://developer.android.com/google/gcm/gcm.html

[3] http://developer.android.com/google/gcm/demo.html

9. Abbreviations

GCM Google Cloud Messaging

App Application

HTTP Hypertext Transfer Protocol

API Application Programming Interface

C2DM Cloud to Device Messaging

KP Knowledge Processor