MWAN MOBILE

×
mwan_logo
blog-banner

Sending Push Notifications by Using Firebase Cloud Messaging

Application Development 20-Mar-2023

Ever wondered how does your smartphone receive and handle notifications whether be in foreground, background or even killed?

Firebase Cloud Messaging is the tool used to send push notifications to single or a group of devices.

Firebase Cloud Messaging: Firebase Cloud Messaging (FCM) is a cross-platform messaging solution that lets you reliably send messages at no cost.

Using FCM, you can notify a client app that new email or other data is available to sync. You can send notification messages to drive user re-engagement and retention. For use cases such as instant messaging, a message can transfer a payload of up to 4KB to a client app.

Now, as you have got a little idea about FCM, let’s implement it to our Android Studio Project.

  1. Create Firebase Project:

Go to Firebase Console.

Follow the steps to set up the project.

After adding project to the Firebase, add App to the same project.

Enter the project name, package name and SHA-1 key of your Android Studio project.

Follow all the steps to complete the Android App linking with Firebase.

If you face any problem while setting up Firebase on your project you can refer to Add Firebase to your Android Project.

Till now, we have only linked our Android Studio project to Firebase. Now, we proceed with adding Firebase SDK to our project to handle FCM.

Adding Firebase SDK:

Step 1: Add below code into <project>/build.gradle file.

buildscript {
dependencies {
// Add this line
classpath 'com.google.gms:google-services:4.3.2'
}
}

Step 2: Add below code into <project>/<app>/build.gradle.

dependencies {
// Add this line
implementation 'com.google.firebase:firebase-messaging:20.0.0'
}
...
// Add to the bottom of the file
apply plugin: 'com.google.gms.google-services'

Step 3: Now, press Sync Now to sync the changes in gradle.

Since, the formalities are done we are now into some real stuff.

Message Targeting Types:

  1. Single Device: To send FCM message to a single device we need to know the Registration Token of the client app which is generated by Firebase SDK. This token is dynamic and keeps on changing after some time.

How to get current Registration Token?

FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
@Override
public void onComplete(@NonNull Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
Log.w(TAG, "getInstanceId failed",
task.getException());
return;
}

// Get new Instance ID token
String token = task.getResult().getToken();
}
});

2. Group of devices: To send FCM message to a group of devices, all such devices need to subscribe to a common topic named “xyz”.

What is Topic and How to subscribe to it:

Topic is like a mailing list, where devices belonging to a common topic receive a common particular message.

Paste the following code in the Activity to subscribe or unsubscribe.

Subscribe Topic :
FirebaseMessaging.getInstance().subscribeToTopic("TopicName");
Unsubscribe Topic : FirebaseMessaging.getInstance().unsubscribeFromTopic("TopicName");

Retain this for some time as I would now give you glimpse about the type of Firebase Messages.

Types of Firebase Messages:

  1. Notification Payload: Notification messages provide nothing much for customization and have fixed object key values( would get to know about it later ) : “title” and “body”.
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"title":"Portugal vs. Denmark",
"body":"great match!"
}
}
}

2. Data Payload: Data messages have to be handled by the android app. You can add this kind of messages if you want to send some only data along with the notification. It contains custom key value pairs.

{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data":{
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
}
}
}

3. Bothof the above two: A message can also contain both notification and data payload. When these kind of messages are sent, it will be handled in two scenarios depending upon app state (background / foreground). For these message we can use both notification and data keys.

{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"title":"Portugal vs. Denmark",
"body":"great match!"
},
"data" : {
"Nick" : "Mario",
"Room" : "PortugalVSDenmark"
}
}
}

Handling Firebase Messages:

Handling firebase messages is the most crucial part of this whole blog.

Basically, FCM messages are handled differently depending upon the Payload type and the state of the app i.e Foreground, Background or Killed.

Handling Notification Payload:

When app is in background, notification is automatically handled by system and displayed without waking up the app.

