Google Cloud Messaging is a service provide by google to send push notification on android device. GCM is used to send new data from server to android application on device. Adding GCM to your android application increase your user experience help you to send latest data from server. In this post i will explain you how to create a GCM enable android application. I am using Android Studio to develop this application.

Getting Started with GCM and PHP

In this post i am using PHP to store GCM registered id of application on server and with this id we can send notification from server to android device.

Setting up GCM

1. Open the google api console page and click on create project.

2. Go to Enable Api Google Cloud Messaging for Android and set its status as ON.
3. Get the Project Number, which will be used as sender id.

4. Click on Api & auth on right side then click on Credential link inside it and create a  Key for server applications leave field empty to allow all ip.

5. Now get Api Key for server application.

GCM Server Application in PHP

I create a simple application to make my app work i save GCM Registered Id received from android application in a text file and when i need to send something i get ID from text file and send notification to application using GCM. You save that id into your database table and send notification to multiple user by using their unique GCM register id.

<?php
	//Function to send PUSH
   function sendPush($registatoin_ids, $message) {
		//Google cloud messaging GCM-API url
        $url = 'https://android.googleapis.com/gcm/send';
        $fields = array(
			'registration_ids' => array($registatoin_ids),
			'data' => array("msg" => $message),
		); 
		// Google Cloud Messaging GCM API Key
		define("GOOGLE_API_KEY", "AIzaSyDVL9ZVPZamdVnh6TVsTv4g_ze-jFEvJv4"); // GCM server key
        $headers = array(
		'Authorization: key=' . GOOGLE_API_KEY,
		'Content-Type: application/json'
        );
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); 
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
        $result = curl_exec($ch);
		print_r($result);
		if ($result === FALSE) {
            die('Curl failed: ' . curl_error($ch));
			//curl_close($ch);
		}
		
        return $result;
	}
	
	//Send Push Notification
	$pushStatus = "";	
	if(!empty($_GET["push"])) {	
		$gcmRegID  = file_get_contents("GCMRegId.txt");
		$pushMessage = $_POST["message"];	
		if (isset($gcmRegID) && isset($pushMessage)) {		
			$gcmRegIds = array($gcmRegID);
			$message = array("msg" => $pushMessage);	
			$pushStatus = sendPush($gcmRegIds, $message);
		}		
	}
	
	// Receive GCM ID
	if(!empty($_GET["shareRegId"])) {
		$gcmRegID  = $_POST["regId"]; 
		file_put_contents("GCMRegId.txt",$gcmRegID);
		echo "Ok!";
		exit;
	}	
?>
<html>
    <head>
        <title>Push Notification android using GCM</title>
    </head>
	<body>
		<h1>Push Notification using GCM</h1>	
		<form method="post" action="?push=1">					                             
			<div>                                
				<textarea rows="2" name="message" cols="23" placeholder="Message to transmit via GCM"></textarea>
			</div>
			<div><input type="submit"  value="Send Push Notification via GCM" /></div>
		</form>
		<p><h3><?php echo $pushStatus; ?></h3></p>        
    </body>
</html>

Android GCM application

For this application i am using Android Studio.

Start your New Android Project

1. Create a new project in Android Studio from File ⇒ New ⇒ Android Application Project .

2. Add GCM.JAR file to provide your app GCM support. Download GCM.JAR file and copy that file into your libs folder { app ⇒ libs ⇒ gcm.jar }. Now after adding jar right click on jar file and click on Add as library

3. Now open your AndroidManifest.xml file under app ⇒ src ⇒main. Add permission to your manifest file

<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.trinitypush.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />

    <uses-permission android:name="com.trinitypush.permission.C2D_MESSAGE" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.VIBRATE" />

