Hello Friends, today we’ll see how to send push notification to our app using FCM in PHP. Firebase Cloud Messaging (FCM) is a cross-platform messaging solution that lets you reliably send messages at no cost. Notification can be sent from Firebase Console also see screenshot below but if we want to send notification directly from our web server to achieve some automation or just to add some feature then this code will help.
To send push notification we need
and device registration ids if we want to send notification to specific devices. But we can send to a topic also where all the devices will receive notification registered to that topic. Server Key we can get from Firebase Console -> Project Settings -> Cloud Messaging after creating project in Firebase Console and device registration id from the app itself (see logcat screenshot below) that will be sent to our server, which we can store to database for further use. But in this example I am not saving it to database just for the simplicity but you can use according to your need. We also need an app to test our push notification, so I’ll share android app code as well in this post.Let’s start coding but before starting code, here is the Lifecycle Flow of Firebase Cloud Messaging (FCM)
- Register devices to receive messages from FCM.
- Send and receive downstream messages.
PushNotification.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
<?php class PushNotification { private static $API_ACCESS_KEY = "AAAAocCl4Mg:APA91bFYF93LgK7wWEIweyR5fIQHuRtPGaAyLuFs5zr7Yq4w19ifxQc43lC9EnMgVfxO0WqfVXTpxeSt9HjFh5wroA8u1oozZa6EyakjXQzyVZZmXVyoH9nXBoKyDNrscLUvXGLQYT4_"; // YOUR FIREBASE API_KEY public static function sendNotification($target = array(), $fields = array(), $data = array()) { $postdata = array(); /* * setting registrations ids or to only one at a time * because we can send notfication to registrations ids or to at once */ if (isset($target['registration_ids']) && is_array($target['registration_ids']) && !empty($target['registration_ids'])) { $postdata['registration_ids'] = $target['registration_ids']; } else if (isset($target['topic']) && trim($target['topic']) <> "") { $postdata['to'] = "/topics/" . $target['topic']; } /* setting Notification title & message body */ $postdata['notification'] = array('title' => $fields['title'], 'body' => $fields['body']); /* setting custom data if not empty */ if (!empty($data)) { $postdata['data'] = $data; } $headers = array( 'Authorization: key=' . self::$API_ACCESS_KEY, 'Content-Type: application/json' ); #Send Request To FireBase Server $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://fcm.googleapis.com/fcm/send"); //API URL of FCM curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postdata)); $result = curl_exec($ch); curl_close($ch); return $result; } public static function registerForNotification($token, $topic = "android") { //$url = "https://iid.googleapis.com/iid/v1:batchRemove"; $fields['registration_tokens'] = is_array($token) ? $token : array($token); $fields['to'] = '/topics/' . $topic; $headers = array( 'Authorization: key=' . self::$API_ACCESS_KEY, 'Content-Type:application/json' ); #Send Request To FireBase Server $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://iid.googleapis.com/iid/v1:batchAdd'); 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); curl_close($ch); return $result; } } |
There are two functions I have created in the PushNotification class here one sendNotification and another one registerForNotification. Just as name suggests sendNotification used to send notification while registerForNotification registers device id to a topic. This PushNotfication.php will be included in both register.php and index.php to use this class and its functions.
register.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?php include './PushNotification.php'; $action = isset($_REQUEST['action']) ? trim($_REQUEST['action']) : ""; if ($action == 'register-device-token') { if (!isset($_REQUEST['key']) || trim($_REQUEST['key']) !== 'TESTKEY') { echo "security key not provided or invalid"; exit; } if (!isset($_REQUEST['token'])) { echo "device token needed!!!"; exit; } /* this token can also be stored in database for further logic/use */ $token = trim($_REQUEST['token']); $topic = isset($_REQUEST['topic']) ? trim($_REQUEST['topic']) : 'android'; echo PushNotification::registerForNotification($token, $topic); exit; } |
index.php (send notification ui)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
<?php include './PushNotification.php'; if (isset($_POST['send'])) { $registration_ids = array(); foreach ($_POST['registration_ids'] as $regid) { if (trim($regid) <> "") { $registration_ids[] = $regid; } } if (!empty($registration_ids)) { $target['registration_ids'] = $registration_ids; } else { $target['topic'] = trim($_POST['topic']); } $fields = array( 'title' => isset($_POST['title']) ? trim($_POST['title']) : "", 'body' => isset($_POST['body']) ? trim($_POST['body']) : "" ); $data = array(); foreach ($_POST['key'] as $key => $value) { if (trim($value) <> "") { $data[$value] = $_POST['value'][$key]; } } $response = PushNotification::sendNotification($target, $fields, $data); } ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Push Notification</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css"> </head> <body> <h1>Send Notification</h1> <form method="post"> <table> <tr> <td style="vertical-align: top;"> <label>Topic</label><br/> <select name="topic"> <option value="">-Select-</option> <option value="android">Android</option> </select> </td> <td>Or</td> <td> <label>Registration Ids</label> <table> <tbody id="registrationIds_container"> <tr id="regid0"> <td><input type="text" name="registration_ids[]" placeholder="Registration Id"/></td> </tr> </tbody> <tfoot> <tr> <td style="text-align: right"><a href="javascript:;" onclick="addRegId()">Add</a></td> </tr> </tfoot> </table> </td> </tr> </table> <br/><br/> <label>Title</label><br/> <input type="text" name="title"/> <br/><br/> <label>Message</label><br/> <textarea name="body" style="width: 490px; height: 100px;"></textarea> <br/><br/> <label>Custom Data</label><br/> <table> <tbody id="custom_data_container"> <tr id="data0"> <td><input type="text" name="key[]" placeholder="Key"/></td> <td><input type="text" name="value[]" placeholder="Value"/></td> </tr> </tbody> <tfoot> <tr> <td></td> <td style="text-align: right"><a href="javascript:;" onclick="addCustomData()">Add</a></td> </tr> </tfoot> </table> <p><?= isset($response) ? $response : "" ?></p> <input type="submit" name="send" value="Send"/> </form> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.0/jquery.min.js" integrity="sha256-xNzN2a4ltkB44Mc/Jz3pT4iU1cmeR0FkXs4pru/JxaQ=" crossorigin="anonymous"></script> <script> function addRegId() { var count = $("#registrationIds_container tr").length + 1; var item = '<tr id="regid' + count + '">'; item += '<td><input type="text" name="registration_ids[]" placeholder="Registration Id"/></td>'; item += '<td><a href="javascript:void();" onclick="deleteRow(\'regid' + count + '\')" class="btn btn-sm btn-danger" title="Delete"><i class="fa fa-trash"></i></a></td>'; item += '</tr>'; $('#registrationIds_container').append(item); } function addCustomData() { var count = $("#custom_data_container tr").length + 1; var item = '<tr id="data' + count + '">'; item += '<td><input type="text" name="key[]" placeholder="Key"/></td>'; item += '<td><input type="text" name="value[]" placeholder="Value"/></td>'; item += '<td><a href="javascript:void();" onclick="deleteRow(\'data' + count + '\')" class="btn btn-sm btn-danger" title="Delete"><i class="fa fa-trash"></i></a></td>'; item += '</tr>'; $('#custom_data_container').append(item); } function deleteRow(id) { $("#" + id).remove(); } </script> </body> </html> |
Android App Code
Our server side code is ready to send notification now but we need an app to test whether our code is working or not. Let’s move to the app part, firstly we need a firebase configuration file to allow our app to interact with firebase. And to get configuration file we have to setup project and app on firebase console. But here I’ll not explain how to setup project, app and download configuration file as it is better explained on official website. Hence, we’ll see only coding and adding dependency part here and to setup project, app and downloading and pasting configuration file in our android project below link can help.
https://firebase.google.com/docs/android/setup#console
Now here is the android app code
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
package com.zatackcoder.pushnotificationexample; import android.content.Intent; import android.os.Bundle; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView textView = findViewById(R.id.text); /** * Notification Data Received in Intent Extras if App not Running or in Background **/ Bundle bundle = getIntent().getExtras(); if (bundle != null) { String dataText = ""; for (String key : bundle.keySet()) { dataText += key + " = " + bundle.get(key) + "\n"; } dataText = "Data Received from Notification\n\n" + dataText.trim(); textView.setText(dataText); } } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); TextView textView = findViewById(R.id.text); /** * Notification Data Received in Intent Extras when App is Running **/ Bundle bundle = intent.getExtras(); if (bundle != null) { String dataText = ""; for (String key : bundle.keySet()) { dataText += key + " = " + bundle.get(key) + "\n"; } dataText = "Data Received from Notification\n\n" + dataText.trim(); textView.setText(dataText); } } } |
Here in the MainActivity class, I have overridden onNewIntent method because this will be called from PendingIntent of notification when we click on notification and our app is running but when our app is not running then custom data will be received in extras of the intent of our launcher activity which we are extracting in onCreate method here. For more info kindly check below link
https://firebase.google.com/docs/cloud-messaging/android/receive
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Firebase Notification Example" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" android:gravity="center"/> </androidx.constraintlayout.widget.ConstraintLayout> |
JsonParser.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
package com.zatackcoder.pushnotificationexample; import android.util.Log; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.util.HashMap; /** * Created by rajesh kumar sahanee on 19/9/17. */ public class JsonParser { private final String TAG = "Json Parser"; private HttpURLConnection conn; private final StringBuilder result = new StringBuilder(); private JSONObject jsonObject; public JSONObject post(String url, HashMap<String, String> params, HashMap<String, String> files) { try { conn = (HttpURLConnection) new URL(url).openConnection(); conn.setDoInput(true);//Allow Inputs conn.setDoOutput(true);//Allow Outputs conn.setUseCaches(false);//Don't use a cached Copy conn.setRequestMethod("POST"); conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("Accept-Charset", "UTF-8"); conn.setReadTimeout(10000); conn.setConnectTimeout(50000); String boundary = "*****"; if (files != null) { conn.setRequestProperty("ENCTYPE", "multipart/form-data"); conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); for (String key : files.keySet()) { conn.setRequestProperty(key, files.get(key)); } } conn.connect(); DataOutputStream dataOutputStream = new DataOutputStream(conn.getOutputStream()); //file uploading String twoHyphens = "--"; String lineEnd = "\r\n"; if (files != null) { for (String key : files.keySet()) { int bytesRead, bytesAvailable, bufferSize; byte[] buffer; int maxBufferSize = 1024 * 1024; //1 * 1024 * 1024 File selectedFile = new File(files.get(key)); if (!selectedFile.isFile()) { break; } dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd); //writing bytes to data outputstream dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" + key + "\";filename=\"" + files.get(key) + "\"" + lineEnd); dataOutputStream.writeBytes(lineEnd); FileInputStream fileInputStream = new FileInputStream(selectedFile); //returns no. of bytes present in fileInputStream bytesAvailable = fileInputStream.available(); //selecting the buffer size as minimum of available bytes or 1 MB bufferSize = Math.min(bytesAvailable, maxBufferSize); //setting the buffer as byte array of size of bufferSize buffer = new byte[bufferSize]; //reads bytes from FileInputStream(from 0th index of buffer to buffersize) bytesRead = fileInputStream.read(buffer, 0, bufferSize); //loop repeats till bytesRead = -1, i.e., no bytes are left to read while (bytesRead > 0) { //write the bytes read from inputstream dataOutputStream.write(buffer, 0, bufferSize); bytesAvailable = fileInputStream.available(); bufferSize = Math.min(bytesAvailable, maxBufferSize); bytesRead = fileInputStream.read(buffer, 0, bufferSize); } dataOutputStream.writeBytes(lineEnd); dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd); fileInputStream.close(); } } //parameters writing when file uploading if (params != null && files != null) { for (String key : params.keySet()) { dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd); dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" + key + "\"" + lineEnd); dataOutputStream.writeBytes(lineEnd); dataOutputStream.writeBytes(params.get(key)); dataOutputStream.writeBytes(lineEnd); dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd); } } //parameters writing when no file uploading else if (params != null) { StringBuilder psb = new StringBuilder(); boolean flag = false; for (String key : params.keySet()) { try { if (flag) { psb.append("&"); } psb.append(key).append("=").append(URLEncoder.encode(params.get(key), "UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } flag = true; } dataOutputStream.writeBytes(psb.toString()); } Log.d(TAG, "RC: " + conn.getResponseCode() + " RM: " + conn.getResponseMessage()); dataOutputStream.flush(); dataOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } try { //Receive the response from the server BufferedReader reader = new BufferedReader(new InputStreamReader(new BufferedInputStream(conn.getInputStream()))); String line; while ((line = reader.readLine()) != null) { result.append(line); } Log.d(TAG, "Result: " + result.toString()); } catch (IOException e) { e.printStackTrace(); } conn.disconnect(); // try parse the string to a JSON object try { jsonObject = new JSONObject(result.toString()); } catch (JSONException e) { Log.e(TAG, "Error parsing data " + e.toString()); } // return JSON Object return jsonObject; } public JSONObject get(String url, HashMap<String, String> params) { StringBuilder psb = new StringBuilder(); boolean flag = false; for (String key : params.keySet()) { if (flag) { psb.append("&"); } try { psb.append(key).append("=").append(URLEncoder.encode(params.get(key), "UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } flag = true; } if (psb.length() != 0) { url += "?" + psb.toString(); Log.d(TAG, "url: " + url); } try { conn = (HttpURLConnection) new URL(url).openConnection(); conn.setDoOutput(false); conn.setRequestMethod("GET"); conn.setRequestProperty("Accept-Charset", "UTF-8"); conn.setConnectTimeout(15000); conn.connect(); } catch (IOException e) { e.printStackTrace(); } try { //Receive the response from the server BufferedReader reader = new BufferedReader(new InputStreamReader(new BufferedInputStream(conn.getInputStream()))); String line; while ((line = reader.readLine()) != null) { result.append(line); } Log.d(TAG, "Result: " + result.toString()); } catch (IOException e) { e.printStackTrace(); } conn.disconnect(); // try parse the string to a JSON object try { jsonObject = new JSONObject(result.toString()); } catch (JSONException e) { Log.e(TAG, "Error parsing data " + e.toString()); } // return JSON Object return jsonObject; } } |
MyFirebaseMessagingService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
package com.zatackcoder.pushnotificationexample; import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.graphics.BitmapFactory; import android.media.RingtoneManager; import android.os.AsyncTask; import android.os.Build; import android.util.Log; import androidx.annotation.NonNull; import androidx.core.app.NotificationCompat; import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage; import org.json.JSONException; import org.json.JSONObject; import java.util.HashMap; public class MyFirebaseMessagingService extends FirebaseMessagingService { private final String TAG = "MyFirebaseMessagingServ"; @Override public void onNewToken(@NonNull String token) { Log.d(TAG, "Refreshed token: " + token); // If you want to send messages to this application instance or // manage this apps subscriptions on the server side, send the // Instance ID token to your app server. sendRegistrationToServer(token); } @Override public void onMessageReceived(RemoteMessage remoteMessage) { String title = null; String content = null; HashMap<String, String> data = new HashMap<>(); // TODO(developer): Handle FCM messages here. // Not getting messages here? See why this may be: https://goo.gl/39bRNJ Log.d(TAG, "From: " + remoteMessage.getFrom()); // Check if message contains a notification payload. if (remoteMessage.getNotification() != null) { Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody()); title = remoteMessage.getNotification().getTitle(); content = remoteMessage.getNotification().getBody(); } // Check if message contains a data payload. if (remoteMessage.getData().size() > 0) { Log.d(TAG, "Message data payload: " + remoteMessage.getData()); // Handle message within 10 seconds data = new HashMap<>(remoteMessage.getData()); } // Also if you intend on generating your own notifications as a result of a received FCM // message, here is where that should be initiated. See sendNotification method below. sendNotification(title, content, data); } private void sendNotification(String title, String content, HashMap<String, String> data) { Intent intent = new Intent(getApplicationContext(), MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); for(String key : data.keySet()) intent.putExtra(key, data.get(key)); PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); String NOTIFICATION_CHANNEL_ID = "101"; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { @SuppressLint("WrongConstant") NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "Notification", NotificationManager.IMPORTANCE_MAX); //Configure Notification Channel notificationChannel.setDescription("ZataCoder Notification Channel"); notificationChannel.enableLights(true); notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000}); notificationChannel.enableVibration(true); notificationManager.createNotificationChannel(notificationChannel); } NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) .setSmallIcon(R.drawable.ic_notification) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) .setContentTitle(title) .setAutoCancel(true) .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)) .setContentText(content) .setContentIntent(pendingIntent) .setWhen(System.currentTimeMillis()) .setPriority(Notification.PRIORITY_MAX); notificationManager.notify(1, notificationBuilder.build()); } private void sendRegistrationToServer(String token) { Log.d("TOKEN ", token); new FirebaseRegistrationAsyncTask(token).execute(); } static class FirebaseRegistrationAsyncTask extends AsyncTask<Void, Void, Void> { final String token; FirebaseRegistrationAsyncTask(String token) { this.token = token; } @Override protected Void doInBackground(Void... voids) { HashMap<String, String> params = new HashMap<>(); params.put("key", "TESTKEY"); params.put("action", "register-device-token"); params.put("topic", "android"); params.put("token", token); JsonParser jsonParser = new JsonParser(); //JSONObject jsonObject = jsonParser.post(Preferences.API_URL, params, null); JSONObject jsonObject = jsonParser.get("https://zatackcoder.com/demo/firebase-push-notification/register.php", params); if (jsonObject != null) { try { //token saved to server jsonObject.getString("results"); } catch (JSONException e) { e.printStackTrace(); } } return null; } @Override protected void onPostExecute(Void voids) { super.onPostExecute(voids); } } } |
AndroidManifest.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.zatackcoder.pushnotificationexample"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".MyFirebaseMessagingService" android:enabled="true" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.INSTANCE_ID_EVENT" /> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service> </application> </manifest> |
build.gradle (Project Level)
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.6.3' classpath 'com.google.gms:google-services:4.3.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } |
build.gradle (App Level)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
apply plugin: 'com.android.application' apply plugin: 'com.google.gms.google-services' android { compileSdkVersion 28 defaultConfig { applicationId "com.zatackcoder.pushnotificationexample" minSdkVersion 16 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' implementation 'com.google.firebase:firebase-messaging:20.1.5' } |
Screenshots
Sending Notification to Topic |
Sending Notification to Registration Id |
Sending Data with Push Notification |
Data Received From Notification when App is Running and when Not Running |
NetBeans Project Download
FCM Push Notification NetBeans Project
AndroidStudio Project Download
FCM Push Notification AndroidStudio Project
Thanks friends
Your queries & suggestions are welcome in comments section
Please don’t forget to share if you find this helpful
Comments