But for the foregrounded apps onMessageReceived function is to be called.

How to call onMessageReceived ?

We need to make an service extending FirebaseMessagingService.

Create a Java class MyFirebaseMessagingService extending FirebaseMessagingService.

Declare the activity as service in the App Manifest.

<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>

In MyFirebaseMessagingService for the onMessageReceived function, write the following code:

@Override
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
sendNotification(remoteMessage);
}
private void sendNotification(RemoteMessage remoteMessage) {
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent =PendingIntent.getActivity(this,
m,intent,PendingIntent.FLAG_ONE_SHOT);
String channelId = getString(R.string.default_notification_channel_id);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder;
notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.geekhaven_transparent)
.setContentTitle(remoteMessage.getNotification.getTitle)
.setContentText(remoteMessage.getNotification.getBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(m, notificationBuilder.build());

If you are sending Only Notification Payload then the above method works. But if you want to send only Data Payload or both Data and Notification payload then you need to make a few changes:

Change this

.setContentTitle(remoteMessage.getNotification.getTitle)
.setContentText(remoteMessage.getNotification.getBody)

To

.setContentTitle(remoteMessage.getData.get("your_key1")
.setContentText(remoteMessage.getData.get("your_key2")

If you are using backend server to send notification, then you need to send the Registration Token to server every time it changes.

For that you can look to onNewToken method in MyMessagingService

Here we will only focus on sending Manual Notifications. If you want to know about Backend server implementation you can have a look at Firebase Push Notifications To Android Using NodeJS.

How to choose Payload?

Choosing a right payload depends on your purpose. For example if you want to send only title and body as notification then go with Notification payload.

Otherwise if wish to send more data and even want to customize your Notification by adding actions, you should go with Only Data Payload as its always received in onMessageReceived method irrespective of the state of the app whereas for notification payload you can only customize it when app is in foreground because during background or killed state the notification is handled by system as it directly goes to the system tray.

How to send FCM message manually?

For sending FCM notification payload you can use Firebase Cloud Messaging Tool in firebase console.

Go to Firebase Console — →Grow — →Cloud Messaging

And click on Send your first message.

Then enter the Title and body field.

If you wish to send it to a particular device then click on Send test message and enter the FCM registration token.(Enter the current FCM registration token).

Click Test.

Whoa! you just received your FCM notification.

Or

If you want to send notification using Topic(discussed earlier) click on next ,select the current app and enter the topic name.

Click on publish!.

Whoa, here is the notification!

You may be wondering how could one send Data Payload messages or both Data and Notification payload manually. As of now there is no Firebase tool to send Data Payload messages, so we use POSTMAN.

Download POSTMAN application or add POSTMAN chrome extension.

Sending data message using HTTP protocol with POSTMAN:

Step 1: Select POST . Enter request URL as https://fcm.googleapis.com/fcm/send

Step 2: Add Headers Authorization: key=<server_key>and Content-Type: application/json.

How to get Server_key?

Go to Firebase console — →Project Settings — →Cloud Messaging.

To send the message select Body — →Raw — →JSON(application/json).

{
"to" : "YOUR_FCM_TOKEN",
"data" : {
"body" : "Notification Body",
"title": "Notification Title",
"key_1" : "Value for key_1",
"key_2" : "Value for key_2"
}
}

You can send Notification Payload , Data Payload and even both using POSTMAN service.

{
"to" : "YOUR_FCM_TOKEN",
"notification" : {
"body" : "Body of Your Notification",
"title": "Title of Your Notification"
},
"data" : {
"body" : "Notification Body",
"title": "Notification Title",
"key_1" : "Value for key_1",
"key_2" : "Value for key_2"
}
}

To send Notification to more than one device use registration_ids instead of to or use "to":"topic/topic_name" .

About me

I am a Tech enthusiast and second year B.Tech IT student at IIIT Allahabad who is always curious about Android related stuff!

Source: Medium