INTERNET – To make your app use internet services
ACCESS_NETWORK_STATE – To access network state (used to detect internet status)
GET_ACCOUNTS – Required as GCM needs google account
WAKE_LOCK – Needed if your app need to wake your device when it sleeps
VIBRATE – Needed if your support vibration when receiving notification

 AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.trinitypush"
    android:versionCode="1"
    android:versionName="1.0">

    <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.trinitypush.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />

    <uses-permission android:name="com.trinitypush.permission.C2D_MESSAGE" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.VIBRATE" />

    <uses-sdk
        android:minSdkVersion="9"
        android:targetSdkVersion="20" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MyActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name=".Main"
            android:configChanges="orientation|keyboardHidden"
            android:label="@string/app_name">

        </activity>

        <activity android:name=".GetIntent"
            android:label="@string/push">

        </activity>
        <receiver
            android:name=".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.trinitypush" />
            </intent-filter>
        </receiver>

        <service android:name=".GCMNotificationIntentService" />
    </application>

</manifest>

 4. Now first we need to get GCM register ID and save that id in device using Shared preference and also send to server. Through which we can send Push Notification to device. I create to Button through which i send first get my GCMregisterId and after i get that i send it to server.

Config.java

package com.trinitypush;

/**
 * Created by aneh on 8/14/2014.
 */
public interface Config {

    static final String APP_SERVER_URL = ""; // PHP app url
    static final String GOOGLE_PROJECT_ID = "1056844275141";
    static final String MESSAGE_KEY = "msg";
}

MyActivity.java

package com.trinitypush;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.google.android.gms.gcm.GoogleCloudMessaging;

import java.io.IOException;

public class MyActivity extends Activity {

    Button Reg, btnAppShare;
    String regId;
    GoogleCloudMessaging gcm;
    public static final String REG_ID = "regId";
    Context context;
    static final String TAG = "Register Activity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);

        Reg = (Button) findViewById(R.id.register);
        Reg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (TextUtils.isEmpty(regId)) {
                    regId = registerGCM();
                    Log.d("RegisterActivity", "GCM RegId: " + regId);
                } else {
                    Toast.makeText(getApplicationContext(),
                            "RegId already available. RegId: " + regId,
                            Toast.LENGTH_LONG).show();
                }
            }
        });

        btnAppShare = (Button) findViewById(R.id.btnAppShare);
        btnAppShare.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                if (TextUtils.isEmpty(regId)) {
                    Toast.makeText(getApplicationContext(), "RegId is empty!",
                            Toast.LENGTH_LONG).show();
                } else {
                    Intent i = new Intent(getApplicationContext(),
                            Main.class);
                    i.putExtra("regId", regId);
                    Log.d("RegisterActivity",
                            "onClick of Share: Before starting main activity.");
                    startActivity(i);
                    finish();
                    Log.d("RegisterActivity", "onClick of Share: After finish.");
                }
            }
        });
    }


    public String registerGCM() {

        gcm = GoogleCloudMessaging.getInstance(this);
        regId = getRegistrationId(context);

        if (TextUtils.isEmpty(regId)) {

            registerInBackground();

            Log.d("RegisterActivity",
                    "registerGCM - successfully registered with GCM server - regId: "
                            + regId);
        } else {
            Toast.makeText(getApplicationContext(),
                    "RegId already available. RegId: " + regId,
                    Toast.LENGTH_LONG).show();
        }
        return regId;
    }

    private String getRegistrationId(Context context) {
        final SharedPreferences prefs = getSharedPreferences(
                MyActivity.class.getSimpleName(), Context.MODE_PRIVATE);
        String registrationId = prefs.getString(REG_ID, "");
        if (registrationId.isEmpty()) {
            Log.i(TAG, "Registration not found.");
            return "";
        }
        return registrationId;
    }

    private void registerInBackground() {
        new AsyncTask<Void, Void, String>() {
            @Override
            protected String doInBackground(Void... params) {
                String msg = "";
                try {
                    if (gcm == null) {
                        gcm = GoogleCloudMessaging.getInstance(context);
                    }
                    regId = gcm.register(Config.GOOGLE_PROJECT_ID);
                    Log.d("RegisterActivity", "registerInBackground - regId: "
                            + regId);
                    msg = "Device registered, registration ID=" + regId;

                } catch (IOException ex) {
                    msg = "Error :" + ex.getMessage();
                    Log.d("RegisterActivity", "Error: " + msg);
                }
                Log.d("RegisterActivity", "AsyncTask completed: " + msg);
                return msg;
            }

            @Override
            protected void onPostExecute(String msg) {
                Toast.makeText(getApplicationContext(),
                        "Registered with GCM Server." + msg, Toast.LENGTH_LONG)
                        .show();
                saveRegisterId(context, regId);
            }
        }.execute(null, null, null);
    }



    private void saveRegisterId(Context context, String regId) {
        final SharedPreferences prefs = getSharedPreferences(
                MyActivity.class.getSimpleName(), Context.MODE_PRIVATE);
        Log.i(TAG, "Saving regId on app version ");
        SharedPreferences.Editor editor = prefs.edit();
        editor.putString(REG_ID, regId);
        editor.commit();
    }
}

 Activity Layout

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MyActivity">

    <Button
        android:id="@+id/register"
        android:layout_centerHorizontal="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/register"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Register to server"
        android:id="@+id/btnAppShare"
        android:layout_marginTop="75dp"
        android:layout_below="@+id/register"
        android:layout_alignLeft="@+id/register"
        android:layout_alignStart="@+id/register" />

