In this tutorial, we will use Kotlin to make a simple Android mobile app that will be able to receive push notifications sent from Firebase. I used to call these kind of messages “push messages” but the correct term for this tutorials will probably be a Firebase Cloud Messaging or the FCM which also stands for Firebase Cloud Messaging.
I will share with you how to setup the Firebase support for your Android mobile app and how to receive and also display the received push messages. And the best part of course is that, I will be using Kotlin 🙂 for doing this.
For using Kotlin with Android Studio, I encourage you to use latest Canary version for Android Studio 3.0 which can be installed along side your stable Android Studio installation. At the time of writing this tutorial, latest Canary version available for Android Studio is Canary version 9, released on July 31st, 2017.
I will be using Firebase to setup Google Cloud messaging and making a sample app. Let us start by creating a project and setting up Firebase dependencies.
Create A New Project in Android Studio
To make this example very simple, I will create a brand new project in Android Studio, so that it does not have any extra code.
We will be creating a very simple Android app for receiving push notifications sent from Firebase and then showing them in a dialog bar when the app is open, and when the app is closed, show notifications in a notification bar.
I will give my new project a name “PlayWithNotifications”. The base package name will be com.appsdeveloperblog. Remember to check the “Include Kotlin support” while setting up the project.
As of now, the MainActivity.kt looks should like this:
package com.appsdeveloperblog.playwithnotifications import android.os.Bundle import android.support.v7.app.AppCompatActivity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } }
Adding Firebase support to Android Studio Project
To add Firebase support to Android Studio project follow these steps:
- Open your project in Android Studio
- Click Tools > Firebase to open the Assistant window.
Once that is done, the Firebase assistant will appear presenting many Firebase services, we need to select the “Cloud Messaging” feature:
Once you click ‘Setup Firebase Cloud Messaging’, following dialog will appear to confirm setting up the project:
Next, Android Studio will offer to add relevant code snippets to our app like for example Gradle dependency:
implementation 'com.google.firebase:firebase-messaging:11.0.4' ... //Added as last line apply plugin: 'com.google.gms.google-services'
With other changes, it is clearly shown in the dialog Android Studio presented us with a title Add FCM to your app:
Now, we will write some code in Kotlin and create our own Firebase service to use the notification data received as a payload. We also need a service with which we can receive a new token whenever it is refreshed. We will do this next.
FirebaseMessagingService. Know when FCM Message is received.
Make a new class in your Android project and extend FirebaseMessagingService. Once it is done. Your source code should like the one I have below:
import android.util.Log import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage class MyFirebaseMessagingService : FirebaseMessagingService() { val TAG = "Service" override fun onMessageReceived(remoteMessage: RemoteMessage?) { // Handle FCM messages here. // If the application is in the foreground handle both data and notification messages here. // Also if you intend on generating your own notifications as a result of a received FCM // message, here is where that should be initiated. Log.d(TAG, "From: " + remoteMessage!!.from) Log.d(TAG, "Notification Message Body: " + remoteMessage.notification.body!!) } }
With the help of the above service, we will know whenever a new message arrives to our app. The onMessageReceived will be triggered every time there is a new FCM message. We can properly handle it and if needed generate our own notifications.
Now let’s test our app by visiting Firebase panel and sending a new FCM message.
Once the message is sent, you should see the following entries in your Android Studio logcat:
Display Push Notification(FCM Message) in a Dialog Window
Now, let us show a simple dialog box by making simple changes. We will modify our FirebaseMessagingService like so:
package com.appsdeveloperblog.playwithnotifications import android.app.NotificationManager import android.app.PendingIntent import android.content.Context import android.content.Intent import android.media.RingtoneManager import android.support.v4.app.NotificationCompat import android.util.Log import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage class MyFirebaseMessagingService : FirebaseMessagingService() { val TAG = "Service" override fun onMessageReceived(remoteMessage: RemoteMessage?) { // TODO: Handle FCM messages here. // If the application is in the foreground handle both data and notification messages here. // Also if you intend on generating your own notifications as a result of a received FCM // message, here is where that should be initiated. Log.d(TAG, "From: " + remoteMessage!!.from) Log.d(TAG, "Notification Message Body: " + remoteMessage.notification.body!!) sendNotification(remoteMessage) val intent = Intent(this@MyFirebaseMessagingService, MainActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) intent.putExtra("message", remoteMessage.notification.body!!) startActivity(intent) } private fun sendNotification(remoteMessage: RemoteMessage) { val intent = Intent(this, MainActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) val pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT) val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) val notificationBuilder = NotificationCompat.Builder(this) .setContentText(remoteMessage.notification.body) .setAutoCancel(true) .setSmallIcon(R.mipmap.ic_launcher) .setSound(defaultSoundUri) .setContentIntent(pendingIntent) val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.notify(0 /* ID of notification */, notificationBuilder.build()) } }
See how we added Notification Builder to create a notification and send the message we received to our activity.
Once we send an intent from our Service to the Activity, let us show a dialog. We will modify the onCreate(…) method like so:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val intent = intent val message = intent.getStringExtra("message") if(!message.isNullOrEmpty()) { AlertDialog.Builder(this) .setTitle("Notification") .setMessage(message) .setPositiveButton("Ok", { dialog, which -> }).show() } }
Once this change is made, we can send a new push message(Firebase Cloud Messaging) notification and it should appear in a dialog window on our device like on the picture below:
Common problems faced with Firebase
During integration of Firebase libraries in Android projects, we usually face common problems like:
- Invalid library versions. Remember to add appropriate version of libraries, plugins and dependencies. Like the app level Gradle file looks like the one below for me:
apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { compileSdkVersion 26 buildToolsVersion "26.0.0" defaultConfig { applicationId "com.appsdeveloperblog.playwithnotifications" ... } buildTypes { ... } } dependencies { ... implementation 'com.google.firebase:firebase-messaging:11.2.2' ... implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" } apply plugin: 'com.google.gms.google-services'
And root level Gradle file looks like this:
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { ext.kotlin_version = '1.1.3-2' repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.0.0-beta6' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files classpath 'com.google.gms:google-services:3.1.0' } } allprojects { ... } task clean(type: Delete) { delete rootProject.buildDir }
- A message like “com.google.firebase.crash.FirebaseCrash is not linked. Skipping initialization.” can also be shown in the Android Monitor log. This one is not a problem because we are not using the Firebase Crash Analytics service.
I hope this tutorial was of some value to you and helped you set up Push Notifications or Google Firebase Cloud Messaging support for you Android mobile application built Kotlin.
To learn more about Android and Kotlin check these books and video courses: