How to send a push notification from node.js & display it in a kotlin app
Published: 2022-06-20 12:42:00

In this article, we look at how you can send a push notification using **Firebase** and **node.js** to a **mobile device**.
First of all, I assume you have a mobile application in which you have Firebase configured. I also assume you have a node.js application.

First of all, you need to install 2 node libraries i.e **firebase-admin** and **fcm-notification** in your node application.
```javascript
npm i firebase-admin --save
npm i fcm-notification --save
```
You need to access your firebase account and private key which is a json file and include it in your node.js application. To get this private key, Go to **Firebase** > **YouProjectName** > **Settings** > **Service Accounts** > click **Generate new private key** button.
Import the following packages in your class or function in your node app.

```javascript
var admin = require("firebase-admin");
var fcm = require('fcm-notification');
var serviceAccount = require("../config/privateKey.json");
const certPath = admin.credential.cert(serviceAccount);
var FCM = new fcm(certPath);
```
I use **firebase-admin** to create a certificate from the private key json file. as seen on code line ``` const certPath = admin.credential.cert(serviceAccount); ``` This certificate created from the private key, is meant to authenticate your requests to your firebase account.

**Function to send push notification**
```javascript
  sendPushNotification= (fcm_token, title, body) => {
        
    try{
        let message = {
            android: {
                notification: {
                    title: title,
                    body: body,
                },
            },
            token: fcm_token
        };
        
        FCM.send(message, function(err, resp) {
            if(err){
                throw err;
            }else{
                console.log('Successfully sent notification');
            }
        });
        
    }catch(err){
        throw err;
        }
        
    }

```
**sendPushNotification()** is the function name i have created to send push notification. it takes 3 parameters i.e fcm_token, title and then body of the push notification. message is an object with **android** and **token** keys. Android is a key that indicates that the notification is being sent to a mobile device. Within android key, is notification object which holds title and body of the push notification. token is the key that holds the fcm token to which the notification is being sent.

**FCM** is the instance of fcm class from **fcm-notification** package which takes in the certificate created from the private key.
Within fcm class, is a method **send** which is accessed through the instance and it takes in 2 parameters i.e the message object and a callback function as seen in the code snippet below;
```javascript
 FCM.send(message, function(err, resp) {
   if(err){
        throw err;
     }else{
        console.log('Successfully sent notification');
     }
   });
```
This is how you can send a push notification to a mobile device from node.js using firebase.
Before I conclude, **note** that **fcm tokens** come from a mobile app in which firebase is configured and used. This means that you can actually access this token from database that is if you are storing it in your database.

**In Kotlin (Mobile App)**
In your kotlin code, you can setup your firebase service as follows;
```kotlin
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.media.RingtoneManager
import android.net.Uri
import android.os.Build
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import com.google.firebase.messaging.FirebaseMessaging
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage

class CustomFirebaseMessagingService : FirebaseMessagingService() {

    override fun onMessageReceived(remoteMessage: RemoteMessage) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val mNotificationManager =
                getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            val importance = NotificationManager.IMPORTANCE_HIGH
            val mChannel = NotificationChannel(
                AppConstants.FCMConstants.CHANNEL_ID,
                AppConstants.FCMConstants.CHANNEL_NAME,
                importance
            )
            mChannel.description = AppConstants.FCMConstants.CHANNEL_DESC
            mNotificationManager.createNotificationChannel(mChannel)
        }

        if(remoteMessage.data.isNotEmpty()) {
            remoteMessage.data.let {

                var title = it["title"]
                var body = it["message"]
                println("From data object, notification title: $title and body: $body")
                sendNotification(title.toString(), body.toString())
            }
        }

        if (remoteMessage.notification != null){
            var title = remoteMessage.notification?.title
            var body = remoteMessage.notification?.body
            println("From notification object, notification title: $title and body: $body")
            if(!title.isNullOrEmpty() && !body.isNullOrEmpty()){
                sendNotification(title.toString(), body.toString())
            }
        }


    }


    private fun sendNotification(title: String, messageBody: String) {
        var intent: Intent? = null
        intent = Intent(this, HomeActivity::class.java)
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
        val pendingIntent = PendingIntent.getActivity(
            this, 0 /* Request code */, intent,
            PendingIntent.FLAG_ONE_SHOT
        )
        var defaultSoundUri: Uri? = null
        defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val importance = NotificationManager.IMPORTANCE_HIGH
            val channel =
                NotificationChannel(
                    AppConstants.FCMConstants.CHANNEL_ID,
                    AppConstants.FCMConstants.CHANNEL_NAME,
                    importance
                )
            channel.description = AppConstants.FCMConstants.CHANNEL_DESC
            // Register the channel with the system; you can't change the importance
            // or other notification behaviors after this
            val notificationManager = this.getSystemService(
                NotificationManager::class.java
            )
            notificationManager.createNotificationChannel(channel)
        }
        val notificationBuilder: NotificationCompat.Builder =
            NotificationCompat.Builder(this, AppConstants.FCMConstants.CHANNEL_ID)
                .setStyle(NotificationCompat.BigTextStyle().bigText(messageBody))
                .setContentTitle(title)
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setPriority(NotificationManager.IMPORTANCE_MAX)
                .setChannelId(AppConstants.FCMConstants.CHANNEL_ID)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            notificationBuilder.setSmallIcon(R.drawable.push_icon)
            notificationBuilder.color = ContextCompat.getColor(this, R.color.pink_500)
        } else {
            notificationBuilder.setSmallIcon(R.mipmap.ic_launcher)
        }
        val notificationManager =
            this.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build())
    }


    override fun onNewToken(p0: String) {
        Log.d("NotificationFCM", "Token: " + p0)
    }

}
```
Thank you for reading through this article, I hope you find it helpful.