App Components in Android: Activity, Service, BroadcastReceiver, ContentProvider
App Components sind die vier Bausteine, mit denen Android Apps startet, verbindet und steuert. Lerne ihre Rollen kennen.
Wenn du eine Android-App baust, schreibst du nicht einfach ein einzelnes Programm mit einer main-Funktion. Stattdessen setzt du deine App aus mehreren Bausteinen zusammen, die Android selbst startet, anhält und miteinander verknüpft. Diese Bausteine heißen App Components. Sie sind die offiziellen Einstiegspunkte des Systems in deinen Code – und wer sie versteht, versteht, warum Android sich so verhält, wie es sich verhält. In diesem Artikel lernst du die vier klassischen Komponententypen kennen, ihren Zweck, ihren Lebenszyklus und worauf du im Alltag mit Kotlin und Jetpack Compose achten solltest.
Was ist das?
App Components sind die vier grundlegenden Klassen, über die Android mit deiner App spricht: Activity, Service, BroadcastReceiver und ContentProvider. Jede Komponente ist eine Klasse, die du selbst implementierst und in der AndroidManifest.xml deiner App registrierst. Das System weiß dadurch, was deine App anbieten kann, und ruft die passende Komponente bei Bedarf auf.
Der Punkt, den du dir früh merken solltest: Eine Android-App hat keinen einzigen Einstiegspunkt. Anders als ein klassisches Java- oder Kotlin-Programm wird sie nicht „oben gestartet und unten beendet”. Stattdessen kann das System jede deiner Komponenten zu einem beliebigen Zeitpunkt instanziieren, in den Vordergrund holen oder wieder zerstören. Tippt der Nutzer auf dein App-Icon, startet Android eine Activity. Empfängt das Gerät einen Push-Trigger, wird vielleicht ein BroadcastReceiver geweckt. Will eine andere App auf deine Daten zugreifen, fragt sie über einen ContentProvider an.
Die vier Komponenten erfüllen unterschiedliche Aufgaben:
- Activity ist ein einzelner Bildschirm mit Benutzeroberfläche. Sie ist die wichtigste und sichtbarste Komponente.
- Service läuft ohne UI im Hintergrund und erledigt länger laufende Arbeit, etwa Musikwiedergabe oder Datensynchronisation.
- BroadcastReceiver reagiert auf systemweite oder app-interne Nachrichten – zum Beispiel „Boot abgeschlossen” oder „Akku niedrig”.
- ContentProvider stellt strukturierte Daten zur Verfügung, die andere Apps (oder andere Teile deiner App) lesen oder ändern dürfen.
Im Roadmap-Kontext sind diese vier Komponenten dein Einstieg in die Android-Plattform jenseits der reinen UI-Schicht. Wenn du Compose-Screens schreibst, lebst du in einer Activity. Wenn du Daten im Hintergrund holst, denkst du an Services – oder, in modernen Apps, an deren Nachfolger wie WorkManager. Das Konzept ist also nicht optional; es ist das Fundament, auf dem alles andere aufbaut.
Wie funktioniert es?
Damit Android eine Komponente starten kann, muss sie zwei Bedingungen erfüllen: Sie muss als Klasse existieren, die von der passenden Basisklasse (ComponentActivity, Service, BroadcastReceiver, ContentProvider) erbt, und sie muss im Manifest deklariert sein. Erst dann kennt das System sie und kann sie über einen Intent adressieren.
Activity
Eine Activity ist ein UI-Bildschirm. In modernen Apps reicht in der Regel eine einzige MainActivity, die mit Jetpack Compose mehrere Screens über einen NavController darstellt. Eine Activity hat einen klar definierten Lebenszyklus mit Methoden wie onCreate, onStart, onResume, onPause, onStop und onDestroy. Der Lebenszyklus ist deshalb so wichtig, weil das System Activities aktiv steuert: Es kann sie pausieren, weil eine andere App in den Vordergrund kommt, sie nach einer Drehung neu erstellen oder sie unter Speicherdruck komplett zerstören. Du musst deinen Zustand also außerhalb der Activity ablegen, typischerweise in einem ViewModel.
Service
Ein Service hat keine UI und läuft im Hintergrund. Es gibt zwei klassische Varianten: Started Services erledigen einen Auftrag und stoppen sich danach selbst; Bound Services stellen anderen Komponenten eine API zur Verfügung. Seit Android 8 gelten strenge Hintergrund-Beschränkungen, deshalb startet das System normale Services nur noch eingeschränkt. Für die meisten Hintergrundaufgaben nutzt du heute WorkManager, Foreground Services mit Notification (z.B. für Musik oder Standortverfolgung) oder Coroutines, die an den Lebenszyklus eines ViewModel gebunden sind.
BroadcastReceiver
Ein BroadcastReceiver hört auf Ereignisse, die als Intents im System verteilt werden. Beispiele sind „Gerät gebootet”, „Konnektivität geändert” oder eigene App-interne Signale. Receiver können statisch im Manifest oder dynamisch im Code (registerReceiver) angemeldet werden. Auch hier hat Android viele frühere Möglichkeiten eingeschränkt: Statisch deklarierte Receiver für die meisten impliziten Broadcasts werden ab Android 8 nicht mehr ausgeliefert. Für reine In-App-Kommunikation nimmst du heute besser Flow, LiveData oder einen Event-Bus aus deinem Architekturlayer.
ContentProvider
Ein ContentProvider exponiert Daten über eine content://-URI. Andere Apps fragen über ContentResolver an und bekommen Cursor-basierte Ergebnisse. Bekannte Beispiele sind Kontakte, Mediathek oder Kalender. In eigenen Apps brauchst du einen ContentProvider nur dann, wenn du Daten prozessübergreifend teilen willst. Innerhalb deiner App nutzt du Room oder DataStore.
Alle vier Komponenten kommunizieren primär über Intents. Ein expliziter Intent nennt die Zielklasse direkt, ein impliziter Intent beschreibt nur, was getan werden soll („sende eine E-Mail”), und das System sucht eine passende Komponente. Das ist der Klebstoff, der Android-Apps modular macht.
In der Praxis
Hier ein schlankes Beispiel, das eine zweite Activity startet und dabei Daten weitergibt – die häufigste Komponentengrenze, die du im Alltag kreuzt:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Button(onClick = { openDetails(itemId = 42) }) {
Text("Details öffnen")
}
}
}
private fun openDetails(itemId: Int) {
val intent = Intent(this, DetailActivity::class.java).apply {
putExtra("EXTRA_ITEM_ID", itemId)
}
startActivity(intent)
}
}
class DetailActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val itemId = intent.getIntExtra("EXTRA_ITEM_ID", -1)
setContent { DetailScreen(itemId) }
}
}
Im Manifest registrierst du beide Activities:
<application>
<activity android:name=".MainActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".DetailActivity" android:exported="false" />
</application>
Entscheidungsregel für moderne Apps: Frag dich bei jeder Hintergrundaufgabe zuerst, ob du wirklich einen Service brauchst. Soll die Arbeit auch nach App-Schließung garantiert ausgeführt werden? Dann nimm WorkManager. Geht es um eine kurze, an die UI gebundene Operation? Dann reicht eine Coroutine im viewModelScope. Service ist die richtige Wahl bei laufender Wiedergabe oder dauerhafter Standortverfolgung – meist als Foreground Service mit Notification.
Typische Stolperfalle: Activities werden bei Konfigurationswechseln (Drehen, Sprachwechsel, Dark Mode) standardmäßig zerstört und neu erstellt. Wer Daten direkt in der Activity hält, verliert sie. Lege Zustand deshalb in ein ViewModel, das den Wechsel überlebt. Genauso heimtückisch: Ein dynamisch im onCreate registrierter BroadcastReceiver muss in onDestroy wieder mit unregisterReceiver abgemeldet werden, sonst leakst du die Activity. Und denke an android:exported: Seit Android 12 musst du diesen Wert für jede Komponente mit Intent-Filter explizit setzen, sonst lässt sich die App gar nicht installieren.
Fazit
Die vier App Components sind das Skelett jeder Android-App. Activity zeigt UI, Service erledigt Hintergrundarbeit, BroadcastReceiver hört auf Ereignisse, ContentProvider teilt Daten. In modernen Kotlin-Projekten verschiebst du viel davon in höhere Schichten – ViewModels, WorkManager, Flows – aber die Komponenten bleiben die offizielle Schnittstelle zwischen Android und deinem Code. Prüfe dein Verständnis konkret: Lege eine kleine App mit zwei Activities an, schau im Logcat zu, in welcher Reihenfolge die Lifecycle-Methoden bei Drehung und Backstack-Navigation feuern, und ersetze einen handgeschriebenen Hintergrund-Service durch einen WorkRequest. Wenn du diese Übungen einmal mit dem Debugger durchgespielt hast, sitzen die Konzepte – und du kannst jede Architektur-Entscheidung in deinem nächsten Projekt sauberer begründen.