Hey guys, so here I am back with another Firebase Cloud Messaging tutorial. You all know about Firebase Cloud Messaging, it is a push notification service and we can use it to send messages to our app users.
This method is deprecated. Follow the updated tutorial here:
Android Push Notification Tutorial using Firebase Cloud Messaging
So here are the points that we are going to cover with this Firebase Cloud Messaging Tutorial.
Table of Contents
- 1 Firebase Cloud Messaging for Android Video Series
- 2 Integrating Firebase Cloud Messaging in Android Project
- 3 Displaying Push Notification
- 4 Building Web Services Part 1
- 5 Storing Token to MySQL Database
- 6 Building Web Services Part 2
- 7 Making Send Notification Option in App
- 8 Firebase Cloud Messaging Source Code
Firebase Cloud Messaging for Android Video Series
- If you want to go with a video tutorial explaining everything about Firebase Cloud Messaging then go through the below playlist.
Integrating Firebase Cloud Messaging in Android Project
Creating a new Android Project
- With Android Studio 2.2 it is really easy to integrate firebase in your project.
- First create a new Android Studio Project with an Empty Activity.
- Once your project is loaded click on firebase from the tools menu.
- After clicking on Firebase an assistant will open showing all the available firebase features.
- As you can see in the above images we have all the Firebase Services. But at this time we care about Cloud Messaging. So click on Cloud Messaging.
Setting Up Firebase Cloud Messaging
- You will see a link saying Set Up Firebase Cloud Messaging. Click on it.
- Now you will see all the steps required to Set up Firebase Cloud Messaging in the project.
#1 Connect Your App to Firebase
- Simply click on the Connect to Firebase button. It will start a connect dialog.
- Here you can create a new Project on Firebase, as I am creating a project named FcmSimplifiedCoding (See the below screenshot). Or you can also select an existing firebase project.
- Now simply click on Connect to Firebase. And wait for a few seconds. And you will see the following message in the assistant.
- So step number 1 is completed successfully. Now lets move ahead.
#2 Add FCM to Your App
- Again click on the button Add FCM to your app and you will see a dialog box.
- Click on Accept Changes. And firebase is setup in your project now.
Generating Device Token
- Every device generates a unique token to receive notifications. And for this we have to create a class that will extend the class FirebaseInstanceIdService. This part is same as we did in the previous Firebase Cloud Messaging Tutorial.
- So create a class named MyFirebaseInstanceIDService.java and write the following code.
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 | package net.simplifiedcoding.firebasecloudmessaging; import android.util.Log; import com.google.firebase.iid.FirebaseInstanceId; import com.google.firebase.iid.FirebaseInstanceIdService; /** * Created by Belal on 03/11/16. */ //Class extending FirebaseInstanceIdService public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService { private static final String TAG = "MyFirebaseIIDService"; @Override public void onTokenRefresh() { //Getting registration token String refreshedToken = FirebaseInstanceId.getInstance().getToken(); //Displaying token on logcat Log.d(TAG, "Refreshed token: " + refreshedToken); //calling the method store token and passing token storeToken(refreshedToken); } private void storeToken(String token) { //we will save the token in sharedpreferences later } } |
- As this is a service we need to define this class inside AndroidManifest.xml. So come inside AndroidManifest.xml and write the following code inside application tag.
1 2 3 4 5 6 7 8 | <service android:name=".MyFirebaseInstanceIDService"> <intent-filter> <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/> </intent-filter> </service> |
Storing Device Token
Saving Token
- First we will store the generated token in SharedPreferences.
- So, for managing the SharedPreferences we will create a class in Singleton Pattern.
- Create a class named SharedPrefManager.java and write the following code.
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 | package net.simplifiedcoding.firebasecloudmessaging; import android.content.Context; import android.content.SharedPreferences; /** * Created by Belal on 03/11/16. */ public class SharedPrefManager { private static final String SHARED_PREF_NAME = "FCMSharedPref"; private static final String TAG_TOKEN = "tagtoken"; private static SharedPrefManager mInstance; private static Context mCtx; private SharedPrefManager(Context context) { mCtx = context; } public static synchronized SharedPrefManager getInstance(Context context) { if (mInstance == null) { mInstance = new SharedPrefManager(context); } return mInstance; } //this method will save the device token to shared preferences public boolean saveDeviceToken(String token){ SharedPreferences sharedPreferences = mCtx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString(TAG_TOKEN, token); editor.apply(); return true; } //this method will fetch the device token from shared preferences public String getDeviceToken(){ SharedPreferences sharedPreferences = mCtx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE); return sharedPreferences.getString(TAG_TOKEN, null); } } |
- Now to save the token generated with the FirebaseInstanceIdService we will call the method of the above class.
- So you need to modify the class MyFirebaseInstanceIDService.java as below.
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 | package net.simplifiedcoding.firebasecloudmessaging; import android.util.Log; import com.google.firebase.iid.FirebaseInstanceId; import com.google.firebase.iid.FirebaseInstanceIdService; /** * Created by Belal on 03/11/16. */ public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService { private static final String TAG = "MyFirebaseIIDService"; @Override public void onTokenRefresh() { String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken); storeToken(refreshedToken); } private void storeToken(String token) { //saving the token on shared preferences SharedPrefManager.getInstance(getApplicationContext()).saveDeviceToken(token); } } |
Displaying Token
- Though this part is not necessary but just to make sure the token is generated and saved in the SharedPreferences, we can display the token.
- For this come inside activity_main.xml and write the following code.
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 | <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="net.simplifiedcoding.firebasecloudmessaging.MainActivity"> <Button android:layout_centerVertical="true" android:text="Display Token" android:id="@+id/buttonDisplayToken" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/textViewToken" android:layout_alignParentBottom="true" android:layout_width="match_parent" android:layout_height="wrap_content" /> </RelativeLayout> |
- The above code will generate the following layout.
- We have a Button and a TextView. On button click we have to display the token on the TextView. We can easily do it by using the Singleton class SharedPrefManager that we created.
- So come inside MainActivity.java and write the following code.
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 | package net.simplifiedcoding.firebasecloudmessaging; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity implements View.OnClickListener { //defining views private Button buttonDisplayToken; private TextView textViewToken; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //getting views from xml textViewToken = (TextView) findViewById(R.id.textViewToken); buttonDisplayToken = (Button) findViewById(R.id.buttonDisplayToken); //adding listener to view buttonDisplayToken.setOnClickListener(this); } @Override public void onClick(View view) { if (view == buttonDisplayToken) { //getting token from shared preferences String token = SharedPrefManager.getInstance(this).getDeviceToken(); //if token is not null if (token != null) { //displaying the token textViewToken.setText(token); } else { //if token is null that means something wrong textViewToken.setText("Token not generated"); } } } } |
- Now just run your application. And click on the button you should see the token in the TextView.
- But if you are seeing token not generated then something is wrong. In this case try with a different emulator. Or try by uninstalling the application from your device.
- If you are getting the token, then you can move ahead.
Creating Messaging Service
- We have the device token, now we need one more class that will extend FirebaseMessagingService, this class will actually receive the notification.
- So create a new class named MyFirebaseMessagingService.java and write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package net.simplifiedcoding.firebasecloudmessaging; import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage; /** * Created by Belal on 03/11/16. */ public class MyFirebaseMessagingService extends FirebaseMessagingService { private static final String TAG = "MyFirebaseMsgService"; @Override public void onMessageReceived(RemoteMessage remoteMessage) { } } |
- In the above code onMessageReceived(RemoteMessage remoteMessage) method will be called when the message is received by the push notification.
- Again we need to define this service inside AndroidManifest.xml. For this write the following xml code inside <application> tag.
1 2 3 4 5 6 7 8 | <service android:name=".MyFirebaseMessagingService"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT"/> </intent-filter> </service> |
- Now we need to handle the message that will be received, to display it as a notification.
Displaying Push Notification
Creating a class to Handle Push Notifications
- To show push notification we will create a class named MyNotificationManager.java. Here we will create the required method to show the notifications.
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 | package net.simplifiedcoding.firebasecloudmessaging; /** * Created by Belal on 03/11/16. */ import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.support.v4.app.NotificationCompat; import android.text.Html; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; /** * Created by Ravi on 31/03/15. */ public class MyNotificationManager { public static final int ID_BIG_NOTIFICATION = 234; public static final int ID_SMALL_NOTIFICATION = 235; private Context mCtx; public MyNotificationManager(Context mCtx) { this.mCtx = mCtx; } //the method will show a big notification with an image //parameters are title for message title, message for message text, url of the big image and an intent that will open //when you will tap on the notification public void showBigNotification(String title, String message, String url, Intent intent) { PendingIntent resultPendingIntent = PendingIntent.getActivity( mCtx, ID_BIG_NOTIFICATION, intent, PendingIntent.FLAG_UPDATE_CURRENT ); NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle(); bigPictureStyle.setBigContentTitle(title); bigPictureStyle.setSummaryText(Html.fromHtml(message).toString()); bigPictureStyle.bigPicture(getBitmapFromURL(url)); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mCtx); Notification notification; notification = mBuilder.setSmallIcon(R.mipmap.ic_launcher).setTicker(title).setWhen(0) .setAutoCancel(true) .setContentIntent(resultPendingIntent) .setContentTitle(title) .setStyle(bigPictureStyle) .setSmallIcon(R.mipmap.ic_launcher) .setLargeIcon(BitmapFactory.decodeResource(mCtx.getResources(), R.mipmap.ic_launcher)) .setContentText(message) .build(); notification.flags |= Notification.FLAG_AUTO_CANCEL; NotificationManager notificationManager = (NotificationManager) mCtx.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(ID_BIG_NOTIFICATION, notification); } //the method will show a small notification //parameters are title for message title, message for message text and an intent that will open //when you will tap on the notification public void showSmallNotification(String title, String message, Intent intent) { PendingIntent resultPendingIntent = PendingIntent.getActivity( mCtx, ID_SMALL_NOTIFICATION, intent, PendingIntent.FLAG_UPDATE_CURRENT ); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mCtx); Notification notification; notification = mBuilder.setSmallIcon(R.mipmap.ic_launcher).setTicker(title).setWhen(0) .setAutoCancel(true) .setContentIntent(resultPendingIntent) .setContentTitle(title) .setSmallIcon(R.mipmap.ic_launcher) .setLargeIcon(BitmapFactory.decodeResource(mCtx.getResources(), R.mipmap.ic_launcher)) .setContentText(message) .build(); notification.flags |= Notification.FLAG_AUTO_CANCEL; NotificationManager notificationManager = (NotificationManager) mCtx.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(ID_SMALL_NOTIFICATION, notification); } //The method will return Bitmap from an image URL private Bitmap getBitmapFromURL(String strURL) { try { URL url = new URL(strURL); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.connect(); InputStream input = connection.getInputStream(); Bitmap myBitmap = BitmapFactory.decodeStream(input); return myBitmap; } catch (IOException e) { e.printStackTrace(); return null; } } } |
- We will be using the methods showBigNotification() and showSmallNotification() to notify the user as required.
- These methods will be called from the MyFirebaseMessagingService.java class. So lets modify this class to display notification.
Displaying Notification
- Come inside MyFirebaseMessagingService.java and modify it as below.
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 | package net.simplifiedcoding.firebasecloudmessaging; import android.content.Intent; import android.util.Log; import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage; import org.json.JSONException; import org.json.JSONObject; /** * Created by Belal on 03/11/16. */ public class MyFirebaseMessagingService extends FirebaseMessagingService { private static final String TAG = "MyFirebaseMsgService"; @Override public void onMessageReceived(RemoteMessage remoteMessage) { if (remoteMessage.getData().size() > 0) { Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString()); try { JSONObject json = new JSONObject(remoteMessage.getData().toString()); sendPushNotification(json); } catch (Exception e) { Log.e(TAG, "Exception: " + e.getMessage()); } } } //this method will display the notification //We are passing the JSONObject that is received from //firebase cloud messaging private void sendPushNotification(JSONObject json) { //optionally we can display the json into log Log.e(TAG, "Notification JSON " + json.toString()); try { //getting the json data JSONObject data = json.getJSONObject("data"); //parsing json data String title = data.getString("title"); String message = data.getString("message"); String imageUrl = data.getString("image"); //creating MyNotificationManager object MyNotificationManager mNotificationManager = new MyNotificationManager(getApplicationContext()); //creating an intent for the notification Intent intent = new Intent(getApplicationContext(), MainActivity.class); //if there is no image if(imageUrl.equals("null")){ //displaying small notification mNotificationManager.showSmallNotification(title, message, intent); }else{ //if there is an image //displaying a big notification mNotificationManager.showBigNotification(title, message, imageUrl, intent); } } catch (JSONException e) { Log.e(TAG, "Json Exception: " + e.getMessage()); } catch (Exception e) { Log.e(TAG, "Exception: " + e.getMessage()); } } } |
- We have done with the notification, but a very important thing still remaining. We have to store the token to the server. As by now, the device token is in the device only and without token we cannot use Firebase Cloud Messaging. So here comes that task of creating the web services that will store the registration token to our server.
Building Web Services Part 1
- In this phase we have to do the following tasks.
- Database Creation
- Web service to store token in database
- I will be using XAMPP, using PHP is not necessary you can use any technology you are comfortable in. I am using PHP with XAMPP. So lets start with Database Creation.
Creating Database
- Go to phpmyadmin and run the following SQL command to make the database.
1 2 3 4 5 6 7 | CREATE TABLE `devices` ( `id` int(11) PRIMARY KEY AUTO_INCREMENT, `email` varchar(100) NOT NULL, `token` text NOT NULL ); |
- We will insert an email and device token in each row of the table. So lets move into creating php scripts.
Creating PHP Scripts
Scripts for DB Connection and DB Operation
- Again I will be doing this thing in the simplest way but in real world scenario you should follow Creating RESTful API for these tasks.
- Inside the directory htdocs (because I am using xampp) create a folder for the php scripts. I created FcmExample.
- Inside FcmExample create a file named Config.php and write the following code.
1 2 3 4 5 6 7 | <?php define('DB_USERNAME','root'); define('DB_PASSWORD',''); define('DB_NAME','fcm'); define('DB_HOST','localhost'); |
- Create a file named DbConnect.php, in this file we will create a class to connect to our database.
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 | <?php //Class DbConnect class DbConnect { //Variable to store database link private $con; //Class constructor function __construct() { } //This method will connect to the database function connect() { //Including the config.php file to get the database constants include_once dirname(__FILE__) . '/Config.php'; //connecting to mysql database $this->con = new mysqli(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME); //Checking if any error occured while connecting if (mysqli_connect_errno()) { echo "Failed to connect to MySQL: " . mysqli_connect_error(); } //finally returning the connection link return $this->con; } } |
- Now create another file named DbOperation.php, in this file we will create a class to handle the database operations.
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 | <?php class DbOperation { //Database connection link private $con; //Class constructor function __construct() { //Getting the DbConnect.php file require_once dirname(__FILE__) . '/DbConnect.php'; //Creating a DbConnect object to connect to the database $db = new DbConnect(); //Initializing our connection link of this class //by calling the method connect of DbConnect class $this->con = $db->connect(); } //storing token in database public function registerDevice($email,$token){ if(!$this->isEmailExist($email)){ $stmt = $this->con->prepare("INSERT INTO devices (email, token) VALUES (?,?) "); $stmt->bind_param("ss",$email,$token); if($stmt->execute()) return 0; //return 0 means success return 1; //return 1 means failure }else{ return 2; //returning 2 means email already exist } } //the method will check if email already exist private function isEmailexist($email){ $stmt = $this->con->prepare("SELECT id FROM devices WHERE email = ?"); $stmt->bind_param("s",$email); $stmt->execute(); $stmt->store_result(); $num_rows = $stmt->num_rows; $stmt->close(); return $num_rows > 0; } //getting all tokens to send push to all devices public function getAllTokens(){ $stmt = $this->con->prepare("SELECT token FROM devices"); $stmt->execute(); $result = $stmt->get_result(); $tokens = array(); while($token = $result->fetch_assoc()){ array_push($tokens, $token['token']); } return $tokens; } //getting a specified token to send push to selected device public function getTokenByEmail($email){ $stmt = $this->con->prepare("SELECT token FROM devices WHERE email = ?"); $stmt->bind_param("s",$email); $stmt->execute(); $result = $stmt->get_result()->fetch_assoc(); return array($result['token']); } //getting all the registered devices from database public function getAllDevices(){ $stmt = $this->con->prepare("SELECT * FROM devices"); $stmt->execute(); $result = $stmt->get_result(); return $result; } } |
Script to Store Device Token in MySQL
- To store the token to database we need one more script that will actually get the token and process it to the database. So create one more php file named RegisterDevice.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 | <?php require_once 'DbOperation.php'; $response = array(); if($_SERVER['REQUEST_METHOD']=='POST'){ $token = $_POST['token']; $email = $_POST['email']; $db = new DbOperation(); $result = $db->registerDevice($email,$token); if($result == 0){ $response['error'] = false; $response['message'] = 'Device registered successfully'; }elseif($result == 2){ $response['error'] = true; $response['message'] = 'Device already registered'; }else{ $response['error'] = true; $response['message']='Device not registered'; } }else{ $response['error']=true; $response['message']='Invalid Request...'; } echo json_encode($response); |
- Now test the script using a REST Client. I am using POSTMAN here.
- As you can see the script is working fine. But before moving ahead in Android side you need to use the host ip instead of localhost in the URL.
- For windows use ipconfig in command prompt and in terminal use ifconfig to know the IP Address. So in my case the URL to this script with the ip is.
http://192.168.1.102/FcmExample/RegisterDevice.php
Script to Fetch All the Registered Device
- As we will send the push from the android device itself. So we need to get all the registered device. For this task we need a php script that will fetch all the registered device from database.
- So create a file named GetRegisteredDevices.php and write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <?php require_once 'DbOperation.php'; $db = new DbOperation(); $devices = $db->getAllDevices(); $response = array(); $response['error'] = false; $response['devices'] = array(); while($device = $devices->fetch_assoc()){ $temp = array(); $temp['id']=$device['id']; $temp['email']=$device['email']; $temp['token']=$device['token']; array_push($response['devices'],$temp); } echo json_encode($response); |
- You can check this script as well.
Storing Token to MySQL Database
- Now we send the token from SharedPreference to MySQL database. As our web service for this action is ready.
- First we will modify the activity_main.xml as below.
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 | <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="net.simplifiedcoding.firebasecloudmessaging.MainActivity"> <EditText android:layout_above="@+id/buttonRegister" android:hint="Enter email" android:id="@+id/editTextEmail" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:layout_centerVertical="true" android:text="Register Device" android:id="@+id/buttonRegister" android:layout_width="match_parent" android:layout_height="wrap_content" /> </RelativeLayout> |
- Now we have the layout for MainActivity as below.
- So we have an EditText and a Button. We need to put email in the EditText then click on the Button to register the device for receiving notification.
- Now to complete the functionality made the following changes in 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 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 | package net.simplifiedcoding.firebasecloudmessaging; import android.app.ProgressDialog; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.android.volley.AuthFailureError; import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; import com.android.volley.toolbox.Volley; import org.json.JSONException; import org.json.JSONObject; import java.util.HashMap; import java.util.Map; public class MainActivity extends AppCompatActivity implements View.OnClickListener { //defining views private Button buttonRegister; private EditText editTextEmail; private ProgressDialog progressDialog; //URL to RegisterDevice.php private static final String URL_REGISTER_DEVICE = "http://192.168.1.102/FcmExample/RegisterDevice.php"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //getting views from xml editTextEmail = (EditText) findViewById(R.id.editTextEmail); buttonRegister = (Button) findViewById(R.id.buttonRegister); //adding listener to view buttonRegister.setOnClickListener(this); } //storing token to mysql server private void sendTokenToServer() { progressDialog = new ProgressDialog(this); progressDialog.setMessage("Registering Device..."); progressDialog.show(); final String token = SharedPrefManager.getInstance(this).getDeviceToken(); final String email = editTextEmail.getText().toString(); if (token == null) { progressDialog.dismiss(); Toast.makeText(this, "Token not generated", Toast.LENGTH_LONG).show(); return; } StringRequest stringRequest = new StringRequest(Request.Method.POST, URL_REGISTER_DEVICE, new Response.Listener<String>() { @Override public void onResponse(String response) { progressDialog.dismiss(); try { JSONObject obj = new JSONObject(response); Toast.makeText(MainActivity.this, obj.getString("message"), Toast.LENGTH_LONG).show(); } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { progressDialog.dismiss(); Toast.makeText(MainActivity.this, error.getMessage(), Toast.LENGTH_LONG).show(); } }) { @Override protected Map<String, String> getParams() throws AuthFailureError { Map<String, String> params = new HashMap<>(); params.put("email", email); params.put("token", token); return params; } }; RequestQueue requestQueue = Volley.newRequestQueue(this); requestQueue.add(stringRequest); } @Override public void onClick(View view) { if (view == buttonRegister) { sendTokenToServer(); } } } |
- After this you can try running your application.
- As you can see we are getting the success message. Now check the MySQL database to ensure that token is stored.
- Yeah we got the device token in our MySQL database.
Building Web Services Part 2
- Again we need to build some more web services. So lets begin.
Building Web Service for Sending Push Notification
- Now we will build the Web Service needed to send push notification.
- We have two kinds of push notification in this project. One when we will send Push to a single device. And the other one is when we will broadcast push notification to all devices.
- But first we will configure some basic things for sending push using Firebase Cloud Messaging.
Getting Firebase Server Key
- Go to Firebase Console and inside your project settings go to cloud messaging tab.
- You will find the Cloud Messaging Server Key here, copy it.
- Now go inside the existing Config.php file and define one more constant that will store our Firebase API Key.
1 2 3 4 5 6 7 8 9 10 | <?php define('DB_USERNAME','root'); define('DB_PASSWORD',''); define('DB_NAME','fcm'); define('DB_HOST','localhost'); //defined a new constant for firebase api key define('FIREBASE_API_KEY', 'PUT_YOUR_API_KEY_HERE'); |
Creating a class to store Push Notification
- Create a file named Push.php and write the following code.
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 | <?php class Push { //notification title private $title; //notification message private $message; //notification image url private $image; //initializing values in this constructor function __construct($title, $message, $image) { $this->title = $title; $this->message = $message; $this->image = $image; } //getting the push notification public function getPush() { $res = array(); $res['data']['title'] = $this->title; $res['data']['message'] = $this->message; $res['data']['image'] = $this->image; return $res; } } |
- The above class is very simple its only initializing the variables required for push in the constructor, and giving us back an array with the required data in getPush() method.
Creating a Separate Class for Handling cURL operation
- To send push notification we need to make http request to firebase server. And we can do it using cURL. So to handle this task create a new php file named Firebase.php and write the following code.
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 | <?php class Firebase { public function send($registration_ids, $message) { $fields = array( 'registration_ids' => $registration_ids, 'data' => $message, ); return $this->sendPushNotification($fields); } /* * This function will make the actuall curl request to firebase server * and then the message is sent */ private function sendPushNotification($fields) { //importing the constant files require_once 'Config.php'; //firebase server url to send the curl request $url = 'https://fcm.googleapis.com/fcm/send'; //building headers for the request $headers = array( 'Authorization: key=' . FIREBASE_API_KEY, 'Content-Type: application/json' ); //Initializing curl to open a connection $ch = curl_init(); //Setting the curl url curl_setopt($ch, CURLOPT_URL, $url); //setting the method as post curl_setopt($ch, CURLOPT_POST, true); //adding headers curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //disabling ssl support curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //adding the fields in json format curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields)); //finally executing the curl request $result = curl_exec($ch); if ($result === FALSE) { die('Curl failed: ' . curl_error($ch)); } //Now close the connection curl_close($ch); //and return the result return $result; } } |
Script to Send Push Notification
Sending to a Single Device
- To send push to a single device create a php script named sendSinglePush.php and write the following code.
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 | <?php //importing required files require_once 'DbOperation.php'; require_once 'Firebase.php'; require_once 'Push.php'; $db = new DbOperation(); $response = array(); if($_SERVER['REQUEST_METHOD']=='POST'){ //hecking the required params if(isset($_POST['title']) and isset($_POST['message']) and isset($_POST['email'])){ //creating a new push $push = null; //first check if the push has an image with it if(isset($_POST['image'])){ $push = new Push( $_POST['title'], $_POST['message'], $_POST['image'] ); }else{ //if the push don't have an image give null in place of image $push = new Push( $_POST['title'], $_POST['message'], null ); } //getting the push from push object $mPushNotification = $push->getPush(); //getting the token from database object $devicetoken = $db->getTokenByEmail($_POST['email']); //creating firebase class object $firebase = new Firebase(); //sending push notification and displaying result echo $firebase->send($devicetoken, $mPushNotification); }else{ $response['error']=true; $response['message']='Parameters missing'; } }else{ $response['error']=true; $response['message']='Invalid request'; } echo json_encode($response); |
- Now again you can test this script using POSTMAN.
- First try sending a notification without image. So we have to put only title, message and email in parameters.
- If you are getting a success then you should see the notification in your device as well.

- Now also try notification with an image. To send an image along with the message you just need to put one more parameter in the request named image and it will contain the url of the image.
- In this time you should see a notification as below in the device.
- So the push notification is working absolutely fine.
Sending to All Device
- Now the second case is when we want to broadcast message to all the register device. For this create one more php script named sendMultiplePush.php and write the following code.
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 | <?php //importing required files require_once 'DbOperation.php'; require_once 'Firebase.php'; require_once 'Push.php'; $db = new DbOperation(); $response = array(); if($_SERVER['REQUEST_METHOD']=='POST'){ //hecking the required params if(isset($_POST['title']) and isset($_POST['message'])) { //creating a new push $push = null; //first check if the push has an image with it if(isset($_POST['image'])){ $push = new Push( $_POST['title'], $_POST['message'], $_POST['image'] ); }else{ //if the push don't have an image give null in place of image $push = new Push( $_POST['title'], $_POST['message'], null ); } //getting the push from push object $mPushNotification = $push->getPush(); //getting the token from database object $devicetoken = $db->getAllTokens(); //creating firebase class object $firebase = new Firebase(); //sending push notification and displaying result echo $firebase->send($devicetoken, $mPushNotification); }else{ $response['error']=true; $response['message']='Parameters missing'; } }else{ $response['error']=true; $response['message']='Invalid request'; } echo json_encode($response); |
- Thats it for the server side coding. Now lets move in Android Studio again to finish our app.
Making Send Notification Option in App
- The first thing we will do is create a separate class for storing all the URLs required. So create a class named EndPoints.java and write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package net.simplifiedcoding.firebasecloudmessaging; /** * Created by Belal on 04/11/16. */ public class EndPoints { public static final String URL_REGISTER_DEVICE = "http://192.168.1.102/FcmExample/RegisterDevice.php"; public static final String URL_SEND_SINGLE_PUSH = "http://192.168.1.102/FcmExample/sendSinglePush.php"; public static final String URL_SEND_MULTIPLE_PUSH = "http://192.168.1.102/FcmExample/sendMultiplePush.php"; public static final String URL_FETCH_DEVICES = "http://192.168.1.102/FcmExample/GetRegisteredDevices.php"; } |
- Now we will create a send notification option for our application. So again come inside activity_main.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 33 34 35 36 37 38 | <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="net.simplifiedcoding.firebasecloudmessaging.MainActivity"> <EditText android:layout_above="@+id/buttonRegister" android:hint="Enter email" android:id="@+id/editTextEmail" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:layout_centerVertical="true" android:text="Register Device" android:id="@+id/buttonRegister" android:layout_width="match_parent" android:layout_height="wrap_content" /> <!-- this button is added --> <Button android:text="Send Notification" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/buttonRegister" android:layout_centerHorizontal="true" android:id="@+id/buttonSendNotification" /> </RelativeLayout> |
- We added one more button and this button will take us to another activity from where we can send push notification to devices.
Creating Activity For Sending Push Notification
- Now create another EmptyActivity named ActivitySendPushNotification.
- For this activity we will create the following layout.

- We have a Radio Button group for individual or multiple push option. Then a Spinner to display registered devices. Three EditTexts for title, message and image url.
- For the above layout here is the xml code.
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 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_send_push_notification" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="net.simplifiedcoding.firebasecloudmessaging.ActivitySendPushNotification"> <RadioGroup android:id="@+id/radioGroup" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <RadioButton android:id="@+id/radioButtonSendAll" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Send to All" /> <RadioButton android:id="@+id/radioButtonSendOne" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Send to One" /> </RadioGroup> <Spinner android:id="@+id/spinnerDevices" android:layout_width="match_parent" android:layout_height="wrap_content"></Spinner> <EditText android:id="@+id/editTextTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Enter Message Title" /> <EditText android:id="@+id/editTextMessage" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Enter Message" /> <EditText android:id="@+id/editTextImageUrl" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Enter Image URL (Optional) " /> <Button android:id="@+id/buttonSendPush" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Send Push" /> </LinearLayout> |
- Now the first thing we will do is we will modify the MainActivity.java to open this activity on button click.
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 | package net.simplifiedcoding.firebasecloudmessaging; import android.app.ProgressDialog; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.android.volley.AuthFailureError; import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; import com.android.volley.toolbox.Volley; import org.json.JSONException; import org.json.JSONObject; import java.util.HashMap; import java.util.Map; public class MainActivity extends AppCompatActivity implements View.OnClickListener { //defining views private Button buttonSendPush; private Button buttonRegister; private EditText editTextEmail; private ProgressDialog progressDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //getting views from xml editTextEmail = (EditText) findViewById(R.id.editTextEmail); buttonRegister = (Button) findViewById(R.id.buttonRegister); buttonSendPush = (Button) findViewById(R.id.buttonSendNotification); //adding listener to view buttonRegister.setOnClickListener(this); buttonSendPush.setOnClickListener(this); } //storing token to mysql server private void sendTokenToServer() { progressDialog = new ProgressDialog(this); progressDialog.setMessage("Registering Device..."); progressDialog.show(); final String token = SharedPrefManager.getInstance(this).getDeviceToken(); final String email = editTextEmail.getText().toString(); if (token == null) { progressDialog.dismiss(); Toast.makeText(this, "Token not generated", Toast.LENGTH_LONG).show(); return; } StringRequest stringRequest = new StringRequest(Request.Method.POST, EndPoints.URL_REGISTER_DEVICE, new Response.Listener<String>() { @Override public void onResponse(String response) { progressDialog.dismiss(); try { JSONObject obj = new JSONObject(response); Toast.makeText(MainActivity.this, obj.getString("message"), Toast.LENGTH_LONG).show(); } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { progressDialog.dismiss(); Toast.makeText(MainActivity.this, error.getMessage(), Toast.LENGTH_LONG).show(); } }) { @Override protected Map<String, String> getParams() throws AuthFailureError { Map<String, String> params = new HashMap<>(); params.put("email", email); params.put("token", token); return params; } }; RequestQueue requestQueue = Volley.newRequestQueue(this); requestQueue.add(stringRequest); } @Override public void onClick(View view) { if (view == buttonRegister) { sendTokenToServer(); } //starting send notification activity if(view == buttonSendPush){ startActivity(new Intent(this, ActivitySendPushNotification.class)); } } } |
Creating a Volley Singleton Class
- As we need to perform http request several time that is why, we are defining a singleton pattern for volley to handle network requests.
- Create a class named MyVolley.java and write the following code.
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 | package net.simplifiedcoding.firebasecloudmessaging; import android.content.Context; import android.graphics.Bitmap; import android.support.v4.util.LruCache; import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.toolbox.ImageLoader; import com.android.volley.toolbox.Volley; /** * Created by Belal on 13/10/16. */ public class MyVolley { private static MyVolley mInstance; private RequestQueue mRequestQueue; private static Context mCtx; private MyVolley(Context context) { mCtx = context; mRequestQueue = getRequestQueue(); } public static synchronized MyVolley getInstance(Context context) { if (mInstance == null) { mInstance = new MyVolley(context); } return mInstance; } public RequestQueue getRequestQueue() { if (mRequestQueue == null) { // getApplicationContext() is key, it keeps you from leaking the // Activity or BroadcastReceiver if someone passes one in. mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext()); } return mRequestQueue; } public <T> void addToRequestQueue(Request<T> req) { getRequestQueue().add(req); } } |
- Now we will code the ActivitySendPushNotification.java, so come inside the class.
- First define the views and all the required methods.
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 | package net.simplifiedcoding.firebasecloudmessaging; import android.app.ProgressDialog; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.RadioGroup; import android.widget.Spinner; public class ActivitySendPushNotification extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener, View.OnClickListener { private Button buttonSendPush; private RadioGroup radioGroup; private Spinner spinner; private ProgressDialog progressDialog; private EditText editTextTitle, editTextMessage, editTextImage; private boolean isSendAllChecked; private List<String> devices; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_send_push_notification); radioGroup = (RadioGroup) findViewById(R.id.radioGroup); spinner = (Spinner) findViewById(R.id.spinnerDevices); buttonSendPush = (Button) findViewById(R.id.buttonSendPush); editTextTitle = (EditText) findViewById(R.id.editTextTitle); editTextMessage = (EditText) findViewById(R.id.editTextMessage); editTextImage = (EditText) findViewById(R.id.editTextImageUrl); devices = new ArrayList<>(); radioGroup.setOnCheckedChangeListener(this); buttonSendPush.setOnClickListener(this); loadRegisteredDevices(); } //method to load all the devices from database private void loadRegisteredDevices() { } //this method will send the push //from here we will call sendMultiple() or sendSingle() push method //depending on the selection private void sendPush(){ } private void sendMultiplePush(){ } private void sendSinglePush(){ } @Override public void onCheckedChanged(RadioGroup radioGroup, int i) { switch (radioGroup.getCheckedRadioButtonId()) { case R.id.radioButtonSendAll: isSendAllChecked = true; spinner.setEnabled(false); break; case R.id.radioButtonSendOne: isSendAllChecked = false; spinner.setEnabled(true); break; } } @Override public void onClick(View view) { //calling the method send push on button click sendPush(); } } |
- Now we have to load the registered devices to the spinner. We already have the webservice to fetch devices.
Fetching All Devices
- Write the following codes in the method loadRegisteredDevices()
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 | private void loadRegisteredDevices() { progressDialog = new ProgressDialog(this); progressDialog.setMessage("Fetching Devices..."); progressDialog.show(); StringRequest stringRequest = new StringRequest(Request.Method.GET, EndPoints.URL_FETCH_DEVICES, new Response.Listener<String>() { @Override public void onResponse(String response) { progressDialog.dismiss(); JSONObject obj = null; try { obj = new JSONObject(response); if (!obj.getBoolean("error")) { JSONArray jsonDevices = obj.getJSONArray("devices"); for (int i = 0; i < jsonDevices.length(); i++) { JSONObject d = jsonDevices.getJSONObject(i); devices.add(d.getString("email")); } ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>( ActivitySendPushNotification.this, android.R.layout.simple_spinner_dropdown_item, devices); spinner.setAdapter(arrayAdapter); } } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }) { }; MyVolley.getInstance(this).addToRequestQueue(stringRequest); } |
- If you will run the application now you will see the emails in the spinner.
Sending Push Notification
- Now the last part of this Firebase Cloud Messaging Tutorial and the main thing, sending push notification to the devices.
- So now we will code the remaining methods.
- First inside the method sendPush() write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 | //this method will send the push //from here we will call sendMultiple() or sendSingle() push method //depending on the selection private void sendPush() { if(isSendAllChecked){ sendMultiplePush(); }else{ sendSinglePush(); } } |
Sending to A Single Device
- Write the following code in method sendSinglePush() for sending to a single device that is selected from the spinner.
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 | private void sendSinglePush() { final String title = editTextTitle.getText().toString(); final String message = editTextMessage.getText().toString(); final String image = editTextImage.getText().toString(); final String email = spinner.getSelectedItem().toString(); progressDialog.setMessage("Sending Push"); progressDialog.show(); StringRequest stringRequest = new StringRequest(Request.Method.POST, EndPoints.URL_SEND_SINGLE_PUSH, new Response.Listener<String>() { @Override public void onResponse(String response) { progressDialog.dismiss(); Toast.makeText(ActivitySendPushNotification.this, response, Toast.LENGTH_LONG).show(); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }) { @Override protected Map<String, String> getParams() throws AuthFailureError { Map<String, String> params = new HashMap<>(); params.put("title", title); params.put("message", message); if (!TextUtils.isEmpty(image)) params.put("image", image); params.put("email", email); return params; } }; MyVolley.getInstance(this).addToRequestQueue(stringRequest); } |
- Now you can test the application for single push as well.
- Now lest code the last method of this Firebase Cloud Messaging Tutorial which is about sending multiple push notification.
Sending to Multiple Device
- Write the following code for sendMultiplePush().
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 | private void sendMultiplePush() { final String title = editTextTitle.getText().toString(); final String message = editTextMessage.getText().toString(); final String image = editTextImage.getText().toString(); progressDialog.setMessage("Sending Push"); progressDialog.show(); StringRequest stringRequest = new StringRequest(Request.Method.POST, EndPoints.URL_SEND_MULTIPLE_PUSH, new Response.Listener<String>() { @Override public void onResponse(String response) { progressDialog.dismiss(); Toast.makeText(ActivitySendPushNotification.this, response, Toast.LENGTH_LONG).show(); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }) { @Override protected Map<String, String> getParams() throws AuthFailureError { Map<String, String> params = new HashMap<>(); params.put("title", title); params.put("message", message); if (!TextUtils.isEmpty(image)) params.put("image", image); return params; } }; MyVolley.getInstance(this).addToRequestQueue(stringRequest); } |
- Now thats it. You just need multiple emulators now to test the application.
- Bingo! Notifications are working absolutely fine.
- Now if you want the source code of the application you can get it from below.
Firebase Cloud Messaging Source Code
Android Side Source Code
Server Side PHP Code
So it is the end of Firebase Cloud Messaging Tutorial. This is the longest tutorial so far, and if you want to make this Firebase Cloud Messaging Tutorial work, have patience and follow the whole tutorial carefully.And yes if you have some confusions regarding this Firebase Cloud Messaging Tutorial. Lets meet in comment section. Also share this tutorial among your friends. Thank You 🙂

Hi, my name is Belal Khan and I am a Google Developers Expert (GDE) for Android. The passion of teaching made me create this blog. If you are an Android Developer, or you are learning about Android Development, then I can help you a lot with Simplified Coding.
Thank you 🙂
For This TUTORIAL
I Hope This Is Very Helpful…
can you helm me?
in my apk said “token not generate”
Wipe data of your emulator and try again.
Dud This is Really Nice Tutorial…..
But I am Getting following Tpe of Error in My Device
Unauthorized
Unauthorized
Error 401
[]
Please Help Me With this….
How to solved It???????
Reply Me….
I think you are using legacy server key…..instead of using it use server key which you will find in firebase console overview->project settings->cloud messaging…i was also having the same problem but after changing…..it worked….hope it may work in your case also….
Hello ,i found your code so insightful and helpful,am able to send notification from local host but when i connect it to remote remote server,it fails to function as expected,what might be the problem?
Thanks for this tutorial, I’m just working on a project with GSM
Hi, I installed the demo apk and registered sucessfully. I selected push and entered all the details and clicked on push. But i didnt receive any push. Is there anything which I need to setup ?
Thumbs up (Y) I love your tutorials ^^
Hi Belal,
Great Tutorial. But I need you your help. B’coz i’m getting “volley timeout exception” error. I followed all steps as you mention. Please reply ASAP.
Belal!
I’ve followed every step but while testing PHP scripts, I got an error:
Fatal error: Call to undefined method mysqli_stmt::get_result() in DBOperation.php
I’ve searched and tried few options from stackoverflow but nothing really worked for me.
P.S: I’ve uploaded these scripts to Hostgator cPanel.
P.P.S: I’m very beginner in PHP.
Try with your local server.. it seems hostinger doesn’t have the mysql driver having this method
Ola, para mim funcionou assim:
//getting all tokens to send push to all devices
public function getAllTokens(){
// $stmt = $//this->con->prepare(“SELECT token FROM devices”);
// $stmt->execute();
// $result = $stmt->get_result();
$result = $this->con->query(“SELECT token FROM devices”);
$tokens = array();
while($token = $result->fetch_assoc()){
array_push($tokens, $token[‘token’]);
}
return $tokens;
}
//getting a specified token to send push to selected device
public function getTokenByEmail($email){
$stmt = $this->con->query(“SELECT token FROM devices WHERE email = ?”);
//$stmt->bind_param(“s”,$email);
//$stmt->execute();
//result = $stmt->get_result()->fetch_assoc();
return array($stmt[‘token’]);
}
//getting all the registered devices from database
public function getAllDevices(){
$stmt = $this->con->query(“SELECT * FROM devices”);
//$stmt->execute();
//$result = $stmt->get_result();
return $stmt;
}
}
Thanks man…
Thanks for the tutorial its awsome, I would like to tell you one point is that replace Constants.php to Config.php in Dbconnect.php file, it may create problem for some freshers
How to open notifiation message in activity after clicking notification.
and use it as a chat app
Check the chat application using gcm tutorial I posted earlier..
please help me i registered devise to database succesfully but when i want to send notification i find this problem
E/Volley: [13428] BasicNetwork.performRequest: Unexpected response code 500 for http://www.mabilisim.com/admfir/GetRegisteredDevices.php
Something wrong with your PHP Scripts or may be it is the problem with your hosting.. So cross check your server side codes..
protected Map getParams() throws AuthFailureError {
Map params = new HashMap();
params.put(“title”, title);
params.put(“message”, message);
if (!TextUtils.isEmpty(image))
params.put(“image”, image);
params.put(“email”, email);
return params;
}
error in MAP , it said params incompatble return type in volly.request,or import class of map
Curl failed: Failed connect to fcm.googleapis.com:443; Operation now in progress, I tried many times but it gives me the same error
Thanks for the tutorial….
Will you please help me to get notification when is no longer is background or in foreground state…
Thanks in advance.
hi there thank you for the article ….Please can you help me i have more than 1000 token so i want to push my notification to my user but how can i do that using php i have been doing trying but bacthing theses users in to 1000 each then send it seems to be a challange really
If the token is more than 1000 then you can use a loop to send notifications..In every turn send notifications to 1000 users
sir,can u tell me how to do that …
When i am making a webservice in local server its working fine but in live i am getting blank response..Can you help me
I’m stuck too, have you got any solution if yes, then could you email me, please? My email Id is viraj07d@gmail.com
Hello. How to send several notifications at one time, when I send a new notification without opening old, it just replaces old notification, not updates it.
Hie, Can you help me i tried to follow your and implement your code, but i am getting the following error
Error:(33, 28) error: cannot find symbol variable SharedPrefManager
hi bro,
i’m yashwanth, i’m new to android.
i followed your code, and i’m getting these output in RegisterDevice.php
{“error”:true,”message”:”Invalid Request…”}
But u r showing something else in screeshot.
can you help me.
can any one help me please
if you used postman for testing like this tutorial, change method from ‘get’ to become ‘post’ at left side address bar.
hi bro,
i’m yashwanth, i’m new to android.
i followed your code, and i’m getting a black spot while registering device on to server
can you help me??
can any one help me please???
How to create this notification Responsive ?? Mean on notification received, i want to response again in Accept or Reject form to that user, from which i received.
can you create chat room activity ? ? Reply fast pls
Thanks alot man, it worked. What if I have application A and Application B. Application A will send notification to Application B and when user clicked the notification, the Application B will be opened.
Heello when i try to send 192.168.1.102:9090/FcmExample/sendSinglePush.php on postman i had
{“multicast_id”:9209621789040171387,”success”:0,”failure”:1,”canonical_ids”:0,”results”:[{“error”:”InvalidRegistration”}]}[]
Pls helpppp !!!!!!!!
even i’m getting the same error, can you reply please
Belal Khan
hi belal! i got this working fine…
Now when a user uninstall the app and again reinstall the app he is not able to get notification…. what will be the solution???
Thank you..
Sir I have two Question . 1) how i will set TTL(time to live) for notification
2) how i will get the Sender id in notification, because after receiving notification i want to send back the notification to that user.
hi, thanks for tutorial. I already follow all that you mentioned in your tutorial and get a response when I try with Postman and the results in accordance with your screenshots, but the problem is the notification did not appear on my android device. can you help…,a little code i’m doing
index.php
$app->post(‘/sendpush’, ‘authenticate’, function() use ($app) {
// check for required params
global $user_id;
verifyRequiredParams(array(‘title’,’message’,’group_id’));
$response = array();
$title = $app->request->post(‘title’);
$data = $app->request->post(‘message’);
$group_id = $app->request->post(‘group_id’);
//getting the token from database object
$db = new DbHandler();
$registration_ids = $db->getAllTokens($group_id, $user_id);
if ($registration_ids) {
$push = new Push($title, $data);
$mPushNotification = $push->getPush();
//var_dump($title);
$fb = new Firebase();
echo $fb->sendMultiple($registration_ids, $mPushNotification);
//var_dump($registration_ids);
echo json_encode($response);
}
echoRespnse(200, $response);
});
DbHandler.php
//getting all tokens to send push to all devices
public function getAllTokens($group_id, $user_id){
$stmt = $this->conn->prepare(“SELECT mst_users.token FROM mst_group INNER JOIN
group_member ON group_member.group_id = mst_group.id
INNER JOIN mst_users ON group_member.user_id = mst_users.id
WHERE mst_group.id = ? AND mst_users.id ?”);
$stmt->bind_param(“ii”, $group_id, $user_id);
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();
$tokens = array();
while($token = $result->fetch_assoc()){
array_push($tokens, $token[‘token’]);
}
return $tokens;
}
push.php
title = $title;
$this->message = $message;
}
//getting the push notification
public function getPush() {
$res = array();
$res[‘data’][‘title’] = $this->title;
$res[‘data’][‘message’] = $this->message;
return $res;
}
}
Can u please help its saying this error.
{“error”:true,”message”:”Device not registered”}
I have try your each step at least 4-5 time but still it issue “token not generated” . i have clear catch , uninstall also make new genymotion emulator but i have not solve problem.
If you are using genymotion then may be the problem is because genymotion emulator don’t have google play services.
Dear Belal
Few Questions Arises To Many Developers including me .Please Have some Solutions for these Such as:
{“multicast_id”:9209621789040171387,”success”:0,”failure”:1,”canonical_ids”:0,”results”:[{“error”:”InvalidRegistration”}]}[]
Alternative For This Instead of local server
Fatal error: Call to undefined method mysqli_stmt::get_result() in DBOperation.php
Did u got any solution for {“multicast_id”:7912757118272451652,”success”:0,”failure”:1,”canonical_ids”:0,”results”:[{“error”:”InvalidRegistration”}]}[]
Plzz Help i also want solution of this…
Thanks for this tutorial.
It helps me so much.
Can u please help its saying this error.
Unauthorized
Unauthorized
Error 401
[]
Fatal error: Call to undefined method mysqli_stmt::get_result() in C:\xampp\htdocs\FcmExample\DbOperation.php on line 71
how to resolve this problem?
its really great tutorial for notification and thanks for sharing this…
Hi SIr,Thank you so much for this wonderful tutorila.I have one question.How to fix ,a registered user again subscribe with the same email id after clear data .He gets the message”Device already registered” but in databse the old token remain same so the device doesnt get push notification.I am stucked with DbOperation file.Please help me to fix this.
Kind Regards,
Madhusudan
Here is my code of DbOperation.php where I am trying to update token when an email id exist.
public function addRegistrationToekn($token,$email){
$stmt = $this->con->prepare(“UPDATE devices SET token=? WHERE email=?”);
$stmt->bind_param(“si”,$token,$email);
$result = $stmt->execute();
$stmt->close();
if($result){
return false;
}
return true;
}
And for this I tried to update RegisterDevice.php
Please help me where I am doing mistakes
registerDevice($email,$token);
$result1=$db->addRegistrationToekn($token,$email);
if($result == 0){
$response[‘error’] = false;
$response[‘message’] = ‘Device registered successfully’;
}elseif($result == 2)
{
if($result1==false)
{
$response[‘error’]=false;
$response[‘message’]=’Device updated with token’;
}
else{$response[‘error’]=true;
$response[‘message’]=’Device updation failed’;
}
}
else{
$response[‘error’]=true;
$response[‘message’]=’Invalid Request…’;
}
}
echo json_encode($response);
what is urlecode for sedSinglePush.php
like http://abc.com/FcmExample/sendsiglePush.php?email=abc@gmail.com&title=hello&message=Good work
but this is not working
hey Belal evrything is working Fine
But the only thing which is not working is while sending the message !!
When we click on Send Push Button we get this error!!
{“multicast_id”:9209621789040171387,”success”:0,”failure”:1,”canonical_ids”:0,”results”:[{“error”:”InvalidRegistration”}]}[]
And many of us are facing the same error!!
Would be great if you tel us how to resolve this 🙂
Waiting!!
i am also getting same error, please help me to rersolve this.Thanks in advance
Hi Sir ,Thank you for this tutorila. I have a doubt.
If I send a notification and the application is starting or in the background, everything works correctly, but if the application is stopped / killer no notifications arrive. Whatsapp or gmail do it and I do not know how do it!!!
Thank u so much for this tutorial …
GEtting this error,
Error:(22, 26) error: cannot access AbstractSafeParcelable
class file for com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable not found
pls help
Can someone please scale this to have users (profiles)
and login/register/forgot password
messages stored in the database too
would be amazing
$fields = array(
‘registration_ids’ => $registration_ids,
‘data’ => $message,
);
this should be like below
$fields = array(
‘to’ => $registration_ids,
‘data’ => $message,
);
I love this tutorial but you server code fails to address very critical concerns.
1. the device token can change after app install I believe. What happens when you try to register the new token and email is you get user already registered and you are left with an old token that doesn’t work.
2. what if the user logs in using two devices or abandoned his old device for a new one? Using the same code you will get the same error that user already registered even in a different device.
if you have time in your schedule you can check and try to update server-side code, please.
Cheeers.
Response for “send multiple push” method is to add header content length after adding content length using getheader(), response is “missing parameter” from scripting files, please provide solution for it.Values are sent correctly from app , don’t know where they are missing.
i am also getting same error but for single notification. How did you resolved that ?
Ajay Have you resolved that issue?
Connected Succsfully…{“multicast_id”:7300338169869987506,”success”:0,”failure”:1,”canonical_ids”:0,”results”:[{“error”:”InvalidRegistration”}]}[]
I need to implement the same tutorial in eclipse IDE . Is it possible ? If yes , please mention the things i want to do manually . (For example : i have created jar files and put it in the libs folder , which really worked and cleared errors . How ever the token is not generating. Do i want to do anything with the google-services.json file , which i downloaded from the firebase console of my project)
Eu fiz o exemplo e funcionaol até a parte de salvar no banco. Mas quando seleciono a spinner não funcional! Alguém consiguio fazer? Selecionar a spinner e mostrar os e-mails? Tô fazendo usando servidor externo da Hosting!
Hi Belal
How to slove this problem
{“multicast_id”:9209621789040171387,”success”:0,”failure”:1,”canonical_ids”:0,”results”:[{“error”:”InvalidRegistration”}]}[] .
This means You used an email that doesn’t exist in the database.
Help i have an error while using postman:
{“error”:true,”message”:”Parameters missing”}
Means you no data was received by the server. Change POSTMAN to POST don’t use GET or ensure you’ve posted data through the URL
thanks
Can u please help its saying this error.
Unauthorized
Unauthorized
Error 401
[]
in Server Page And Following Show in Device
Unauthorized
Unauthorized
Error 401
[]
How to Fixed It…..Please Help Me….
I always get HTTP 500 error when i get results from GetRegisteredDevices.php
(But I can add a device to DB)
I couldn’t fix it. It’s an online server, not local and i will use this online.
How can i do now? Thanks.
Check the error_log on the folder that your server side code resides.
Dear Sir,
(1) Notification using FCM,php error but notification not display on device/emulator
(2) instead of mysqli_xx() can i use only mysql_xx() because i used to wamp
I want Google MAP on android studio, if possible please upload tutorial step by step
thanx for tutorial can u please tell how to vibrate mobile on push notification any idea…
“notification”:{
“sound”:”default”
}
Hi Belal Khan a lot of thanks!!!! you just saved my day….but there is one request can you please upload the video tutorial of this entire project as i am a fresher i want to understand it indepth (i.e. specially php part as i am completely new to it) i’ve implemented it but still ….it’s a humble request…and thank you once again….
dear sir,
is it possible make the message stored/saved in database like mysql or firebase database?
thank you
Hey Dear! this tutorial is awesome but php file not working on live its only working on local server. You used old php function please can you update these functions.
There is problem in dbOperation class. I am unable to fetch all email only register is working on live server. My Live server has no MySQLnd driver.
Please can anyone help am waiting for good response. Thank You
Use this way to fetch tokens
public function getAllTokens(){
$stmt = $this->con->prepare(“SELECT token FROM devices”);
$stmt->execute();
$stmt->bind_result($token);
$tokens = array();
while($stmt->fetch()){
array_push($tokens, $token);
}
return $tokens;
}
this is also not working dear..
now devices are not registering and fetching . latest errors
[21-Mar-2017 06:47:31 America/Chicago] PHP Parse error: syntax error, unexpected ‘token’ (T_STRING) in /home/comsolne/public_html/FcmExample/DbOperation.php on line 58
[21-Mar-2017 06:47:35 America/Chicago] PHP Parse error: syntax error, unexpected ‘token’ (T_STRING) in /home/comsolne/public_html/FcmExample/DbOperation.php on line 58
please can you mail me all latest php code which can work on live server my email address is
zeeshanarif34@gmail.com
Hi zeeshanarif
Are you solved this problem.If you solved kindly reply to mail hameed.1483@gmail.com
no dear i didn’t solve till now.. i am trying to solve but did’nt find any solution. I am also waiting for @Belal Khan responce..
Hey guys just send me an email with your DbOperations page. It indicates there’s an unwanted character present in your code. swagzmania@gmail.com
Assalamualaikum Belal, i have a problem like this ..
Fatal error: Call to undefined method mysqli_stmt::get_result() in C:\xampp\htdocs\FcmExample\DbOperation.php on line 50
how to resolve this problem?
{“multicast_id”:9209621789040171387,”success”:0,”failure”:1,”canonical_ids”:0,”results”:[{“error”:”InvalidRegistration”}]}[]
For the users who are having this issues please use the correct email which you specified on the register device section of the app and you will successfully send the message, however I cant go on further because I’m having a crash right afterwards with myfirebaseinstance….
Lol never mind I fixed the code it was a simple method error in java class….
What change have you made?
You are awesome.
You save my day..
Thank you so much for code and guidance..
Thanks
please i need te chat rooom for see the message
thank you. you made my day better
hey Belal .. I want to send a notification to a single device when a new a new record is added to the database how can I achieve this?
there is two radio button one for send to many and other for send to one.. now go to spinner and select desire email where you want to send.
Hey Sara. You could use a mySQL trigger for this. You could also tell your android device to call another URL i.e for sending the Push notification once it has stored the new record in your database. You could also introduce curl in your php code for inserting a record into the database such that after storing the record, it also sends a push notification
Thank you so much for the detailed and clear tutorial, I managed to make Firebase app with this where users are able to go into a chat room and send messages. BUT i have a problem where when a user press send to send a message, all users who’s got the app receive the notification even if there not in the chat room. can you please show us or make a tutorial on how to send push notification to some certain numbers of users who has commented in a chat room? please am other people might need this as well thanks.
In my real device, i get the refresh token successfully then after a moment it disappears, and the logs never stop scrolling, hence the token never gets stored to server…i don’t know why and how this is happening. On both genymotion and android studio emulator everything works as expected. please help?
I am getting Mismatch sender Id error. Please help me to solve this issue.
{“multicast_id”:6245778731055199638,”success”:0,”failure”:1,”canonical_ids”:0,”results”:[{“error”:”MismatchSenderId”}]}[]
I am getting this error.Please help me to solve this error.
{“multicast_id”:8388467262669440974,”success”:0,”failure”:1,”canonical_ids”:0,”results”:[{“error”:”MismatchSenderId”}]}[]
Please solve this Error.
{“multicast_id”:7300338169869987506,”success”:0,”failure”:1,”canonical_ids”:0,”results”:[{“error”:”InvalidRegistration”}]}[]
If i send it all devices it also send push to sender, how to disable sending to sender? please…
Add a parameter to your messages you’re sending to firebase with the username. Check when a message comes through for the authorizing username and if they are similar, don’t display. If they are not similar, send the data to display the message and remove the username part from your string.
I am getting this error.
“registration_ids” field is not a JSON array
please help me to solve it.
Can you please write also the php code to send to topic?
Hi Belal!
I am not getting all the registered devices please share the php code of this
Hey dude.. I don’t have a static IP address. What should I do??
Thanks belal for this tutorial….it’s too much easy to understand…hope you’ll adding tutorial’s like this in near future…for developer like us…..once again thanks a lot….
sendUserActionEvent() mView == null
I getting this error when clicked register device. Could you please help me ?
Inactivity, disconnecting from the service
Hello, I also get this error. Could you please help me why I am getting this ?
{“multicast_id”:9209621789040171387,”success”:0,”failure”:1,”canonical_ids”:0,”results”:[{“error”:”InvalidRegistration”}]}[]
Your Hosting does’nt have MYSQLND. try with https://in.000webhost.com/ it is free hosting
Did you get any resuts even im facing same issue..
Thank you
did u find the solution i m also facing the same problem.. Please Help
I have successfully done folloed your tutorial. But if I do build apk and install to my phone, this app can’t register token, can’t send notification and can’t get any notification. ???
Does this just work on emulator or also on my phone?
Because i can’t set the token into the textview on my phone…
However Logcat says that the file isn’t found in data/users/0/MYAPLLICATIONNAME/ etc.
Can you give me a short hint what I’m doing wrong?
Thanks alot.
how can i get the notification when the app is closed or not running?
Hello Mr belal do you know how to make an android application that automatically receives notification when it checks in mysql database and finds that there is a new entry in the table..
{“error”:true,”message”:”Invalid Request…”}
how to deal with this error
Hello, i am getting the following error in
Failed to connect to MySQL: Unknown database ‘fcm'{“error”:true,”message”:”Parameters missing”}
Please Help !
Thanks for this tutorial .I have error, Token not generated. I uninstalled application and tried again but still error did not solve . please help me how to solve it
Try with different emulators . it worked for me
It is sending the message . But the message is not being received on the device to which the message has to be sent.
The toast when Send to one device is showing : {“multicast_id”: 789070…, “success”:1 , “failure”: 0 ,”canonical_ids”:0,”results”:[{“message_id”:”2398043094….”}]}[]
Very nice Tutorial.. Thank you so much
I have on error , when i click on send push button that time throws error on my application :-
The request was missing an Authentification Key (FCM Token). Please, refer to section "Authentification" of the FCM documentation, at https://firebase.google.com/docs/cloud-messaging/server.
The request was missing an Authentification Key (FCM Token). Please, refer to section "Authentification" of the FCM documentation, at https://firebase.google.com/docs/cloud-messaging/server.
Error 401
error in console –
W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
E/EGL_emulation: tid 3553: eglSurfaceAttrib(1174): error 0x3009 (EGL_BAD_MATCH)
W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0x977c6640, error=EGL_BAD_MATCH
please help sir, how to solve this error and explain in brief how to modify my answer….
Thank you so much…………………….
Thanks for your tutorial..But My App is not receiving push notification if i remove app from all task(task manager)..Please help me how to solve it
Hi Sir ,Thank you for this tutorial. I have a doubt.
by giving image url, image is not showing can you help me
Hi
Thanks for your useful tutorial.
I implement that it is working , i can get notification in some devices but i can not get in some other devices. POST send get back success but notification not received.
this problem lost more than 1 week of my time.
please help me.
First, Thank you for this tutorial.
But i face issue when app is in foreground i am not able to receive notification, i receive application when app in background.
Thanks for your help.