Firebase Push Notification – Kotlin Tutorial Series – 3

Hello everyone,

In this post, I am going to explain “How to integrate firebase push notification to android project.” I am going to write all of the code while writing this post and I am going to share the GitHub repository end of the article.

NOTE: Before writing this, I have written the same topic for React-Native. If you want, you can access it from here.

Let’s start from the beginning. What is push notification? Push notifications are clickable application popup messages. It is sent from the application. It is possible to block them completely or some of them. They are application based. It means, every application has a different notification channel and permission. It is possible to get them while you have the application. 

I am going to pass the project creation steps on the android studio side. As a first step, I am going to create a project on the firebase and then I am going to include firebase dependencies to my android project.

I assume you do not know anything about Firebase and I am not going to pass any step. If you are familiar, you can pass some steps.

First of all, I am going to go to the Firebase [Link] website from my browser and click the Get Started button on the opened page. The screenshot is like the following.

Firebase project creation
Screenshot 1: Firebase website.

In the opened page, I am going to click the add project button and I am going to start to create my project on the firebase side. You can see the mentioned button from the following screenshot.

Screenshot 2: Step 2 for create a project in the Firebase.

As a first step for project creation, I am going to give a name for my project. It is just for the firebase console. This will not affect anything in my application.

After clicking the continue button, it offers us to use Google Analytics. For this tutorial, I do not need to use it. Because of this I unchecked this option.

After choosing the google analytics option, I am going to click the Create project button and I am going to complete project creation on the firebase console. It is possible to wait in here for a while. After project creation is completed, I am going to see the left hand side picture as a result.

After clicking the Continue button on the final project creation step, I am going to configure my application with firebase info. After clicking the Continue button, I am going to click the android icon in the redirected page to start the configuration steps. You can see the screenshot on the right hand side.

In the first configuration step, just the package name is required. All other fields are optional. In my project, I also added an app nickname but you can pass this field too. If you do not know where your package name is, you can check the app level build.gradle file. It has to be in defaultConfig section. It is applicationId field.

Screenshot 7: Application registration (configuration) first step.

In the next step, I am going to download the generated google-services.json file and I am going to copy it to my app folder. The screenshot for this step is like below. For this step, the project option can be better. I pointed it out in the screenshot.

In the third step, I am going to add firebase SDK to my project. For this, I am going to update my project level and app level build.gradle files. I have to start from the project level build.gradle file. I am going to add the following codes respectively. Some of them can be in your file. In this situation, you can pass those files.

buildscript -> repositories

google() 

buildscript -> dependencies

classpath 'com.google.gms:google-services:4.3.5'

allprojects -> repositories

google() 

Now, I am going to do the same thing for app level build.gradle file.

Top of the file (plugin apply section.)

apply plugin: 'com.google.gms.google-services'

dependencies

implementation 'com.google.firebase:firebase-messaging:20.1.0'
implementation platform('com.google.firebase:firebase-bom:26.8.0')

After this, I have to sync my project again. It is possible to wait for a while. After completing the synchronization, everything is ready.

After completing the build.gradle modifications, I clicked the continue button on the last step and I returned to the project overview page in Firebase Console. After this step, I am going to return back to my application for a while. I have to create a Notification channel, Notification class and Firebase class on the application side. Let’s start from Notification channel.

Before creating a notification channel, what is the notification channel and why am I creating the notification channel? Every application has to have at least one notification channel for firebase push notification. I am thinking of them like phone lines. If you do not have a line to your application, you can not call it. I am going to continue with a tutorial scenario. When my application starts, I am going to create a subscription via one method. After this, my application can receive the notifications from this channel. If I do not register any channel, then my application can not get any notification. If you try to send notification via any unregistered channel the result is going to be the same as the previous scenario. We can think of this as a main subscription or main pipeline for notification.

private fun createChannel(channelId: String, channelName: String) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val notificationChannel = NotificationChannel(
                channelId,
                channelName,
                NotificationManager.IMPORTANCE_DEFAULT
            ).apply {
                setShowBadge(false)
            }

            notificationChannel.enableLights(true)
            notificationChannel.lightColor = Color.GREEN
            notificationChannel.enableVibration(true)
            notificationChannel.description = getString(R.string.app_name)

            val notificationManager = requireActivity().getSystemService(
                NotificationManager::class.java
            )
            notificationManager.createNotificationChannel(notificationChannel)
        }
    }

To create a channel, I am going to use createChannel function. It is going to be in main activity and It is going to be called in onCreate function. In this function, I create a new channel with some specifications. Like vibration, light color etc.

After the channel creation method, I am going to create a new package. It’s utils. It is going to be on the same level with Main Activity and all of my notification business is going to be in there. The screenshot for this step is like the left hand lane one.

