Push Notification Pada Android Menggunakan GCM dan PHP

Push Notification Pada Android Menggunakan GCM dan PHP

Tutorial Information

ProgramJava & PHP
VersionJDK Android & PHP 5.3
DifficultyPemula - Standar
Estimated Time30-60 menit

Tulisan kali ini, ditujukan untuk developer Android. Di sini, kita akan belajar bagaimana mengimplementasikan push notification di aplikasi kita. Implementasi yang dilakukan, termasuk setting…

Tulisan kali ini, ditujukan untuk developer Android. Di sini, kita akan belajar bagaimana mengimplementasikan push notification di aplikasi kita. Implementasi yang dilakukan, termasuk setting register/unregister di device, juga persiapan kode di sisi server dengan menggunakan PHP. Untuk memulai, siapkan kopi Anda terlebih dahulu, karena tulisan kali ini akan lumayan panjang.

Membuat Project Android

Sebelum kita bisa membuat push notification dengan menggunakan GCM, kita buat dulu project baru di Android. Setelah project jadi, catat package name yang digunakan. Pada tutorial kali ini, saya memakai id.flwi.example.gcmappdemo.

Langkah selanjutnya, install gcm extra melalui Window » Android SDK Manager. Proses ini akan men-install library GCM yang akan kita gunakan dalam aplikasi ini.

Install Gcm eclipse

Install gcm eclipse

Setelah selesai, gcm extra akan ter-install di alamat $ANDROID-SDK-PATH/extras/google/gcm/. Silahkan copy file gcm.jar dari alamat $ANDROID-SDK-PATH/extras/google/gcm/gcm-client/dist/gcm.jar ke dalam direktori libs pada project Android Anda.  Setelah selesai di-copy, kembali lagi ke eclipse, lakukan navigasi ke lokasi gcm.jar dan klik kanan, kemudian pilih Build Path » Add to Build Path.

Menambahkan gcm.jar ke dalam build path, agar bisa dikenali oleh eclipse

Menambahkan gcm.jar ke dalam build path, agar bisa dikenali oleh eclipse

Membuat Project Google API

Untuk bisa menggunakan GCM, kita membutuhkan apikey. Hal ini bisa diperoleh dengan cara mendaftarkan project ke Google Api. Caranya, buka website Google API Console dan klik icon Create project...

Buat Project Google Api

Buat Project Google Api

Kalau Anda sudah pernah membuat project Google Api, maka, untuk membuat project baru, bisa dengan cara masuk ke Other Projects » Create

Setelah project berhasil dibuat, masuk ke halaman All Services, kemudian aktifkan Google Could Messaging for Android. Kalau ditanya persetujuan TOS, silahkan dibaca dan disetujui. Kalau Anda memilih untuk tidak setuju, silahkan tutup tutorial ini. Step berikutnya, buka API Access dan catat informasi apikey yang ada di halaman tersebut.

Setting GCM di AndroidManifest.xml

Berikut ini beberapa tambahan informasi yang wajib dimasukkan ke AndroidManifest.xml.

<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="xx"/>
minSdkVersion merujuk pada versi SDK terkecil yang disupport. Sedangkan targetSDKVersion adalah versi SDK yang ingin dituju.
<permission android:name="nama_package.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="nama_package.permission.C2D_MESSAGE" />
Setting permission C2D_MESSAGE digunakan untuk mengaktifkan GCM. Setting ini dibuat dengan level package. Ganti nama_package dengan informasi package dari aplikasi Anda.
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
Ke-empat uses-permission ini digunakan agar GCM bisa digunakan. INTERNET dibutuhkan karena GCM butuh koneksi internet untuk terhubung ke server. GET_ACCOUNTS digunakan karena setting GCM terhubung dengan akun Google yang ada di device. WAKE_LOCK juga harus ada karena proses GCM menggunakan mekanisme service yang ada di Android, di mana service membutuhkan permission WAKE_LOCK. Sedangkan c2dm.permission.RECEIVE digunakan agar aplikasi kita bisa menerima push notification melalui GCM.

di dalam <application>, tambahkan informasi:

<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="nama_package" />
  </intent-filter>
