How to Push Notification in Android using Firebase Cloud Messaging?

Firebase Cloud Messaging is a real-time solution for sending notifications to client apps without any kind of charges. FCM can reliably transfer notifications of up to 4Kb of payload. In this article, a sample app showing how this service can be availed is developed. Though FCM also allows sending out notifications using an app server, here Firebase admin SDK is used. Follow the complete article to implement an example of FCM.
push-notofication

Approach

Step 1: Add Firebase to the project and the required permissions

To add firebase to the project please refer Adding Firebase to Android App. The following is the gist of adding FCM to the app. Go to Tools -> Firebase -> Cloud Messaging -> Set up Firebase Cloud Messaging

  1. Connect your app to Firebase: Complete the three steps of creating a Firebase project.
  2. Add FCM to the app.

Since receiving FCM notifications require the use of the internet, add the following permission to the AndroidManifest.xml file anywhere between the </application> and </manifest> tags.

<uses-permission android:name=”android.permission.INTERNET” />



Note:
compile ‘…..’
this format for setting up dependencies is deprecated, instead, use
implementation ‘…..’
to declare dependencies in case of any discrepancy.

Step 2: Add all the required drawable resources

Here, the following icon has been used as a drawable resource. Add all the drawable resources to the drawable resource folder.
gfg icon

Step 3: Customize the activity_main.xml

Here, the home screen of the app just holds a TextView, however, one can customize the app as per the requirements.

activity_main.xml

filter_none

edit
close

play_arrow

link
brightness_4
code

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
  
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="20dp"
        android:text="Welcome to GeeksforGeeks!"
        android:textColor="#006600"
        android:textSize="40dp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
  
</androidx.constraintlayout.widget.ConstraintLayout>

chevron_right


Step 4: Create the Notification Layout

Create a new notification.xml file to design the layout for the Notification. This step is stated as optional because the content and title too can be directly set too without customizing the appearance of the notification, however here the notification has the following layout. Here the Notification consists of:



  1. An ImageView
  2. A TextView for the Title
  3. A TextView for the Message.

notification.xml

filter_none

edit
close

play_arrow

link
brightness_4
code

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    android:id="@+id/linear_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="20dp">
  
    <!-- Parent Layout of ImageView -->
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
  
        <!--Image to be displayed beside the notification text-->
        <ImageView
            android:id="@+id/icon"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:padding="5dp"
            android:src="@drawable/gfg" />
    </LinearLayout>
  
    <!-- Parent layout for holding the Title and the Body-->
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical"
        android:padding="5dp">
  
        <!-- TextView for Title -->
        <TextView
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Title"
            android:textColor="#000"
            android:textStyle="bold" />
  
        <!-- TextView for Body -->
        <TextView
            android:id="@+id/message"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Message"
            android:textSize="15sp" />
  
    </LinearLayout>
  
</LinearLayout>

chevron_right


Step 5: Create the message receiving class

Create a FirebaseMessageReceiver.java class. This class extends the FirebaseMessagingService. Add the following code to the AndroidManifest.xml file between the </activity> and </application> tags to recognise the FirebaseMessagingService as a service in the app.

AndroidManifest.xml

filter_none

edit
close

play_arrow

link
brightness_4
code

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

chevron_right


Here the attribute ‘android: name’ is assigned the name of the Java file that extends the FirebaseMessagingService so pass the class name FirebaseMessageReceiver. This service is required to do any type of message handling beyond just receiving notifications, while the client app runs in the background. It also serves the purpose of receiving notifications in foreground apps and much more. The complete AndroidManifest.xml file is given below.

AndroidManifest.xml

filter_none

edit
close

play_arrow

link
brightness_4
code

   
<?xml version="1.0" encoding="utf-8"?>
<manifest 
    package="com.example.pushnotification">
  
    <uses-permission android:name="android.permission.INTERNET" />
  
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
  
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
          
        <service android:name=".FirebaseMessageReceiver">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
          
    </application>
  
</manifest>

chevron_right


Step 6: Working with FirebaseMessageReceiver.java class

FirebaseMessageReceiver.java class overrides the onMessageReceived() method to handle 2 events:

  1. If Notification contains any data payload, i.e it is received from the app server.
  2. If Notification contains any notification payload, i.e. it is sent via the Firebase Admin SDK.

This method takes RemoteMessage as a parameter. RemoteMessage is a class that extends Object Class and implements Parcelable interface. It is nothing but the object of the message passed using FCM. The above method then calls a user-defined method showNotification() which in turn accepts two parameters. A detailed explanation is provided via comments in the code itself.  A notification channel is required for Notifications in Android Versions greater than Oreo.

In this example, since a customized notification is designed, a method getCustomDesign() is defined and called to set the resources accordingly. This method sets the custom layout for the display of the notification received. Assuming that only title and body are received from the notification, it appropriately maps the TextViews according to the IDs and sets the image resource for the notification. The complete code for this file is given below.



FirebaseMessageReceiver.java

filter_none

edit
close

play_arrow

link
brightness_4
code

package com.example.fcmnotfication_gfg;
  
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.widget.RemoteViews;
  
import androidx.core.app.NotificationCompat;
  
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
  
