Skip to content

Firebase Messaging with Image in Android | Android Kotlin push notification

Published:

Hello friends, I came back with a new post.
In this post, we are going to learn how to handle notifications with an image from the firebase console.

Here are a few steps I think we can skip.


Add dependency (in “app/build.gradle”)

implementation 'com.google.firebase:firebase-messaging:20.0.0'

Create a class that extends FirebaseMessangingService in my case it is “MyFirebaseMessangingService”

Your class look like this initially

class MyFirebaseMessangingService : FirebaseMessagingService(){
    override fun onNewToken(p0: String) {
        super.onNewToken(p0)

    }
    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)
    }
}

onNewToken“: Function will be called when firebase creates/update a unique token for a particular user.
This can be updated periodically, reinstall the app, clear data, etc.

onMessageReceived“: This is a special function that is called when a message is received from the firebase console or by your app’s backend, in this function you have to create and show the notification.
Note: This function only triggers when your app is in the foreground state.

Q. What happens when the app is in the background & how to show notification in that condition?
Ans: Firebase will handle itself and show the notification & on click on that notification it will open the very first activity of your projects like Splash or Dashboard.


Add Firebase messaging service to Manifest.xml inside the application tag.

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

Show Notification (first download image to bitmap and then show notification)

private fun downloadImage(notification: RemoteMessage.Notification?) {
        Observable.fromCallable(object : Callable<Bitmap?> {
            override fun call(): Bitmap? {
                val future = Glide.with(applicationContext).asBitmap()
                        .load(notification?.imageUrl).submit()
                return future.get()
            }
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : Observer<Bitmap?> {
                    override fun onComplete() {

                    }

                    override fun onSubscribe(d: Disposable) {

                    }

                    override fun onNext(t: Bitmap) {
                        showNotification(notification,t)
                    }

                    override fun onError(e: Throwable) {
                        showNotification(notification,null)
                    }

                })

}

Note: I used RxJava here for threading, you can use any method you want.


Show the notification

private fun showNotification(notification: RemoteMessage.Notification?, image: Bitmap?) {

    val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    val channelId = getString(R.string.notification_channel_id)
    val channelName = getString(R.string.notification_channel_name)
    val importance = NotificationManager.IMPORTANCE_LOW

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        val mChannel = NotificationChannel(channelId, channelName, importance)
        notificationManager.createNotificationChannel(mChannel)
    }

    val intent = Intent(applicationContext, MainActivity::class.java)
    val pendingIntent = PendingIntent.getService(applicationContext, 1, intent, 0)
    var builder: Notification.Builder? = null
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        builder = Notification.Builder(applicationContext, channelId)
    } else {
        builder = Notification.Builder(applicationContext)
    }

    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        builder.setSmallIcon(R.mipmap.ic_launcher)
    } else {
        builder.setSmallIcon(R.mipmap.ic_launcher)
    }

    val title = if (notification?.title.toString().isNullOrEmpty()) {
        getString(R.string.app_name)
    }else{
        notification?.title
    }

    val content = if (notification?.body.isNullOrEmpty()) {
        getString(R.string.app_name)
    }else{
        notification?.body
    }

    builder.setContentTitle(title)
            .setContentText(content)
            .setDeleteIntent(pendingIntent)

    if (image != null) {
        builder.setStyle(Notification.BigPictureStyle().bigPicture(image))
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        builder.setVisibility(Notification.VISIBILITY_PUBLIC)
    }

    notificationManager.notify((0..100).random(), builder.build())
}

Here is the whole file code:

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.os.Build
import android.util.Log
import com.bumptech.glide.Glide
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import com.techpaliyal.uniquegallery.R
import com.techpaliyal.uniquegallery.activities.MainActivity
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.util.concurrent.Callable

class MyFirebaseMessangingService : FirebaseMessagingService(){
    override fun onNewToken(p0: String) {
        super.onNewToken(p0)
        Log.d("TestingNotification",""+p0)
    }
    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)
        downloadImage(remoteMessage.notification)
    }

    private fun downloadImage(notification: RemoteMessage.Notification?) {
        Observable.fromCallable(object : Callable<Bitmap?> {
            override fun call(): Bitmap? {
                val future = Glide.with(applicationContext).asBitmap()
                        .load(notification?.imageUrl).submit()
                return future.get()
            }
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : Observer<Bitmap?> {
                    override fun onComplete() {

                    }

                    override fun onSubscribe(d: Disposable) {

                    }

                    override fun onNext(t: Bitmap) {
                        showNotification(notification,t)
                    }

                    override fun onError(e: Throwable) {
                        showNotification(notification,null)
                    }

                })
    }

    private fun showNotification(notification: RemoteMessage.Notification?, image: Bitmap?) {
        val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        val channelId = getString(R.string.notification_channel_id)
        val channelName = getString(R.string.notification_channel_name)
        val importance = NotificationManager.IMPORTANCE_LOW

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            val mChannel = NotificationChannel(channelId, channelName, importance)
            notificationManager.createNotificationChannel(mChannel)
        }

        val intent = Intent(applicationContext, MainActivity::class.java)
        val pendingIntent = PendingIntent.getService(applicationContext, 1, intent, 0)
        var builder: Notification.Builder? = null
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            builder = Notification.Builder(applicationContext, channelId)
        } else {
            builder = Notification.Builder(applicationContext)
        }

        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            builder.setSmallIcon(R.mipmap.ic_launcher)
        } else {
            builder.setSmallIcon(R.mipmap.ic_launcher)
        }

        val title = if (notification?.title.toString().isNullOrEmpty()) {
            getString(R.string.app_name)
        }else{
            notification?.title
        }

        val content = if (notification?.body.isNullOrEmpty()) {
            getString(R.string.app_name)
        }else{
            notification?.body
        }

        builder.setContentTitle(title)
                .setContentText(content)
                .setDeleteIntent(pendingIntent)

        if (image != null) {
            builder.setStyle(Notification.BigPictureStyle().bigPicture(image))
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            builder.setVisibility(Notification.VISIBILITY_PUBLIC)
        }

        notificationManager.notify((0..100).random(), builder.build())
    }
}

If having any question/doubts or feedback please comment below.


Previous Post
Android Fast Networking with Kotlin Coroutines
Next Post
Getting Started with Android Data Binding