Android-App mit Firebase und Jetpack Compose erstellen

1. Einführung

Zuletzt aktualisiert: 16.11.2022

Android-App mit Firebase und Jetpack Compose entwickeln

In diesem Codelab erstellen Sie eine Android-App namens Make It So. Die Benutzeroberfläche dieser App wird vollständig mit Jetpack Compose erstellt, dem modernen Toolkit von Android zum Erstellen nativer Benutzeroberflächen .Es ist intuitiv und erfordert weniger Code als das Schreiben von XML-Dateien und das Binden dieser Dateien an Aktivitäten, Fragmente oder Ansichten.

Der erste Schritt, um zu verstehen, wie gut Firebase und Jetpack Compose zusammenarbeiten, besteht darin, die moderne Android-Architektur zu verstehen. Eine gute Architektur macht das System leicht verständlich, einfach zu entwickeln und einfach zu warten, da sie sehr deutlich macht, wie die Komponenten organisiert sind und miteinander kommunizieren. In der Android-Welt wird die empfohlene Architektur als Model – View – ViewModel bezeichnet. Das Modell stellt die Ebene dar, über die auf Daten in der Anwendung zugegriffen wird. Die View ist die UI-Ebene und sollte nichts über die Geschäftslogik wissen. In der ViewModel wird die Geschäftslogik angewendet. Dazu muss die ViewModel manchmal die Model-Ebene aufrufen.

Wir empfehlen Ihnen dringend, diesen Artikel zu lesen, um zu verstehen, wie das Model-View-ViewModel-Muster auf eine mit Jetpack Compose erstellte Android-App angewendet wird. So ist die Codebasis leichter zu verstehen und die nächsten Schritte lassen sich einfacher ausführen.

Umfang

Make It So ist eine einfache To-do-Listen-App, mit der Nutzer Aufgaben hinzufügen und bearbeiten, Flags, Prioritäten und Fälligkeitsdaten hinzufügen und Aufgaben als erledigt markieren können. Die Bilder unten zeigen die beiden Hauptseiten dieser Anwendung: die Seite zum Erstellen von Aufgaben und die Hauptseite mit der Liste der erstellten Aufgaben.

„Aufgabe hinzufügen“-Bildschirm „Make it So“-Startbildschirm

Sie fügen einige Funktionen hinzu, die in dieser App fehlen:

  • Nutzer mit E-Mail-Adresse und Passwort authentifizieren
  • Listener für eine Firestore-Sammlung hinzufügen und die Benutzeroberfläche auf Änderungen reagieren lassen
  • Benutzerdefinierte Traces hinzufügen, um die Leistung von bestimmtem Code in der App zu beobachten
  • Funktionsschalter mit Remote Config erstellen und mit stufenweisem Roll-out einführen

Lerninhalte

  • Firebase Authentication, Performance Monitoring, Remote Config und Cloud Firestore in einer modernen Android-Anwendung verwenden
  • Firebase-APIs in eine MVVM-Architektur einfügen
  • Änderungen, die mit Firebase APIs vorgenommen wurden, in einer Compose-Benutzeroberfläche darstellen

Voraussetzungen

2. Beispiel-App herunterladen und Firebase einrichten

Code der Beispiel-App abrufen

Klonen Sie das GitHub-Repository über die Befehlszeile:

git clone https://github.com/FirebaseExtended/make-it-so-android.git

Firebase-Projekt erstellen

  1. Melden Sie sich mit Ihrem Google-Konto in der Firebase Console an.
  2. Klicken Sie auf die Schaltfläche zum Erstellen eines neuen Projekts und geben Sie einen Projektnamen ein (z. B. Compose Firebase codelab).
  3. Klicken Sie auf Weiter.
  4. Lesen und akzeptieren Sie bei Aufforderung die Firebase-Nutzungsbedingungen und klicken Sie dann auf Weiter.
  5. (Optional) Aktivieren Sie die KI-Unterstützung in der Firebase Console (als „Gemini in Firebase“ bezeichnet).
  6. Für dieses Codelab benötigen Sie Google Analytics, um erweiterte Targeting-Optionen mit Remote Config zu verwenden. Lassen Sie die Ein/Aus-Schaltfläche für die Google Analytics-Option also aktiviert. Folgen Sie der Anleitung auf dem Bildschirm, um Google Analytics einzurichten.
  7. Klicken Sie auf Projekt erstellen, warten Sie, bis Ihr Projekt bereitgestellt wurde, und klicken Sie dann auf Weiter.

