Rundfunkempfänger für Anfänger

Angenommen, Sie haben eine Anwendung, die von einer festen Internetverbindung abhängt. Sie möchten, dass Ihre Anwendung benachrichtigt wird, wenn sich die Internetverbindung ändert. Wie machst du das? Eine mögliche Lösung wäre ein Dienst, der immer die Internetverbindung überprüft. Diese Implementierung ist aus verschiedenen Gründen schlecht, daher werden wir sie nicht einmal in Betracht ziehen. Die Lösung für dieses Problem ist ein Rundfunkempfänger, der Änderungen überwacht, die Sie ihm mitteilen. Ein Rundfunkempfänger wird unabhängig vom Status Ihrer Anwendung immer über eine Sendung benachrichtigt. Es spielt keine Rolle, ob Ihre Anwendung gerade ausgeführt wird, im Hintergrund oder überhaupt nicht ausgeführt wird.

Hintergrund

Broadcast-Empfänger sind Komponenten in Ihrer Android-Anwendung, die Broadcast-Nachrichten (oder Ereignisse) von verschiedenen Verkaufsstellen abhören:

  • Aus anderen Anwendungen
  • Aus dem System selbst
  • Aus Ihrer Bewerbung

Dies bedeutet, dass sie aufgerufen werden, wenn eine bestimmte Aktion aufgetreten ist, für die sie programmiert wurden (IE, eine Sendung).

Eine Sendung ist einfach eine Nachricht, die in ein Intent-Objekt eingeschlossen ist. Eine Sendung kann entweder implizit oder explizit sein.

  • Eine implizite Übertragung ist eine Übertragung , die nicht speziell auf Ihre Anwendung ausgerichtet ist, sodass sie nicht ausschließlich für Ihre Anwendung gilt. Um sich für einen zu registrieren, müssen Sie einen IntentFilter verwenden und in Ihrem Manifest deklarieren. Sie müssen dies alles tun, da das Android-Betriebssystem alle deklarierten Absichtsfilter in Ihrem Manifest überprüft und feststellt, ob eine Übereinstimmung vorliegt. Aufgrund dieses Verhaltens haben implizite Broadcasts kein Zielattribut. Ein Beispiel für eine implizite Übertragung wäre eine Aktion einer eingehenden SMS-Nachricht.
  • Eine explizite Übertragung ist eine Übertragung , die speziell für Ihre Anwendung auf eine im Voraus bekannte Komponente ausgerichtet ist. Dies geschieht aufgrund des Zielattributs, das den Paketnamen der Anwendung oder einen Komponentenklassennamen enthält.

Es gibt zwei Möglichkeiten, einen Empfänger zu deklarieren:

  1. Indem Sie eine in Ihrer AndroidManifest.xml-Datei mit dem Tag deklarieren (auch als statisch bezeichnet)

Sie werden feststellen, dass der oben deklarierte Rundfunkempfänger die Eigenschaft exported = "true" hat . Dieses Attribut teilt dem Empfänger mit, dass er Broadcasts von außerhalb des Anwendungsbereichs empfangen kann.

2. Oder dynamisch durch Registrieren einer Instanz bei registerReceiver (sogenannter Kontext registriert)

public abstract Intent registerReceiver (BroadcastReceiver receiver, IntentFilter filter);

Implementierung

Um Ihren eigenen Broadcast-Empfänger zu erstellen, müssen Sie zuerst die übergeordnete BroadcastReceiver-Klasse erweitern und die obligatorische Methode onReceive überschreiben:

public void onReceive(Context context, Intent intent) { //Implement your logic here }

Alles zusammen ergibt:

public class MyBroadcastReceiver extends BroadcastReceiver { @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(); Toast.makeText(context, log, Toast.LENGTH_LONG).show(); } }
⚠️Die Methode onReceive wird auf dem Hauptthread ausgeführt. Aus diesem Grund sollte ihre Ausführung kurz sein.

Wenn ein langer Prozess ausgeführt wird, kann das System den Prozess beenden, nachdem die Methode zurückgegeben wurde. Um dies zu umgehen, sollten Sie goAsync verwenden oder einen Job planen. Weitere Informationen zum Planen eines Jobs finden Sie am Ende dieses Artikels.

Beispiel für eine dynamische Registrierung

Um einen Empfänger mit einem Kontext zu registrieren, müssen Sie zuerst eine Instanz Ihres Rundfunkempfängers instanziieren:

BroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();

Anschließend können Sie es je nach gewünschtem Kontext registrieren:

IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); this.registerReceiver(myBroadcastReceiver, filter);

Vergessen Sie nicht, die Registrierung Ihres Rundfunkempfängers aufzuheben, wenn Sie ihn nicht mehr benötigen

@Override protected void onStop() { super.onStop(); unregisterReceiver(myBroadcastReceiver); }

Ausstrahlung eines Ereignisses

Der Grund für das Senden von Nachrichten aus Ihrer Anwendung besteht darin, dass Ihre Anwendung auf Ereignisse reagieren kann, die innerhalb der Anwendung auftreten. Stellen Sie sich ein Szenario vor, in dem der Benutzer in einem Teil des Codes eine bestimmte Aktion ausführt und aus diesem Grund eine andere Logik ausführen möchte, die Sie an einem anderen Ort haben.

