Firebase Messaging with Image in Android

firebase-messaging-with-image in-android

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.
# Login/Register to the firebase.
# Setup your project in android studio.
# Create a project on the firebase console.
# Add firebase to your project.

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

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

Step 2: 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 project like Splash or Dashboard.

Step 3: 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>

Step 4: Show Notification (first download image to bitmap and then create 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.

Step 5: 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.

Leave a Reply