Android-App zu Ihrem Firebase-Projekt hinzufügen

In Ihrem Firebase-Projekt können Sie verschiedene Apps registrieren: für Android, iOS, Web, Flutter und Unity.

Wählen Sie die Android-Option aus, wie hier zu sehen:

Firebase-Projektübersicht

Führen Sie dann folgende Schritte aus:

  1. Geben Sie com.example.makeitso als Paketnamen und optional einen Alias ein. Für dieses Codelab müssen Sie das Debug-Signaturzertifikat nicht hinzufügen.
  2. Klicken Sie auf Weiter, um Ihre App zu registrieren und auf die Firebase-Konfigurationsdatei zuzugreifen.
  3. Klicken Sie auf google-services.json herunterladen, um die Konfigurationsdatei herunterzuladen, und speichern Sie sie im Verzeichnis make-it-so-android/app.
  4. Klicken Sie auf Weiter. Da die Firebase-SDKs bereits in der Datei build.gradle im Beispielprojekt enthalten sind, klicken Sie auf Weiter, um zu Nächste Schritte zu gelangen.
  5. Klicken Sie auf Weiter zur Konsole, um den Vorgang abzuschließen.

Damit die App Make it So richtig funktioniert, müssen Sie in der Console zwei Dinge tun, bevor Sie mit dem Programmieren beginnen: Authentifizierungsanbieter aktivieren und die Firestore-Datenbank erstellen.

Authentifizierung einrichten

Aktivieren wir zuerst die Authentifizierung, damit sich Nutzer in der App anmelden können:

  1. Wählen Sie im Menü Build (Erstellen) die Option Authentifizierung aus und klicken Sie dann auf Jetzt starten.
  2. Wählen Sie auf der Karte Anmeldemethode die Option E-Mail/Passwort aus und aktivieren Sie sie.
  3. Klicken Sie als Nächstes auf Neuen Anbieter hinzufügen und wählen Sie Anonym aus und aktivieren Sie die Option.

Cloud Firestore einrichten

Richten Sie als Nächstes Firestore ein. Sie verwenden Firestore, um die Aufgaben eines angemeldeten Nutzers zu speichern. Jeder Nutzer erhält ein eigenes Dokument in einer Sammlung der Datenbank.

  1. Maximieren Sie im linken Bereich der Firebase Console Build und wählen Sie dann Firestore-Datenbank aus.
  2. Klicken Sie auf Datenbank erstellen.
  3. Belassen Sie die Database ID (Datenbank-ID) auf (default).
  4. Wählen Sie einen Speicherort für Ihre Datenbank aus und klicken Sie auf Weiter.
    Für eine echte App sollten Sie einen Speicherort auswählen, der sich in der Nähe Ihrer Nutzer befindet.
  5. Klicken Sie auf Im Testmodus starten. Lesen Sie den Haftungsausschluss zu den Sicherheitsregeln.
    In den nächsten Schritten dieses Abschnitts fügen Sie Sicherheitsregeln hinzu, um Ihre Daten zu schützen. Veröffentlichen Sie eine App nicht öffentlich, ohne Sicherheitsregeln für Ihre Datenbank hinzuzufügen.
  6. Klicken Sie auf Erstellen.

Wir erstellen jetzt robuste Sicherheitsregeln für die Firestore-Datenbank.

  1. Öffnen Sie das Firestore-Dashboard und rufen Sie den Tab Regeln auf.
  2. Aktualisieren Sie die Sicherheitsregeln so:
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /tasks/{document} {
      allow create: if request.auth != null;
      allow read, update, delete: if request.auth != null
        && resource.data.userId == request.auth.uid
        && request.data.userId == resource.data.userId;
    }
  }
}

