Android-Apps können Nachrichten an alle über das Android-System und anderen Android-Apps, ähnlich wie die publish-Subscribe Designmuster. Diese Broadcasts werden gesendet, wenn ein Ereignis von Interesse auftritt. Beispielsweise sendet das Android-System Broadcasts, wenn verschiedene Systemereignisse z. B. wenn das System hochfährt oder das Gerät aufgeladen wird. Apps können auch benutzerdefinierte Nachrichten senden, um z. B. andere Apps über etwas, das sie interessieren könnte (zum Beispiel, wenn einige neue Daten heruntergeladen wurden).
Das System optimiert die Übertragung von Sendungen, um um den Zustand des Systems zu optimieren. Daher ist die Lieferdauer von Übertragungen garantiert. Anwendungen, die eine Interprozesskommunikation mit niedriger Latenz benötigen, sollten gebundene Dienste in Betracht ziehen
Apps können sich für den Empfang bestimmter Broadcasts registrieren. Wenn eine Nachricht an alle gesendet wird, leitet das System Broadcasts automatisch an Apps weiter, die um diese Art von Übertragung zu empfangen.
Im Allgemeinen können Nachrichten an alle Apps als Nachrichtensystem verwendet werden. und außerhalb des normalen User Flows. Achten Sie jedoch darauf, die Möglichkeit, auf Broadcasts zu reagieren und Jobs im Hintergrund auszuführen, kann die Systemleistung beeinträchtigen.
Informationen zu Systemnachrichten
Das System sendet bei verschiedenen Systemereignissen automatisch Broadcasts, z. B. wenn das System den Flugmodus ein- und ausschaltet. System Broadcasts werden an alle Apps gesendet, die den Empfang von .
Die Broadcast-Nachricht selbst ist in einen Intent
umschlossen.
Objekt, dessen Aktionsstring das eingetretene Ereignis identifiziert (z. B.
android.intent.action.AIRPLANE_MODE
). Der Intent kann auch
zusätzliche Informationen
in einem zusätzlichen Feld. Zum Beispiel könnte das Flugzeug
Der Modus-Intent enthält ein boolesches Extra, das angibt, ob ein Flugzeug
Modus ist aktiviert.
Weitere Informationen zum Lesen von Intents und zum Abrufen des Aktionsstrings aus eines Intents, siehe Intents und Intents Filter:
Eine vollständige Liste aller System-Broadcast-Aktionen finden Sie in der
BROADCAST_ACTIONS.TXT
-Datei im Android SDK. Jede Übertragungsaktion hat ein
Konstante ein, die damit verknüpft ist. Zum Beispiel ist der Wert der Konstante
ACTION_AIRPLANE_MODE_CHANGED
ist
android.intent.action.AIRPLANE_MODE
. Dokumentation für jede Übertragungsaktion
im zugehörigen Feld für die Konstante verfügbar.
Änderungen an System-Broadcasts
Im Zuge der Weiterentwicklung der Android-Plattform ändert sich regelmäßig die Art und Weise, wie das System verhalten. Beachte die folgenden Änderungen, damit alle Versionen von Android unterstützt werden können.
Android 14
Solange sich Apps in einem zwischengespeicherten
Bundesstaat, Broadcast-Zustellung ist
optimiert für Systemzustand. Weniger wichtiges System sendet beispielsweise
da ACTION_SCREEN_ON
sind
verzögert, während sich die Anwendung im Cache-Status befindet. Sobald die Anwendung aus dem Cache
in einen aktiven Prozess
Lebenszyklus, liefert das System
verzögerte Übertragungen.
Wichtige Übertragungen, die in der Manifest vorübergehend Apps aus dem Cache entfernt. für die Auslieferung angeben.
Android 9
Ab Android 9 (API-Level 28)
NETWORK_STATE_CHANGED_ACTION
keine Informationen über den Standort oder die Person,
Daten zu identifizieren.
Wenn Ihre App auf einem Gerät mit Android 9 oder höher installiert ist,
System-Broadcasts vom WLAN enthalten keine SSIDs, BSSIDs,
oder Scanergebnisse. Diese Informationen erhalten Sie unter
getConnectionInfo()
.
Android 8.0
Ab Android 8.0 (API-Level 26) schreibt das System zusätzliche Einschränkungen für durch Manifest deklarierte Empfänger.
Wenn deine App auf Android 8.0 oder höher ausgerichtet ist, kannst du das Manifest nicht für folgende Zwecke verwenden: einen Empfänger für die meisten impliziten Broadcasts (Übertragungen, die nicht speziell für Ihre App). Sie können weiterhin ein kontextregistrierten Empfänger Nutzer Ihre App aktiv verwenden.
Android 7.0
Android 7.0 (API-Level 24) und höher senden das folgende System nicht Nachrichten an alle:
Apps, die auf Android 7.0 und höher ausgerichtet sind, müssen außerdem die CONNECTIVITY_ACTION
-Übertragung registrieren.
mit registerReceiver(BroadcastReceiver, IntentFilter)
.
Die Angabe eines Empfängers im Manifest funktioniert nicht.
Broadcasts werden empfangen
Apps können Broadcasts auf zwei Arten empfangen: über von Manifest deklarierte Empfänger und kontextregistrierten Empfängern.
Durch Manifest deklarierte Empfänger
Wenn du in deinem Manifest einen Übertragungsempfänger deklarierst, startet das System deinen (sofern die App noch nicht ausgeführt wird), wenn die Übertragung gesendet wird.
So deklarierst du einen Übertragungsempfänger im Manifest:
Geben Sie den
<receiver>
an. -Element im Manifest Ihrer App.<!-- 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="APP_SPECIFIC_BROADCAST" /> </intent-filter> </receiver>
Die Intent-Filter geben die Übertragungsaktionen an, die der Empfänger abonniert.
Erstellen Sie abgeleitete Klassen von
BroadcastReceiver
und implementieren SieonReceive(Context, Intent)
. Die Broadcast-Receiver in den folgenden Beispielprotokollen und zeigt den Inhalt an der Übertragung:Kotlin
private const val TAG = "MyBroadcastReceiver" class MyBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { StringBuilder().apply { append("Action: ${intent.action}\n") append("URI: ${intent.toUri(Intent.URI_INTENT_SCHEME)}\n") toString().also { log -> Log.d(TAG, log) val binding = ActivityNameBinding.inflate(layoutInflater) val view = binding.root setContentView(view) Snackbar.make(view, log, Snackbar.LENGTH_LONG).show() } } } }
Java
public class MyBroadcastReceiver extends BroadcastReceiver { private static final String TAG = "MyBroadcastReceiver"; @Override public void onReceive(Context context, Intent intent) { StringBuilder sb = new StringBuilder(); sb.append("Action: " + intent.getAction() + "\n"); sb.append("URI: " + intent.toUri(Intent.URI_INTENT_SCHEME).toString() + "\n"); String log = sb.toString(); Log.d(TAG, log); ActivityNameBinding binding = ActivityNameBinding.inflate(layoutInflater); val view = binding.root; setContentView(view); Snackbar.make(view, log, Snackbar.LENGTH_LONG).show(); } }
Um die Bindung der Ansicht zu aktivieren, Konfigurieren Sie viewBinding auf Ihrer Modulebene. build.gradle-Datei herunter.
Der Systempaketmanager registriert den Empfänger, wenn die App installiert wird. Der Empfänger wird zu einem separaten Einstiegspunkt in Ihre App, was bedeutet, dass das System die App starten und die Übertragung senden kann, wenn die App derzeit ausgeführt wird.
Das System erstellt eine neue BroadcastReceiver
-Komponente
-Objekt zur Verarbeitung jeder empfangenen Übertragung. Dieses Objekt ist nur gültig
für die Dauer des Aufrufs von onReceive(Context, Intent)
. Sobald Sie Ihren Code
gibt diese Methode zurück, betrachtet das System die Komponente nicht mehr
aktiv ist.
Kontextregistrierte Empfänger
Kontextregistrierte Empfänger empfangen Broadcasts,
Kontext gültig ist. Wenn Sie sich z. B. innerhalb eines
Activity
erhalten Sie Broadcasts, solange die Aktivität nicht gelöscht wird. Wenn Sie
erhalten 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:
Groovig
dependencies { def core_version = "1.13.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.0.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-alpha01" }
Kotlin
dependencies { val core_version = "1.13.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.0.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-alpha01") }
Instanz von erstellen
BroadcastReceiver
:Kotlin
val br: BroadcastReceiver = MyBroadcastReceiver()
Java
BroadcastReceiver br = new MyBroadcastReceiver();
Instanz von erstellen
IntentFilter
:Kotlin
val filter = IntentFilter(APP_SPECIFIC_BROADCAST)
Java
IntentFilter filter = new IntentFilter(APP_SPECIFIC_BROADCAST);
Legen Sie fest, ob der Übertragungsempfänger exportiert und sichtbar sein soll für andere Apps auf dem Gerät. Wenn dieser Empfänger auf gesendete Nachrichten wartet aus dem System oder aus anderen Apps – selbst aus Ihren eigenen Apps – Flag
RECEIVER_EXPORTED
. Wenn dieser Empfänger stattdessen nur Broadcasts, die von deiner App gesendet werden, verwende das FlagRECEIVER_NOT_EXPORTED
.Kotlin
val listenToBroadcastsFromOtherApps = false val receiverFlags = if (listenToBroadcastsFromOtherApps) { ContextCompat.RECEIVER_EXPORTED } else { ContextCompat.RECEIVER_NOT_EXPORTED }
Java
boolean listenToBroadcastsFromOtherApps = false; if (listenToBroadcastsFromOtherApps) { receiverFlags = ContextCompat.RECEIVER_EXPORTED; } else { receiverFlags = ContextCompat.RECEIVER_NOT_EXPORTED; }
Registrieren Sie den Empfänger über folgenden Anruf:
registerReceiver()
:Kotlin
ContextCompat.registerReceiver(context, br, filter, receiverFlags)
Java
ContextCompat.registerReceiver(context, br, filter, receiverFlags);
Wenn du keine Nachrichten an alle mehr erhalten möchtest, ruf
unregisterReceiver(android.content.BroadcastReceiver)
an. Heben Sie die Registrierung des Empfängers auf, wenn Sie ihn nicht mehr benötigen. Kontext nicht mehr gültig ist.Achten Sie darauf, wo Sie den Empfänger registrieren und abmelden: Wenn Sie beispielsweise einen Empfänger in
onCreate(Bundle)
mit dem Kontext der Aktivität registrieren, sollte es inonDestroy()
abmelden, um zu verhindern, dass der Empfänger aus dem Aktivitätskontext gerät. Wenn Sie sich registrieren an einen Empfänger inonResume()
, sollten Sie können Sie sie inonPause()
abmelden, und registriert haben. Wenn Sie keine Broadcasts empfangen möchten, Dadurch wird unnötiger Systemaufwand reduziert. Das sollten Sie nicht tun: sich inonSaveInstanceState(Bundle)
abmelden, da dies nicht aufgerufen wird, wenn der Nutzer in den Verlaufsstapel zurückkehrt.
Auswirkungen auf den Prozessstatus
Ob Ihr BroadcastReceiver
funktioniert oder nicht auf den enthaltenen Prozess auswirkt, wodurch seine
zum Absterben des Systems. Ein Vordergrundprozess führt die Methode onReceive()
eines Empfängers aus. Die
führt das System den Prozess aus,
außer unter extremer Speicherauslastung.
BroadcastReceiver wird nach onReceive()
deaktiviert. Der Host des Empfängers
ist nur so wichtig wie die App-Komponenten. Wenn dieser Prozess nur
ein durch ein Manifest deklarierter Empfänger (häufig für Apps, die der Nutzer noch nie
oder nicht mit ihnen interagiert haben), beendet das System das Gerät möglicherweise nach onReceive()
,
für andere kritische
Prozesse zur Verfügung.
Daher sollten Übertragungsempfänger keine Hintergrundthreads mit langer Ausführungszeit initiieren.
Das System kann den Prozess zur Rückforderung jederzeit nach onReceive()
beenden
Arbeitsspeicher, wodurch der erstellte Thread beendet wird. Um den Prozess am Laufen zu halten, planen Sie
JobService
vom Empfänger über die JobScheduler
damit das System weiß,
dass der Prozess noch funktioniert.
Weitere Informationen finden Sie in der Übersicht über die Hintergrundarbeit.
Broadcasts werden gesendet
Android bietet drei Möglichkeiten zum Senden von Nachrichten an Apps:
- Das
sendOrderedBroadcast(Intent, String)
-Methode Broadcasts an jeweils nur einen Empfänger sendet. Bei Ausführung jedes Empfängers wiederum kann ein Ergebnis an den nächsten Empfänger weitergegeben werden. Übertragung vollständig abbrechen, sodass sie nicht an andere Empfänger. Die Reihenfolge, in der die Empfänger ausgeliefert werden, kann mit dem android:Priority-Attribut des übereinstimmenden Intent-Filters. mit der werden in beliebiger Reihenfolge ausgeführt. - Die Methode
sendBroadcast(Intent)
sendet die in einer undefinierten Reihenfolge an alle Empfänger gesendet werden. Dies wird als „Normal“ bezeichnet. Nachricht an alle. Dies ist effizienter, bedeutet aber, dass Empfänger die Daten von anderen Empfängern empfangene Daten verbreiten brich die Übertragung ab.
Das folgende Code-Snippet zeigt, wie ein Broadcast gesendet wird, indem ein
Intent und Aufruf von sendBroadcast(Intent)
.
Kotlin
Intent().also { intent -> intent.setAction("com.example.broadcast.MY_NOTIFICATION") intent.putExtra("data", "Nothing to see here, move along.") sendBroadcast(intent) }
Java
Intent intent = new Intent(); intent.setAction("com.example.broadcast.MY_NOTIFICATION"); intent.putExtra("data", "Nothing to see here, move along."); sendBroadcast(intent);
Die Nachricht an alle ist in ein Intent
-Objekt umschlossen.
Der Aktionsstring des Intents muss die Syntax des Java-Paketnamens der App und
um das Übertragungsereignis eindeutig zu identifizieren. Sie können zusätzliche Informationen
mit putExtra(String, Bundle)
hinzu.
Sie können eine Übertragung auch auf eine Reihe von Apps in derselben Organisation beschränken.
setPackage(String)
für den Intent aufrufen.
Broadcasts mit Berechtigungen einschränken
Mit Berechtigungen kannst du Broadcasts auf die Apps beschränken, die bestimmte Berechtigungen. Sie können Einschränkungen für den Absender oder Empfänger einer Nachricht an alle.
Senden mit Berechtigungen
Wenn Sie sendBroadcast(Intent, String)
anrufen oder
sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
können Sie einen
Berechtigungsparameter. Nur Empfänger, die diese Berechtigung mit
das
Kotlin
sendBroadcast(Intent(BluetoothDevice.ACTION_FOUND), Manifest.permission.BLUETOOTH_CONNECT)
Java
sendBroadcast(new Intent(BluetoothDevice.ACTION_FOUND), Manifest.permission.BLUETOOTH_CONNECT)
Um die Übertragung zu empfangen, muss die empfangende App die Berechtigung folgendermaßen anfordern: (siehe unten):
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
Sie können entweder eine vorhandene Systemberechtigung wie
BLUETOOTH_CONNECT
oder definieren Sie eine benutzerdefinierte Berechtigung mit dem
<permission>
-Element. Für
Informationen zu Berechtigungen und Sicherheit im Allgemeinen finden Sie im System
Berechtigungen:
Empfangen mit Berechtigungen
Wenn Sie bei der Registrierung eines Übertragungsempfängers einen Berechtigungsparameter angeben
(entweder mit registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)
oder in
<receiver>
-Tag in Ihrem
Manifest) angezeigt werden, sind nur Sender, die die Berechtigung mit dem
<uses-permission>
-Tag
in ihrem Manifest (und haben dann die Berechtigung erhalten, falls sie
können einen Intent
an den Empfänger senden.
Angenommen, Ihre empfangende App hat einen durch Manifest deklarierten Empfänger als (siehe unten):
<receiver android:name=".MyBroadcastReceiver"
android:permission="android.permission.BLUETOOTH_CONNECT">
<intent-filter>
<action android:name="android.intent.action.ACTION_FOUND"/>
</intent-filter>
</receiver>
Oder die empfangende App hat einen kontextregistrierten Empfänger, wie unten gezeigt:
Kotlin
var filter = IntentFilter(Intent.ACTION_FOUND) registerReceiver(receiver, filter, Manifest.permission.BLUETOOTH_CONNECT, null )
Java
IntentFilter filter = new IntentFilter(Intent.ACTION_FOUND); registerReceiver(receiver, filter, Manifest.permission.BLUETOOTH_CONNECT, null );
Anschließend muss die sendende App Broadcasts an diese Empfänger senden wie unten gezeigt die Berechtigung anzufordern:
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
Sicherheitsüberlegungen und Best Practices
Im Folgenden finden Sie einige Sicherheitsaspekte und Best Practices für das Senden und Broadcasts empfangen:
Wenn viele Apps sich für den Empfang derselben Übertragung in ihrem Zuhause registriert haben, kann das System viele Apps starten, was zu einer erheblichen Einfluss auf die Geräteleistung und die Nutzererfahrung. Um dies zu vermeiden sollten Sie die Kontextregistrierung gegenüber der Manifestdeklaration verwenden. Manchmal erzwingt das Android-System selbst die Verwendung kontextregistrierter Empfänger. Beispielsweise wird die Übertragung
CONNECTIVITY_ACTION
nur kontextregistrierten Empfängern.Senden Sie keine vertraulichen Informationen mit einem impliziten Intent. Die Informationen können von jeder App gelesen werden, die sich für den Empfang der Übertragung registriert. Es gibt drei Möglichkeiten, festzulegen, wer deine Nachrichten empfangen kann:
- Du kannst beim Senden eines Broadcasts eine Berechtigung festlegen.
- Unter Android 4.0 und höher können Sie eine
package mit
setPackage(String)
beim Senden einer Nachricht an alle. Das System beschränkt die Übertragung auf die Apps, die mit dem Paket übereinstimmen.
Wenn Sie einen Empfänger registrieren, kann jede App potenziell schädliche Daten senden an den Receiver Ihrer App gesendet. Es gibt mehrere Möglichkeiten, Nachrichten, die Ihre App empfängt:
- Sie können bei der Registrierung eines Übertragungsempfängers eine Berechtigung angeben.
- Für durch ein Manifest deklarierte Empfänger können Sie die android:exported Attribut auf „false“ setzen im Manifest. Der Empfänger erhält keine 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, der Ihnen gehört. Andernfalls können Sie versehentlich mit anderen Apps in Konflikt stehen.
Da die Methode
onReceive(Context, Intent)
eines Empfängers Hauptthreads hat, sollte er schnell ausgeführt werden und zurückgegeben werden. Bei Bedarf lang andauernde Arbeit ausführen, sollten Sie vorsichtig sein, wenn Sie Threads erzeugen oder da das System den gesamten Prozess nach eineronReceive()
kehrt zurück. Weitere Informationen finden Sie unter Auswirkung auf Prozesse. State Um lang andauernde Arbeiten auszuführen, empfehlen:goAsync()
wird angerufen in deinemonReceive()
-Methode des Empfängers und übergibtBroadcastReceiver.PendingResult
an einen Hintergrundthread. Dadurch bleibt die Übertragung nach der Rückkehr vononReceive()
aktiv. Aber selbst bei diesem Ansatz erwartet das System, dass Sie mit die Übertragung sehr schnell (weniger als 10 Sekunden). Es ermöglicht Ihnen, zu einem anderen Thread wechseln, um Störungen im Hauptthread zu vermeiden.- Einen Job mit
JobScheduler
planen Weitere Informationen erhalten Sie unter Intelligenter Job Planung.
Starten Sie keine Aktivitäten von Übertragungsempfängern, da die Nutzererfahrung ist irritierend; vor allem, wenn es mehr als einen Empfänger gibt. Überlegen Sie sich stattdessen, Durch Anzeigen einer Benachrichtigung