</receiver>
<service android:name=".GCMIntentService" />
intent receiver di atas digunakan untuk proses registrasi dan penerimaan pesan GCM. Silahkan ganti nama_package dengan informasi package aplikasi anda. Intent receiver ini digunakan sebagai penanda kalau aplikasi kita akan menerima intent dengan action RECEIVE dan REGISTRATION dari com.google.android.gcm.GCMBroadcastReceiver. Sedangkan informasi service adalah nama class service yang digunakan untuk menghandle pesan yang diterima. Di sini, kita menggunakan class GCMIntentService.

Persiapan aplikasi PHP untuk proses registrasi dan unregistrasi

Sebelum menyentuh script php, kita buat terlebih dahulu table yang akan menyimpan daftar device yang terdaftar GCM:

CREATE TABLE `android_gcm__devices` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `device_id` varchar(200) NOT NULL,
 `added_date` datetime NOT NULL,
 `last_update_date` datetime NOT NULL,
 `active` tinyint(1) NOT NULL DEFAULT '1',
 PRIMARY KEY (`id`),
 UNIQUE KEY `device_id` (`device_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

Selanjutnya, buat file register.php yang akan digunakan untuk proses registrasi device. Isikan dengan kode sebagai berikut:

<?php

$conn = mysql_connect("mysql-server-host", "db-username", "db-password") or die("NG #1: " . mysql_error());
mysql_select_db("nama-database");
$regId = isset($_POST['regId']) ? $_POST['regId'] : "";

if( !empty($regId)){
    $cdate = date("Y-m-d H:i:s");
    $sql = "INSERT INTO android_gcm_devices(device_id, added_date, last_update_date, active) VALUES('$regId', '$cdate', '$cdate', 1);";
    mysql_query($sql, $conn) or die("NG #2:".mysql_error());
    echo "OK";
} else {
    echo "NG";
}

Lalu buat juga file unregister.phpuntuk proses unregister device. Isikan dengan kode berikut:

<?php

$conn = mysql_connect("mysql-server-host", "db-username", "db-password") or die("NG #1: " . mysql_error());
mysql_select_db("nama-database");
$regId = isset($_POST['regId']) ? $_POST['regId'] : "";

if( !empty($regId)){
    $cdate = date("Y-m-d H:i:s");
    $sql = "UPDATE android_gcm_devices SET last_update_date = '$cdate', active = '0' WHERE id = '$regId'";
    mysql_query($sql, $conn) or die("NG #2:".mysql_error());
    echo "OK";
} else {
    echo "NG";
}

Handle Proses Register/Unregister di Android

Silahkan buat file GCMIntentService.java di lokasi package aplikasi Anda.

Setting GcmIntentService

Setting GcmIntentService

Isikan dengan kode berikut:

package id.flwi.example.gcmappdemo;

import id.flwi.util.ActivityUtil;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import com.google.android.gcm.GCMBaseIntentService;

public class GCMIntentService extends GCMBaseIntentService {

    public GCMIntentService(){
        super(MainActivity.GCM_SENDER_ID);
    }

    @Override
    protected void onError(Context context, String errorId) {
        Log.i("LOG", "got error: " + errorId);
    }

    @Override
    protected void onMessage(Context context, Intent intent) {
        Log.i("LOG", "got message from GCM server");
    }

    @Override
    protected void onRegistered(Context context, String regId) {
        Log.i("GCM LOG", "registering " + regId);
        APIWrapper.registerDevice(regId);
        ActivityUtil.setSharedPreference(context, "SHAREDPREF-GCM-REGID", regId);
    }

    @Override
    protected void onUnregistered(Context context, String regId) {
        Log.i("GCM LOG", "unregistering " + regId);
        APIWrapper.unregisterDevice(regId);
        ActivityUtil.setSharedPreference(context, "SHAREDPREF-GCM-REGID", "");
    }

}

Selanjutnya, tambahkan class baru dengan nama APIWrapper.javadan isikan kode berikut:

package id.flwi.example.gcmappdemo;

import id.flwi.util.HttpUtil;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class APIWrapper {
    public static boolean registerDevice(String regId) {
        boolean response = false;
        String result = "";

        Map<String, String> params = new HashMap<String, String>();
        params.put("regId", regId);

        try {
            //FIXME: change it to real API_URL
            result = HttpUtil.post("http://server-address/gcm/register.php", params);
            //Log.i("LOG", "XML Response: " + xmlresult);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if(result.equalsIgnoreCase("OK")){
            response = true;
        }
        return response;
    }

    public static boolean unregisterDevice(String regId){
        boolean response = false;
        String result = "";

        Map<String, String> params = new HashMap<String, String>();
        params.put("regId", regId);

        try {
            //FIXME: change it to real API_URL
            result = HttpUtil.post("http://server-address/gcm/unregister.php", params);
            //Log.i("LOG", "XML Response: " + xmlresult);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if(result.equalsIgnoreCase("OK")){
            response = true;
        }
        return response;
    }

}

Lalu ubah xml layout dengan isi sebagai berikut:

<LinearLayout 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:orientation="vertical" >

    <Button android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btnRegister"
        android:text="Register" />
    <Button android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btnUnregister"
        android:text="Unregister" />

</LinearLayout>

Terakhir, isikan file Activity dengan kode berikut:

package id.flwi.example.gcmappdemo;

import com.google.android.gcm.GCMRegistrar;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {
    Button btnReg;
    Button btnUnreg;
    public static String GCM_SENDER_ID = "409216998333";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnReg = (Button) findViewById(R.id.btnRegister);
        btnUnreg = (Button) findViewById(R.id.btnUnregister);

        btnReg.setOnClickListener(new View.OnClickListener() {

            public void onClick(View arg0) {
                GCMRegistrar.checkDevice(getApplicationContext());
                GCMRegistrar.checkManifest(getApplicationContext());
                final String regId = GCMRegistrar.getRegistrationId(getApplicationContext());
                if (regId.equals("")) {
                  GCMRegistrar.register(getApplicationContext(), GCM_SENDER_ID);
                } else {
                  Log.v("GCM LOG", "Device already registered.");
                }
            }
        });

        btnUnreg.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                GCMRegistrar.checkDevice(getApplicationContext());
                GCMRegistrar.checkManifest(getApplicationContext());
                final String regId = GCMRegistrar.getRegistrationId(getApplicationContext());
                if (!regId.equals("")) {
                    GCMRegistrar.unregister(getApplicationContext());
                } else {
                  Log.v("GCM TEST", "Device not registered, yet.");
                }
            }
        });
    }
}
di class ini terdapat informasi GCM_SENDER_ID. Informasi ini didapat dari URL halaman Google Api consoles. Perhatikan gambar berikut.

gcm-sender-id-information

Sampai pada tahap ini, sesungguhnya aplikasi kita sudah bisa melakukan proses register/unregister. Proses berikutnya yang akan kita lakukan adalah membuat file php untuk mengirim push notification dan menambahkan kode Java untuk menerima push tersebut.

Membuat Script PHP Untuk Mengirim Push Notification Dan Kode Android Untuk Menerimanya

Untuk script PHP, silahkan buat file push-sender.phpdan isikan dengan kode berikut:

<?php
$apiKey = "api-key-dari-website-google-api-project";

if(isset($_POST['message'])){

    $registrationIDs = getRegistrationIDs();

    $message = $_POST['message'];

    $fields = array(
        'registration_ids'  => $id,
        'data'              => array( "message" => $message ),
    );

    $headers = array( 
        'Authorization: key=' . $apiKey,
        'Content-Type: application/json'
    );

    $ch = curl_init();
    curl_setopt( $ch, CURLOPT_URL, 'https://android.googleapis.com/gcm/send' );
    curl_setopt( $ch, CURLOPT_POST, true );
    curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
    curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $fields ) );

    $result = curl_exec($ch);
    curl_close($ch);

    echo "$result<br />";
}

function getRegistrationIDs(){
    $conn = mysql_connect("mysql-server-host", "db-username", "db-password") or die("NG #1: " . mysql_error());
    mysql_select_db("nama-database");

    $deviceIds = array();

    $sql = "SELECT device_id FROM garusuta_device_id WHERE active = '1'";
    $rs = mysql_query($sql) or die("mysql error: " . mysql_error());
    while(false !== ($row = mysql_fetch_assoc($rs))){
        $deviceIds[] = $row['device_id'];
    }

    return $deviceIds;
}

?>
<form method="post" action="index.php">
<h3>Message</h3>
<textarea name="message" rows="2" cols="50"></textarea><br />
<input type="submit" name="submit" value="send!" />
</form>

Selanjutnya, untuk kode android yang akan menerima push notification, kita akan letakkan di class GCMIntentService.java. Silahkan ganti method onMessage(Context, Intent)dengan isi sebagai berikut:

    private int count = 0;
    @Override
    protected void onMessage(Context context, Intent intent) {
        String message = intent.getStringExtra("message");

        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        Notification note = new Notification(R.drawable.ic_launcher, getResources().getString(R.string.app_name), System.currentTimeMillis());
        Intent notificationIntent = new Intent(context, MainActivity.class);
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
        Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
        note.setLatestEventInfo(context, getResources().getString(R.string.app_name), message, pendingIntent);
        note.number = count++;
        note.defaults |= Notification.DEFAULT_SOUND;
        note.defaults |= Notification.DEFAULT_VIBRATE;
        note.defaults |= Notification.DEFAULT_LIGHTS;
        note.flags |= Notification.FLAG_AUTO_CANCEL;
        notificationManager.notify(0, note);
    }

Sekian tutorial Android kali ini, untuk project lengkap berikut script PHP yang siap dijalankan, bisa didownload di sini.

Tag: , , , , ,

20 Comments

Leave Comment
  1. Dede Pradana says:

    ada bau2 garasuta dalam kode di atas.. hehehe.. makasih tutorialnya. :D

  2. Mustofa says:

    keren mas GCM-nya, tapi apakah service ini terbuka untuk semua aplikasi tanpa ada batasan?

  3. rudi says:

    Mas kalau maksud dari
    $sql = “SELECT device_id FROM garusuta_device_id WHERE active = ‘1’”;
    ini apa ya? harus diganti gimana?
    thx buat tutorialnya

  4. aguzzackerz says:

    mas,,, mw nanya nih,, klo misalkan menampilkan notification dari DBsql bikin sendiri gimana ?
    apa bisa dari localhost…. input terus nampil notification ke emulator android….. tolong bantuannya mas,,, tanks,,

  5. Riky Sunandi says:

    Mas, ko saya stuck di acquiring wakelock muncul di log saya. kenapa ya? salah dimananya kira2?

  6. Diki Afriadi says:

    mas saya mau tanya ni, yg untuk Api key nya itu, yg gmna ya, yg hrus di isi IP nya?, apa IP laptop atau IP di hostingan nya?

    • Eve says:

      First of all I would like to say great blog! I had a quick question that I’d like to ask if you don;28#17&t mind. I was interested to know how you center yourself and clear your mind before writing. I’ve had trouble clearing my mind in getting my thoughts out. I do enjoy writing however it just seems like the first 10 to 15 minutes are wasted simply just trying to figure out how to begin. Any ideas or hints? Appreciate it!

  7. adhe hidayat says:

    mas sya sdh coba untuk buat api gcm tpi kok ada tulisan charges..ini berbayar ato free…

  8. alit says:

    selamat pagi semua’a
    numpang tanya klao membuat push notifikasi windows phoen cara’a bgaimna ..??
    aplikasi’a yg digunakan apa ..??
    klao android google cloud, klao win phone pa ya ..??
    mohon pecerahnnya
    terima kasih

  9. devye bellika says:

    ini harus dihosting atau bisa dengan localhost saja?

  10. Iwan says:

    Ketika kirim pesan dari server..ko notifikasi di device tidak muncul ya?..mohon pencerahan..tmksh

  11. Iwan says:

    Hallo admin..Ketika kirim pesan dari server..ko notifikasi di device tidak muncul ya?..mohon pencerahan..tmksh

  12. mohon info donk, kenapa di SDK Manager tidak keluar-keluar Menu GCM, padahal sudah update terbaru..
    terima kasih

  13. saddam says:

    wow, working 100%,
    terima kasih banyak gans,

    • Bei says:

      Agan berhasil y? Gmn caranya gan? ane udh coba, pas register bisa tp gada notifikasi. pas kirim push dr index.php ga ada respon apa2 di anroid ane gan. Ada yang agan rubah2 ga selain dari id project sama key api.nya?

  14. Yudha says:

    mas ni kok muncul “MismatchSenderId”. tw solusi ngilanginnya gk? notifikasinya gk bisa terkirim jadinya

  15. diah novita says:

    mas, kalau import id.flwi.util.ActivityUtil; diganti dengan apa ya? karena saya error disitu. trimakasih jika berkenan dibales..

  16. Husnan says:

    Pak, mohon di reupload dong, link nya udah mati,, terimakasih banyak

Write Comment

Your email will not be published. The marked label is required.