Es gibt drei Möglichkeiten, Sendungen zu senden:

  1. Der sendOrderedBroadcastMethode, stellt sicher, dass Sendungen jeweils nur an einen Empfänger gesendet werden. Jede Sendung kann wiederum Daten an die folgende Sendung weiterleiten oder die Weitergabe der Sendung an die folgenden Empfänger stoppen
  2. Der sendBroadcast ähnelt der oben genannten Methode, mit einem Unterschied. Alle Rundfunkempfänger empfangen die Nachricht und sind nicht voneinander abhängig
  3. Die LocalBroadcastManager.sendBroadcast- Methode sendet nur Broadcasts an Empfänger, die in Ihrer Anwendung definiert sind, und überschreitet nicht den Umfang Ihrer Anwendung. Beispiel für das Senden einer benutzerdefinierten Broadcast

//giphy.com/gifs/23gUJhHyWkXEwl7UYV/html5

Fallstricke und Dinge, auf die man achten sollte

  • Senden Sie keine vertraulichen Daten über eine implizite Übertragung, da jede Anwendung, die darauf wartet, diese empfängt. Sie können dies verhindern, indem Sie entweder ein Paket angeben oder der Broadcast eine Berechtigung hinzufügen
  • Starten Sie Aktivitäten nicht mit einer empfangenen Sendung, da die Benutzererfahrung fehlt. Wählen Sie stattdessen die Anzeige einer Benachrichtigung.

Die folgenden Aufzählungspunkte beziehen sich auf Änderungen an Rundfunkempfängern, die für jede Android-Betriebssystemversion relevant sind (ab 7.0). Für jede Version wurden bestimmte Einschränkungen vorgenommen, und auch das Verhalten hat sich geändert. Beachten Sie diese Einschränkungen, wenn Sie über die Verwendung eines Rundfunkempfängers nachdenken.

  • 7.0 und höher (API-Stufe 24) - Zwei System-Broadcasts wurden deaktiviert, Action_New_Picture und Action_New_Video (sie wurden jedoch für registrierte Empfänger in Android O zurückgebracht).
  • 8.0 und höher (API-Stufe 26) - Die meisten impliziten Broadcasts müssen dynamisch und nicht statisch (in Ihrem Manifest) registriert werden. Unter diesem Link finden Sie die Sendungen, die auf der Whitelist standen.
  • 9.0 und höher (API-Ebene 28) - Weniger Informationen über Wi-Fi-System-Broadcast und Network_State_Changed_Action empfangen.

Die Änderungen in Android O sind diejenigen, die Sie am besten kennen müssen. Der Grund, warum diese Änderungen vorgenommen wurden, war, dass sie zu Leistungsproblemen, Batterieentladung und einer Beeinträchtigung der Benutzererfahrung führten. Dies geschah, weil viele Anwendungen (auch diejenigen, die derzeit nicht ausgeführt werden) eine systemweite Änderung mithörten und als diese Änderung eintrat, kam es zu Chaos. Stellen Sie sich vor, jede für die Aktion registrierte Anwendung wurde zum Leben erweckt, um zu überprüfen, ob aufgrund der Übertragung etwas unternommen werden muss. Berücksichtigen Sie so etwas wie den WLAN-Status, der sich häufig ändert, und Sie werden verstehen, warum diese Änderungen stattgefunden haben.

Alternativen zu Rundfunkempfängern

Um das Navigieren in all diesen Einschränkungen zu vereinfachen, finden Sie unten eine Aufschlüsselung anderer Komponenten, die Sie verwenden können, wenn kein Rundfunkempfänger vorhanden ist. Jeder hat eine andere Verantwortung und einen anderen Anwendungsfall. Versuchen Sie also herauszufinden, welcher Ihren Anforderungen entspricht.

  • LocalBroadcastManager - Wie oben erwähnt, gilt dies nur für Sendungen in Ihrer Anwendung
  • Planen eines Jobs - Ein Job kann abhängig von einem empfangenen Signal oder Trigger ausgeführt werden, sodass Sie möglicherweise feststellen, dass die Sendung, die Sie abgehört haben, durch einen Job ersetzt werden kann. Darüber hinaus ist dieJobScheduler garantiert, dass Ihr Job beendet wird, berücksichtigt jedoch verschiedene Systemfaktoren (Zeit und Bedingungen), um zu bestimmen, wann er ausgeführt werden soll. Beim Erstellen eines Jobs überschreiben Sie eine Methode namens onStartJob . Diese Methode wird auf dem Hauptthread ausgeführt. Stellen Sie daher sicher, dass die Arbeit in einer begrenzten Zeit abgeschlossen ist. Wenn Sie eine komplexe Logik ausführen müssen, sollten Sie eine Hintergrundaufgabe starten. Darüber hinaus ist der Rückgabewert für diese Methode ein Boolescher Wert, wobei true angibt, dass bestimmte Aktionen noch ausgeführt werden, und false bedeutet, dass der Job ausgeführt wird

Wenn Sie die Freude und das Wunder, die Rundfunkempfänger sind, aus erster Hand erleben möchten, können Sie diesen Links zu den von mir eingerichteten Repositories folgen:

  1. Benutzerdefinierte Sendung (mit Manifestdeklaration)
  2. Registrierung der Sendung (ohne eine im Manifest anzugeben)
  3. LocalBroadcastManager

Sendung über.