0
0
Android Kotlinmobile~20 mins

Cloud Firestore integration in Android Kotlin - Mini App: Build & Ship

Choose your learning style9 modes available
Build: Simple Firestore Notes
This screen lets users add notes to Cloud Firestore and shows a list of saved notes.
Target UI
-------------------------
| Simple Firestore Notes |
-------------------------
| [Enter note here...]  |
| [Add Note Button]     |
|-----------------------|
| Notes:                |
| - Note 1              |
| - Note 2              |
| - Note 3              |
-------------------------
A TextField for user to enter a note
A Button labeled 'Add Note' to save the note to Firestore
A list below showing all saved notes from Firestore in real-time
Use Firestore collection named 'notes' with a 'text' field
Handle empty input by disabling the Add button
Starter Code
Android Kotlin
package com.example.firestoreapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.google.firebase.firestore.FirebaseFirestore

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            FirestoreNotesScreen()
        }
    }
}

@Composable
fun FirestoreNotesScreen() {
    // TODO: Add Firestore integration and UI here
}
Task 1
Task 2
Task 3
Task 4
Task 5
Task 6
Task 7
Solution
Android Kotlin
package com.example.firestoreapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.ListenerRegistration

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            FirestoreNotesScreen()
        }
    }
}

@Composable
fun FirestoreNotesScreen() {
    val db = remember { FirebaseFirestore.getInstance() }
    var noteText by remember { mutableStateOf("") }
    var notes by remember { mutableStateOf(listOf<String>()) }
    var listenerRegistration by remember { mutableStateOf<ListenerRegistration?>(null) }

    DisposableEffect(Unit) {
        listenerRegistration = db.collection("notes")
            .addSnapshotListener { snapshot, error ->
                if (error != null) {
                    // Handle error if needed
                    return@addSnapshotListener
                }
                if (snapshot != null) {
                    val noteList = snapshot.documents.mapNotNull { it.getString("text") }
                    notes = noteList
                }
            }
        onDispose {
            listenerRegistration?.remove()
        }
    }

    Column(modifier = Modifier.padding(16.dp)) {
        OutlinedTextField(
            value = noteText,
            onValueChange = { noteText = it },
            label = { Text("Enter note here...") },
            modifier = Modifier.fillMaxWidth()
        )
        Spacer(modifier = Modifier.height(8.dp))
        Button(
            onClick = {
                if (noteText.isNotBlank()) {
                    val noteData = hashMapOf("text" to noteText.trim())
                    db.collection("notes").add(noteData)
                    noteText = ""
                }
            },
            enabled = noteText.isNotBlank(),
            modifier = Modifier.fillMaxWidth()
        ) {
            Text("Add Note")
        }
        Spacer(modifier = Modifier.height(16.dp))
        Text("Notes:", style = MaterialTheme.typography.titleMedium)
        Spacer(modifier = Modifier.height(8.dp))
        LazyColumn {
            items(notes) { note ->
                Text("- $note", style = MaterialTheme.typography.bodyLarge)
                Spacer(modifier = Modifier.height(4.dp))
            }
        }
    }
}

This solution uses Jetpack Compose to build the UI and Firebase Firestore to store and retrieve notes.

We keep the note input text in a mutableStateOf variable to update the UI as the user types.

We listen to the Firestore 'notes' collection with addSnapshotListener to get real-time updates and update the notes list state.

The Add Note button is disabled when the input is empty to prevent empty notes.

When the button is clicked, the note is trimmed and added to Firestore, then the input is cleared.

The notes list is displayed below with a simple bullet style.

Final Result
Completed Screen
-------------------------
| Simple Firestore Notes |
-------------------------
| [Enter note here...]  |
| [Add Note Button]     |
|-----------------------|
| Notes:                |
| - Buy groceries       |
| - Call mom            |
| - Read a book         |
-------------------------
User types a note in the text field
Add Note button enables only when text is not empty
Tapping Add Note saves the note to Firestore and clears input
Notes list updates instantly showing all saved notes
Stretch Goal
Add a swipe-to-delete gesture to remove notes from Firestore
💡 Hint
Use Compose's Modifier.pointerInput with detectSwipeGestures and call Firestore delete on the note document