I had to recently work on GCM as poc for some project, though I have already implemented GCM client side code lot many time on Android, but never worked on server side code. But here had to do both to test if things were working properly. So in here I will be explaining both the GCM client and how can we either have server code in our android project itself or a seperate project in eclipse with minimum work.
Google Cloud Messaging for Android (GCM) is a service that allows you to send data from your server to your users' Android-powered device, and also to receive messages from devices on the same connection. The GCM service handles all aspects of queueing of messages and delivery to the target Android application running on the target device.
Google Cloud Messaging for Android (GCM) is a free service that helps developers send data from servers to their Android applications on Android devices, and upstream messages from the user's device back to the cloud. This could be a lightweight message telling the Android application that there is new data to be fetched from the server (for instance, a "new email" notification informing the application that it is out of sync with the back end), or it could be a message containing up to 4kb of payload data (so apps like instant messaging can consume the message directly). The GCM service handles all aspects of queueing of messages and delivery to the target Android application running on the target device.
Lets get a basic idea of GCM high level architecture.
Assuming readers know how to register app in Google console, enable GCM service and register your app at https://code.google.com/apis/console
- Note down project id which would be the sender id.
- Also note down Access key generated.
Lets start with GCM client side coding first.
Create a new android project with Google APIs and add below code in manifest, also get the gcm.jar from gcm.jar and put it in lib folder.
The manifest basically includes
- Permissions to access internet, receive GCM messages and access Google account.
- Broadcast Receiver to receive registration id and gcm messages.
<permission
android:name="com.neeraja.gcmdemo.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.neeraja.gcmdemo.permission.C2D_MESSAGE" />
<!-- receives GCM messages -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- GCM connects to Google services -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- GCM requires a Google account -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.READ_OWNER_DATA" />
<!-- wake the processor if a GCM message is received -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="title_activity_main" >
<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>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.neeraja.gcmdemo" />
</intent-filter>
</receiver>
<service
android:name=".GCMIntentService">
</service>
</application>
We would need an Activity to register with GCM server and an intentService which would extend GCMBaseIntentService to receive push notification message.Activity
Call registerClient() in onCreate method which basically check if device is already registered, checks for proper Manifest permissions, and gets the registeration id if not already done by registering with GCM Server.
// Replace the xxx with the project id generated from the Google console when // you defined a Google APIs project. private static final String PROJECT_ID = "xxx";
public void registerClient() {
try {
// Check that the device supports GCM (should be in a try / catch)
GCMRegistrar.checkDevice(this);
// Check the manifest to be sure this app has all the required
// permissions.
GCMRegistrar.checkManifest(this);
// Get the existing registration id, if it exists.
regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals("")) {
registrationStatus = "Registering...";
// register this device for this project
GCMRegistrar.register(this, PROJECT_ID);
regId = GCMRegistrar.getRegistrationId(this);
registrationStatus = "Registration Acquired";
// This is actually a dummy function. At this point, one
// would send the registration id, and other identifying
// information to your server, which should save the id
// for use when broadcasting messages.
sendRegistrationToServer();
} else {
registrationStatus = "Already registered";
}
} catch (Exception e) {
e.printStackTrace();
}
}
We will talk about sendRegistrationToServer() later as this would be covered in GCM Server side code where in we have to send this registeration id to server. Also don't forget to call GCMRegistrar.onDestroy(this); in onDestroy() method. Thats it in Activity.IntentService
Now create a service which would extend GCMBaseIntentService from gcm.jar and override onError and onMessage methods.
public class GCMIntentService extends GCMBaseIntentService { private static final String PROJECT_ID = "xxx"; public GCMIntentService() { super(PROJECT_ID); Log.d(TAG, "GCMIntentService init"); } @Override protected void onError(Context ctx, String sError) { // TODO Auto-generated method stub Log.d(TAG, "Error: " + sError); } @Override protected void onMessage(Context ctx, Intent intent) { Log.d(TAG, "Message Received"); String message = intent.getStringExtra("message"); generateNotification(ctx, message); }When ever a push notification is sent from server it is received in onMessage and can then be taken from here and can form a Notification or send it as broadcast to do some other work.
Now from server end code, we can simply have another class or a method which we can revoke by some user action like a button click and the notification message is sent. Note this is just for testing purpose and would be static.
First download below libraries
Either create a java project in eclipse and add below code.
Here first add the Google API key we received from Google console and build a message with some test data, then add your proxy host and proxy port of your system.
public class GCMServer { public static void main(String args[]) { new Thread(){ public void run(){ try { //add your own google APIkey here Sender sender = new Sender("AIzaSyAqxLyhq-Q_k10Q5A86WrE3BMk3VUMrH2E"); // use this to send message with payload data Message message = new Message.Builder() .collapseKey("message") .timeToLive(3) .delayWhileIdle(true) .addData("message", "Push Notifications test") //you can get this message on client side app .build(); System.setProperty("http.proxyHost", "172.30.36.41"); //write your own proxyHost System.setProperty("http.proxyPort", "8080"); //write your own proxyPort //Use this code to send notification message to a single device Result result = sender.send(message, "APA91bGtfm81Sgr4h-oRUTTyfWFEZNQtDguR1QhlAliSrFjkIsI5eG1Muan1MMPscF7ul73ULbsYGvQmb_XSN0bccZzdPMpMl89FHVM8F0mnt1NzkYmuWql24UPaKuDV-eGGCz6yI4a6Dut3tj_jSWIh4QnsCzi99g", 1); System.out.println("Message Result: "+result.toString()); //Print message result on console //Use this code to send notification message to multiple devices ArrayList<String> devicesList = new ArrayList<String>(); //add your devices RegisterationID, one for each device devicesList.add("APA91bGtfm81Sgr4h-oRUTTyfWFEZNQtDguR1QhlAliSrFjkIsI5eG1Muan1MMPscF7ul73ULbsYGvQmb_XSN0bccZzdPMpMl89FHVM8F0mnt1NzkYmuWql24UPaKuDV-eGGCz6yI4a6Dut3tj_jSWIh4QnsCzi99g"); devicesList.add("APA91bHqSTI3JPNRoj64qB3ik4-eqyPOHQAjHSCnZGUTo57YRy4abLSq6RfH7RWhldtA13DMzh0Zw-M01AZhu4ToD93xppoxChouhMzn4KRVMoV0Y_h3KRwzcC_l8vo7EI87T0bvxbuQBYl6wOgrETY99ULLxgdgoA"); //Use this code for multicast messages MulticastResult multicastResult = sender.send(message, devicesList, 0); sender.send(message, devicesList, 0); System.out.println("Message Result: "+multicastResult.toString());//Print multicast message result on console } catch (Exception e) { e.printStackTrace(); } } }.start(); } }
Now to send a message we would need the registration id, that we have saved in activity. if you have created a separate java project, then just add it manually and run the project. You should get a notification in your device. Or also can create a simple app with a button and add this code onClick of that button, which would simply send message to the device with the registration id.
0 comments:
Post a Comment