Basically, what am I going to do with those files? I am going to listen to firebase for incoming notification requests via FirebaseUtil.kt. When I get a new notification from firebase, I am going to send it as a Push notification via Notification.kt file.

I am going to start with Notification.kt file. Because in the FirebaseUtil.kt, I need this function. This file is going to have just one extension method for NotificationManager. It is going to send push notifications. It is going to take two parameters. Those are message body and application context. The final NotificationUtil.kt file is like the following.

import android.app.NotificationManager
import android.content.Context
import androidx.core.app.NotificationCompat
import your.application.package.R

private val NOTIFICATION_ID = 0

fun NotificationManager.sendNotification(messageBody: String, applicationContext: Context) {
    val builder = NotificationCompat.Builder(
        applicationContext,
        applicationContext.getString(R.string.general_notification)
    )
        .setSmallIcon(R.drawable.ic_launcher_foreground)
        .setContentTitle(applicationContext.getString(R.string.app_name))
        .setContentText(messageBody)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)

    notify(NOTIFICATION_ID, builder.build())
}

It is possible to define more properties in this (sendNotification) function. In this function, R.string.general_notification is my channel name which is defined in createChannel method. If I try to use a different (unregistered) channel name in here, the application can not receive any notification. This channel information has been registered via the createChannel method before sending any notification.

Now, I nearly completed all of the integration. I have to do the last two things. Firstly, like I said before I am going to complete FirebaseUtil.kt file. I have used the following class in my android learning program. My teacher told me “This class can be used for other android projects too.” With this article, I am going to give the same advice to you. You can use this class in your other projects too.

Basically, what is this class doing? Firstly, when you launch the application, It takes the user’s device token for future push notifications via onNewToken function. You can get any information from the user in this step.

Second function is onMessageReceived. This function receives the firebase notifications from the application side and triggers the push notification send method. (PushNotificationUtil.kt) You can see my completed FirebaseUtil.kt file from below.

import android.app.NotificationManager
import android.util.Log
import androidx.core.content.ContextCompat
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage

class FirebasePushUtil : FirebaseMessagingService() {

    /**
     * Called when message is received.
     *
     * @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
     */
    // [START receive_message]
    override fun onMessageReceived(p0: RemoteMessage) {
        if(p0 != null) {
            // Not getting messages here? See why this may be: https://goo.gl/39bRNJ
            Log.d(TAG, "From: ${p0?.from}")

            // Check if message contains a data payload.
            p0?.data?.let {
                Log.d(TAG, "Message data payload: " + p0.data)
            }

            // Check if message contains a notification payload.
            p0?.notification?.let {
                Log.d(TAG, "Message Notification Body: ${it.body}")
                sendNotification(it.body!!)
            }
        }
    }
    // [END receive_message]

    /**
     * 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 fun onNewToken(p0: String) {
        Log.d(TAG, "Refreshed token: $p0")

        // If you want to send messages to this application instance or
        // manage this apps subscriptions on the server side, send the
        // Instance ID token to your app server.
        sendRegistrationToServer(p0)
    }
    // [END on_new_token]


    /**
     * Persist token to third-party servers.
     *
     * @param token The new token.
     */
    private fun sendRegistrationToServer(token: String?) {
    }

    /**
     * Create and show a simple notification containing the received FCM message.
     *
     * @param messageBody FCM message body received.
     */
    private fun sendNotification(messageBody: String) {
        val notificationManager = ContextCompat.getSystemService(applicationContext, NotificationManager::class.java) as NotificationManager
        notificationManager.sendNotification(messageBody, applicationContext)
    }

    companion object {
        private const val TAG = "MyFirebaseMsgService"
    }
}

Let’s complete the last step and test push notification via firebase. In the final step, I am going to add FirebaseUtil.kt file as a Service and I am going to define some default properties. Application icon, notification color and default notification channel id. I added the following code block before closing the application tag. It is possible to see the completed AndroidManifest.xml file from GitHub repository.

<service
            android:name=".utils.FirebasePushUtil"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_icon"
            android:resource="@drawable/ic_launcher_foreground"/>
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_color"
            android:resource="@color/white"/>
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_channel_id"
            android:value="@string/general_notification" />

Note: If you do not have internet permission on your application, you have to add it. For this, you have to add the following line before the application tag on AndroidManifest.xml file.

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

Picture by picture explanation can be long for the notification send process. Because of that, I record video. It is possible to send notifications via this video.

After clicking the publish button on the firebase console, it is going to send a notification like below. If notification does not appear like this tutorial, you can change the channel importance level. In low level importance channels, just the application icon appears on the status bar.

Github Link: cinarrtolga/ART-Firebase-Push-Notification: This project created for Firebase Push Notification Tutorial (github.com)

I tried to explain firebase notification structure for Android applications. If you see any mistake or wrong explanation in the article, you can contact with me via comment or article[at]cinarr[dot]com

See you 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *