Managing user presence with Firestore in Android

Handle your users’ online and offline status using Firestore, Firebase, and Cloud Functions in Android

Wajahat Karim
AndroidPub
Published in
5 min readJan 22, 2018

--

This article is the response to a previous article by Abinav Seelan, who managed to create users presence with Firestore in Java Script for web. Good Job Abinav. :) This article applies almost similar approach in Android using our new kid in block — Kotlin.

Also, if you would like to see the app demo first, head to last section of the article and you will understand what’s this all about.

Since the Google acquired Firebase in October 2014, it has been getting more and more popular due to its feature-rich and easily codeable functionality. Initially, Firebase’s Real Time Database (RTDB) was a major part of Firebase and loved by thousands of developers worldwide. But, it has lots of flaws and disadvantages, and to fix it, Google announced Cloud Firestore few months ago. It is currently in beta, but it includes far more power and features than the old Firebase RTDB.

The Setup

Let’s say we have a collection in Firestore for our users. Each document in the user collection is an object containing basic fields such as name, email, a Boolean flag for online/offline status, and the timestamp to show last active status.

Firestore Users Collection Schema
Firestore Database

Marking a user as online

When any user starts the app, the user’s status will be changed to online in the Firebase. Now, the trick is that we have to update the status to two places: Firestore and Firebase. Following code snippet shows to make the user online in both places.

Marking user as online on Firestore and Firebase RTDB

Marking user as offline

The issue at hand is this — we need to mark the user as offline when the user closes our application or device shuts off or network failure happens or any other kind of exit happens. But the moment the user does so, our client-side application’s execution context ends and it stops executing. So… how do we set the user as online: false now? Also, note that along with online flag, we have to update the last online time as to show keep record of when user went offline.

The onDisconnect() method

Firebase’s Realtime database (not the same as Firestore; it is the older version of their real-time database) has support for use-cases like this. Any reference made to a key-value pair in the database using the FirebaseDatabase.getInstance() method comes with an onDisconnect(), which is a hook that fires when the client disconnects from the firebase database. It also allows you to specify the value(s) to be set for the key, when the client disconnects from the database.

All active connections to the database are listed in the /.list/connected collection in the Realtime database. Any time a client disconnects from the Realtime database, it is removed from this collection.

onDisconnect() method example

Unfortunately, there is no such method of onDisconnect() in Firestore. So, we have to use Firebase with Firestore using Cloud Functions to make a workaround for this.

Cloud Functions

Firebase also offers another service called Cloud Functions. Cloud functions are functions that you can write and deploy to firebase, to be hosted. These functions can be triggered by

  • HTTPS requests
  • Events emitted from other firebase features

The latter, is actually pretty interesting. Cloud functions have access to onChange hooks in other firebase products like the realtime database and Firestore.

Aha! We can finally put all three of these together to help us in marking a user as offline 🤓

The Solution (Thanks to Abinav Seelan 🤓)

  1. When we set the User’s online status in Firestore to online: true on loading up the application, let’s also create a record for the user in Firebase’s Realtime database. The key for this record will be the user ID (and this should match the corresponding Firestore document ID) the value set for this key will be 'online’.
  2. Set up an onDisconnect() hook for the key that we will create in the Firebase Realtime database. When the user disconnects from the Realtime database, we need to set the key’s value to 'offline'.
  3. Prior to the above two steps, we will deploy a Cloud Function that listens on change events in the Firebase Realtime database. When the value changes for a key (where the key is the user ID) in the Realtime database, we capture the event, check if the value changed from 'online' to 'offline', and then set the user’s online status in Firestore to online: false.

So, this is how does our Cloud Function looks like:

Firebase Cloud Function for User Presence Demo

onUserStatusChange will be triggered whenever any change occurs in the Firebase Realtime database to a key that matches this ref pattern — /status/{userId}

The function captures the event that is sent from the Realtime database to the Cloud Function, parses out the value from the event, checks if the value is 'offline' and if yes, it updates the Firestore document’s online status to online: false along with the current timestamp last_active: Date.now(), thereby marking the user as offline in Firestore!

Now, we have already updated Firestore and Firebase database on online earlier in the article. Now, final task is to add onDisconnect() hook to make the user offline and trigger cloud function to do final job,

Since only the Firebase Realtime database supports this, we’ll need to attach this hook to a reference made with Firebase Database. We also need to be sure to set up the onDisconnect hook before we set ourselves as online.

Setting up the onDisconnect Hook

And that’s about it! 🚀

It might be a lot to take in at once. It took me a couple of days and tries to get this right even though I was following this great article by Abinav Seelan. But if everything has been set up properly, every time you navigate away from your application or close it, or disconnect your mobile internet, your Firestore user document will reflect the correct online status, all thanks to the Firebase Realtime Database and Firebase’ Cloud Functions! 😃

You can get the full working code of both Android app and Cloud Function at following repository.

Demo

Updating Firebase Database (Left) with two two devices of users Zeeshan(Left) and Wajahat(Right).

Thanks for reading this article. Don’t forget to press clap multiple times. Also, if you liked this article, you can read more about my Year-in-Review at here:

--

--

Wajahat Karim
AndroidPub

🔥 Google Dev Expert (GDE) in Android . 📱 Android Dev . 💻FOSS Contributor . 📝 Tech Writer . 🎤 Public Speaker — 🌐Subscribe at https://wajahatkarim.com