public class FirebaseMessageReceiver
        extends FirebaseMessagingService {
  
    // Override onMessageReceived() method to extract the
    // title and
    // body from the message passed in FCM
    @Override
    public void
    onMessageReceived(RemoteMessage remoteMessage) {
        // First case when notifications are received via
        // data event
        // Here, 'title' and 'message' are the assumed names
        // of JSON
        // attributes. Since here we do not have any data
        // payload, This section is commented out. It is
        // here only for reference purposes.
        /*if(remoteMessage.getData().size()>0){
            showNotification(remoteMessage.getData().get("title"),
                          remoteMessage.getData().get("message"));
        }*/
  
        // Second case when notification payload is
        // received.
        if (remoteMessage.getNotification() != null) {
            // Since the notification is received directly from
            // FCM, the title and the body can be fetched
            // directly as below.
            showNotification(
                    remoteMessage.getNotification().getTitle(),
                    remoteMessage.getNotification().getBody());
        }
    }
  
    // Method to get the custom Design for the display of
    // notification.
    private RemoteViews getCustomDesign(String title,
                                        String message) {
        RemoteViews remoteViews = new RemoteViews(
                getApplicationContext().getPackageName(),
                R.layout.notification);
        remoteViews.setTextViewText(R.id.title, title);
        remoteViews.setTextViewText(R.id.message, message);
        remoteViews.setImageViewResource(R.id.icon,
                R.drawable.gfg);
        return remoteViews;
    }
  
    // Method to display the notifications
    public void showNotification(String title,
                                 String message) {
        // Pass the intent to switch to the MainActivity
        Intent intent
                = new Intent(this, MainActivity.class);
        // Assign channel ID
        String channel_id = "notification_channel";
        // Here FLAG_ACTIVITY_CLEAR_TOP flag is set to clear
        // the activities present in the activity stack,
        // on the top of the Activity that is to be launched
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        // Pass the intent to PendingIntent to start the
        // next Activity
        PendingIntent pendingIntent
                = PendingIntent.getActivity(
                this, 0, intent,
                PendingIntent.FLAG_ONE_SHOT);
  
        // Create a Builder object using NotificationCompat
        // class. This will allow control over all the flags
        NotificationCompat.Builder builder
                = new NotificationCompat
                .Builder(getApplicationContext(),
                channel_id)
                .setSmallIcon(R.drawable.gfg)
                .setAutoCancel(true)
                .setVibrate(new long[]{1000, 1000, 1000,
                        1000, 1000})
                .setOnlyAlertOnce(true)
                .setContentIntent(pendingIntent);
  
        // A customized design for the notification can be
        // set only for Android versions 4.1 and above. Thus
        // condition for the same is checked here.
        if (Build.VERSION.SDK_INT
                >= Build.VERSION_CODES.JELLY_BEAN) {
            builder = builder.setContent(
                    getCustomDesign(title, message));
        } // If Android Version is lower than Jelly Beans,
        // customized layout cannot be used and thus the
        // layout is set as follows
        else {
            builder = builder.setContentTitle(title)
                    .setContentText(message)
                    .setSmallIcon(R.drawable.gfg);
        }
        // Create an object of NotificationManager class to
        // notify the
        // user of events that happen in the background.
        NotificationManager notificationManager
                = (NotificationManager) getSystemService(
                Context.NOTIFICATION_SERVICE);
        // Check if the Android Version is greater than Oreo
        if (Build.VERSION.SDK_INT
                >= Build.VERSION_CODES.O) {
            NotificationChannel notificationChannel
                    = new NotificationChannel(
                    channel_id, "web_app",
                    NotificationManager.IMPORTANCE_HIGH);
            notificationManager.createNotificationChannel(
                    notificationChannel);
        }
  
        notificationManager.notify(0, builder.build());
    }
}

chevron_right


Note: The notification when clicked will always redirect to the launcher activity of the app when the app is in the background and to the activity passed in the intent if it is in the foreground. To redirect the user always to some other activity than the launcher, you’ll have to send data payload using a server app, sending messaging using Firebase SDK does not support this.

Step 7: Complete the MainActivity.java file

Since here nothing much is presented in the activity_main.xml, the MainActivity file does not need any additional code.

MainActivity.java

filter_none

edit
close

play_arrow

link
brightness_4
code

package com.example.fcmnotfication_gfg;
  
import androidx.appcompat.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);
    }
}

chevron_right


Now run the app on your emulator or in your mobile device.

Step 8: Send the notification using FCM

  • Go to Firebase console and choose the appropriate project.
  • Choose Cloud Messaging.
    FCM

  • Choose Send your First Message. The following window pops up. Fill out the details. While the text field is compulsory, rest all is optional. One can also add an image using a link or upload it, however uploading an image cost additional storage charges.
    FCM
  • In the target section, choose the app domain.
    FCM
  • One can either send out the notification now or schedule it for some time in the future.
    FCM
  • Rest all the other fields are optional and can be left empty. Click on Review and then Publish.

Output: Run on Emulator

Attention reader! Don’t stop learning now. Get hold of all the important Java and Collections concepts with the Fundamentals of Java and Java Collections Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.


Article Tags :
Practice Tags :


1


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.