</RelativeLayout>

 5. Now after saving appId we also create a broadcast and receiver to receive the notification.

GcmBroadcastReceiver.java

package com.trinitypush;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.WakefulBroadcastReceiver;
import android.util.Log;

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
        Log.e("Broadcast", "----------------------- GCM Broad cast");
		ComponentName comp = new ComponentName(context.getPackageName(),
                GCMNotificationIntentService.class.getName());
		startWakefulService(context, (intent.setComponent(comp)));
		setResultCode(Activity.RESULT_OK);
	}
}

 GCMNotificationIntentservice.java

In this class we get get notification and display notification on device

package com.trinitypush;

import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.SystemClock;
import android.provider.Settings;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.google.android.gms.gcm.GoogleCloudMessaging;

public class GCMNotificationIntentService extends IntentService {

	public static final int NOTIFICATION_ID = 1;
	private NotificationManager mNotificationManager;
	NotificationCompat.Builder builder;

	public GCMNotificationIntentService() {
		super("GcmIntentService");
	}

	public static final String TAG = "GCMNotificationIntentService";

	@Override
	protected void onHandleIntent(Intent intent) {
		Bundle extras = intent.getExtras();
		GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);

		String messageType = gcm.getMessageType(intent);
        Log.e("test recieve", "------------------------------ Catch");

		if (!extras.isEmpty()) {
			if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR
					.equals(messageType)) {
				sendNotification("Send error: " + extras.toString());
			} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
					.equals(messageType)) {
				sendNotification("Deleted messages on server: "
						+ extras.toString());
			} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
					.equals(messageType)) {

				for (int i = 0; i < 3; i++) {
					Log.i(TAG,
							"Working... " + (i + 1) + "/5 @ "
									+ SystemClock.elapsedRealtime());
					try {
						Thread.sleep(5000);
					} catch (InterruptedException e) {
					}

				}
				Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime());

				sendNotification(""+extras.get(Config.MESSAGE_KEY));
				Log.i(TAG, "Received: " + extras.toString());
			}
		}
		GcmBroadcastReceiver.completeWakefulIntent(intent);
	}

	private void sendNotification(String msg) {
		Log.d(TAG, "Preparing to send notification...: " + msg);
		mNotificationManager = (NotificationManager) this
				.getSystemService(Context.NOTIFICATION_SERVICE);

        Intent in = new Intent(this, GetIntent.class);
        in.putExtra("Notif", msg);
		PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
				in, 0);

        int numMessages = 0;
		NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
				this).setSmallIcon(R.drawable.icon)
				.setContentTitle("Trinity Tuts")
                .setSound(Settings.System.DEFAULT_NOTIFICATION_URI)
				.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
                .setAutoCancel(true)
				.setContentText(msg)
                .setNumber(++numMessages);

		mBuilder.setContentIntent(contentIntent);
		mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
		Log.d(TAG, "Notification sent successfully.");
	}
}

You can download this complete application from above download link.