How to integrate Push Notifications using Firebase Cloud Messaging (FCM)

Hey guys! Today, I am going to tell you about how do you integrate Firebase Cloud Messaging in your android app. As we all know, Google has acquired Firebase and released a couple of free products for developers like Firebase Notifications, Firebase Invites, Firebase Analytics, Firebase Authentication etc. You can check on their website. Its pretty awesome.

View Project on Github

Setting up Firebase project

  1. Login with your Google account and go to Firebase Console.
  2. Click on Create Project. Enter your project name and country.
    Screenshot at Jul 02 12-00-12
  3. And Done, your Firebase project has been created and you have been redirected to the dashboard. There are lot of things there. You can integrate a lot of things from this one firebase project into your app.
  4. Click on Notifications on the left tab and you will see a screen to add your app (Android or iOS). I am going to select Android.
  5. It now shows to complete three steps. Step one is to enter your package name and SHA1 fingerprint. Enter your android application package name and run below commands to generate SHA1 fingerprint:
    On Mac:
    keytool -exportcert -list -v \
    -alias androiddebugkey -keystore ~/.android/debug.keystore

    On Windows:

    keytool -exportcert -list -v \
    -alias androiddebugkey -keystore %USERPROFILE%\.android\debug.keystore

    Again, as you see, this is using default key store provided by android studio. For production purposes, you need to use your release key store.
    Screenshot at Jun 25 18-27-50
    Screenshot at Jul 02 12-12-54

  6. Click on Add app. Step two is download and copy your google-services.json file and copy into app directory of your Android project. This json file is a configuration file for your firebase project. Your project needs a plugin to read it.
    Screenshot at Jul 02 12-40-21
  7. Open your root folder build.gradle file and include this dependency:
    classpath 'com.google.gms:google-services:3.0.0'

    Your root folder build.gradle should look like this:

    // Top-level build file where you can add configuration options common to all sub-projects/modules.
    
    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:2.1.2'
            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
        }
    }
    
    allprojects {
        repositories {
            jcenter()
        }
    }
    
    task clean(type: Delete) {
        delete rootProject.buildDir
    }
  8. Then, open app level build.gradle file, add this dependency:
    dependencies {
      // ...
     
        compile 'com.google.firebase:firebase-messaging:9.2.0'
     }
    Also, apply above plugin at the bottom of the file:
    apply plugin: 'com.google.gms.google-services'

    Your app level build.gradle should look like this:

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 24
        buildToolsVersion "23.0.3"
    
        defaultConfig {
            applicationId "vi.firebasenotifcations"
            minSdkVersion 15
            targetSdkVersion 23
            versionCode 1
            versionName "1.0"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        testCompile 'junit:junit:4.12'
        compile 'com.android.support:appcompat-v7:24.0.0'
        compile 'com.google.firebase:firebase-messaging:9.2.0'
    }
    
    // ADD THIS AT THE BOTTOM
    apply plugin: 'com.google.gms.google-services'

    Note: If you are getting error “Failed to resolve com.google.firebase:firebase-messaging:9.2.0”, then you need to update your Google Play services version (as of now 31) and Google Repository version (as of now 29) to the latest or else, you can replace 9.2.0 to 9.0.2 (not recommended).
    Screenshot at Jul 02 12-58-40

    Integrate Firebase Cloud Messaging

    Firebase provides quick-start code for getting familiar with their products. You can always checkout their Github repository to get the latest updates.

  9. Create a service class FCMMessagingService that will handle all the notifications payload that you will receive. Basically, this class is a receiver of all notification messages.FCMMessagingService.java
    
    public class FCMMessagingService extends FirebaseMessagingService {
    
        private static final String TAG = "FCMMessagingService";
    
        /**
         * Called when message is received.
         *
         * @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
         */
    
        @Override
        public void onMessageReceived(RemoteMessage remoteMessage) {
            // If the application is in the foreground handle both data and notification messages here.
            // Also if you intend on generating your own notifications as a result of a received FCM
            // message, here is where that should be initiated. See sendNotification method below.
            Log.d(TAG, "From: " + remoteMessage.getFrom());
            Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
            handleMessage(remoteMessage);
        }
    
        private void handleMessage(RemoteMessage remoteMessage) {
            sendNotification(remoteMessage.getNotification().getTitle(),remoteMessage.getNotification().getBody());
        }
    
    
        /**
         * Create and show a simple notification containing the received FCM message.
         *
         * @param messageBody FCM message body received.
         */
        private void sendNotification(String title, String messageBody) {
            Intent intent = new Intent(this, MainActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                    PendingIntent.FLAG_ONE_SHOT);
    
            Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
            NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentTitle(title)
                    .setContentText(messageBody)
                    .setAutoCancel(true)
                    .setSound(defaultSoundUri)
                    .setContentIntent(pendingIntent);
    
            NotificationManager notificationManager =
                    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    
            notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
        }
    }
    

    In onMessageReceived() method, you will receive your notification payload in the form of RemoteMessage object.
    Various methods of RemoteMessage:
    getFrom(): Which is used to test whether the message is a topic message. The string returned is the topic used to send the message.
    getNotification().getTitle(): which is used to get notification title.
    getNotification().getBody(): which is used to get notification message.
    getData(): This method is mostly used as It is map containing key value pair of data sent through notification.Screenshot at Jul 02 15-48-36

  10. Create another service class FCMInstanceIdService that will handle registration of device and gets you a token which you can store in database on your server.

    FCMInstanceIdService.java
    public class FCMInstanceIDService extends FirebaseInstanceIdService {
    
        private static final String TAG = "FCMInstanceIDService";
    
        /**
         * Called if InstanceID token is updated. This may occur if the security of
         * the previous token had been compromised. Note that this is called when the InstanceID token
         * is initially generated so this is where you would retrieve the token.
         */
    
        @Override
        public void onTokenRefresh() {
            // Get updated InstanceID token.
            String refreshedToken = FirebaseInstanceId.getInstance().getToken();
            Log.d(TAG, "Refreshed token: " + refreshedToken);
    
    
            sendRegistrationToServer(refreshedToken);
        }
    
        /**
         * Persist token to third-party servers.
         *
         * Modify this method to associate the user's FCM InstanceID token with any server-side account
         * maintained by your application.
         *
         * @param token The new token.
         */
        private void sendRegistrationToServer(String token) {
            // Add custom implementation, as needed.
        }
    }

    Here, In sendRegistrationToServer() method, you can fire an network call to store token on your database. Note that You should always put a logic that If currently saved registration token is refreshed or changed, you should update the token on your database too.

  11. Then, Last step is to include these services in the manifest file. Your manifest file should look like this:
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="vi.firebasenotifcations">
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            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>
    
            <!--Firebase start-->
            <service
                android:name=".FCMMessagingService">
                <intent-filter>
                    <action android:name="com.google.firebase.MESSAGING_EVENT"/>
                </intent-filter>
            </service>
    
            <service
                android:name=".FCMInstanceIDService">
                <intent-filter>
                    <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
                </intent-filter>
            </service>
            <!-- Firebase end-->
        </application>
    
    </manifest>
    
  12. And Done, all things are set. Just build and run. You can test your implementation by going to firebase console, then go to notification section. Then, Click on Send your first message. It will open a form with a lot of inputScreenshot at Jul 02 15-59-44 Screenshot at Jul 02 16-00-17
    Click on Send Message. You should receive a notification on your device. (ignore second notification).
    Screenshot at Jul 02 16-02-21
    So, If there’s any problem. Mail me or just comment down below. Firebase is awesome product by Google. You should try it right now. Next, I will show how to integrate Firebase invites in your app.