java.lang.IllegalArgumentException: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent bedeutet, dass eine Android-App mit Ziel-API-Level 31 oder höher ein PendingIntent erstellt hat, ohne dessen Veränderlichkeit anzugeben. Die Ausnahme tritt zur Laufzeit beim Erstellen des PendingIntent auf. Als Erstes sollten Sie den Stacktrace untersuchen und den genauen Factory-Aufruf ermitteln, bevor Sie Flags ändern. Gehört der Aufruf zum App-Code und ist kein nachträgliches Ausfüllen erforderlich, behalten Sie die vorhandenen Flags bei und ergänzen Sie FLAG_IMMUTABLE.

Was der PendingIntent-Fehler „Targeting S+“ bedeutet

Die Android-Anforderung zur Veränderlichkeit von PendingIntents greift, wenn eine App mit Zielversion Android 12/API-Level 31 oder höher PendingIntent.getActivity(), getActivities(), getBroadcast(), getService() oder getForegroundService() ohne eines der beiden ausdrücklichen Veränderlichkeits-Flags aufruft.

FLAG_IMMUTABLE und FLAG_MUTABLE sind Alternativen und dürfen nicht miteinander kombiniert werden. Android empfiehlt in den meisten Fällen unveränderliche PendingIntents. Veränderlichkeit ist nur angebracht, wenn ein Empfänger oder eine Android-API nicht ausgefüllte Felder des umschlossenen Intent ändern muss. Die PendingIntent-API-Referenz unterscheidet diese Veränderlichkeitsangaben außerdem von Verhaltens-Flags wie FLAG_UPDATE_CURRENT, FLAG_CANCEL_CURRENT und FLAG_ONE_SHOT.

Diese Laufzeitausnahme ist nicht mit der separaten android:exported-Anforderung von Android 12 zu verwechseln. Diese betrifft Komponentendeklarationen im Manifest.

Den PendingIntent-Aufruf finden, der die Ausnahme tatsächlich auslöst

Die Fehlermeldung weist auf die fehlende Angabe hin, zeigt aber nicht, ob der Aufruf zum Anwendungscode, zu generiertem Code oder zu einer eingebundenen Bibliothek gehört.

  1. Beginnen Sie bei der Meldung java.lang.IllegalArgumentException im vollständigen Stacktrace.
  2. Suchen Sie den ersten relevanten Frame außerhalb des Frameworks, der mit einer der PendingIntent-Factory-Methoden verknüpft ist.
  3. Ordnen Sie diesen Frame dem zugehörigen Paket, Modul, der generierten Komponente oder der eingebundenen Abhängigkeit zu.
  4. Notieren Sie die Factory-Methode, den Request-Code, den umschlossenen Intent und den vollständigen Flags-Ausdruck.
  5. Ordnen Sie den Aufruf dem Anwendungscode, generiertem Code oder einer Abhängigkeit zu, bevor Sie eine Reparatur auswählen.

Ändern Sie nicht irgendein anderes PendingIntent, nur weil es im App-Code sichtbar ist. Gehört der relevante Frame zu einer Abhängigkeit, kann eine Flag-Änderung an anderer Stelle im App-Code die fehlerhafte Implementierung unberührt lassen.

App-Code standardmäßig mit FLAG_IMMUTABLE korrigieren

Wann dies zutrifft: Verwenden Sie diesen Weg, wenn der Factory-Aufruf zum App-Code gehört und weder Absender, Empfänger noch Android-API nicht ausgefüllte Felder des umschlossenen Intent ändern müssen.

Voraussetzungen: Ermitteln Sie den genauen Aufruf und behalten Sie den vorhandenen Request-Code, Intent, die Factory-Methode und die Verhaltens-Flags bei. Beim Hinzufügen von FLAG_IMMUTABLE dürfen FLAG_UPDATE_CURRENT, FLAG_CANCEL_CURRENT, FLAG_ONE_SHOT oder andere erforderliche vorhandene Flags nicht entfernt werden.

  1. Lassen Sie den aktuellen Request-Code und Intent unverändert.
  2. Kombinieren Sie FLAG_IMMUTABLE in Kotlin mit or beziehungsweise in Java mit | mit den vorhandenen Flags.
  3. Erstellen Sie das PendingIntent mit dem kombinierten Ausdruck.
  4. Führen Sie die Funktion erneut aus, die das PendingIntent sendet.

Kotlin-Beispiel

Vorher:

PendingIntent.getActivity(context, existingRequestCode, existingIntent, existingFlags)

Nachher:

PendingIntent.getActivity(context, existingRequestCode, existingIntent, existingFlags or PendingIntent.FLAG_IMMUTABLE)

Java-Beispiel

Vorher:

PendingIntent.getActivity(context, existingRequestCode, existingIntent, existingFlags)

Nachher:

PendingIntent.getActivity(context, existingRequestCode, existingIntent, existingFlags | PendingIntent.FLAG_IMMUTABLE)

