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 2 of 4 of this article. Click here to view the first page.

Configuring the Demo App

At this point, you’ve done all the configuration you need to do in the Firebase console. Next, you’ll add some code to the Drink-it app so it can remind you to drink water! If you haven’t had any recently, you can take a drink right now, by the way. :]

Including the Maven Repository

Google recommends adding their Maven repository to your app, but all Android Studio 3.6 projects include it by default. Take a moment to ensure this repository isn’t missing.

In your project-level build.gradle file — labeled Project: DrinkIt in Android Studio — make sure you have a line of code with google() in the repositories section of buildscript and allprojects respectively.

Next, you need to edit the Android Manifest.

Open AndroidManifest.xml in app/manifests. Inside the application tags, add the following:

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

The code above adds a service for handling the received notifications. Within the project, you have a file called MyFirebaseMessagingService in com.raywenderlich.android.drinkit. That service is currently empty, but once you complete it later, it will take care of receiving and processing your notification information.

For now, open MyFirebaseMessagingService and make sure it extends from FirebaseMessagingService as shown below:

class MyFirebaseMessagingService : FirebaseMessagingService() {

Next, you need to add the following dependency in your app module build.gradle:

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

This dependency includes the sources for FirebaseMessagingService. However, you still need to add the following import on the top of MyFirebaseMessagingService:

import com.google.firebase.messaging.FirebaseMessagingService

Using the Device Token

The device token is a unique identifier that contains two things:

  1. Which device will receive the notification.
  2. The app within that device that will receive the notification.

Firebase automatically generates these tokens and delivers them to you as a developer.

Retrieving the Device Token

Device tokens may change over time, due to circumstances like:

  • The app deleted the Instance ID.
  • The user got a new device and restored the app.
  • The user uninstalled and reinstalled the app.
  • The user cleared app data.

In these cases, you’ll need to retrieve the device token.

In most of your apps, you’ll retrieve this token in the background. Sometimes, you’ll need to save it to a database so you can use it to send push notifications with internal APIs. In this app, you already have a Retrieve token button, which you’ll use so you can see the operation’s result.

Open MainActivity.kt. In the layout of this screen, there’s a Retrieve token button. Create an onClickListener for the button inside onCreate() by using the following code:

  button_retrieve_token.setOnClickListener {
    // 1
    FirebaseInstanceId.getInstance().instanceId
      .addOnCompleteListener(OnCompleteListener { task ->
        // 2
        if (!task.isSuccessful) {
          Log.w(TAG, "getInstanceId failed", task.exception)
          return@OnCompleteListener
        }
        // 3
        val token = task.result?.token

        // 4
        val msg = getString(R.string.token_prefix, token)
        Log.d(TAG, msg)
        Toast.makeText(baseContext, msg, Toast.LENGTH_LONG).show()
       })
    }
  }

Here’s what this code does, step-by-step:

  1. You get the instance of the app that’s tied to the Firebase back end and add a complete listener to it so you know when the task finishes, whether with an error or success.
  2. You check if the task, which is the result of this function, isn’t successful and return an error to the console.
  3. If the task is successful, you get the result from it.
  4. After getting the token, you set it as a string and output it for both the terminal and a toast message.

The code shows several errors now because you need to import some classes. To fix those errors, add this code to the top of MainActivity.kt with the rest of the imports:

import com.google.firebase.iid.FirebaseInstanceId
import com.google.android.gms.tasks.OnCompleteListener
import android.util.Log
import android.widget.Toast

Build and run, then tap the Retrieve token button. The token now shows in the toast message. Check the console and you’ll also see the token there.

App showing the retrieve token in a toast message

With the device token retrieved, Firebase can now connect with your device. In the next section, you’ll see how to do that shortly.

Checking if Devices Can Receive Notifications

When sending push notifications in Android, it’s important to make sure the devices you’re pushing to have Google Play Services enabled. Otherwise, they won’t be able to receive your messages.

In a small app, sending push notification to some devices that can’t receive them might not matter. However, when you’re using resources on a paid quota, distinguishing the devices that can get messages from the ones that can’t is vital.

To do this, add this function in MainActivity.kt:

private fun checkGooglePlayServices(): Boolean {
  // 1
  val status = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this)
  // 2
  return if (status != ConnectionResult.SUCCESS) {
    Log.e(TAG, "Error")
    // ask user to update google play services and manage the error.
    false
  } else {
    // 3
    Log.i(TAG, "Google play services updated")
    true
  }
}

Check out what this code does:

  1. First, you use Android’s availability API to check for Google Play Services.
  2. If the status isn’t successful, you need to manage the error. In this case, you know the user can’t receive push notifications.
  3. If it is successful, there’s no problem and you can continue with the notification process.

Again, you’ll get errors because of missing imports. Add those imports at the top of the file with this code:

import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability

Now, use the following code to add the check to onClickListener, right after button_retrieve_token.setOnClickListener {:

if (checkGooglePlayServices()) {

} else {
  //You won't be able to send notifications to this device
  Log.w(TAG, "Device doesn't have google play services")
}

Depending on the purpose of your notifications, you may want to display an alert message to the user. For this app, you’ll just show the message in the terminal.

Test this error by creating an Android Virtual Device with Google Play Services disabled. Notice that the screen has a message suggesting that you use another image. That’s because most app dependencies use Google Play Services.

Android Studio virtual device manager showing a device without Google Play Services

Build and run. You should see no change in the app.

App running with no changes

Sending a Test Message With Notification Composer

Firebase includes a tool called Notification Composer that lets you send tests or custom messages when your user base isn’t too big. For larger projects, you’ll need to create an API or another tool to automate this process.

Either way, it’s important to learn to use this tool, because it’s always handy to be able to send messages for testing.

To access the Notification Composer in the Firebase console, click the project name.

Firebase console with the Drink-It project listed in the main page

Since the project is new, you’ll find the option to Send your first message.

Firebase console in the project Drink-it view prompting to send the first message

If you don’t have this option available, you can find it on the left side menu under the grow section:

Left-side menu of the Firebase console