Android-Apps senden und empfangen Broadcast-Nachrichten vom Android-System und von anderen Android-Apps. Das funktioniert ähnlich wie beim Publish-Subscribe-Muster. Das System und Apps senden in der Regel Broadcasts, wenn bestimmte Ereignisse eintreten. Das Android-System sendet beispielsweise Broadcasts, wenn verschiedene Systemereignisse eintreten, z. B. beim Systemstart oder beim Aufladen des Geräts. Apps senden auch benutzerdefinierte Broadcasts, um andere Apps über etwas zu informieren, das für sie von Interesse sein könnte, z. B. einen neuen Datendownload.
Apps können sich registrieren, um bestimmte Broadcasts zu empfangen. Wenn eine Broadcast-Nachricht gesendet wird, leitet das System sie automatisch an Apps weiter, die für den Empfang dieser Art von Broadcast-Nachricht registriert sind.
Im Allgemeinen können Broadcasts als Nachrichtensystem für Apps und außerhalb des normalen Nutzerablaufs verwendet werden. Sie müssen jedoch darauf achten, dass Sie die Möglichkeit, auf Broadcasts zu reagieren und Jobs im Hintergrund auszuführen, nicht missbrauchen, da dies zu einer langsamen Systemleistung führen kann.
Systemnachrichten
Das System sendet automatisch Broadcasts, wenn verschiedene Systemereignisse eintreten, z. B. wenn das System in den Flugmodus wechselt oder den Flugmodus verlässt. Alle abonnierten Apps empfangen diese Broadcasts.
Das Intent-Objekt umschließt die Nachricht an alle. Der String action gibt das aufgetretene Ereignis an, z. B. android.intent.action.AIRPLANE_MODE. Die Absicht kann auch zusätzliche Informationen enthalten, die im Feld „extra“ gebündelt sind.
Der Intent „Flugmodus“ enthält beispielsweise ein boolesches Extra, das angibt, ob der Flugmodus aktiviert ist.
Weitere Informationen zum Lesen von Intents und zum Abrufen des Aktions-Strings aus einem Intent finden Sie unter Intents und Intent-Filter.
Systemnachrichtenaktionen
Eine vollständige Liste der System-Broadcast-Aktionen finden Sie in der Datei BROADCAST_ACTIONS.TXT im Android SDK. Jeder Broadcast-Aktion ist ein konstantes Feld zugeordnet. Der Wert der Konstanten ACTION_AIRPLANE_MODE_CHANGED ist beispielsweise android.intent.action.AIRPLANE_MODE.
Die Dokumentation für jede Broadcast-Aktion ist im zugehörigen Konstantfeld verfügbar.
Änderungen bei System-Broadcasts
Im Laufe der Entwicklung der Android-Plattform ändert sich regelmäßig das Verhalten von System-Broadcasts. Beachten Sie die folgenden Änderungen, um alle Android-Versionen zu unterstützen.
Android 16
In Android 16 wird die Reihenfolge der Broadcast-Zustellung bei Verwendung des Attributs android:priority oder IntentFilter.setPriority() über verschiedene Prozesse hinweg nicht garantiert. Broadcast-Prioritäten werden nur innerhalb desselben Anwendungsprozesses berücksichtigt, nicht über alle Prozesse hinweg.
Außerdem sind Broadcast-Prioritäten automatisch auf den Bereich (SYSTEM_LOW_PRIORITY + 1, SYSTEM_HIGH_PRIORITY – 1) beschränkt.
Nur Systemkomponenten dürfen SYSTEM_LOW_PRIORITY,
SYSTEM_HIGH_PRIORITY als Broadcast-Priorität festlegen.
Android 14
Wenn sich Apps im Cache-Zustand befinden, optimiert das System die Übertragung von Broadcasts für die Systemintegrität. Das System verschiebt beispielsweise weniger wichtige System-Broadcasts wie ACTION_SCREEN_ON, während sich die App im Cache befindet.
Sobald die App vom Cache-Status in einen aktiven Prozesslebenszyklus wechselt, liefert das System alle verzögerten Broadcasts aus.
Wichtige Broadcasts, die im Manifest deklariert sind, entfernen Apps vorübergehend aus dem Cache für die Zustellung.
Android 9
Ab Android 9 (API-Level 28) werden bei der NETWORK_STATE_CHANGED_ACTION-Broadcast keine Informationen zum Standort des Nutzers oder personenbezogene Daten empfangen.
Wenn Ihre App auf einem Gerät mit Android 9.0 (API-Level 28) oder höher installiert ist, enthält das System keine SSIDs, BSSIDs, Verbindungsinformationen oder Scanergebnisse in WLAN-Broadcasts. Rufen Sie stattdessen getConnectionInfo() auf, um diese Informationen zu erhalten.
Android 8.0
Ab Android 8.0 (API-Level 26) unterliegt das System zusätzlichen Einschränkungen für im Manifest deklarierte Empfänger.
Wenn Ihre App auf Android 8.0 oder höher ausgerichtet ist, können Sie das Manifest nicht verwenden, um einen Empfänger für die meisten impliziten Broadcasts (Broadcasts, die nicht speziell auf Ihre App ausgerichtet sind) zu deklarieren. Sie können weiterhin einen kontextregistrierten Receiver verwenden, wenn der Nutzer Ihre App aktiv verwendet.
Android 7.0
Unter Android 7.0 (API-Level 24) und höher werden die folgenden System-Broadcasts nicht gesendet:
Außerdem müssen Apps, die auf Android 7.0 und höher ausgerichtet sind, den CONNECTIVITY_ACTION-Broadcast mit registerReceiver(BroadcastReceiver, IntentFilter) registrieren. Die Deklaration eines Empfängers im Manifest funktioniert nicht.
Übertragungen empfangen
Apps können Broadcasts auf zwei Arten empfangen: über kontextregistrierte Empfänger und über im Manifest deklarierte Empfänger.
Kontextregistrierte Empfänger
Kontextregistrierte Empfänger empfangen Broadcasts, solange ihr Registrierungskontext gültig ist. Dies geschieht in der Regel zwischen den Aufrufen von registerReceiver und unregisterReceiver. Der Registrierungskontext wird auch ungültig, wenn das System den entsprechenden Kontext zerstört. Wenn Sie sich beispielsweise in einem Activity-Kontext registrieren, erhalten Sie Broadcasts, solange die Aktivität aktiv bleibt. Wenn Sie sich mit dem Anwendungskontext registrieren, erhalten Sie Broadcasts, solange die App ausgeführt wird.
So registrieren Sie einen Receiver mit einem Kontext:
Fügen Sie in die Build-Datei auf Modulebene Ihrer App Version 1.9.0 oder höher der AndroidX Core-Bibliothek ein:
Groovy
dependencies { def core_version = "1.19.1" // Java language implementation implementation "androidx.core:core:$core_version" // Kotlin implementation "androidx.core:core-ktx:$core_version" // To use RoleManagerCompat implementation "androidx.core:core-role:1.1.0" // To use the Animator APIs implementation "androidx.core:core-animation:1.0.0" // To test the Animator APIs androidTestImplementation "androidx.core:core-animation-testing:1.0.0" // Optional - To enable APIs that query the performance characteristics of GMS devices. implementation "androidx.core:core-performance:1.0.0" // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google implementation "androidx.core:core-google-shortcuts:1.1.0" // Optional - to support backwards compatibility of RemoteViews implementation "androidx.core:core-remoteviews:1.1.0" // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12 implementation "androidx.core:core-splashscreen:1.2.0" }
Kotlin
dependencies { val core_version = "1.19.1" // Java language implementation implementation("androidx.core:core:$core_version") // Kotlin implementation("androidx.core:core-ktx:$core_version") // To use RoleManagerCompat implementation("androidx.core:core-role:1.1.0") // To use the Animator APIs implementation("androidx.core:core-animation:1.0.0") // To test the Animator APIs androidTestImplementation("androidx.core:core-animation-testing:1.0.0") // Optional - To enable APIs that query the performance characteristics of GMS devices. implementation("androidx.core:core-performance:1.0.0") // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google implementation("androidx.core:core-google-shortcuts:1.1.0") // Optional - to support backwards compatibility of RemoteViews implementation("androidx.core:core-remoteviews:1.1.0") // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12 implementation("androidx.core:core-splashscreen:1.2.0") }
Erstellen Sie eine Instanz von
BroadcastReceiver:Kotlin
val myBroadcastReceiver = MyBroadcastReceiver()Java
MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();Erstellen Sie eine Instanz von
IntentFilter:Kotlin
val filter = IntentFilter("com.example.snippets.ACTION_UPDATE_DATA")Java
IntentFilter filter = new IntentFilter("com.example.snippets.ACTION_UPDATE_DATA");Wählen Sie aus, ob der Übertragungsempfänger exportiert und für andere Apps auf dem Gerät sichtbar sein soll. Wenn dieser Receiver auf Broadcasts wartet, die vom System oder von anderen Apps gesendet werden – auch von anderen Apps, die Ihnen gehören –, verwenden Sie das Flag
RECEIVER_EXPORTED. Wenn dieser Receiver stattdessen nur auf Broadcasts wartet, die von Ihrer App gesendet werden, verwenden Sie das FlagRECEIVER_NOT_EXPORTED.Kotlin
val listenToBroadcastsFromOtherApps = false val receiverFlags = if (listenToBroadcastsFromOtherApps) { ContextCompat.RECEIVER_EXPORTED } else { ContextCompat.RECEIVER_NOT_EXPORTED }Java
boolean listenToBroadcastsFromOtherApps = false; int receiverFlags = listenToBroadcastsFromOtherApps ? ContextCompat.RECEIVER_EXPORTED : ContextCompat.RECEIVER_NOT_EXPORTED;Registrieren Sie den Empfänger, indem Sie
registerReceiver()anrufen:Kotlin
ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags)Java
ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags);Wenn Sie keine Broadcasts mehr erhalten möchten, rufen Sie
unregisterReceiver(android.content.BroadcastReceiver)an. Registrieren Sie den Receiver ab, wenn Sie ihn nicht mehr benötigen oder der Kontext nicht mehr gültig ist.
Übertragungsempfänger abmelden
Solange der Übertragungsempfänger registriert ist, enthält er einen Verweis auf den Kontext, mit dem Sie ihn registriert haben. Dies kann zu Lecks führen, wenn der registrierte Bereich des Empfängers den Bereich des Context-Lebenszyklus überschreitet. Das kann beispielsweise passieren, wenn Sie einen Receiver in einem Activity-Bereich registrieren, aber vergessen, die Registrierung aufzuheben, wenn das System die Activity beendet. Melden Sie Ihren Übertragungsempfänger daher immer ab.
Kotlin
class MyActivity : ComponentActivity() {
private val myBroadcastReceiver = MyBroadcastReceiver()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ...
ContextCompat.registerReceiver(this, myBroadcastReceiver, filter, receiverFlags)
setContent { MyApp() }
}
override fun onDestroy() {
super.onDestroy()
// When you forget to unregister your receiver here, you're causing a leak!
this.unregisterReceiver(myBroadcastReceiver)
}
}
Java
class MyActivity extends ComponentActivity {
MyBroadcastReceiver myBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
ContextCompat.registerReceiver(this, myBroadcastReceiver, filter, receiverFlags);
// Set content
}
}
Empfänger im kleinstmöglichen Bereich registrieren
Ihr Übertragungsempfänger sollte nur registriert werden, wenn Sie tatsächlich am Ergebnis interessiert sind. Wählen Sie den kleinstmöglichen Empfängerbereich aus:
LifecycleResumeEffectoder Aktivitäts-Lifecycle-MethodenonResume/onPause: Der Übertragungsempfänger empfängt nur Updates, wenn sich die App im fortgesetzten Zustand befindet.LifecycleStartEffectoder Aktivitäts-Lifecycle-MethodenonStart/onStop: Der Übertragungsempfänger empfängt nur Updates, wenn sich die App im fortgesetzten Zustand befindet.DisposableEffect: Der Übertragungsempfänger empfängt nur Updates, wenn sich das Composable im Kompositionsbaum befindet. Dieser Bereich ist nicht an den Bereich des Aktivitätslebenszyklus angehängt. Registrieren Sie den Receiver im Anwendungskontext. Das liegt daran, dass das Composable theoretisch den Aktivitätslebenszyklus überdauern und die Aktivität verloren gehen könnte.- Aktivität
onCreate/onDestroy: Der Übertragungsempfänger empfängt Updates, während sich die Aktivität im Status „Erstellt“ befindet. Melden Sie sich inonDestroy()und nicht inonSaveInstanceState(Bundle)ab, da diese möglicherweise nicht aufgerufen wird. - Benutzerdefinierter Bereich: Sie können beispielsweise einen Receiver in Ihrem
ViewModel-Bereich registrieren, damit er die Neuerstellung von Aktivitäten übersteht. Verwenden Sie den Anwendungskontext, um den Empfänger zu registrieren, da der Empfänger den Lebenszyklusbereich der Aktivität überdauern und die Aktivität leaken kann.
Zustandsorientierte und zustandslose Composables erstellen
Compose hat zustandsorientierte und zustandslose Composables. Durch das Registrieren oder Aufheben der Registrierung eines Übertragungsempfängers in einem Composable wird es zustandsbehaftet. Die Composable ist keine deterministische Funktion, die bei Übergabe derselben Parameter denselben Inhalt rendert. Der interne Status kann sich basierend auf Aufrufen des registrierten Broadcast-Empfängers ändern.
Als Best Practice in Compose empfehlen wir, Ihre Composables in zustandsbehaftete und zustandslose Versionen aufzuteilen. Daher empfehlen wir, die Erstellung des Übertragungsempfängers aus einem Composable herauszuziehen, damit er zustandslos ist:
@Composable
fun MyStatefulScreen() {
val myBroadcastReceiver = remember { MyBroadcastReceiver() }
val context = LocalContext.current
LifecycleStartEffect(true) {
// ...
ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, flags)
onStopOrDispose { context.unregisterReceiver(myBroadcastReceiver) }
}
MyStatelessScreen()
}
@Composable
fun MyStatelessScreen() {
// Implement your screen
}
Im Manifest deklarierte Empfänger
Wenn Sie einen Übertragungsempfänger in Ihrem Manifest deklarieren, startet das System Ihre App, wenn der Broadcast gesendet wird. Wenn die App noch nicht ausgeführt wird, startet das System sie.
So deklarieren Sie einen Übertragungsempfänger im Manifest:
Geben Sie das Element
<receiver>im Manifest Ihrer App an.<!-- If this receiver listens for broadcasts sent from the system or from other apps, even other apps that you own, set android:exported to "true". --> <receiver android:name=".MyBroadcastReceiver" android:exported="false"> <intent-filter> <action android:name="com.example.snippets.ACTION_UPDATE_DATA" /> </intent-filter> </receiver>Die Intent-Filter geben die Broadcast-Aktionen an, die dein Empfänger abonniert.
Erstellen Sie eine Unterklasse von
BroadcastReceiverund implementieren SieonReceive(Context, Intent). Der Übertragungsempfänger im folgenden Beispiel protokolliert und zeigt den Inhalt des Broadcasts an:Kotlin
class MyBroadcastReceiver : BroadcastReceiver() { @Inject lateinit var dataRepository: DataRepository override fun onReceive(context: Context, intent: Intent) { if (intent.action == "com.example.snippets.ACTION_UPDATE_DATA") { val data = intent.getStringExtra("com.example.snippets.DATA") ?: "No data" // Do something with the data, for example send it to a data repository: dataRepository.updateData(data) } } }Java
public static class MyBroadcastReceiver extends BroadcastReceiver { @Inject DataRepository dataRepository; @Override public void onReceive(Context context, Intent intent) { if (Objects.equals(intent.getAction(), "com.example.snippets.ACTION_UPDATE_DATA")) { String data = intent.getStringExtra("com.example.snippets.DATA"); // Do something with the data, for example send it to a data repository: if (data != null) { dataRepository.updateData(data); } } } }
Der Systempaketmanager registriert den Receiver, wenn die App installiert wird. Der Receiver wird dann zu einem separaten Einstiegspunkt in Ihre App. Das bedeutet, dass das System die App starten und den Broadcast senden kann, wenn die App nicht ausgeführt wird.
Das System erstellt ein neues BroadcastReceiver-Komponentenobjekt, um jede empfangene Broadcast-Nachricht zu verarbeiten. Dieses Objekt ist nur für die Dauer des Aufrufs von onReceive(Context, Intent) gültig. Sobald Ihr Code von dieser Methode zurückkehrt, betrachtet das System die Komponente als nicht mehr aktiv.
Auswirkungen auf den Prozessstatus
Ob Ihr BroadcastReceiver in Betrieb ist oder nicht, wirkt sich auf den darin enthaltenen Prozess aus, was die Wahrscheinlichkeit, dass das System beendet wird, verändern kann. Ein Vordergrundprozess führt die Methode onReceive() eines Empfängers aus. Das System führt den Prozess aus, es sei denn, es besteht eine extreme Arbeitsspeicherauslastung.
Das System deaktiviert BroadcastReceiver nach onReceive().
Die Bedeutung des Hostprozesses des Empfängers hängt von seinen App-Komponenten ab. Wenn in diesem Prozess nur ein im Manifest deklarierter Empfänger gehostet wird, kann das System ihn nach onReceive() beenden, um Ressourcen für andere, wichtigere Prozesse freizugeben. Das ist häufig bei Apps der Fall, mit denen der Nutzer noch nie oder in letzter Zeit nicht interagiert hat.
Daher sollten Broadcast-Empfänger keine Hintergrundthreads mit langer Ausführungszeit starten.
Das System kann den Prozess jederzeit nach onReceive() beenden, um Speicherplatz freizugeben, und den erstellten Thread beenden. Damit der Prozess aktiv bleibt, plane mit JobScheduler eine JobService vom Empfänger aus, damit das System weiß, dass der Prozess noch aktiv ist. Weitere Informationen finden Sie unter Hintergrundaufgaben – Übersicht.
Übertragungen senden
Android bietet zwei Möglichkeiten für Apps, Broadcasts zu senden:
- Mit der Methode
sendOrderedBroadcast(Intent, String)werden Broadcasts jeweils an einen Empfänger gesendet. Da jeder Empfänger nacheinander ausgeführt wird, kann er ein Ergebnis an den nächsten Empfänger weitergeben. Außerdem kann die Übertragung vollständig abgebrochen werden, sodass sie nicht auf anderen Empfängern wiedergegeben wird. Sie können die Reihenfolge steuern, in der Empfänger im selben App-Prozess ausgeführt werden. Verwenden Sie dazu das Attributandroid:prioritydes entsprechenden Intent-Filters. Empfänger mit derselben Priorität werden in beliebiger Reihenfolge ausgeführt. - Die Methode
sendBroadcast(Intent)sendet Broadcasts in einer nicht definierten Reihenfolge an alle Empfänger. Das wird als normale Übertragung bezeichnet. Das ist effizienter, bedeutet aber, dass Empfänger keine Ergebnisse von anderen Empfängern lesen, vom Broadcast empfangene Daten weiterleiten oder den Broadcast abbrechen können.
Das folgende Code-Snippet zeigt, wie Sie einen Broadcast senden, indem Sie einen Intent erstellen und sendBroadcast(Intent) aufrufen.
Kotlin
val intent = Intent("com.example.snippets.ACTION_UPDATE_DATA").apply {
putExtra("com.example.snippets.DATA", newData)
setPackage("com.example.snippets")
}
context.sendBroadcast(intent)
Java
Intent intent = new Intent("com.example.snippets.ACTION_UPDATE_DATA");
intent.putExtra("com.example.snippets.DATA", newData);
intent.setPackage("com.example.snippets");
context.sendBroadcast(intent);
Die Nachricht an alle ist in ein Intent-Objekt eingebunden. Der action-String des Intents muss die Java-Paketnamensyntax der App enthalten und das Broadcast-Ereignis eindeutig identifizieren. Mit putExtra(String, Bundle) können Sie dem Intent zusätzliche Informationen anhängen. Sie können eine Broadcast-Nachricht auch auf eine Reihe von Apps in derselben Organisation beschränken, indem Sie setPackage(String) für den Intent aufrufen.
Übertragungen mit Berechtigungen einschränken
Mit Berechtigungen können Sie Broadcasts auf die Apps beschränken, die bestimmte Berechtigungen haben. Sie können Einschränkungen für den Absender oder Empfänger einer Broadcast-Nachricht erzwingen.
Broadcasts mit Berechtigungen senden
Wenn Sie sendBroadcast(Intent, String) oder sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String,
Bundle) aufrufen, können Sie einen Berechtigungsparameter angeben. Nur Empfänger, die diese Berechtigung mit dem Tag <uses-permission> in ihrem Manifest angefordert haben, können den Broadcast empfangen. Wenn die Berechtigung gefährlich ist, müssen Sie sie erteilen, bevor der Empfänger den Broadcast empfangen kann. Mit dem folgenden Code wird beispielsweise ein Broadcast mit einer Berechtigung gesendet:
Kotlin
context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION)
Java
context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION);
Damit die empfangende App die Broadcast-Nachricht empfangen kann, muss sie die Berechtigung so anfordern:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
Sie können entweder eine vorhandene Systemberechtigung wie BLUETOOTH_CONNECT angeben oder eine benutzerdefinierte Berechtigung mit dem Element <permission> definieren. Informationen zu Berechtigungen und Sicherheit im Allgemeinen finden Sie unter Systemberechtigungen.
Übertragungen mit Berechtigungen empfangen
Wenn Sie beim Registrieren eines Übertragungsempfängers einen Berechtigungsparameter angeben (entweder mit registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) oder im <receiver>-Tag in Ihrem Manifest), können nur Broadcaster, die die Berechtigung mit dem <uses-permission>-Tag in ihrem Manifest angefordert haben, einen Intent an den Empfänger senden. Wenn die Berechtigung gefährlich ist, muss sie auch dem Broadcaster gewährt werden.
Angenommen, Ihre Empfänger-App hat einen im Manifest deklarierten Empfänger wie folgt:
<!-- If this receiver listens for broadcasts sent from the system or from
other apps, even other apps that you own, set android:exported to "true". -->
<receiver
android:name=".MyBroadcastReceiverWithPermission"
android:permission="android.permission.ACCESS_COARSE_LOCATION"
android:exported="true">
<intent-filter>
<action android:name="com.example.snippets.ACTION_UPDATE_DATA" />
</intent-filter>
</receiver>
Oder Ihre empfangende App hat einen kontextregistrierten Empfänger wie folgt:
Kotlin
ContextCompat.registerReceiver(
context, myBroadcastReceiver, filter,
android.Manifest.permission.ACCESS_COARSE_LOCATION,
null, // scheduler that defines thread, null means run on main thread
receiverFlags
)
Java
ContextCompat.registerReceiver(
context, myBroadcastReceiver, filter,
android.Manifest.permission.ACCESS_COARSE_LOCATION,
null, // scheduler that defines thread, null means run on main thread
receiverFlags
);
Damit die sendende App Broadcasts an diese Empfänger senden kann, muss sie die Berechtigung so anfordern:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
Broadcasts innerhalb desselben Prozesses vermeiden
Broadcasts sind als Mechanismus für die Interprozesskommunikation (IPC) konzipiert, um Nachrichten zwischen verschiedenen Apps oder zwischen dem System und Apps zu senden. Das Senden einer Selbst-Broadcast, bei der alle Empfänger im selben Prozess wie der Sender ausgeführt werden, ist sehr ineffizient, verursacht unnötigen System-Aufwand und wird dringend abgeraten.
Zwei häufige Szenarien, in denen Apps Broadcasts an sich selbst senden:
Kommunikation zwischen Komponenten im selben Prozess: Zum Beispiel das Übergeben von Ereignissen oder Daten zwischen Aktivitäten, Fragmenten, Diensten oder Hintergrundthreads. Verwenden Sie anstelle von Broadcasts standardmäßige In-Process-Kommunikationsmechanismen wie das Observer-Muster oder reaktive Streams:
- Kotlin-Flows (
SharedFlowundStateFlow): Eine moderne, idiomatische Lösung in Kotlin zum Ausgeben und Beobachten von Event-Streams oder Statusaktualisierungen über Koroutinen und Komponenten in Ihrer App hinweg. - Gemeinsam
ViewModel: Ermöglicht die gemeinsame Nutzung von Daten und Ereignissen zwischen verschiedenen UI-Komponenten (z. B. Fragmenten oder Composables) innerhalb derselben Aktivität. - Callbacks und Listener: Standardmäßige Interface-Callbacks oder Funktionsreferenzen, die direkt zwischen Komponenten übergeben oder in einem zentralen Repository oder Controller registriert werden.
- Kotlin-Flows (
Systemereignisse, Jobs oder Alarme verarbeiten: Zum Beispiel einen geplanten Job, Alarm oder System-Callback empfangen und dann einen Broadcast senden, um die eigentliche Arbeit auszulösen. Anstatt eine Broadcast-Nachricht zu senden, sollten Sie die Arbeit direkt in diesem Job erledigen, z. B. in einem
JobService- oder WorkManager-Worker, einem Alarm-Handler oder einer System-Callback-Komponente, oder die Aufgabe direkt an die Klassen der Geschäftslogik Ihrer App delegieren.
Auf Geräten mit Android 17 QPR2 oder höher werden Self-Broadcasts effizienter zugestellt, indem sie an den Sendeprozess zurückgegeben werden, der sie an seine eigenen Empfänger im Hauptthread sendet. Das Senden eines Self-Broadcasts erhöht die Wichtigkeit Ihres Prozesses nicht und verhindert auch nicht, dass ein im Cache gespeicherter Prozess eingefroren wird. Verlassen Sie sich daher nicht auf Self-Broadcasts, um Ihre App am Laufen zu halten oder Aufgaben im Hintergrund auszuführen. Selbst mit dieser Optimierung sind Self-Broadcasts weniger effizient als In-Process-Kommunikationsmechanismen. Verwenden Sie daher diese Alternativen.
Weitere Informationen zum Entwerfen der Kommunikation zwischen App-Komponenten finden Sie im Leitfaden zur App-Architektur.
Sicherheitsaspekte
Hier sind einige Sicherheitsaspekte für das Senden und Empfangen von Broadcasts:
Wenn viele Apps registriert sind, um denselben Broadcast in ihrem Manifest zu empfangen, kann dies dazu führen, dass das System viele Apps startet, was sich erheblich auf die Geräteleistung und die Nutzerfreundlichkeit auswirkt. Um dies zu vermeiden, sollten Sie die Kontextregistrierung der Manifestdeklaration vorziehen. Manchmal erzwingt das Android-System selbst die Verwendung von kontextregistrierten Broadcast-Empfängern. So wird die
CONNECTIVITY_ACTION-Broadcast beispielsweise nur an kontextregistrierte Empfänger gesendet.Senden Sie keine vertraulichen Informationen über eine implizite Intention. Jede App kann die Informationen lesen, wenn sie sich für den Empfang des Broadcasts registriert. Es gibt drei Möglichkeiten, festzulegen, wer Ihre Broadcasts empfangen kann:
- Sie können beim Senden einer Broadcast-Nachricht eine Berechtigung angeben.
- Unter Android 4.0 (API-Level 14) und höher können Sie beim Senden eines Broadcasts mit
setPackage(String)ein package angeben. Das System beschränkt den Broadcast auf die Apps, die dem Paket entsprechen.
Wenn Sie einen Empfänger registrieren, kann jede App potenziell schädliche Broadcasts an den Empfänger Ihrer App senden. Es gibt mehrere Möglichkeiten, die von Ihrer App empfangenen Broadcasts einzuschränken:
- Sie können eine Berechtigung angeben, wenn Sie einen Übertragungsempfänger registrieren.
- Für im Manifest deklarierte Receiver können Sie das Attribut android:exported im Manifest auf „false“ setzen. Der Empfänger empfängt keine Broadcasts von Quellen außerhalb der App.
Der Namespace für Broadcast-Aktionen ist global. Achten Sie darauf, dass Aktionsnamen und andere Strings in einem Namespace geschrieben werden, der Ihnen gehört. Andernfalls kann es zu unbeabsichtigten Konflikten mit anderen Apps kommen.
Da die
onReceive(Context, Intent)-Methode eines Empfängers im Hauptthread ausgeführt wird, sollte sie schnell ausgeführt und zurückgegeben werden. Wenn Sie lang andauernde Aufgaben ausführen müssen, sollten Sie keine Threads erstellen oder Hintergrunddienste starten, da das System den gesamten Prozess nach der Rückgabe vononReceive()beenden kann. Weitere Informationen finden Sie unter Auswirkungen auf den Prozessstatus. Für Vorgänge mit langer Laufzeit empfehlen wir Folgendes:- Rufen Sie
goAsync()in deronReceive()-Methode des Receivers auf und übergeben SieBroadcastReceiver.PendingResultan einen Hintergrundthread. So bleibt die Übertragung aktiv, wenn du vononReceive()zurückkehrst. Auch bei diesem Ansatz erwartet das System, dass du die Übertragung sehr schnell (in weniger als 10 Sekunden) beendest. Sie können damit Aufgaben in einen anderen Thread verschieben, um Störungen im Hauptthread zu vermeiden. - Einen Job mit
JobSchedulerplanen Weitere Informationen finden Sie unter Intelligent Job Scheduling.
- Rufen Sie
Starten Sie keine Aktivitäten über Broadcast-Empfänger, da dies die Nutzerfreundlichkeit beeinträchtigt, insbesondere wenn es mehr als einen Empfänger gibt. Stattdessen können Sie eine Benachrichtigung anzeigen.