Erwartetes Ergebnis: Der Factory-Aufruf enthält nun die erforderliche Veränderlichkeitsangabe. Die betroffene Benachrichtigungsaktion, der Activity-Start, Alarm, das Widget, der Callback oder Dienststart muss weiterhin getestet werden, damit das ursprüngliche Verhalten erhalten bleibt. Der Ersteller kann ein unveränderliches PendingIntent weiterhin mit FLAG_UPDATE_CURRENT aktualisieren.

Risiko und Rücknahme: Dies ist eine Codeänderung mit geringem Risiko und ohne dokumentiertes Datenverlustrisiko. Falls Tests zeigen, dass der Empfänger oder die Plattform-API ein nachträgliches Ausfüllen benötigt, nehmen Sie nur die ergänzte Unveränderlichkeitsangabe zurück und prüfen Sie den eng begrenzten veränderlichen Ansatz im nächsten Abschnitt.

FLAG_MUTABLE nur verwenden, wenn die Funktion nachträgliches Ausfüllen benötigt

Wann dies zutrifft: Verwenden Sie FLAG_MUTABLE nur, wenn eine dokumentierte Funktion den umschlossenen Intent ändern muss. Dazu gehören Inline-Antworten, Bubbles, Standort-Callbacks, Zähler-Extras bei wiederkehrenden Alarmen oder andere erforderliche Fill-in-Vorgänge.

Anforderung Angabe
Keine Änderung durch Empfänger oder Plattform erforderlich FLAG_IMMUTABLE
Eine dokumentierte Funktion muss Fill-in-Daten ergänzen FLAG_MUTABLE

Voraussetzungen: Prüfen Sie, ob die betroffene Funktion tatsächlich eine Änderung benötigt. Behalten Sie alle erforderlichen Verhaltens-Flags bei und verwenden Sie nach Möglichkeit einen expliziten Basis-Intent, bei dem Aktion, Paket und Komponente festgelegt sind.

  1. Behalten Sie den vorhandenen Request-Code, den Factory-Typ und die erforderlichen Verhaltens-Flags bei.
  2. Fügen Sie FLAG_MUTABLE anstelle von FLAG_IMMUTABLE hinzu.
  3. Gestalten Sie den Basis-Intent nach Möglichkeit explizit.
  4. Testen Sie genau den Vorgang erneut, der das nachträgliche Ausfüllen benötigt.
  5. Bestätigen Sie, dass nur die dokumentierten Felder weiterhin ausgefüllt werden können.

Kotlin-Beispiel

PendingIntent.getActivity(context, existingRequestCode, explicitIntent, existingFlags or PendingIntent.FLAG_MUTABLE)

Java-Beispiel

PendingIntent.getActivity(context, existingRequestCode, explicitIntent, existingFlags | PendingIntent.FLAG_MUTABLE)

Erwartetes Ergebnis: Der Factory-Aufruf erklärt das PendingIntent für veränderlich, behält die vorhandenen Verhaltens-Flags bei und ermöglicht weiterhin den dokumentierten Fill-in-Vorgang durch den Empfänger oder die Plattform.

Risiko und Rücknahme: Dies ist eine Sicherheitsentscheidung mit mittlerem Risiko, jedoch ohne dokumentiertes Datenverlustrisiko. Ein veränderliches PendingIntent überträgt die Kontrolle über nicht ausgefüllte Intent-Felder. Eine zu breite Verwendung kann daher die Angriffsfläche vergrößern. Befolgen Sie die offiziellen Android-Sicherheitshinweise zu PendingIntents, bevorzugen Sie einen expliziten Basis-Intent und ersetzen Sie FLAG_MUTABLE durch FLAG_IMMUTABLE, wenn die Abhängigkeit vom Fill-in-Verhalten entfällt. Dasselbe Prinzip der geringstmöglichen Berechtigung gilt bei der Prüfung der sicheren URI-Freigabe zwischen Android-Apps.

Ein von einer Abhängigkeit erstelltes PendingIntent korrigieren

Gehört der erste relevante Stacktrace-Frame zu generiertem Code oder einem eingebundenen SDK, ist die Änderung eines anderen PendingIntent im Anwendungscode keine bestätigte Lösung. Die Behebung in einer Abhängigkeit ist projektspezifisch und muss anhand der Primärdokumentation des verantwortlichen Artefakts geprüft werden.

  1. Ordnen Sie das verantwortliche Paket oder Modul aus dem Stacktrace dem genauen eingebundenen Artefakt zu.
  2. Prüfen Sie in der primären Release-Dokumentation dieses Artefakts, ob eine gepflegte Version ausdrücklich die PendingIntent-Kompatibilität mit Android 12 behandelt.
  3. Ist eine solche Version dokumentiert, führen Sie das Update ausschließlich über den etablierten Abhängigkeitsprozess des Projekts durch.
  4. Prüfen Sie den aufgelösten Abhängigkeitsgraphen, um sicherzustellen, dass das vorgesehene Artefakt und nicht eine ältere transitive Version ausgewählt wurde.
  5. Erstellen Sie die App neu und führen Sie dieselbe Funktion erneut aus.
  6. Bestätigen Sie, dass die korrigierte Implementierung paketiert wurde und der ursprüngliche Aufruf ohne Veränderlichkeitsangabe nicht mehr vorhanden ist.