Diese Regeln besagen im Grunde, dass jeder angemeldete Nutzer der App in jeder Sammlung ein Dokument für sich selbst erstellen kann. Nach der Erstellung kann nur der Nutzer, der das Dokument erstellt hat, es ansehen, aktualisieren oder löschen.

Anwendung ausführen

Jetzt können Sie die Anwendung ausführen. Öffnen Sie den Ordner make-it-so-android/start in Android Studio und führen Sie die App aus (das kann mit einem Android-Emulator oder einem echten Android-Gerät erfolgen).

3. Firebase Authentication

Welche Funktion möchten Sie hinzufügen?

In der aktuellen Version der Make It So-Beispiel-App kann ein Nutzer die App verwenden, ohne sich zuerst anmelden zu müssen. Dazu wird die anonyme Authentifizierung verwendet. Mit anonymen Konten können Nutzer jedoch nicht auf ihre Daten auf anderen Geräten oder in zukünftigen Sitzungen zugreifen. Die anonyme Authentifizierung ist zwar für ein sanftes Onboarding nützlich, Sie sollten Nutzern aber immer die Möglichkeit geben, zu einer anderen Anmeldeform zu wechseln. In diesem Codelab fügen Sie der App Make It So die E‑Mail- und Passwortauthentifizierung hinzu.

Zeit zum Programmieren!

Sobald der Nutzer ein Konto erstellt hat, indem er eine E-Mail-Adresse und ein Passwort eingibt, müssen Sie die Firebase Authentication API nach Anmeldedaten für die E-Mail-Adresse fragen und die neuen Anmeldedaten mit dem anonymen Konto verknüpfen. Öffnen Sie die Datei AccountServiceImpl.kt in Android Studio und aktualisieren Sie die Funktion linkAccount so, dass sie so aussieht:

model/service/impl/AccountServiceImpl.kt

override suspend fun linkAccount(email: String, password: String) {
    val credential = EmailAuthProvider.getCredential(email, password)
    auth.currentUser!!.linkWithCredential(credential).await()
}

Öffnen Sie nun SignUpViewModel.kt und rufen Sie die Dienstfunktion linkAccount innerhalb des launchCatching-Blocks der Funktion onSignUpClick auf:

screens/sign_up/SignUpViewModel.kt

launchCatching {
    accountService.linkAccount(email, password)
    openAndPopUp(SETTINGS_SCREEN, SIGN_UP_SCREEN)
}

Zuerst wird versucht, die Authentifizierung durchzuführen. Wenn der Aufruf erfolgreich ist, wird zum nächsten Bildschirm (SettingsScreen) gewechselt. Da Sie diese Aufrufe in einem launchCatching-Block ausführen, wird die Ausnahme abgefangen und verarbeitet, wenn in der ersten Zeile ein Fehler auftritt. Die zweite Zeile wird dann gar nicht erreicht.

Sobald SettingsScreen wieder geöffnet wird, müssen Sie dafür sorgen, dass die Optionen Anmelden und Konto erstellen nicht mehr angezeigt werden, da der Nutzer jetzt bereits authentifiziert ist. Dazu lassen wir SettingsViewModel auf den Status des aktuellen Nutzers (verfügbar in AccountService.kt) warten, um zu prüfen, ob das Konto anonym ist oder nicht. Aktualisieren Sie dazu uiState in SettingsViewModel.kt so:

screens/settings/SettingsViewModel.kt

val uiState = accountService.currentUser.map {
    SettingsUiState(it.isAnonymous)
}

Als Letztes müssen Sie uiState in SettingsScreen.kt aktualisieren, um die vom SettingsViewModel ausgegebenen Status zu erfassen:

screens/settings/SettingsScreen.kt

val uiState by viewModel.uiState.collectAsState(
    initial = SettingsUiState(false)
)

