Managing user presence with Firestore in Android
Handle your users’ online and offline status using Firestore, Firebase, and Cloud Functions in Android
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.
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.
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 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/connectedcollection in the Realtime database. Any time a client disconnects from the Realtime database, it is removed from this collection.
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.
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
The Solution (Thanks to Abinav Seelan 🤓)
- When we set the User’s online status in Firestore to
online: trueon 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
- 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
- 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
'offline', and then set the user’s online status in Firestore to
So, this is how does our Cloud Function looks like:
onUserStatusChange will be triggered whenever any change occurs in the Firebase Realtime database to a key that matches this
ref pattern —
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
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.
User-Online-Demo-Firestore - Managing users' presence like users' online and offline status using Firestore and Cloud…
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: