Firebase Cloud Messaging for Android: Sending Push Notifications

In this Firebase Cloud Messaging tutorial, you will learn how to add push notifications to Drink-It, an app that reminds you to drink water through the day. By Evana Margain Puig.

4.8 (21) · 1 Review

Download materials
Save for later
Share
You are currently viewing page 3 of 4 of this article. Click here to view the first page.

Configuring Notification Composer

Notification Composer allows you to configure the data of the message you’ll send and preview your notification on the right side of the window. Enter the following data:

  • Notification title: Most apps use the name of the app, but you can actually add any title.
  • Notification text: Add: “This is a reminder to drink water!”
  • Notification image: This is optional. For this tutorial, you won’t add an image.
  • Notification name: This is for your personal use, so you can identify the notification in the console. This data is also optional.

Note that the notification text can be anything you want, but it should be brief or the entire message won’t display.

Notification composer step one

Now, select your app identifier: com.raywenderlich.android.drinkit

Notification composer target app

You can schedule the time, but for this tutorial select now — unless you want to wait for it to arrive!

Notification composer scheduling

You can play around with the other values, but they aren’t necessary. When you’re done, click Review.

Notification composer extra optional values

A confirmation window will appear. If you didn’t activate Google Analytics, you’ll see a red alert. Don’t worry about it, it’s not required.

Click Publish and take a look at the emulator or device where you installed your app.

Alert displayed in Firebase console confirming the notification data

If you’re in the list of notifications, you can either click the New notification button or select the Duplicate notification option from the drop-down menu to send another one.

History of notifications with duplicate option

Be careful! If the app is in the foreground, you won’t see the notification. Later, you’ll configure foreground notifications.

For now, send the app to the background and try again, and you’ll see a notification appear.

Notification in the emulator

When you click on the notification, it will open the app. Nothing happens because you haven’t configured any additional actions.

Background-Restricted Apps

If for some reason your notification isn’t appearing. It could be because of the version of Android your device is using. Android 9, also known as Android P, introduced the possibility of restricting apps from running in the background. Although you’re probably testing on an emulator or on your own device, it’s important to know this is possible.

If you have trouble testing, check that the app isn’t background-restricted.

To access these settings, go to Settings ▸ Apps & notifications, select the Drink it app from the list then scroll down and select Battery. You might need to open the Advanced section before you see the Battery option.

Once in the Battery usage screen, tap on Background restriction. You’ll get a warning that notifications may arrive later or not arrive at all.

Background restricted apps alert in settings

If your notification shows up without problems, you’re good to carry on to the next section.

Setting Custom Icons and Colors

Android gives you the possibility to set a custom icon and color for the notifications through Android Manifest.

There are several ways to set the notification’s icon:

  1. Don’t assign an icon. In this case, the app icon will appear.
  2. Set it in Android Manifest.
  3. Send it in the notification payload.

The color of the notification will vary depending on the Android version. If the version is earlier than Android N, the color will appear in the background of the icon. If the version is N or above, the icon and app name will use the color.

You’ll set the color and icon using Android Manifest. Add the following code to AndroidManifest.xml inside of the application tag:

<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/colorPrimary" />

The first tag sets the notification icon; the second sets the color. The name values are standard, so every time you want to change the icon or color, you’ll add the same value to the name attribute. The resource value is the one you’ll configure. For the icon, it can have any drawable and for the color, any valid value is possible.

Build and run, then send another notification. It will use the color and icon you selected, which may vary depending on the device or emulator you’re using.

Notification with custom color and icon

Receiving Notifications in the Foreground Versus Background

When receiving notifications, it’s important to distinguish whether the app is running on the foreground or background. Basically, you need to consider the following:

  • Foreground: The notification and the data are both handled in onMessageReceived().
  • Background: The System UI handles the notification, while onMessageReceived() handles the data payload.

You’ll now configure Drink-it to handle notifications when it’s running in the foreground.

Add the following code to MyFirebaseMessagingService:

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

Then you’ll add another method for handling the message:

private fun handleMessage(remoteMessage: RemoteMessage) {
  //1
  val handler = Handler(Looper.getMainLooper())

  //2
  handler.post(Runnable { 
      Toast.makeText(baseContext, getString(R.string.handle_notification_now), 
                     Toast.LENGTH_LONG).show() 
    }
  )
}

Now, review the code above:

  1. You create a handler to get the message and extract the data.
  2. You use that handler to post the toast through a runnable.

You’ll get errors because of missing imports. Add them at the top of the file with this code:

import android.os.Handler
import android.os.Looper
import android.widget.Toast
import com.google.firebase.messaging.RemoteMessage

Build and run and check the notification with the app in the foreground.

Notification in the emulator in foreground

Displaying Notification Data in Activities

Sometimes, you want to do something with the data that arrived through the notification. For your last step, you want to display the text of the notification in the activity.

To do this, you’ll add a broadcast manager, which listens to incoming data from notifications and does the appropriate treatment.

To start, add this code to MyFirebaseMessagingService:

private var broadcaster: LocalBroadcastManager? = null

override fun onCreate() {
  broadcaster = LocalBroadcastManager.getInstance(this)
}

Then add this code to handleMessage() , inside handle.post:

remoteMessage.notification?.let {
  val intent = Intent("MyData")
  intent.putExtra("message", it.body);
  broadcaster?.sendBroadcast(intent);
}

If you see an error on the intent, import this code at the top:

import android.content.Intent

In MainActivity.kt, you need to add some more code to receive the message. First, add a BroadcastReceiver with the following code:

private val messageReceiver: BroadcastReceiver = object : BroadcastReceiver() {
  override fun onReceive(context: Context?, intent: Intent) {
    text_view_notification.text = intent.extras?.getString("message")
  }
}

This BroadcastReceiver checks the notification when it arrives and looks for the string called message. It then puts it on the screen, assigning it to notification_text.

If you have errors, it’s because you need to import some more classes. Add this at the top of your file:

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent

Next, in the activity, add this code to OnStart():

LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, IntentFilter("MyData"))

With the code above, you create the broadcast manager instance so whenever a notification arrives, you check if the data labeled MyData is available.

Then, add this code to OnStop():

LocalBroadcastManager.getInstance(this).unregisterReceiver(messageReceiver)

With this code, you’ll unregister this receiver to avoid keeping it in memory when it’s no longer needed.

You also need to import the context, as some of the added code may show errors. Add this to your imports:

import androidx.localbroadcastmanager.content.LocalBroadcastManager
import android.content.IntentFilter

Build, run and send a notification. You’re now receiving the notifications correctly! Check the image below to compare your code:

App with the notification in the foreground with the text in the screen changed