Wie erstellt man ein Backend für eine Android-App?
In diesem Artikel sprechen wir über Android – eines der beliebtesten Betriebssysteme. Wir befassen uns mit den Vor- und Nachteilen der Android-Entwicklung, Backend-Optionen für mobile Anwendungen und zeigen Ihnen, wie Sie Ihr eigenes mobiles Backend erstellen können.
Contents
- 1 Wichtigste Erkenntnisse
- 2 Was ist Android?
- 3 Vorteile der Android-Entwicklung
- 4 Beschränkungen der Android-Entwicklung
- 5 Backend-Optionen für Android-Anwendungen
- 6 Wie erstellt man ein Backend für eine Android-App?
- 7 Schlussfolgerung
Wichtigste Erkenntnisse
- Die Dominanz von Android: Android ist ein Open-Source-Betriebssystem, das auf rund 70 % aller mobilen Geräte mit über drei Milliarden aktiven Nutzern zum Einsatz kommt.
- Backend-Optionen für Apps: Für mobile App-Backends können sich Entwickler für Infrastructure as a Service (IaaS), Platform as a Service (PaaS) oder Backend as a Service (BaaS) entscheiden.
- Schritte zur Erstellung Ihres Backends: Am Ende des Artikels finden Sie eine ausführliche Anleitung, wie Sie ein Android-Backend mit einer BaaS-Plattform und dem Quellcode erstellen können.
Was ist Android?
Android ist ein freies und quelloffenes Linux-basiertes Betriebssystem. Es wurde in erster Linie für mobile Geräte wie Smartphones und Tablets entwickelt, wird aber inzwischen auch für Smart-TVs, eingebettete Systeme, Spielkonsolen usw. verwendet.
Die Entwicklung von Android begann im Jahr 2003 durch Android Inc. Das Unternehmen wollte ursprünglich ein Betriebssystem für Digitalkameras entwickeln, verlegte sich aber schnell auf die Entwicklung mobiler Betriebssysteme, um einen breiteren Markt zu erreichen.
Im Jahr 2005 wurde das Unternehmen mitsamt seinen Mitarbeitern von Google übernommen. Die erste Version von Android wurde im Jahr 2008 veröffentlicht.
Obwohl Android ein Open-Source-Betriebssystem ist, läuft auf den meisten Mobilgeräten die proprietäre Version von Google. Auf dieser Version ist Software wie Google Chrome, YouTube, Google TV und Gmail vorinstalliert.
Aufgrund der großartigen Anpassungsmöglichkeiten von Android passen viele Hersteller auch Android an, um ihr Unternehmen besser zu repräsentieren. Aus diesem Grund sieht OnePlus Android ganz anders aus als Pixel Android.
Android ist seit 2013 das beliebteste Betriebssystem. Es wird von rund 70 % der mobilen Geräte verwendet und hat über drei Milliarden monatlich aktive Nutzer.
Darüber hinaus bietet Ihnen der Google Play Store Zugang zu mehr als drei Millionen mobilen Anwendungen. Lesen Sie weiter, um zu erfahren, wie Sie ein Backend für eine Android-App erstellen.
Vorteile der Android-Entwicklung
Lassen Sie uns einige der Vorteile der Entwicklung für Android erkunden.
Plattformübergreifend
Durch die Entwicklung für Android können Sie eine breite Palette von Geräten ansprechen. Dazu gehören Mobiltelefone, Wearables, Smart-TVs, Spielkonsolen und mehr. Wenn Sie wissen, wie man eine mobile App programmiert, werden Sie kein Problem haben, eine App für Wearables oder Smart-TVs zu entwickeln.
Enormer Markt
Wie bereits erwähnt, hat Android mit 70 % einen größeren Marktanteil als iOS mit 30 %. Wenn Sie Android-Apps entwickeln, erhalten Sie automatisch Zugang zu einem breiteren Publikum.
Darüber hinaus sind Android-Apps für ihre geringen Investitionen und ihre hohe Rentabilität bekannt. Im Gegensatz zu iOS fallen auch keine jährlichen Entwicklergebühren an.
Anpassungsfähigkeit
Android-Geräte sind im Vergleich zu anderen Betriebssystemen sehr anpassbar. Sie ermöglichen es Ihnen, praktisch alles zu ändern, was Sie sich vorstellen können.
Außerdem können Sie Ihre App unter Android problemlos in andere Dienste von Drittanbietern integrieren.
Gemeinschaft
Android wird von einer großen Gemeinschaft von Open-Source-Entwicklern unterstützt. Außerdem wird es mit vielen entwicklerfreundlichen Tools wie Android Studio, ADB und Logcat geliefert, mit denen Sie ganz einfach Anwendungen programmieren können.
Sollten Sie einmal nicht weiterkommen, gibt es mehrere Plattformen, auf denen Sie Hilfe finden können, darunter GitHub, StackOverflow, Reddit und andere Android-Communitys.
Beschränkungen der Android-Entwicklung
Hier sind einige der Nachteile der Android-Entwicklung.
Sicherheit
Android ist weniger sicher als iOS und hält sich nicht an strenge Sicherheitsprotokolle. Da Android Open-Source ist, werden wöchentlich Sicherheitslücken entdeckt. Dies gibt Hackern die Möglichkeit, diese Schwachstellen auszunutzen, bevor sie gepatcht werden.
Android-Geräte können auch verwurzelt werden, um Superuser-Zugriff zu erhalten. Dies macht Ihr Gerät zwar leistungsfähiger, ist aber auch riskant, da einige integrierte Sicherheitsmaßnahmen deaktiviert werden.
Komplexität
Android-Geräte gibt es in verschiedenen Formen und Größen. Das ist zwar großartig, kann aber auch ein großer Nachteil sein, wenn man Android-Apps für verschiedene Gerätetypen entwickelt.
Um sicherzustellen, dass Ihre App mit so vielen Geräten wie möglich kompatibel ist, müssen Sie ein responsives Design einführen, die Hardware der verschiedenen Geräte berücksichtigen und so weiter.
Premium-Anwendungen
Premium-Apps sind im Google Play Store weniger erfolgreich als im App Store. Es ist kein Geheimnis, dass Android-Nutzer tendenziell weniger für Apps ausgeben als iOS-Nutzer. Wenn Sie an einer Premium-Anwendung arbeiten, sollten Sie Android als Ihre zweite Wahl betrachten.
Backend-Optionen für Android-Anwendungen
Welches ist das beste Backend für eine Android-Anwendung? Backends für mobile Anwendungen können in Ihrer eigenen Infrastruktur gehostet oder in Cloud-Diensten bereitgestellt werden. Zu den beliebtesten Cloud-Computing-Modellen für mobile Backends gehören:
- Infrastruktur als Dienstleistung (IaaS)
- Plattform als Dienstleistung (PaaS)
- Backend als Dienstleistung (BaaS)
Jede Option deckt verschiedene Abstraktionsebenen ab, wie in der folgenden Abbildung dargestellt.
Schauen wir uns jede Option im Detail an, damit Sie das am besten geeignete Cloud-Modell für Ihre Backend-Anwendungen auswählen können.
Infrastruktur als Dienstleistung (IaaS)
Infrastructure as a Service (IaaS) ist das am wenigsten abstrahierte Cloud-Computing-Modell. Bei diesem Modell bietet der Anbieter den Nutzern virtualisierte Ressourcen wie Server, Netzwerke, Speicher und Betriebssysteme über hochentwickelte APIs oder intuitive Dashboards an.
Das Beste an IaaS ist, dass es den Nutzern die vollständige Kontrolle über ihre gesamte Infrastruktur gibt. IaaS ist das flexibelste und skalierbarste Modell, aber auch das am schwierigsten zu verwaltende. Wenn Sie sich für diese Option entscheiden, benötigen Sie höchstwahrscheinlich einen oder zwei SysAdmins.
Einige Beispiele für IaaS sind Amazon Web Services, Google Cloud Platform und Azure.
Plattform als Dienstleistung (PaaS)
Platform as a Service (PaaS) ist ein Cloud-Computing-Modell, das Benutzern bei der Entwicklung, Verwaltung und Bereitstellung von Anwendungen helfen soll.
PaaS bietet nicht nur eine Infrastruktur, sondern auch benutzerfreundliche Tools für die Entwicklung, Anpassung und das Testen von Anwendungen.
Durch die Nutzung von PaaS können Sie sich auf Ihre Software und das Benutzererlebnis konzentrieren, ohne sich um die zugrunde liegende Infrastruktur kümmern zu müssen.
Außerdem stellt PaaS sicher, dass Ihre Anwendung bei Bedarf skaliert wird, kümmert sich um die Backups usw. Die Nachteile von PaaS sind ein geringeres Maß an Kontrolle, das Risiko der Anbieterbindung und vergleichsweise höhere Kosten.
Zu den beliebtesten PaaS-Plattformen gehören Heroku, Render und Digital Ocean App Platform.
Backend als Dienstleistung (BaaS)
Backend as a Service (BaaS) automatisiert den Backend-Teil der Entwicklung durch Bereitstellung einer vollwertigen Backend-Lösung.
Zu den BaaS-Funktionen gehören Benutzerverwaltung, Datenbanken, Authentifizierung, soziale Integrationen, Push-Benachrichtigungen, APIs, SDKs und mehr.
BaaS bietet Ihnen alle Vorteile von IaaS und PaaS und bietet gleichzeitig zusätzliche Funktionen. Teams, die BaaS nutzen, bringen ihre Produkte in der Regel schneller auf den Markt, senken die Entwicklungskosten und entwickeln bessere Software.
Zu den Nachteilen von BaaS gehören ein geringeres Maß an Kontrolle und Anpassung sowie die Möglichkeit einer Anbieterbindung bei nicht quelloffenen Plattformen.
BaaS-Beispiele sind Back4app, AWS Amplify und Firebase.
Wie erstellt man ein Backend für eine Android-App?
In diesem Artikel sehen wir uns an, wie man eine Back4app-basierte Backend-App erstellt und sich von einer Android-Anwendung aus mit ihr verbindet.
Voraussetzungen
- Erfahrung mit Kotlin und Android-Entwicklung.
- Grundlegendes Verständnis von Mobile Backend as a Service.
- Java und Android Studio müssen auf Ihrem lokalen Rechner installiert sein.
Was ist Back4app?
Back4app ist eine hervorragende Plattform, um Backends für moderne Anwendungen zu erstellen und den Entwicklungsprozess zu beschleunigen.
Es ist mit nützlichen serverseitigen Funktionen wie Benutzerverwaltung, Echtzeit-Datenbanken, sozialen Integrationen, Cloud-Code-Funktionen, Push-Benachrichtigungen, APIs und vielem mehr ausgestattet!
Durch den Einsatz von Back4app können Sie einen Großteil der Backend-Arbeiten auslagern und sich auf die kritischen Aspekte Ihrer Anwendung konzentrieren und die Entwicklung einer Android-App im Backend beschleunigen.
Sie müssen sich nicht mit der zugrundeliegenden Infrastruktur Ihres Backends, dem Backend-Server, der Skalierung, der Wartung usw. befassen.
Am wichtigsten ist, dass Back4app eine kostenlose Stufe anbietet, die sich hervorragend zum Experimentieren und Ausprobieren der Plattform eignet. Wenn Ihre App wächst, können Sie gegen eine monatliche Gebühr auf Premium-Pläne upgraden.
Projekt-Einführung
In diesem Artikel werden wir eine einfache Notizen-App erstellen. Mit der App können Benutzer Notizen hinzufügen, bearbeiten und löschen. Die Notizen werden in der Back4app-Datenbank gespeichert und über das Parse SDK bearbeitet.
Wir werden die Programmiersprache Kotlin verwenden, um die App zu erstellen. Für die Benutzeroberfläche verwenden wir Jetpack Compose – das moderne Android-Toolkit zur Erstellung nativer Benutzeroberflächen.
Back4app App erstellen
Als ersten Schritt zur Entwicklung eines Backends für eine Android-App benötigen Sie ein Back4app-Konto. Wenn Sie noch keins haben, melden Sie sich an.
Wenn Sie sich bei Ihrem Back4app-Konto anmelden, werden Sie zur App-Ansicht weitergeleitet. Klicken Sie auf “Neue App erstellen”, um den App-Erstellungsprozess zu starten.
Die Back4app-Plattform bietet zwei Lösungen:
- Backend as a Service (BaaS) — robuste Backend-Lösung
- Containers as a Service (CaaS) – Plattform für die Verwaltung von Containern (insbesondere Webanwendungen)
In Anbetracht der Tatsache, dass wir ein Backend für eine mobile App erstellen, entscheiden wir uns für “Backend as a Service”.
Geben Sie Ihrer App einen schönen und informativen Namen, wählen Sie “NoSQL” als Datenbank und klicken Sie auf “Erstellen”. Das ist ein wichtiger Schritt für die Bereitstellung eines Backends für eine Android-App.
Back4app benötigt eine gewisse Zeit, um alles für Ihre Anwendung vorzubereiten. Dazu gehören die Datenbank, die Benutzerverwaltung, die Skalierung, die Konfigurationen und so weiter. Sobald Ihre Anwendung fertig ist, werden Sie zur Datenbankansicht Ihrer Anwendung weitergeleitet.
Entwerfen Sie die Datenbank
Lassen Sie uns nun die Datenbank entwerfen. Dies ist ein notwendiger Schritt zur Entwicklung eines Backends für eine Android-App.
Da wir eine einfache Notizen-App erstellen, benötigen wir nur eine Klasse. Klicken Sie auf “Klasse erstellen”, nennen Sie sie Note
, aktivieren Sie “Public Read and Write” und klicken Sie auf “Klasse erstellen und Spalten hinzufügen”.
Fügen Sie anschließend die folgenden drei Felder zu der neu erstellten Klasse hinzu:
+-------------+-------------+--------------------+----------+
| Data type | Name | Default value | Required |
+-------------+-------------+--------------------+----------+
| String | icon | <leave blank> | yes |
+-------------+-------------+--------------------+----------+
| String | title | <leave blank> | yes |
+-------------+-------------+--------------------+----------+
| String | content | <leave blank> | yes |
+-------------+-------------+--------------------+----------+
Klicken Sie abschließend auf die Schaltfläche “Zeile hinzufügen” und füllen Sie Ihre Datenbank mit einigen Beispieldaten auf. Wenn Ihnen nichts einfällt, können Sie diesen Daten-Dump auch importieren.
Gut, das war’s mit dem Backend.
Code Frontend
In diesem Artikel werden wir eine neue Android-App booten, ein ViewModel einrichten, die Benutzeroberfläche implementieren, Parse SDK installieren und konfigurieren und schließlich Daten aus der Back4app-Echtzeitdatenbank abrufen.
Init-Projekt
Wie im Abschnitt “Voraussetzungen” erwähnt, müssen Sie für die folgenden Schritte Android Studio installiert haben. Wenn Sie es noch nicht haben, laden Sie es herunter.
Öffnen Sie zunächst Android Studio und klicken Sie auf die Schaltfläche “Neues Projekt”.
Wählen Sie dann “Leere Aktivität” als Projektvorlage und klicken Sie auf “Weiter”.
Um Ihr Projekt zu erstellen, müssen Sie einen Namen und einen Paketnamen angeben. Ich schlage vor, dass Sie AndroidApp
als Projektnamen und den Namen der umgekehrten Domäne als Paketnamen für Ihr Projekt verwenden.
Nachdem Sie alles konfiguriert haben, klicken Sie auf “Fertigstellen”, um das Projekt zu erstellen.
Android Studio benötigt etwa zwei Minuten, um alles Notwendige vorzubereiten. Dazu gehören die Erstellung der Projektdateistruktur, die Einrichtung von Gradle, die Installation von Abhängigkeiten usw.
Sobald Ihr Projekt fertig ist, verwenden Sie den Explorer, um zu MainActivity.kt zu navigieren und seinen Inhalt zu ersetzen:
// app/src/main/java.<your_package_name>/MainActivity.kt
package <your.package.name>
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.sp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background,
) {
Text(text = "Back4app rocks!", fontSize = 18.sp)
}
}
}
}
}
Stellen Sie sicher, dass Sie immer durch Ihren tatsächlichen Paketnamen ersetzen.
Versuchen Sie schließlich, die App zu starten, indem Sie auf den grünen Play-Button oder die Tastenkombination Shift + F10
auf Ihrer Tastatur klicken. Wenn alles gut geht, sollte der Emulator starten und Sie sollten die Back4app-Rocks-Meldung
auf dem Bildschirm sehen.
ViewModel
Um den globalen Zustand unserer App zu verwalten, werden wir ein ViewModel
verwenden. Zuvor müssen wir jedoch eine Note-Datenklasse
mit denselben Attributen wie in unserer Back4app-Datenbank erstellen.
Erstellen Sie eine Datenklasse mit dem Namen Note
:
// app/src/main/java.<your_package_name>/Note.kt
package <your.package.name>
data class Note(
var objectId: String? = null,
var icon: String,
var title: String,
var content: String,
) {
companion object {
fun generateObjectId(): String {
val chars = ('a'..'z') + ('A'..'Z') + ('0'..'9')
return (1..10).map { chars.random() }.joinToString("")
}
}
}
- Wir haben die statische Methode
generateObjectId()
definiert, um Parse-ähnliche Objekt-IDs zu erzeugen. objectId
ist nullbar, da wir später davon ausgehen, dass das Objekt noch nicht in der Datenbank gespeichert wurde, wennobjectId == null ist
.
Als nächstes erstellen Sie eine AppViewModel-Klasse
mit dem folgenden Inhalt:
// app/src/main/java.<your_package_name>/AppViewModel.kt
package <your.package.name>
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
class AppViewModel : ViewModel() {
val notes: MutableState<Map<String, Note>> = mutableStateOf(mapOf(
"7IggsqFAKt" to Note(
objectId = "7IggsqFAKt",
icon = "\uD83D\uDE80",
title = "Deploy app",
content = "Go ahead and deploy your backend to Back4app.",
),
"eFRNm0hTat" to Note(
objectId = "eFRNm0hTat",
icon = "\uD83C\uDFA8",
title = "Design website",
content = "Design the website for the conference.",
),
"uC7hTQmG5F" to Note(
objectId = "uC7hTQmG5F",
icon = "\uD83D\uDC42",
title = "Attend meeting",
content = "Attend meeting with the team to discuss the conference.",
),
))
companion object {
@Volatile
private var instance: AppViewModel? = null
fun getInstance(): AppViewModel {
return instance ?: synchronized(this) {
instance ?: AppViewModel().also { instance = it }
}
}
}
}
- Wir haben Compose’s
MutableState
verwendet, um UI-Updates im Falle von Datenänderungen auszulösen. - Der
MutableState
enthält eineMap
mitObjectIds
undNotes
, die wir mit Daten gefüllt haben. - Um sicherzustellen, dass es nur eine einzige Instanz von
AppViewModel
gibt, haben wir das Singleton-Muster verwendet.
Wir können nun auf die AppViewModel-Instanz
in unseren Aktivitäten über AppViewModel.getInstance()
zugreifen.
Haupttätigkeit
Ersetzen Sie den Inhalt von MainActivity.kt durch den folgenden Code, um die Notizen anzuzeigen:
// app/src/main/java.<your_package_name>/MainActivity.kt
package <your.package.name>
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
class MainActivity : ComponentActivity() {
private val viewModel = AppViewModel.getInstance()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val context = this as Context
setContent {
MainActivityContent(
viewModel = viewModel,
onNoteListItemClick = {
// TODO: Open note edit form
},
onNoteAddClick = {
// TODO: Open note create form
},
)
}
}
}
@Composable
fun MainActivityContent(
viewModel: AppViewModel,
onNoteListItemClick: (note: Note) -> Unit,
onNoteAddClick: () -> Unit,
) {
val notes = viewModel.notes.value
MaterialTheme {
Scaffold(
topBar = { TopAppBar(title = { Text("My Notes") }) },
floatingActionButton = {
ExtendedFloatingActionButton(
onClick = { onNoteAddClick() },
icon = { Icon(Icons.Filled.Add, contentDescription = "Add") },
text = { Text("Add") }
)
},
) { contentPadding ->
Box(modifier = Modifier.padding(contentPadding)) {
NoteList(notes, onNoteListItemClick = { onNoteListItemClick(it) })
}
}
}
}
@Composable
fun NoteListItem(note: Note, onNoteListItemClick: (note: Note) -> Unit) {
Row(
modifier = Modifier
.fillMaxWidth()
.clickable(onClick = { onNoteListItemClick(note) })
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Text(text = note.icon, fontSize = 32.sp, modifier = Modifier.size(48.dp))
Spacer(modifier = Modifier.width(8.dp))
Column {
Text(text = note.title, fontSize = 18.sp)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = note.content,
fontSize = 14.sp,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
}
@Composable
fun NoteList(notes: Map<String, Note>, onNoteListItemClick: (note: Note) -> Unit) {
LazyColumn {
items(notes.entries.toList()) { (_, note) ->
NoteListItem(note = note, onNoteListItemClick = onNoteListItemClick)
}
}
}
- Die
Notizen
werden jetzt aus demAppViewModel
geholt. - Anstatt die Klick-Ereignisse in Composables zu definieren, haben wir sie als Argumente weitergegeben.
- Wir haben Compose verwendet, um die Benutzeroberfläche zu gestalten. Um die Oberfläche glatter zu gestalten, haben wir
MaterialTheme
in dasScaffold-Layout
integriert.
Wenn Sie die App jetzt neu erstellen, sollten Sie die Liste der “fest codierten” Notizen auf dem Bildschirm sehen.
Notizformular Aktivität
In diesem Abschnitt fügen wir eine neue Aktivität hinzu, die es den Benutzern ermöglicht, Notizen hinzuzufügen und zu bearbeiten.
Beginnen Sie mit der Erstellung einer neuen Klasse namens FormActivity
mit folgendem Inhalt:
// app/src/main/java.<your_package_name>/FormActivity.kt
package <your.package.name>
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.Button
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
class FormActivity : ComponentActivity() {
private val viewModel = AppViewModel.getInstance()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val objectId = intent.getStringExtra("objectId")
val note = if (objectId !== null) viewModel.notes.value[objectId] else null
setContent {
FormActivityContent(
note,
onNoteAddClick = { icon: String, title: String, content: String ->
if (note !== null) return@FormActivityContent
val newNote = Note(
icon = icon,
title = title,
content = content,
)
newNote.objectId = Note.generateObjectId()
viewModel.notes.value += (newNote.objectId!! to newNote)
finish()
},
onNoteSaveClick = { icon: String, title: String, content: String ->
if (note === null) return@FormActivityContent
val updatedNote = note.copy()
updatedNote.icon = icon
updatedNote.title = title
updatedNote.content = content
viewModel.notes.value += (updatedNote.objectId!! to updatedNote)
finish()
},
onNoteDeleteClick = {
if (note === null) return@FormActivityContent
viewModel.notes.value = viewModel.notes.value.filter {
it.value.objectId != note.objectId
}
finish()
},
)
}
}
}
@Composable
fun FormActivityContent(
note: Note?,
onNoteAddClick: (icon: String, title: String, content: String) -> Unit,
onNoteSaveClick: (icon: String, title: String, content: String) -> Unit,
onNoteDeleteClick: () -> Unit,
) {
MaterialTheme {
Scaffold(
topBar = {
TopAppBar(title = { Text(note?.let { "Edit Note" } ?: ("Add Note")) })
},
floatingActionButton = {
if (note !== null) {
ExtendedFloatingActionButton(
onClick = { onNoteDeleteClick() },
icon = { Icon(Icons.Filled.Delete, "Delete") },
text = { Text("Delete") },
)
}
},
) { contentPadding ->
Box(modifier = Modifier.padding(contentPadding)) {
NoteForm(note = note, onNoteSave = { icon, title, content ->
if (note === null) {
onNoteAddClick(icon, title, content)
} else {
onNoteSaveClick(icon, title, content)
}
})
}
}
}
}
@Composable
fun NoteForm(
note: Note?,
onNoteSave: (icon: String, title: String, content: String) -> Unit
) {
var icon by remember { mutableStateOf(TextFieldValue(note?.icon ?: "")) }
var title by remember { mutableStateOf(TextFieldValue(note?.title ?: "")) }
var content by remember { mutableStateOf(TextFieldValue(note?.content ?: "")) }
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
TextField(
label = { Text(text = "Icon") },
value = icon,
onValueChange = { icon = it },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(16.dp))
TextField(
label = { Text(text = "Title") },
value = title,
onValueChange = { title = it },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(16.dp))
TextField(
label = { Text(text = "Content") },
value = content,
onValueChange = { content = it },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = { onNoteSave(icon.text, title.text, content.text) },
Modifier.fillMaxWidth()
) {
Text(text = "Save")
}
}
}
- Dieses Formular wird sowohl zum Hinzufügen als auch zum Bearbeiten von Notizen verwendet. Um die Aktion zu bestimmen, vergleichen wir
objectId == null
. Im Falle vonnull
handelt es sich um eine Hinzufügung, ansonsten um eine Bearbeitung. - Wenn
objectId !== null ist
, holen wir dieNotiz
aus dem Status und füllen das Formular aus. - Damit
MutableState
korrekt funktioniert, mussten wir seinen Inhalt als unveränderlich behandeln. Deshalb haben wir manchmal den Inhalt kopiert, anstatt ihn zu ändern. - Wir haben den Zustand des Compose-Formulars über
mutableStateOf()
behandelt.
Als nächstes registrieren Sie die FormActivity
am unteren Ende der Anwendung
in AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application>
<!-- ... -->
<activity android:name=".FormActivity"/>
</application>
</manifest>
Erstellen Sie schließlich ein neues Intent
auf onNoteListItemClick
und onNoteAddClick
in MainActivity.kt:
// app/src/main/java.<your_package_name>/MainActivity.kt
class MainActivity : ComponentActivity() {
// ...
override fun onCreate(savedInstanceState: Bundle?) {
// ...
setContent {
MainActivityContent(
viewModel = viewModel,
onNoteListItemClick = {
// triggers the edit action, since `objectId` is provided
val intent = Intent(context, FormActivity::class.java)
intent.putExtra("objectId", it.objectId)
context.startActivity(intent)
},
onNoteAddClick = {
// triggers the add action, since no `objectId` is present
val intent = Intent(context, FormActivity::class.java)
context.startActivity(intent)
},
)
}
}
}
Vergessen Sie nicht, Intent
am Anfang der Datei zu importieren:
import android.content.Intent
Wenn Sie die Anwendung neu erstellen, werden Sie feststellen, dass wir jetzt eine funktionierende Anwendung haben. Die Anwendung ermöglicht es uns, Notizen hinzuzufügen, sie zu bearbeiten und sie zu löschen.
Das einzige Problem ist, dass ein Neustart der App ihren Status zurücksetzt (auf die “hart kodierten” Notizen).
Im nächsten Abschnitt werden wir die App mit dem Back4app-Backend verbinden. So können wir den Status beibehalten und ihn zwischen mehreren Geräten synchronisieren.
Parse SDK installieren
Wie Sie vielleicht wissen, basiert Back4app auf der Parse-Plattform. Wenn wir mit der Back4app-Datenbank oder Back4app im Allgemeinen interagieren wollen, müssen wir das Parse SDK installieren.
Beginnen Sie damit, das JitPack-Repository zu settings.gradle hinzuzufügen:
// settings.gradle
pluginManagement {
repositories {
// ...
maven { url "https://jitpack.io" }
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
// ...
maven { url "https://jitpack.io" }
}
}
Als nächstes fügen Sie das Android Parse SDK zur build.gradle der App-Ebene hinzu:
// app/build.gradle
dependencies {
// ...
implementation "com.github.parse-community.Parse-SDK-Android:parse:4.2.0"
}
Synchronisieren Sie die Gradle-Einstellungen und stellen Sie sicher, dass keine Fehler vorhanden sind.
Parse SDK konfigurieren
Um sich mit dem Back4app-Backend zu verbinden, müssen Sie dem Parse SDK Ihre Anwendungs-ID und Ihren Client-Schlüssel mitteilen. Um Ihre Anmeldedaten zu erhalten, navigieren Sie zu Ihrer Back4app-App und wählen Sie “App Settings > Security & Keys” in der Seitenleiste.
Fügen Sie sie dann wie folgt zu Ihrer strings.xml hinzu:
<!-- app/src/main/res/values/strings.xml -->
<resources>
<string name="app_name">back4app-android-app</string>
<string name="back4app_server_url">https://parseapi.back4app.com/</string>
<string name="back4app_app_id">your_parse_app_id</string>
<string name="back4app_client_key">your_parse_client_key</string>
</resources>
Stellen Sie sicher, dass Sie
your_parse_app_id
undyour_parse_client_key
durch Ihre Anmeldedaten ersetzen.
Ändern Sie als Nächstes Ihre AndroidManifest.xml, um den Internetzugang zu aktivieren und die Metadaten für die Anmeldedaten anzuhängen:
<!-- app/src/main/AndroidManifest.xml -->
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- these two permissions enable internet access -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<application>
<!-- ... -->
<!-- newly added metadata -->
<meta-data
android:name="com.parse.SERVER_URL"
android:value="@string/back4app_server_url" />
<meta-data
android:name="com.parse.APPLICATION_ID"
android:value="@string/back4app_app_id" />
<meta-data
android:name="com.parse.CLIENT_KEY"
android:value="@string/back4app_client_key" />
</application>
</manifest>
Das letzte, was wir tun müssen, ist die Initialisierung von Parse. Um sicherzustellen, dass Parse vor allen anderen Aktivitäten initialisiert wird, erstellen wir eine neue Klasse namens App
, die von der Klasse Application
erbt.
Erstellen Sie App.kt und initialisieren Sie Parse wie folgt:
// app/src/main/java/<your_package_name>/App.kt
package <your.package.name>
import android.app.Application
import com.parse.Parse
class App : Application() {
override fun onCreate() {
super.onCreate()
Parse.initialize(
Parse.Configuration.Builder(this)
.applicationId(getString(R.string.back4app_app_id))
.clientKey(getString(R.string.back4app_client_key))
.server(getString(R.string.back4app_server_url))
.build()
)
}
}
Registrieren Sie dann die App-Klasse
in AndroidManifest.xml:
<!-- app/src/main/AndroidManifest.xml -->
<application
android:name=".App"
...
>
<!-- ... -->
</application>
Erstellen Sie die Anwendung erneut und überprüfen Sie das Logcat-Fenster auf Fehler. Wenn es keine Fehler gibt, war die Verbindung zu Back4app erfolgreich.
Notizen von Back4app laden
Das letzte, was wir vor der Fertigstellung unserer App tun müssen, ist, die Notizen aus der Back4app-Datenbank zu laden und uns anzusehen, wie man Parse in der Praxis einsetzt.
Navigieren Sie zunächst zum AppViewModel
. Entfernen Sie die Daten aus der Karte und fügen Sie den Init-Block
hinzu:
// app/src/main/java/<your_package_name>/AppViewModel.kt
package <your.package.name>
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
class AppViewModel : ViewModel() {
val notes: MutableState<Map<String, Note>> = mutableStateOf(mapOf())
init {
val query = com.parse.ParseQuery.getQuery<com.parse.ParseObject>("Note")
query.orderByDescending("createdAt")
query.findInBackground { notes, e ->
if (e == null) {
for (parseNote in notes) {
val note = Note(
objectId = parseNote.objectId,
icon = parseNote.getString("icon")!!,
title = parseNote.getString("title")!!,
content = parseNote.getString("content")!!,
)
this.notes.value += (note.objectId!! to note)
}
} else {
println("Error: ${e.message}")
}
}
}
companion object {
// ...
}
}
Dieser Code verwendet Parse SDK, um die Notizen aus den Datenbanken zu holen, sie in die Datenklasse "Note"
umzuwandeln und sie in der Karte zu speichern.
Fügen Sie dann die folgenden drei Methoden zu Note
hinzu:
// app/src/main/java/<your_package_name>/Note.kt
package <your.package.name>
import com.parse.ParseObject
import com.parse.ParseQuery
data class Note(
var objectId: String? = null,
var icon: String,
var title: String,
var content: String,
) {
fun addToParse(callback: (objectId: String) -> Unit) {
if (objectId !== null) throw Exception("Note is already saved to Parse!")
val parseNote = ParseObject("Note")
parseNote.put("icon", icon)
parseNote.put("title", title)
parseNote.put("content", content)
parseNote.saveInBackground {
if (it !== null) throw Exception("Error: ${it.message}")
objectId = parseNote.objectId
callback(parseNote.objectId)
}
}
fun updateToParse(callback: (objectId: String) -> Unit) {
if (objectId === null) throw Exception("Note hasn't been saved to Parse yet!")
val query = ParseQuery.getQuery<ParseObject>("Note")
val parseNote = query.get(objectId)
parseNote.put("icon", icon)
parseNote.put("title", title)
parseNote.put("content", content)
parseNote.saveInBackground {
if (it !== null) throw Exception("Error: ${it.message}")
callback(parseNote.objectId)
}
}
fun deleteFromParse(callback: () -> Unit) {
if (objectId === null) throw Exception("Note hasn't been saved to Parse yet!")
val query = ParseQuery.getQuery<ParseObject>("Note")
val parseNote = query.get(objectId)
parseNote.deleteInBackground {
if (it !== null) throw Exception("Error: ${it.message}")
callback()
}
}
}
addToParse()
fügt dem Parse-Server eine neue Notiz mit ihren Details hinzu. Bei Erfolg speichert sie den eindeutigen Bezeichner der Notiz und benachrichtigt, wenn sie fertig ist.updateToParse()
aktualisiert die Informationen zu einer bestehenden Notiz auf dem Parse-Server. Im Erfolgsfall meldet sie nach den Änderungen den Abschluss.deleteFromParse()
löscht eine gespeicherte Notiz vom Parse-Server. Im Erfolgsfall wird die Löschung nach Beendigung bestätigt.
Schließlich ändern Sie die Klickmethoden in FormActivity
, um die neu definierten Methoden aufzurufen:
// app/src/main/java/<your_package_name>/NoteFormActivity.kt
class FormActivity : ComponentActivity() {
// ...
override fun onCreate(savedInstanceState: Bundle?) {
// ...
setContent {
FormActivityContent(
note,
onNoteAddClick = { icon: String, title: String, content: String ->
if (note !== null) return@FormActivityContent
val newNote = Note(
icon = icon,
title = title,
content = content,
)
newNote.addToParse {
viewModel.notes.value += (it to newNote)
finish()
}
},
onNoteSaveClick = { icon: String, title: String, content: String ->
if (note === null) return@FormActivityContent
val updatedNote = note.copy()
updatedNote.icon = icon
updatedNote.title = title
updatedNote.content = content
updatedNote.updateToParse {
viewModel.notes.value += (it to updatedNote)
finish()
}
},
onNoteDeleteClick = {
if (note === null) return@FormActivityContent
viewModel.notes.value = viewModel.notes.value.filter {
it.value.objectId != note.objectId
}
note.deleteFromParse {
finish()
}
},
)
}
}
}
Das war’s!
Die Anwendung ist nun voll funktionsfähig und mit dem Back4app-Backend synchronisiert. Versuchen Sie, mit der Anwendung zu spielen, indem Sie die Daten ändern und prüfen, ob die Änderungen in der Datenbankansicht wiedergegeben werden.
Schlussfolgerung
In diesem Artikel haben wir erfolgreich ein mobiles Backend gebaut und uns von unserer Android-App aus mit diesem verbunden. Für das Backend haben wir die BaaS-Lösung von Back4app verwendet, und für das Frontend haben wir Kotlin mit Jetpack Compose eingesetzt.
Inzwischen sollten Sie ein gutes Verständnis dafür haben, wie mobile Backends funktionieren und in der Lage sein, Ihre eigenen zu erstellen. Sehen Sie sich den endgültigen Quellcode auf dem back4app-android-app-Repositorium an.