Android C2DM server and client implementation working
1. We will start from server end code
a)create a database named ‘push_android’
and a table to containing 2 fields
devicetoken - c2dm token recieved from c2dm server deviceid - android device IMIE Number
< ?php
$host = 'localhost'; // most of the time
$user = 'databaseusername';
$pass = 'databasepassword';
$database = 'push_android';
$connection = mysql_connect ($host, $user, $pass) or die ('Error connecting to mysql'.mysql_error());
//mysql_select_db ( $database,$connection)or die ('Error selecting database '.mysql_error());
mysql_selectdb($database) or die ('->>Error selecting database'.mysql_error());
if ( $_GET [ 'devicetoken' ] != ''&& $_GET['deviceid'] )
{
$token =$_GET ['devicetoken'];
$device_id = $_GET['deviceid'];
$result=mysql_query("SELECT * FROM devicetokens where deviceid='".$device_id."'");
if(mysql_num_rows($result)>0 ){
$sucess= 'Token Updated ';
$query = "UPDATE `devicetokens` SET `devicetoken`=
'".$token."' WHERE deviceid='".$device_id."'
";
if ( mysql_query ( $query ) )
{
$success = 'New Device Token Updated';
}
else {
die ( mysql_error () );
}
}else{
$query = "INSERT INTO `devicetokens` (`deviceid`,`devicetoken`)
VALUES('".$device_id."','".$token."'
)";
if ( mysql_query ( $query ) )
{
$success = 'New Device Token added';
}
else {
die ( mysql_error () );
}
}
}
else {
echo 'Please ensure that you have a title and some content for this article!';
}
if ( isset ( $success ) ) {
echo $success;
}
?>
3.Now we can write some client code (android)
before that lets reuse some code
make a checkout of a sample application by google
svn checkout http://jumpnote.googlecode.com/svn/trunk/ jumpnote-read-only
In the checked directory you can find folder named “JumpNoteAndroid” import that in eclipse.
now copy ‘com.google.android.c2dm’ as it is in your project
now go to your main android package and add the following classes
package com.example.push;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.c2dm.C2DMBaseReceiver;
import com.google.android.c2dm.C2DMessaging;
// TODO: Auto-generated Javadoc
/**
* Broadcast receiver that handles Android Cloud to Data Messaging (AC2DM)
* messages, initiated by the JumpNote App Engine server and routed/delivered by
* Google AC2DM servers. The only currently defined message is 'sync'.
*/
public class C2DMReceiver extends C2DMBaseReceiver {
/** The Constant TAG. */
static final String TAG = C2DMConfig.makeLogTag(C2DMReceiver.class);
/**
* Instantiates a new c2 dm receiver.
*/
public C2DMReceiver() {
super( C2DMConfig.C2DM_GOOGLE_ACCOUNT);
}
/* (non-Javadoc)
* @see com.google.android.c2dm.C2DMBaseReceiver#onError(android.content.Context, java.lang.String)
*/
@Override
public void onError(Context context, String errorId) {
Toast.makeText(context, "Messaging registration error: " + errorId,
Toast.LENGTH_LONG).show();
}
/* (non-Javadoc)
* @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)
*/
@Override
public void onReceive(Context context, Intent intent) {
super.onHandleIntentRecieved(context, intent);
}
/* (non-Javadoc)
* @see com.google.android.c2dm.C2DMBaseReceiver#onMessage(android.content.Context, android.content.Intent)
*/
@Override
protected void onMessage(Context context, Intent intent) {
String message = intent.getExtras().getString("message");
String strTitle = intent.getExtras().getString("title");
if (message != null) {
//write code to do something with your msg
}
}
/* (non-Javadoc)
* @see com.google.android.c2dm.C2DMBaseReceiver#onRegistered(android.content.Context, java.lang.String)
*/
@Override
public void onRegistered(Context context, String registrationId)
throws IOException {
// TODO
super.onRegistered(context, registrationId);
Log.e(TAG, ">>>>id recieved" + registrationId);
TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
Log.e(TAG, ">>>>device unique id " + telephonyManager.getDeviceId());
// send to server
BufferedReader in = null;
try {
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet();
try {
request.setURI(new URI("{your server url}/register_token.php?deviceid="+URLEncoder.encode(telephonyManager.getDeviceId())+"&devicetoken="+URLEncoder.encode(registrationId).toString()));
} catch (URISyntaxException e) {
e.printStackTrace();
}
HttpResponse response = client.execute(request);
in = new BufferedReader
(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
String page = sb.toString();
System.out.println(page);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/* (non-Javadoc)
* @see com.google.android.c2dm.C2DMBaseReceiver#onUnregistered(android.content.Context)
*/
@Override
public void onUnregistered(Context context) {
super.onUnregistered(context);
}
/**
* Register or unregister based on phone sync settings. Called on each
* performSync by the SyncAdapter.
*
* @param context the context
* @param autoSyncDesired the auto sync desired
*/
public static void refreshAppC2DMRegistrationState(Context context,
boolean register) {
// Determine if there are any auto-syncable accounts. If there are, make
// sure we are
// registered with the C2DM servers. If not, unregister the application.
if (Build.VERSION.SDK_INT < 8) {
return;
} else {
if (register) {
C2DMessaging.register(context, C2DMConfig.C2DM_GOOGLE_ACCOUNT);
} else {
C2DMessaging.unregister(context);
}
}
}
}
Now the class where you put your configuration C2DMConfig.java
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.push;
/**
* Configuration settings for the Android client.
*/
public class C2DMConfig {
/**
* Enabling this is will turn on sync UI icons that notify the user of
* pending and active sync status. This is useful for debugging, but
* generally not recommended for real applications, as sync on Android is
* intended to be unobtrusive. Users can get the same sync status info by
* going to Settings > Accounts & Sync.
*/
public static final boolean ENABLE_SYNC_UI = true;
public static final String C2DM_GOOGLE_ACCOUNT = "{your-google-c2dm account}";
@SuppressWarnings("unchecked")
public static String makeLogTag(Class cls) {
String tag = "PushDemo_" + cls.getSimpleName();
return (tag.length() > 23) ? tag.substring(0, 23) : tag;
}
}
We are near to the finish
go to AndroidManifest.xml
< ?xml version="1.0" encoding="utf-8"?>
My default package is “com.example.push” keep in mind to change this accordingly in android manifest
Till here i recieved push notification devicetoken from android C2DM server and on recieve i sent it to the server to store the device token (this completes registration on 3rd party server).
Now remaining stuff is to send a notification to the register devices from the 3rd party server.
here is that php server side code file:send_notification.php
< ?php
$host = 'localhost';
$user = '{your-db-username}';
$pass = '{your-db-passwd}';
$database = 'push_android';
$username ="your-google-c2dm-email-id";
$password = "{your-google-c2dm-acc-passwd}";
$source="My-Server-Event-Alerter"; //anything that says about ur app
$service="ac2dm";
$connection = mysql_connect ($host, $user, $pass) or die ('Error connecting to mysql'.mysql_error());
//mysql_select_db ( $database,$connection)or die ('Error selecting database '.mysql_error());
mysql_selectdb($database) or die ('->>Error selecting database'.mysql_error());
if ( $_GET [ 'message' ] != '' )
{
$message =$_GET ['message'];
echo 'Message sent to server '.$message;
$post_params = array ( "Email" => $username, "Passwd" => $password, "accountType"=>"GOOGLE", "source" => $source, "service"=>$service );
$first = true;
$data_msg = "";
foreach ($post_params as $key => $value) {
if ($first)
$first = false;
else
$data_msg .= "&";
$data_msg .= urlencode($key) ."=". urlencode($value);
}
$x = curl_init("https://www.google.com/accounts/ClientLogin");
curl_setopt($x, CURLOPT_HEADER, 1);
curl_setopt($x, CURLOPT_POST, 1);
curl_setopt($x, CURLOPT_POSTFIELDS, $data_msg);
curl_setopt($x, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($x);
curl_close($x);
echo $response;
$pos = strpos($response, "Auth=");
$authKey = trim(substr($response, 5+$pos));
$result=mysql_query("SELECT * FROM devicetokens");
if(mysql_num_rows($result)>0 ){
$sucess= 'Message sent to '.mysql_num_rows($result).' devices';
$row = mysql_fetch_assoc ( $result );
do {
$deviceToken = $row['devicetoken'];
echo 'Device Token:'.$deviceToken . '';
$data = array(
'registration_id' => $deviceToken,
'collapse_key' => 'ck_' . 'col_key',
'data.message' => $message,
'data.title' =>'Requestec Push Demo');
//$data = (is_array($data)) ? http_build_query($data) : $data;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://android.apis.google.com/c2dm/send");
echo 'Content-Length:'.strlen($data);
$headers = array('Authorization: GoogleLogin auth=' . $authKey/*,'Content-Length:'.strlen($data)*/);
if($headers){
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$messagedata = curl_exec($ch);
echo $messagedata;
curl_close($ch);
}while($row = mysql_fetch_assoc ( $result ));
}
}
?>
Push Notification
< ?=$sucess;?>
type http://{your-server-url}/send_notification.php in your browser.
there are some extra echo statements put to debug – remove it in production environment
Do post your reply ..
Here is the project PushDemo.zip
Enjoy
Tags: android c2dm, android c2dm client and server, android push client, android push notification, android push server, c2dm server

can you please upload your full project.
thank you,
Hey Prathvi,
Nice Article. But I have my doubts about few things.
I have just started working on Java , though have expertise in PHP.
Even following the steps are causing errors in Java Manifest and other files.
So might be helpful if you provide us with the source code as well.
Thanks again ,
Varun
Also what is the name of the first php file and when it called.
first file is called when u actually get the token from android C2DM Sever and u sent it to your 3rd party server along with ur imie number
Please Post what the error msg is so that it clears doubt of many ppl
hi Prathvi
i have some problem .it’s about send_notification.php
i don’t know why
access “https://www.google.com/accounts/ClientLogin”
the response and the authkey is nothing
but i use curl not php curl
will appear the authkey
is it my php sever problem ? but already extend php curl
plz help
i change below code can work now
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, “https://www.google.com/accounts/ClientLogin”);
$post_fields = “accountType=” . urlencode(‘HOSTED_OR_GOOGLE’)
. “&Email=” . urlencode($username)
. “&Passwd=” . urlencode($password)
. “&source=” . urlencode($source)
. “&service=” . urlencode($service);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// for debugging the request
//curl_setopt($ch, CURLINFO_HEADER_OUT, true); // for debugging
$response = curl_exec($ch);
podeyyyyy
Please tell me in which java file you extend activity because to get launch app activity class need to be extended.
The file that extends Activity is of your choice . Its the Activity from which you will register to the C2DM or send a message.
please reply me as soon as possible.. thanx nice tutorial..
Hi,
I get 2 errors :
I get this error in Eclipse from AndroidManifest.xml
[2011-07-21 04:03:05 - com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper] Parser exception for /home/sputnick/workspace/Notifier/AndroidManifest.xml: Element type “uses” must be followed by either attribute specifications, “>” or “/>”.
[2011-07-21 04:03:05 - Notifier] Error in an XML file: aborting build.
http://pastie.org/2246205
And this one in the code : http://ompldr.org/vOWs4eQ
Any hint ?
should be
And for @Override error go to Project>Properties and change “Java compiler” Compiler compliance level to 1.5
Hope it helps
Where do you actually call the registration or should that automatically occur? Can you please post the full project or at least your PushDemoActivity.java file to see what is in your OnCreate()?
/* (non-Javadoc)
* @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)
*/
@Override
public void onReceive(Context context, Intent intent) {
super.onHandleIntentRecieved(context, intent);
}
causes errors as neither the onReceive nor the onHandleIntentReceived methods exist in C2DMBaseReceiver
Not entirely sure what the solution to this should be. any guidance appreciated and thanks for a great post
Hi,
It seems to be a nice article, thanks for that but i want to implement push notification in my android application.
So can u upload full running project so that i can get some information.
Once again Thanks
Your code snippets incorrectly format copied data, each line copied starts with ‘#’ or the line number, depending on whether copied by keyboard command or snippet tool.
On top of that, the java code doesn’t work.
Is there no way for you to share the project files?
same here – errors on onReceive and onHandleIntentReceived.
Ant advice?
cheers
I have implement same code but still I am not receiving notification on device.
The response which I am getting through send_notifiation.php is-
id=0:1317191270928916%1716893036225a49
Please help me
Sonia