Jedes Mal, wenn sich der Nutzer ändert, wird die SettingsScreen neu zusammengesetzt, um die Optionen entsprechend dem neuen Authentifizierungsstatus des Nutzers anzuzeigen.

Zeit für einen Test!

Führen Sie Make it So aus und rufen Sie die Einstellungen auf, indem Sie rechts oben auf dem Bildschirm auf das Zahnradsymbol klicken. Klicken Sie dort auf die Option zum Erstellen eines Kontos:

Bildschirm „Mach es so“ „Make it So“-Registrierungsbildschirm

Geben Sie eine gültige E‑Mail-Adresse und ein starkes Passwort ein, um Ihr Konto zu erstellen. Es sollte funktionieren und Sie sollten zur Einstellungsseite weitergeleitet werden, auf der Sie zwei neue Optionen sehen: zum Abmelden und zum Löschen Ihres Kontos. Sie können das neue Konto, das im Authentifizierungs-Dashboard in der Firebase Console erstellt wurde, auf dem Tab „Nutzer“ aufrufen.

4. Cloud Firestore

Welche Funktion möchten Sie hinzufügen?

Für Cloud Firestore fügen Sie der Firestore-Sammlung, in der die Dokumente gespeichert sind, die die in Make it So angezeigten Aufgaben darstellen, einen Listener hinzu. Sobald Sie diesen Listener hinzugefügt haben, erhalten Sie jede Aktualisierung, die an dieser Sammlung vorgenommen wird.

Zeit zum Programmieren!

Aktualisieren Sie die Flow in StorageServiceImpl.kt so:

model/service/impl/StorageServiceImpl.kt

override val tasks: Flow<List<Task>>
    get() =
      auth.currentUser.flatMapLatest { user ->
        firestore.collection(TASK_COLLECTION).whereEqualTo(USER_ID_FIELD, user.id).dataObjects()
      }

Mit diesem Code wird ein Listener für die Sammlung „tasks“ basierend auf user.id hinzugefügt. Jede Aufgabe wird durch ein Dokument in einer Sammlung namens tasks dargestellt und jede Aufgabe hat ein Feld namens userId. Wenn sich der Status des currentUser ändert (z. B. durch Abmelden), wird ein neues Flow ausgegeben.

Jetzt müssen Sie dafür sorgen, dass die Flow in TasksViewModel.kt mit der im Dienst übereinstimmt:

screens/tasks/TasksViewModel.kt

val tasks = storageService.tasks

Und schließlich muss die composable function in TasksScreens.kt, die die Benutzeroberfläche darstellt, diesen Ablauf kennen und als Status erfassen. Jedes Mal, wenn sich der Status ändert, wird die zusammensetzbare Funktion automatisch neu zusammengesetzt und dem Nutzer wird der aktuelle Status angezeigt. Fügen Sie Folgendes zu TasksScreen composable function hinzu:

screens/tasks/TasksScreen.kt

val tasks = viewModel
    .tasks
    .collectAsStateWithLifecycle(emptyList())

Sobald die zusammensetzbare Funktion Zugriff auf diese Status hat, können Sie LazyColumn (die Struktur, die Sie zum Anzeigen einer Liste auf dem Bildschirm verwenden) so aktualisieren:

screens/tasks/TasksScreen.kt

LazyColumn {
    items(tasks.value, key = { it.id }) { taskItem ->
        TaskItem( [...] )
    }
}

Zeit für einen Test!

Um zu testen, ob es funktioniert hat, fügen Sie über die App eine neue Aufgabe hinzu. Klicken Sie dazu rechts unten auf dem Bildschirm auf die Schaltfläche „Hinzufügen“. Nachdem Sie die Aufgabe erstellt haben, sollte sie in der Firestore-Sammlung in der Firestore Console angezeigt werden. Wenn Sie sich auf anderen Geräten mit demselben Konto in Mach es möglich anmelden, können Sie Ihre Aufgaben bearbeiten und sehen, wie sie auf allen Geräten in Echtzeit aktualisiert werden.

5. Performance Monitoring

