Android-Apps senden und empfangen Broadcast-Nachrichten vom Android-System und anderen Android-Apps, ähnlich dem Publish-Subscribe-Designmuster. Das System und die Apps senden in der Regel Broadcasts, wenn bestimmte Ereignisse eintreten. Das Android-System sendet beispielsweise Broadcasts, wenn verschiedene Systemereignisse auftreten, z. B. beim Systemstart oder beim Aufladen des Geräts. Apps senden auch benutzerdefinierte Broadcasts, um beispielsweise andere Apps über etwas zu benachrichtigen, das für sie von Interesse sein könnte (z. B. ein neuer Download).
Apps können sich registrieren, um bestimmte Broadcasts zu empfangen. Wenn ein Broadcast gesendet wird, leitet das System ihn automatisch an Apps weiter, die ihn abonniert haben.
Im Allgemeinen können Broadcasts als Messaging-System für Apps und außerhalb des normalen Nutzerablaufs verwendet werden. Sie müssen jedoch darauf achten, die Möglichkeit, auf Broadcasts zu reagieren und Jobs im Hintergrund auszuführen, nicht zu missbrauchen, da dies die Systemleistung beeinträchtigen kann.
System-Broadcasts
Das System sendet automatisch Broadcasts, wenn verschiedene Systemereignisse auftreten, z. B. wenn das System in den Flugmodus wechselt oder ihn verlässt. Alle abonnierten Apps erhalten 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.
Die Absicht für den Flugmodus enthält beispielsweise ein boolesches Extra, das angibt, ob der Flugmodus aktiviert ist oder nicht.
Weitere Informationen zum Lesen von Intents und zum Abrufen des Aktionsstrings aus einem Intent finden Sie unter Intents und Intent-Filter.
System-Broadcast-Aktionen
Eine vollständige Liste der System-Broadcast-Aktionen finden Sie in der Datei BROADCAST_ACTIONS.TXT im Android SDK. Jeder Broadcast-Aktion ist ein Konstantenfeld 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 Konstantenfeld verfügbar.
Änderungen an System-Broadcasts
Mit der Weiterentwicklung 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 kann die Reihenfolge der Broadcast-Zustellung mit dem android:priority
Attribut oder IntentFilter.setPriority() über verschiedene Prozesse hinweg
nicht garantiert werden. Broadcast-Prioritäten werden nur innerhalb desselben Anwendungsprozesses berücksichtigt, nicht über alle Prozesse hinweg.
Außerdem sind die Broadcast-Prioritäten automatisch auf den Bereich
(SYSTEM_LOW_PRIORITY + 1, SYSTEM_HIGH_PRIORITY - 1) beschränkt.
Nur Systemkomponenten dürfen SYSTEM_LOW_PRIORITY und SYSTEM_HIGH_PRIORITY als Broadcast-Priorität festlegen.
Android 14
Wenn sich Apps im Cache befinden, optimiert das System die Broadcast-Zustellung
um die Systemleistung zu gewährleisten. Das System verschiebt beispielsweise weniger wichtige System
Broadcasts wie ACTION_SCREEN_ON, während sich die App im Cache befindet.
Sobald die App aus dem Cache in einen aktiven Prozesslebenszyklus,
liefert das System alle verschobenen Broadcasts.
Wichtige Broadcasts, die im Manifest deklariert sind, entfernen Apps vorübergehend aus dem Cache, damit sie zugestellt werden können.
Android 9
Ab Android 9 (API-Level 28) enthält der NETWORK_STATE_CHANGED_ACTION
Broadcast keine Informationen zum Standort des Nutzers oder zu personenbezogenen
Daten.
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) gelten für im Manifest deklarierte Empfänger zusätzliche Einschränkungen.
Wenn Ihre App auf Android 8.0 oder höher ausgerichtet ist, können Sie im Manifest keinen Empfänger für die meisten impliziten Broadcasts deklarieren (Broadcasts, die nicht speziell auf Ihre App ausgerichtet sind). Sie können weiterhin einen kontextregistrierten Empfänger 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.
Broadcasts empfangen
Apps können Broadcasts auf zwei Arten empfangen: über kontextregistrierte Empfänger und im Manifest deklarierte Empfänger.
Kontextregistrierte Empfänger
Kontextregistrierte Empfänger empfangen Broadcasts, solange ihr Registrierungskontext gültig ist. Dies ist 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, empfangen Sie Broadcasts, solange die Aktivität
aktiv bleibt. Wenn Sie sich mit dem Anwendungskontext registrieren, empfangen Sie Broadcasts, solange die App ausgeführt wird.
So registrieren Sie einen Empfänger mit einem Kontext:
Fügen Sie in der Build-Datei auf Modulebene Ihrer App Version 1.9.0 oder höher von der AndroidX Core-Bibliothek hinzu:
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 Empfänger auf Broadcasts wartet, die vom System oder von anderen Apps gesendet werden – auch von anderen Apps, deren Inhaber Sie sind –, verwenden Sie das Flag
RECEIVER_EXPORTED. Wenn dieser Empfänger 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 mit
registerReceiver():Kotlin
ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags)Java
ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags);Wenn Sie keine Broadcasts mehr empfangen möchten, rufen Sie
unregisterReceiver(android.content.BroadcastReceiver)auf. Heben Sie die Registrierung des Empfängers auf, wenn Sie ihn nicht mehr benötigen oder der Kontext nicht mehr gültig ist.
Registrierung des Broadcast-Empfängers aufheben
Solange der Übertragungsempfänger registriert ist, enthält er einen Verweis auf den Kontext, mit dem Sie ihn registriert haben. Dies kann zu Speicherlecks führen, wenn der registrierte Bereich des Empfängers den Lebenszyklusbereich des Kontexts überschreitet. Dies kann beispielsweise auftreten, wenn Sie einen Empfänger im Bereich einer Aktivität registrieren, aber vergessen, die Registrierung aufzuheben, wenn das System die Aktivität zerstört. Heben Sie daher immer die Registrierung Ihres Broadcast-Empfängers auf.
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 an dem Ergebnis interessiert sind. Wählen Sie den kleinstmöglichen Empfängerbereich aus:
LifecycleResumeEffectoder die LebenszyklusmethodenonResume/onPauseder Aktivität: Der Übertragungsempfänger erhält nur Updates, wenn sich die App im fortgesetzten Zustand befindet.LifecycleStartEffectoder die LebenszyklusmethodenonStart/onStopder Aktivität: Der Übertragungsempfänger erhält nur Updates, wenn sich die App im fortgesetzten Zustand befindet.DisposableEffect: Der Übertragungsempfänger erhält nur Updates, wenn sich die zusammensetzbare Funktion im Kompositionsbaum befindet. Dieser Bereich ist nicht an den Aktivitätslebenszyklus gebunden. Registrieren Sie den Empfänger im Anwendungskontext. Dies liegt daran, dass die zusammensetzbare Funktion theoretisch den Aktivitätslebenszyklus überdauern und die Aktivität lecken könnte.onCreate/onDestroyder Activity: Der Übertragungsempfänger erhält Updates, wenn sich die Activity im erstellten Zustand befindet. Heben Sie die Registrierung inonDestroy()und nicht inonSaveInstanceState(Bundle)auf, da diese möglicherweise nicht aufgerufen wird.- Ein benutzerdefinierter Bereich: Sie können beispielsweise einen Empfänger im Bereich
ViewModelregistrieren, damit er die Neuerstellung der Aktivität überdauert. Verwenden Sie den Anwendungskontext, um den Empfänger zu registrieren, da der Empfänger den Lebenszyklusbereich der Aktivität überdauern und die Aktivität lecken kann.
Zustandsbehaftete und zustandslose zusammensetzbare Funktionen erstellen
Compose hat zustandsbehaftete und zustandslose zusammensetzbare Funktionen. Wenn Sie einen Übertragungsempfänger innerhalb einer zusammensetzbaren Funktion registrieren oder die Registrierung aufheben, wird er zustandsbehaftet. Die zusammensetzbare Funktion ist keine deterministische Funktion, die bei Übergabe derselben Parameter denselben Inhalt rendert. Der interne Zustand kann sich je nach Aufrufen des registrierten Broadcast-Empfängers ändern.
Als Best Practice in Compose empfehlen wir, Ihre zusammensetzbaren Funktionen in zustandsbehaftete und zustandslose Versionen aufzuteilen. Wir empfehlen daher, die Erstellung des Übertragungsempfängers aus einer zusammensetzbaren Funktion herauszuheben, um ihn zustandslos zu machen:
@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 im 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
<receiver>Element 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 Ihr 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 System-Paketmanager registriert den Empfänger, wenn die App installiert wird. Der Empfänger wird dann zu einem separaten Einstiegspunkt in Ihre App. Das bedeutet, dass das System die App starten und den Broadcast zustellen kann, wenn die App nicht ausgeführt wird.
Das System erstellt ein neues BroadcastReceiver-Komponentenobjekt, um
jeden empfangenen Broadcast zu verarbeiten. Dieses Objekt ist nur für die Dauer von
dem Aufruf 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 ausgeführt wird oder nicht, wirkt sich auf den enthaltenen
Prozess aus, was die Wahrscheinlichkeit beeinflussen kann, dass er vom System beendet wird. Ein Vordergrundprozess
führt die Methode onReceive() eines Empfängers aus. Das System führt den Prozess aus, es sei denn, der Arbeitsspeicher ist extrem ausgelastet.
Das System deaktiviert den BroadcastReceiver nach onReceive().
Die Bedeutung des Hostprozesses des Empfängers hängt von seinen App-Komponenten ab. Wenn dieser Prozess nur einen im Manifest deklarierten Empfänger hostet, beendet das System ihn möglicherweise nach onReceive(), um Ressourcen für andere, wichtigere Prozesse freizugeben. Dies ist häufig bei Apps der Fall, mit denen der Nutzer noch nie oder seit Kurzem nicht mehr interagiert hat.
Daher sollten Übertragungsempfänger keine lang andauernden Hintergrundthreads starten.
Das System kann den Prozess jederzeit nach onReceive() beenden, um Arbeitsspeicher freizugeben, und dabei den erstellten Thread beenden. Wenn Sie den Prozess aktiv halten möchten, planen Sie einen
JobService vom Empfänger mit dem JobScheduler, damit das
System weiß, dass der Prozess noch ausgeführt wird. Weitere Informationen
finden Sie unter Hintergrundaufgaben.
Broadcasts senden
Android bietet zwei Möglichkeiten für Apps, Broadcasts zu senden:
- Die
sendOrderedBroadcast(Intent, String)Methode sendet Broadcasts jeweils an einen Empfänger. Da jeder Empfänger nacheinander ausgeführt wird, kann er ein Ergebnis an den nächsten Empfänger weitergeben. Er kann den Broadcast auch vollständig abbrechen, sodass er andere Empfänger nicht erreicht. Sie können die Reihenfolge steuern, in der Empfänger innerhalb desselben App-Prozesses ausgeführt werden. Verwenden Sie dazu das Attributandroid:prioritydes entsprechenden Absichtsfilters. Empfänger mit derselben Priorität werden in beliebiger Reihenfolge ausgeführt. - Die
sendBroadcast(Intent)Methode sendet Broadcasts in undefinierter Reihenfolge an alle Empfänger Dies wird als normaler Broadcast bezeichnet. Diese Methode ist effizienter, aber Empfänger können keine Ergebnisse von anderen Empfängern lesen, Daten weitergeben, die sie vom Broadcast erhalten haben, oder den Broadcast abbrechen.
Das folgende Code-Snippet zeigt, wie Sie einen Broadcast senden, indem Sie eine
Absicht 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 String action der Absicht muss die Java-Paketnamenssyntax der App enthalten und das Broadcast-Ereignis eindeutig identifizieren. Mit putExtra(String, Bundle) können Sie der
Absicht zusätzliche Informationen anhängen. Sie können einen Broadcast auch auf
eine Reihe von Apps in derselben Organisation beschränken, indem Sie setPackage(String) für
die Absicht aufrufen.
Broadcasts 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 den Empfänger eines Broadcasts 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 <uses-permission> Tag 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. Der folgende Code sendet beispielsweise einen Broadcast mit einer Berechtigung:
Kotlin
context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION)
Java
context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION);
Damit die empfangende App den Broadcast 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 mit dem
<permission> Element eine benutzerdefinierte Berechtigung definieren. Informationen zu Berechtigungen und Sicherheit im
Allgemeinen finden Sie unter den Systemberechtigungen.
Broadcasts mit Berechtigungen empfangen
Wenn Sie beim Registrieren eines Übertragungsempfängers einen Berechtigungsparameter angeben
(entweder mit
registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) oder im
<receiver> Tag im Manifest), können nur Absender, die die Berechtigung mit dem <uses-permission> Tag in ihrem
Manifest angefordert haben, eine Absicht an den Empfänger senden. Wenn die Berechtigung gefährlich ist, muss sie dem Absender auch erteilt werden.
Angenommen, Ihre empfangende 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 Interprocess Communication (IPC) konzipiert, um Nachrichten zwischen verschiedenen Apps oder zwischen dem System und Apps zu senden. Das Senden eines Selbst-Broadcasts, bei dem alle der Empfänger im selben Prozess ausgeführt werden, der den Broadcast gesendet hat, ist sehr ineffizient, verursacht unnötigen Systemaufwand und wird dringend abgeraten.
In zwei häufigen Szenarien senden Apps Broadcasts an sich selbst:
Kommunikation zwischen Komponenten im selben Prozess: Beispielsweise 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 Senden und Beobachten von Ereignisstreams oder Statusaktualisierungen über Coroutinen und Komponenten in Ihrer App hinweg. - Gemeinsames
ViewModel: Ermöglicht die gemeinsame Nutzung von Daten und Ereignissen zwischen verschiedenen UI-Komponenten (z. B. Fragmenten oder zusammensetzbaren Funktionen) innerhalb derselben Aktivität. - Callbacks und Listener: Standardmäßige Interface-Callbacks oder Funktions verweise, die direkt zwischen Komponenten übergeben oder in einem zentralen Repository oder Controller registriert werden.
- Kotlin-Flows (
Systemereignisse, Jobs oder Alarme verarbeiten: Beispielsweise einen geplanten Job, Alarm oder System-Callback empfangen und dann einen Broadcast senden, um die eigentliche Arbeit auszulösen. Senden Sie keinen Broadcast, sondern führen Sie die Arbeit direkt in diesem Job (z. B. einem
JobServiceoder WorkManager-Worker), Alarm-Handler oder der System-Callback-Komponente aus oder delegieren Sie sie direkt an die Klassen der Geschäftslogik Ihrer App.
Auf Geräten mit Android 17 QPR2 oder höher liefert das System Selbst-Broadcasts effizienter, indem es sie an den sendenden Prozess zurückgibt, der sie im Hauptthread an seine eigenen Empfänger liefert. Das Senden eines Selbst-Broadcasts erhöht die Wichtigkeit Ihres Prozesses nicht und verhindert nicht, dass ein im Cache gespeicherter Prozess eingefroren wird. Verlassen Sie sich daher nicht auf Selbst-Broadcasts, um Ihre App auszuführen oder Arbeit im Hintergrund zu erledigen. Wählen Sie stattdessen die entsprechende API für Ihre Aufgabe aus, wie unter Hintergrundaufgabenbeschrieben. Auch mit dieser Optimierung sind Selbst-Broadcasts weniger effizient als In-Process-Kommunikationsmechanismen. Verwenden Sie daher stattdessen diese Alternativen.
Weitere Informationen zum Entwerfen der Kommunikation zwischen App-Komponenten finden Sie unter dem Leitfaden zur App-Architektur.
Sicherheitsaspekte
Hier sind einige Sicherheitsaspekte für das Senden und Empfangen von Broadcasts:
Wenn viele Apps im Manifest registriert sind, um denselben Broadcast 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 Empfängern. Der
CONNECTIVITY_ACTIONBroadcast wird beispielsweise nur an kontextregistrierte Empfänger gesendet.Senden Sie keine vertraulichen Informationen mit einer impliziten Absicht. Jede App kann die Informationen lesen, wenn sie sich für den Empfang des Broadcasts registriert. Es gibt drei Möglichkeiten, zu steuern, wer Ihre Broadcasts empfangen kann:
- Sie können beim Senden eines Broadcasts eine Berechtigung angeben.
- Unter Android 4.0 (API-Level 14) und höher können Sie beim Senden eines Broadcasts mit
setPackage(String)ein Paket 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 Broadcasts zu beschränken, die Ihre App empfängt:
- Sie können beim Registrieren eines Übertragungsempfängers eine Berechtigung angeben.
- Für im Manifest deklarierte Empfänger können Sie das android:exported Attribut 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 sind, dessen Inhaber Sie sind. Andernfalls kann es zu unbeabsichtigten Konflikten mit anderen Apps kommen.
Da die Methode
onReceive(Context, Intent)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 vorsichtig sein, Threads zu erstellen oder Hintergrunddienste zu starten, da das System den gesamten Prozess beenden kann, nachdemonReceive()zurückgegeben wurde. Weitere Informationen finden Sie unter Auswirkungen auf den Prozessstatus. So führen Sie lang andauernde Aufgaben aus:- Rufen Sie in der Methode
onReceive()Ihres EmpfängersgoAsync()auf und übergeben SieBroadcastReceiver.PendingResultan einen Hintergrund thread. Dadurch bleibt der Broadcast aktiv, nachdemonReceive()zurückgegeben wurde. Auch bei dieser Methode erwartet das System jedoch, dass Sie den Broadcast sehr schnell (innerhalb von 10 Sekunden) beenden. Sie können die Arbeit jedoch in einen anderen Thread verschieben, um zu vermeiden, dass der Hauptthread fehlerhaft funktioniert. - Planen Sie einen Job mit dem
JobScheduler. Weitere Informationen finden Sie unter Intelligente Jobplanung.
- Rufen Sie in der Methode
Starten Sie keine Activities von Übertragungsempfängern, da dies die Nutzerfreundlichkeit beeinträchtigt, insbesondere wenn es mehrere Empfänger gibt. Erwägen Sie stattdessen, eine Benachrichtigung anzuzeigen.