Android Coden
Android 4 min lesen

PendingIntents sicher erstellen

Ein PendingIntent kapselt einen Intent, den fremde Prozesse später in deinem Namen ausführen dürfen. Du lernst, ihn sicher und explizit anzulegen.

Wenn eine Benachrichtigung angetippt wird, öffnet sich deine App – obwohl das System in diesem Moment eigenständig handelt. Das ist kein Zufall, sondern das Werk eines PendingIntent. Er ist eine der zentralen Mechaniken, um Aktionen zeitversetzt und komponentenübergreifend auszulösen. Wer PendingIntent falsch erstellt, öffnet jedoch Sicherheitslücken, die Android-Lint und der Play-Store-Review zuverlässig aufspüren. Dieser Artikel zeigt dir, wie du ihn korrekt und sicher verwendest.

Was ist das?

Ein PendingIntent ist ein Token, das einen vorbereiteten Intent einschließt und einem fremden Prozess die Erlaubnis erteilt, diesen Intent zu einem späteren Zeitpunkt im Namen deiner App auszuführen. Der entscheidende Unterschied zu einem gewöhnlichen Intent ist der Besitz: Während du einen normalen Intent selbst abschickst, delegierst du mit einem PendingIntent die Ausführung an einen anderen Akteur – typischerweise das System, einen AlarmManager, den NotificationManager oder eine Widget-Infrastruktur.

Das Android-Sicherheitsmodell macht sich das zunutze: Der empfangende Prozess erhält nicht deine gesamte App-Identität, sondern nur die eng begrenzte Erlaubnis, genau diesen einen Intent auszuführen. Das System erzwingt dabei die Berechtigungen deiner App, nicht die des aufrufenden Prozesses. Du verleihst also kurzfristig eine Fähigkeit, ohne die Kontrolle über deine App aufzugeben.

Wie funktioniert es?

PendingIntent wird über vier statische Factory-Methoden erzeugt, je nach Zielkomponente:

  • PendingIntent.getActivity(...) – startet eine Activity
  • PendingIntent.getService(...) – startet einen Service
  • PendingIntent.getBroadcast(...) – sendet einen Broadcast
  • PendingIntent.getForegroundService(...) – startet einen Foreground Service (ab API 26 empfohlen)

Alle vier Methoden erwarten einen Context, einen Request-Code zur Unterscheidung, einen Intent sowie einen Flags-Parameter. Seit Android 12 (API 31) ist es Pflicht, entweder FLAG_IMMUTABLE oder FLAG_MUTABLE anzugeben. Fehlt beides, wirft das System eine IllegalArgumentException – auch auf älteren Geräten, sobald die App mit targetSdkVersion 31 oder höher gebaut wird.

FLAG_IMMUTABLE vs. FLAG_MUTABLE

FLAG_IMMUTABLE bedeutet: Der enthaltene Intent kann nach dem Erstellen nicht mehr verändert werden. Das ist die sichere Standardwahl für nahezu alle Anwendungsfälle – Benachrichtigungen, Alarme, Widget-Aktionen. Ein externer Prozess, der den PendingIntent erhält, kann die Intent-Extras nicht nachträglich manipulieren.

FLAG_MUTABLE erlaubt es dem empfangenden Prozess, bestimmte Teile des Intents (zum Beispiel Extras) zu ergänzen. Verwende dieses Flag nur dann, wenn das Framework es ausdrücklich fordert – etwa beim Einsatz von BubbleMetadata oder wenn der AlarmManager den Auslösezeitpunkt als Extra eintragen muss.

Explizite Intents

Ein PendingIntent darf nur explizite Intents enthalten, also Intents, die ComponentName oder setClass(...) gesetzt haben. Implizite Intents – solche, die über einen Action-String nach einer passenden App suchen – sind in diesem Kontext ein Sicherheitsrisiko: Eine Schad-App könnte sich als Handler registrieren und den Intent abfangen. Android-Lint meldet diesen Fall als Warnung der Kategorie „Security”.

In der Praxis

Das häufigste Szenario ist eine Benachrichtigung, die beim Antippen eine Activity öffnet:

val intent = Intent(context, MainActivity::class.java).apply {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

val pendingIntent = PendingIntent.getActivity(
    context,
    0,
    intent,
    PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)

val notification = NotificationCompat.Builder(context, CHANNEL_ID)
    .setContentTitle("Neue Nachricht")
    .setContentText("Tippe, um sie zu lesen.")
    .setSmallIcon(R.drawable.ic_notification)
    .setContentIntent(pendingIntent)
    .setAutoCancel(true)
    .build()

FLAG_UPDATE_CURRENT sorgt dafür, dass ein bereits vorhandener PendingIntent mit demselben Request-Code aktualisiert statt dupliziert wird – praktisch, wenn du den Intent-Inhalt regelmäßig erneuern möchtest.

Typische Stolperfalle: Request-Code und Eindeutigkeit

Der Request-Code dient als Schlüssel: Zwei PendingIntents mit demselben Request-Code und demselben Intent werden vom System als identisch behandelt und zeigen auf dasselbe Ziel. Erstellst du für verschiedene Konversationen in einer Messaging-App jeweils eine Benachrichtigung, musst du pro Konversation einen eindeutigen Request-Code wählen – sonst überschreibt der zweite PendingIntent den ersten, und beide Benachrichtigungen führen zum gleichen Ziel.

// Falsch: gleicher Request-Code für verschiedene Konversationen
val pi1 = PendingIntent.getActivity(context, 0, intentForChat1, FLAG_IMMUTABLE)
val pi2 = PendingIntent.getActivity(context, 0, intentForChat2, FLAG_IMMUTABLE) // überschreibt pi1!

// Richtig: eindeutiger Request-Code pro Entität
val pi1 = PendingIntent.getActivity(context, chat1.id.hashCode(), intentForChat1, FLAG_IMMUTABLE)
val pi2 = PendingIntent.getActivity(context, chat2.id.hashCode(), intentForChat2, FLAG_IMMUTABLE)

Führe ./gradlew lint aus und sieh dir die Kategorie „Security” an – Lint meldet unsichere PendingIntent-Konfigurationen zuverlässig, bevor sie zur Laufzeit oder im Play-Store-Review auffallen.

Fazit

PendingIntent ist ein mächtiges Werkzeug, das Android nutzt, um Aktionen komponentenübergreifend und zeitversetzt auszuführen. Die zwei wichtigsten Regeln bleiben dabei konstant: Verwende stets FLAG_IMMUTABLE und ausschließlich explizite Intents, damit kein fremder Prozess den Inhalt manipulieren oder missbrauchen kann. Geh jetzt deine bestehenden PendingIntent-Aufrufe im Projekt durch, prüfe die Request-Codes auf Eindeutigkeit und lass Lint darüber laufen. Wer diese Grundsätze verinnerlicht hat, schreibt robustere Benachrichtigungs- und Alarm-Integrationen – und besteht den Play-Store-Sicherheitscheck ohne Überraschungen.

Quellen (4)
Redaktion

Geschrieben von

Redaktion

Das Redaktionsteam recherchiert und schreibt Artikel zu aktuellen Themen rund um Tech, Lifestyle und Ratgeber.