Erwartetes Ergebnis: Enthält die geprüfte Version der Abhängigkeit die Korrektur und löst die neu erstellte App diese Version tatsächlich auf, sollte der zur Abhängigkeit gehörende Factory-Aufruf eine ausdrückliche Veränderlichkeitsangabe enthalten. Dieses Ergebnis darf nicht allein aus der angeforderten Versionsnummer abgeleitet werden.

Risiko und Rücknahme: Änderungen an Abhängigkeiten können auch das Verhalten außerhalb der fehlerhaften Funktion beeinflussen. Prüfen Sie die Release-Informationen der Abhängigkeit und stellen Sie den vorherigen Abhängigkeitsstand des Projekts wieder her, wenn das Update eine Regression verursacht. Für diese Ausnahme gibt es weder einen allgemeingültigen Namen der betroffenen Abhängigkeit noch eine universell korrigierte Version.

PendingIntentCompat verwenden, wenn eine Kompatibilitätslösung geeignet ist

Wann dies zutrifft: Verwenden Sie AndroidX PendingIntentCompat, wenn der App-Code Plattformversionen unterstützt, für die die Kompatibilitätshilfe bevorzugt wird, und der Aufrufer weiterhin festlegen kann, ob das PendingIntent veränderlich ist.

Voraussetzungen: Prüfen Sie, ob die AndroidX-Core-Version des Projekts PendingIntentCompat enthält, ermitteln Sie den ursprünglichen Factory-Typ und entscheiden Sie anhand der tatsächlichen Funktionsanforderungen über die Veränderlichkeit.

  1. Wählen Sie die zum ursprünglichen Vorgang passende Hilfsmethode: getActivity, getBroadcast, getService oder getForegroundService.
  2. Übergeben Sie der Hilfsmethode die vorhandenen Verhaltens-Flags, die nicht die Veränderlichkeit betreffen.
  3. Setzen Sie isMutable auf false, sofern keine bestätigte Anforderung an die Veränderlichkeit besteht.
  4. Lassen Sie den Request-Code und das Verhalten des umschlossenen Intent unverändert.
  5. Testen Sie mit der betroffenen Zielkonfiguration für Android 12 oder höher.

Erwartetes Ergebnis: Die Kompatibilitätshilfe kombiniert die ausdrückliche Entscheidung des Aufrufers über die Veränderlichkeit auf den unterstützten Plattformversionen mit den vorhandenen Flags.

Risiko und Rücknahme: Dies ist eine Kompatibilitätslösung mit geringem Risiko und ohne dokumentiertes Datenverlustrisiko. Der Wechsel der Hilfs-API kann jedoch die Aufrufstruktur beeinflussen. Kehren Sie zur entsprechenden Framework-Factory zurück und behalten Sie dabei ein ausdrückliches Veränderlichkeits-Flag bei, wenn die Hilfs-API eine Regression verursacht.

Die Reparatur prüfen, ohne das PendingIntent-Verhalten zu ändern

  1. Führen Sie die neu erstellte App mit einem Ziel-SDK von API-Level 31 oder höher aus und lösen Sie den ursprünglichen Vorgang erneut aus.
  2. Bestätigen Sie, dass die genaue Ausnahme Targeting S+ beim ermittelten Factory-Aufruf nicht mehr auftritt.
  3. Testen Sie das betroffene Antippen oder die Aktion einer Benachrichtigung, den Alarm, das Widget, den Callback, den Activity-Start oder den Dienststart erneut.
  4. Falls FLAG_UPDATE_CURRENT, FLAG_CANCEL_CURRENT oder FLAG_ONE_SHOT vorhanden war, prüfen Sie das ursprüngliche Aktualisierungs-, Abbruch- beziehungsweise Einmalverhalten.
  5. Prüfen Sie bei einem veränderlichen PendingIntent ausschließlich das benötigte Fill-in-Verhalten und bestätigen Sie, dass der Basis-Intent nach Möglichkeit explizit ist.
  6. Bestätigen Sie bei einer Reparatur über eine Abhängigkeit, dass das aufgelöste und paketierte Artefakt der geprüften Version entspricht. Verlassen Sie sich nicht allein auf die angeforderte Abhängigkeitsdeklaration.

Ein erfolgreicher Build allein beweist nicht, dass der Laufzeitpfad repariert wurde. Behandeln Sie außerdem die Einschränkungen für veränderliche implizite PendingIntents unter Android 14/API-Level 34 getrennt: Sie führen zu einer anderen Fehlerbedingung und werden durch dieses Verfahren für API-Level 31 nicht behoben.