Integrate Firebase Realtime Database and User Authentication into your Android App
Tags: android, firebase, kotlin, beginners
Published: 2023-08-04 13:13:56

**A Step-by-Step tutorial to integrate Firebase Realtime Database and User Authentication into your Android app with Kotlin and Jetpack Compose**

This is part of the Firebase tutorial series:

* [Part 1 - Simple Firebase Sign-in UI Demo App](https://vtsen.hashnode.dev/simple-firebase-sign-in-ui-demo-app)
    
* **Part 2 - Integrate Firebase Realtime Database and User Authentication into your Android App**
    

This article is the continuity of the previous article, in which we learned how to create a simple Firebase sign-in/authentication in the Android app.

So, this assumes you have already set up the Firebase console project for your app. The overview of the demo app looks like this.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690689167164/d17b05aa-a4dc-472c-a399-6728e10cb3d5.gif)

## 1\. Enable Realtime Database in Firebase Project

On the left panel of your Firebase project, click **Build -&gt; Realtime Database.**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690608919121/2b450c27-16eb-4a7d-809a-d52a49f6067b.png)

Click **Create Database.**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690609242035/b1cff779-b7b9-462e-b5b4-6bb9b070be76.png)

In **Database options**, let's use the database location from the US. Click **Next**.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690609374748/d9e5806b-2fa2-4eed-9dd3-577ede61fee5.png)

In **Security rules**, let's choose **test mode** and click **Enable**.

> It doesn't matter what you choose here, we're going to change the security later.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690609471828/bef54e20-b04d-42ce-91bb-04dd832678c1.png)

Congratulation! Now Firebase Realtime Database is enabled in your project.

## 2\. Change Security Rules to Content-owner only Access

Go to **Realtime Database -&gt; Rules**, you see something like this.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690610186831/dbfaf05c-bc4a-4433-96fe-d40b594dcfa4.png)

It means everyone who installs your app can read or write to your database before the expiration date. That is usually for development purposes.

What we want here is only the authenticated user can only access a certain path of the database.

So, I'm going to change the rules to the following.

```json
{
  "rules": {
    "users": {
      "$uid": {
        ".read": "auth !== null && auth.uid === $uid",
        ".write": "auth !== null && auth.uid === $uid"
      }
    }
  }
}
```

These rules mean only the authenticated user can access (read from and write to) the **\\users\\&lt;uid&gt;** path. uid is the unique string ID that is assigned to the |Firebase user.

The official document reference is [here](https://firebase.google.com/docs/rules/basics).

## 3\. Add Firebase Database SDK to your App

**build.gradle/kts (app level)**

```kotlin
 dependencies {
     /*...*/
    implementation("com.google.firebase:firebase-database-ktx:20.1.0") 
 }
```

## 4\. Write User Data to Database

The Firebase Realtime Database supports the [Kotlin data class](https://vtsen.hashnode.dev/complete-c-to-kotlin-syntax-comparisons#heading-record-vs-data-classes) serialization and deserialization. So instead of operating on every single user data directly, you can create `UserData` data class below to hold them.

```kotlin
data class UserData (
    val name:String?,
    val age: Int?,
    val favoriteFood:List<String>?
) {
    //Note: this is needed to read the data from the firebase database
    //firebase database throws this exception: UserData does not define a no-argument constructor
    constructor() : this(null, null, null)
}
```

> The gotcha is you MUST create a no-argument `conustructor()`. Firebase database throws the exception when you try to read the data from it. Damn it, it tooks me sometime to figure this out and it is not documented anywhere.

**Write Data to Database**

Once we signed in, we can retrieve the `FirebaseUser` from `FirebaseAuth.getInstance().currentUser`. From here, we can get the `FirebaseUser.uid`.

To get the reference to **/users/&lt;uid&gt;** path in the database, we use `Firebase.database.reference.child("users").child(user.uid).` A Firebase reference represents a particular location in your Database and can be used for reading or writing data to that Database location.

Then, we can call `DatabaseReference.setValue()` to write the data into the database.

```kotlin
val user = FirebaseAuth.getInstance().currentUser
user?.run {
    val userIdReference = Firebase.database.reference
        .child("users").child(user.uid)
    val userData = UserData(
        name = displayName,
        age = 7,
        favoriteFood = listOf("Apple", "Orange")
    )
    userIdReference.setValue(userData)
}
```

Before you write the data, in the Firebase console Realtime Database data tab, it looks like this, which doesn't contain any data.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690692622385/9bea589e-d39b-459a-99a5-b1d0f07f2b60.png)

After you write data into it, it becomes like this.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690692673450/80ce03c7-fe2d-48a4-8949-284aa32c2364.png)

## 5\. Read User Data from Database

**Read Data from Database (One-time Read)**

The `DatabaseReference.Get()` returns `Task<DataSnapshot>` which allows you to register a callback from the task. To read data, we register this callback task, `Task.addOnSuccessListener()`.

```kotlin
val user = FirebaseAuth.getInstance().currentUser
user?.run {
    val userIdReference = Firebase.database.reference
        .child("users").child(uid)

    userIdReference.get().addOnSuccessListener { dataSnapShot ->
        val userData = dataSnapShot.getValue<UserData?>()
        //successfully read UserData from the database
    }
}
```

**Read Data from Database (Continuous Read)**

If you want to continuously reading the data instead reading on-demand, you register this `ValueEventListener` with `DatabaseReference.addValueEventListener()`. In the `onDataChange()` callback, you can expose the `UserData` to either `Flow` or `StateFlow`.

```kotlin
val user = FirebaseAuth.getInstance().currentUser
val userIdReference = Firebase.database.reference
    .child("users").child(user!!.uid)

userIdReference.addValueEventListener(object : ValueEventListener {
    override fun onDataChange(dataSnapshot: DataSnapshot) {
        val userData = dataSnapshot.getValue<UserData?>()
        //expose userData as flow or stateFlow here     
    }

    override fun onCancelled(error: DatabaseError) {
    }
})
```

## Next Steps

The Firebase Realtime database is easy to set up (maybe not? Because it took me a while, too). The drawback of using it is not completely free, especially after you finish your quota. I will explore MangoDB next...

## Source Code

GitHub Repository: [**Demo\_FirebaseSignInRealtimeDB**](https://github.com/vinchamp77/Demo_FirebaseSignInRealtimeDB)

---

*Originally published at [https://vtsen.hashnode.dev](https://vtsen.hashnode.dev/integrate-firebase-realtime-database-and-user-authentication-into-your-android-app)*.