Welche Funktion möchten Sie hinzufügen?

Die Leistung ist sehr wichtig, da Nutzer Ihre App wahrscheinlich nicht mehr verwenden, wenn die Leistung schlecht ist und sie zu viel Zeit benötigen, um eine einfache Aufgabe damit zu erledigen. Deshalb ist es manchmal nützlich, einige Messwerte zu einem bestimmten Ablauf zu erfassen, den ein Nutzer in Ihrer App durchläuft. Firebase Performance Monitoring bietet Ihnen dazu benutzerdefinierte Traces. Folgen Sie der Anleitung, um benutzerdefinierte Traces hinzuzufügen und die Leistung in verschiedenen Codeabschnitten in Make it So zu messen.

Zeit zum Programmieren!

Wenn Sie die Datei Performance.kt öffnen, sehen Sie eine Inline-Funktion namens „trace“. Diese Funktion ruft die Performance Monitoring API auf, um einen benutzerdefinierten Trace zu erstellen, und übergibt den Tracenamen als Parameter. Der andere Parameter ist der Codeblock, den Sie überwachen möchten. Der Standardmesswert, der für jeden Trace erfasst wird, ist die Zeit, die für die vollständige Ausführung benötigt wird:

model/service/Performance.kt

inline fun <T> trace(name: String, block: Trace.() -> T): T = Trace.create(name).trace(block)

Sie können auswählen, welche Teile des Quellcodes für Sie wichtig sind und benutzerdefinierte Traces hinzufügen. Hier ist ein Beispiel für das Hinzufügen eines benutzerdefinierten Traces zur Funktion linkAccount, die Sie zuvor (in AccountServiceImpl.kt) in diesem Codelab gesehen haben:

model/service/impl/AccountServiceImpl.kt

override suspend fun linkAccount(email: String, password: String): Unit =
  trace(LINK_ACCOUNT_TRACE) {
      val credential = EmailAuthProvider.getCredential(email, password)
      auth.currentUser!!.linkWithCredential(credential).await()
  }

Jetzt sind Sie an der Reihe. Fügen Sie der App Make it So einige benutzerdefinierte Traces hinzu und fahren Sie mit dem nächsten Abschnitt fort, um zu testen, ob alles wie erwartet funktioniert hat.

Zeit für einen Test!

Nachdem Sie die benutzerdefinierten Traces hinzugefügt haben, führen Sie die App aus und verwenden Sie die Funktionen, die Sie messen möchten, einige Male. Rufen Sie dann die Firebase Console auf und öffnen Sie das Leistungs-Dashboard. Unten auf dem Bildschirm sehen Sie drei Tabs: Netzwerkanfragen, Benutzerdefinierte Traces und Bildschirmrendering.

Rufen Sie den Tab Benutzerdefinierte Traces auf und prüfen Sie, ob die Traces, die Sie im Code hinzugefügt haben, dort angezeigt werden und wie viel Zeit für die Ausführung dieser Codeabschnitte benötigt wird.

6. Remote Config

Welche Funktion möchten Sie hinzufügen?

Es gibt viele Anwendungsfälle für Remote Config, von der Änderung des Erscheinungsbilds Ihrer App bis hin zur Konfiguration unterschiedlicher Verhaltensweisen für verschiedene Nutzersegmente. In diesem Codelab verwenden Sie Remote Config, um ein Feature-Toggle zu erstellen, mit dem das neue Feature Aufgabe bearbeiten in der App Mach es möglich ein- oder ausgeblendet wird.

Zeit zum Programmieren!

Zuerst müssen Sie die Konfiguration in der Firebase Console erstellen. Rufen Sie dazu das Remote Config-Dashboard auf und klicken Sie auf die Schaltfläche Parameter hinzufügen. Füllen Sie die Felder entsprechend dem Bild unten aus:

Dialogfeld „Remote Config-Parameter erstellen“

