If u have followed our Previous blog (Send Push Notification to Android and IOS APP [Part 1]), you will be understanding how Restful API implementation for Push Notification was done using FCM and LARAVEL/PHP .Android and iOS app
Firebase Cloud Messaging implementation for Android
Push notifications are apparently an essential thing in Android Application. It helps us gaining user retention, increasing active user, etc. To send a push notification to all our app users, we can use Firebase Cloud Messaging. We can send some promotional as well as regular information using Firebase Cloud Messaging (or FCM) very quickly.
What is Firebase Cloud Messaging?
Firebase Cloud Messaging (FCM) is a cross-platform messaging solution that lets you reliably deliver messages at no cost.
So it is free and at the same time easy to use.
Message Types
Before moving ahead in the post let’s first understand the types of message that can be sent using FCM.
- Notification Message: This type of message is automatically displayed to end user. In this kind of message, we have a predefined set of key-value pairs. We also have a data payload by using it we can set the custom key-value pairs as well.
- Data message: Default does not display this type of message to the end user. To show it we need to add some coding. This message contains only custom key-value pairs.
Integrating Firebase Cloud Messaging
I hope the above information gave you good overview of firebase features and the options they are providing. Now we’ll create a simple app that receives firebase messages.
- First thing you need to do is go to https://firebase.google.com/ and make an account to gain access to their console. After you gain access to the console you can start by creating your first project.
- Give the package name of your project (mine is com.example.ahextech.ahexpushsample) in which you are going to integrate the Firebase. Here the google-services.json file will be downloaded when you press add app button.
- Create a new project in Android Studio from File ⇒ New Project. While filling the project details, use the same package name which you gave in firebase console. In my case I am using same com.example.ahextech.ahexpushsample.
- Paste the google-services.json file to your project’s app folder. This step is very important as your project won’t build without this file.
- Now open the build.gradle located in project’s home directory and add firebase dependency.
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.google.gms:google-services:3.0.0'
// NOTE: Do not place your application dependencies here; they
belong
// in the individual module build.gradle files
}
- Open app/build.gradle and add firebase messaging dependency. At the very bottom of the file, add apply plugin: ‘com.google.gms.google-services’
app/build.gradle :
dependencies {
compile 'com.google.firebase:firebase-messaging:10.2.1'
}
apply plugin: 'com.google.gms.google-services'
Firebase Cloud Messaging using FCM Access Token
In this method first, we will generate the access token. Now to get the access token, we create a class that extends FirebaseInstanceIdService. It is a service that we also need to define inside our Manifest file. Now let’s see how we can do this in our project.
Generating Access Token
Create a class named MyFirebaseInstanceIdService in your project, and write the following code.
package com.example.ahextech.ahexpushsample;
import android.util.Log;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
/**
* Created by ahextech on 2/2/18.
*/
public class MyFirebaseInstanceIdService extends FirebaseInstanceIdService {
//this method will be called
//when the token is generated
@Override
public void onTokenRefresh() {
super.onTokenRefresh();
//now we will have the token
String token = FirebaseInstanceId.getInstance().getToken();
//for now we are displaying the token in the log
//copy it as this method is called only when the new token is generated
//and usually new token is only generated when the app is reinstalled or the data is cleared
Log.d("FCM_TOKEN", token);
}
}
- As this class is a service, we need to define it in AndroidManifest.xml as well.
So open your AndroidManifest.xml file and just before the closing </application> tag add the following code.
<service
android:name=".MyFirebaseInstanceIdService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
- Now run the application, and you will see the token in your logcat.
- Copy this token and save it somewhere. We will use this token to receive notification.
Receiving Messages
To receive the message we need to create a class that will extend FirebaseMessagingService. Here we will override a method onMessageReceived() that is called when we receive a message.This is also a service, so we need to define it in our AndroidManifest.xml
- Create a class named MyFirebaseMessagingService and write the following code.
package com.example.ahextech.ahexpushsample;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
/**
* Created by ahextech on 2/2/18.
*/
public class MyFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
//if the message contains data payload
//It is a map of custom keyvalues
//we can read it easily
if(remoteMessage.getData().size() > 0){
//handle the data message here
}
//getting the title and the body
String title = remoteMessage.getNotification().getTitle();
String body = remoteMessage.getNotification().getBody();
//then here we can use the title and body to build a notification
}
}
- Now again define it using the below XML code in your AndroidManifest.xml just before the closing tag </application>.
<service
android:name=".MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
- But to see the notification we need to build it. So now let’s make the
Notification.
Building Push Notification
- So first we will define some constants for our Notification Channel in a separate class. Create a class named Constants. And write the following code.
package com.example.ahextech.ahexpushsample;
/**
* Created by ahextech on 2/2/18.
*/
public class Constants {
public static final String CHANNEL_ID = "ahex_channel";
public static final String CHANNEL_NAME = "Ahex Push Notification";
public static final String CHANNEL_DESCRIPTION = "www.ahex.co";
}
- Now, create a class named MyNotificationManager and write the following code.
package com.example.ahextech.ahexpushsample;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import static android.content.Context.NOTIFICATION_SERVICE;
/**
* Created by ahextech on 2/2/18.
*/
public class MyNotificationManager {
private Context mCtx;
private static MyNotificationManager mInstance;
private MyNotificationManager(Context context) {
mCtx = context;
}
public static synchronized MyNotificationManager getInstance(Context context) {
if (mInstance == null) {
mInstance = new MyNotificationManager(context);
}
return mInstance;
}
public void displayNotification(String title, String body) {
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(mCtx, Constants.CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle(title)
.setContentText(body);
/*
* Clicking on the notification will take us to this intent
* Right now we are using the MainActivity as this is the only activity we have in our application
* But for your project you can customize it as you want
* */
Intent resultIntent = new Intent(mCtx, MainActivity.class);
/*
* Now we will create a pending intent
* The method getActivity is taking 4 parameters
* All paramters are describing themselves
* 0 is the request code (the second parameter)
* We can detect this code in the activity that will open by this we can get
* Which notification opened the activity
* */
PendingIntent pendingIntent = PendingIntent.getActivity(mCtx, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
/*
* Setting the pending intent to notification builder
* */
mBuilder.setContentIntent(pendingIntent);
NotificationManager mNotifyMgr =
(NotificationManager) mCtx.getSystemService(NOTIFICATION_SERVICE);
/*
* The first parameter is the notification id
* better don't give a literal here (right now we are giving a int literal)
* because using this id we can modify it later
* */
if (mNotifyMgr != null) {
mNotifyMgr.notify(1, mBuilder.build());
}
}
}
Testing a Local Notification
Before moving ahead, we will confirm that the notification is working correctly. For this, we will create a local notification from the app itself.
Open MainActivity.java and write the following code.
package com.example.ahextech.ahexpushsample;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
* If the device is having android oreo we will create a notification channel
* */
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel(Constants.CHANNEL_ID, Constants.CHANNEL_NAME, importance);
mChannel.setDescription(Constants.CHANNEL_DESCRIPTION);
mChannel.enableLights(true);
mChannel.setLightColor(Color.RED);
mChannel.enableVibration(true);
mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
mNotificationManager.createNotificationChannel(mChannel);
}
/*
* Displaying a notification locally
*/
MyNotificationManager.getInstance(this).displayNotification("Welcome to ahex...", "Your first push notification!!");
}
}
- Now try running your application.
- If you see this then awesome, it is working 🙂
Testing Notification from Firebase Console
- Now let’s send a real notification from Firebase Console.
- Open firebase console,Select your project.you’ll able to see the following dashboard
- Click on “GET STARTED” in the Notifications section.Click on “Send Your First Message”.Compose the message like shown in the below image
- And after pressing the Send Message button, you should see your notification message on the app.
- As you can see the notification from firebase console, it is working fine 🙂
Testing notification from Server
- After setting up the server side like we explained in the last tutorial,just send the FCM token of the device to server where you want to see the notification.
Place the following code in your MainActivity.class
package com.example.ahextech.ahexpushsample;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String token = FirebaseInstanceId.getInstance().getToken();
Log.i("fcm-token",""+token);
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("token",token);
} catch (JSONException e) {
e.printStackTrace();
}
sendFcmToken(jsonObject);
}
private void sendFcmToken(JSONObject jsonObject) {
final String mRequestBody = jsonObject.toString();
JsonObjectRequest getRequest = new JsonObjectRequest(Request.Method.POST, "URL_TO_SEND_FCM_TOKEN",null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.i("success-fcm",""+response);
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.i("failure","fcm :",error);
NetworkResponse response = error.networkResponse;
if (response == null) {
String errorMessage = error.getClass().getSimpleName();
} else {
String responseBody = null;
try {
responseBody = new String(error.networkResponse.data, "utf-8");
JSONObject errorObj = new JSONObject(responseBody);
if (errorObj.has("errors")) {
JSONObject obj = errorObj.getJSONObject("errors");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}) {
@Override
public byte[] getBody() {
try {
return mRequestBody == null ? null : mRequestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s",
mRequestBody, "utf-8");
return null;
}
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Authorization", "Bearer "+ token);
params.put("Content-Type","application/json");
params.put("Accept","application/json");
return params;
}
};
getRequest.setRetryPolicy(new DefaultRetryPolicy(0, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
requestQueue.add(getRequest);
}
}
- After successful request for sending FCM token to server,whenever there is a notification posted from server you should see the notification in the device like above.
- So that’s all for this Firebase Cloud Messaging implementation for Android 🙂
Our Services are Laravel Development | Mean Stack Development