Wenn alle Felder ausgefüllt sind, können Sie auf die Schaltfläche Speichern und dann auf Veröffentlichen klicken. Nachdem der Parameter erstellt wurde und in Ihrem Code verfügbar ist, müssen Sie den Code hinzufügen, mit dem die neuen Werte in Ihrer App abgerufen werden. Öffnen Sie die Datei ConfigurationServiceImpl.kt und aktualisieren Sie die Implementierung dieser beiden Funktionen:

model/service/impl/ConfigurationServiceImpl.kt

override suspend fun fetchConfiguration(): Boolean {
  return remoteConfig.fetchAndActivate().await()
}

override val isShowTaskEditButtonConfig: Boolean
  get() = remoteConfig[SHOW_TASK_EDIT_BUTTON_KEY].asBoolean()

Die erste Funktion ruft die Werte vom Server ab. Sie wird in SplashViewModel.kt aufgerufen, sobald die App gestartet wird. So können Sie am besten dafür sorgen, dass von Anfang an die aktuellsten Werte auf allen Bildschirmen verfügbar sind. Es ist nicht nutzerfreundlich, wenn Sie die Benutzeroberfläche oder das Verhalten der App später ändern, während der Nutzer gerade etwas tut.

Die zweite Funktion gibt den booleschen Wert zurück, der für den Parameter veröffentlicht wurde, den Sie gerade in der Console erstellt haben. Sie müssen diese Informationen in TasksViewModel.kt abrufen, indem Sie der Funktion loadTaskOptions Folgendes hinzufügen:

screens/tasks/TasksViewModel.kt

fun loadTaskOptions() {
  val hasEditOption = configurationService.isShowTaskEditButtonConfig
  options.value = TaskActionOption.getOptions(hasEditOption)
}

Sie rufen den Wert in der ersten Zeile ab und verwenden ihn, um die Menüoptionen für die Aufgaben in der zweiten Zeile zu laden. Wenn der Wert false ist, enthält das Menü die Bearbeitungsoption nicht. Nachdem Sie die Liste der Optionen haben, müssen Sie dafür sorgen, dass sie in der Benutzeroberfläche richtig angezeigt wird. Wenn Sie eine App mit Jetpack Compose entwickeln, müssen Sie nach der composable function suchen, die angibt, wie die Benutzeroberfläche der TasksScreen aussehen soll. Öffnen Sie also die Datei TasksScreen.kt und aktualisieren Sie LazyColum, sodass sie auf die in TasksViewModel.kt verfügbaren Optionen verweist:

screens/tasks/TasksScreen.kt

val options by viewModel.options

LazyColumn {
  items(tasks.value, key = { it.id }) { taskItem ->
    TaskItem(
      options = options,
      [...]
    )
  }
}

Das TaskItem ist ein weiteres composable function, das festlegt, wie die Benutzeroberfläche einer einzelnen Aufgabe aussehen soll. Jede Aufgabe hat ein Menü mit Optionen, das angezeigt wird, wenn der Nutzer auf das Dreipunkt-Menü am Ende der Aufgabe klickt.

Zeit für einen Test!

Jetzt können Sie die App ausführen. Prüfen Sie, ob der Wert, den Sie über die Firebase Console veröffentlicht haben, dem Verhalten der App entspricht:

  • Wenn es false ist, sollten beim Klicken auf das Dreipunkt-Menü nur zwei Optionen angezeigt werden:
  • Wenn es true ist, sollten beim Klicken auf das Dreipunkt-Menü drei Optionen angezeigt werden:

Ändern Sie den Wert einige Male in der Console und starten Sie die App neu. So einfach lassen sich neue Funktionen in Ihrer App mit Remote Config einführen.

7. Glückwunsch

Herzlichen Glückwunsch! Sie haben erfolgreich eine Android-App mit Firebase und Jetpack Compose erstellt.

Sie haben Firebase Authentication, Performance Monitoring, Remote Config und Cloud Firestore in eine Android-App eingebunden, die vollständig mit Jetpack Compose für die Benutzeroberfläche erstellt wurde, und sie in die empfohlene MVVM-Architektur integriert.

Weitere Informationen

Referenzdokumente