Broadcast Receiver Register in Manifest vs. Aktivität

72

Ich brauche Hilfe, um zu verstehen, wann ich erwarten kann, dass mein Rundfunkempfänger funktioniert, wenn er nur im Manifest registriert ist, anstatt von einer laufenden Aktivität oder einem laufenden Dienst registriert zu werden.

Wenn ich beispielsweise einen eigenständigen Empfänger mit dem folgenden Absichtsfilter registriere, funktioniert er ohne einen Dienst- / Aktivitätsverweis darauf:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.blk_burn.standalonereceiver"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />
    <uses-permission android:name="android.permission.WAKE_LOCK"/>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >

        <receiver android:name="TestReceiver">
            <intent-filter>
                <action android:name="android.media.AUDIO_BECOMING_NOISY"/>
            </intent-filter>
        </receiver>

    </application>

</manifest>

Allerdings, wenn ich android.media.AUDIO_BECOMING_NOISYmit android.intent.action.HEADSET_PLUGdem Empfänger ersetze, wird nicht ausgelöst ( Android-Dokumentation )

Nach dem, was ich auf dieser Site gefunden habe, müssen Sie diesen Empfänger von einer Aktivität oder einem Dienst registrieren, der bereits ausgeführt wird, damit er funktioniert ( Post ).

  • Kann mir jemand sagen, warum dies nicht funktioniert, wenn Sie nur Ihren Absichtsfilter im Manifest anpassen und warum im Hintergrund ein Dienst ausgeführt werden muss, der auf den Empfänger verweist / ihn registriert?

  • Gibt es eine Problemumgehung, mit der ich meinen Empfänger mithilfe eines Absichtsfilters mit im Manifest meiner App registrieren kann android.intent.action.HEADSET_PLUG?

  • Wie kann ich anhand der Android-Dokumentation feststellen, welche Broadcast-Aktionen von einem Dienst oder einer Aktivität registriert werden müssen, anstatt nur den richtigen Filter im Manifest zu haben?

Arnab C.
quelle

Antworten:

99

Wenn Ihr Empfänger im Manifest registriert ist und Ihre App nicht ausgeführt wird, wird ein neuer Prozess für die Übertragung erstellt. Wenn Sie es im Code registrieren, hängt es von der Lebensdauer der Aktivität / des Dienstes ab, bei der Sie es registriert haben. Bei einigen Sendungen ist es nicht wirklich sinnvoll, einen neuen App-Prozess zu erstellen, wenn er nicht vorhanden ist oder es einige gibt Auswirkungen auf Sicherheit, Leistung usw., und daher können Sie den Empfänger nur im Code registrieren.

Bei der HEADSET_PLUGÜbertragung scheint die Idee zu sein, dass Ihre bereits ausgeführte App damit app-spezifische Anpassungen an Benutzeroberfläche, Lautstärke usw. vornehmen kann. Wenn Ihre App nicht ausgeführt wird, sollten Sie sich nicht wirklich darum kümmern, dass die Kopfhörer vom Stromnetz getrennt werden.

AFAIK, es gibt keinen einzigen Ort, an dem diese Informationen für alle Sendungen zusammengefasst sind, aber jeder Intent sollte im JavaDoc einen Kommentar zur Registrierung und Verwendung enthalten, aber anscheinend fehlt er an einigen Stellen. Sie sollten in der Lage sein, eine Liste zu erstellen, wenn Sie den Android- Quellbaum nach Intent.FLAG_RECEIVER_REGISTERED_ONLY durchsuchen .

Nikolay Elenkov
quelle
1
intent.Flag .. und es im Quellcode zu finden macht Sinn. danke
Arnab C.
2
Für den ersten Absatz
Hut
1
Haben Sie ein offizielles Dokument, das Ihre Aussage unterstützt ( Wenn Ihr Empfänger im Manifest registriert ist und Ihre App nicht ausgeführt wird, wird ein neuer Prozess für die Übertragung erstellt ).
Behzad Bahmanyar
@BehzadBahmanyar Der folgende Link ist das Nächste, was ich finden konnte. developer.android.com/reference/android/content/… .
AnV
@BehzadBahmanyar Siehe auch CommonsWares Kommentare in dieser Frage: stackoverflow.com/a/3652085/2818583
AnV
26

Wie üblich können Rundfunkempfänger in der Manifestdatei AndroidManifest.xml konfiguriert werden. Ein auf diese Weise konfigurierter BroadcastReceiver wird als statisch registriert bezeichnet.

Sie können Ihren Empfänger in der Manifestdatei registrieren, indem Sie das folgende Element verwenden:

<receiver
   android:name=".ConnectivityChangeReceiver">
   <intent-filter>
      <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
   </intent-filter>
</receiver>

Das verschachtelte Element wird verwendet, um das Ereignis anzugeben, auf das der Empfänger reagieren soll.

Dyanmic Broadcast Recievers

Alternativ können Sie Ihre BroadcastReceiver-Implementierung dynamisch in Ihrem Code registrieren. Sie müssen nur die registerReceiver () -Methode für Ihr Context-Objekt aufrufen.

Die Methode registerReceiver () akzeptiert zwei Parameter:

Die Argumente der Methode registerReceiver ()

  • Empfänger: Der BroadcastReceiver, den Sie registrieren möchten
  • filter: Das IntentFilter-Objekt, das angibt, welches Ereignis Ihr Empfänger abhören soll.

Wenn Sie Ihren Empfänger auf diese Weise registrieren, lebt er so lange, wie die Komponente lebt, und Android sendet Ereignisse an diesen Empfänger, bis die erstellende Komponente selbst zerstört wird.

Es ist Ihre Aufgabe, den Lebenszyklus korrekt zu handhaben. Wenn Sie also einen Empfänger dynamisch hinzufügen, müssen Sie die Registrierung desselben Empfängers in der onPause () -Methode Ihrer Aktivität aufheben!

Ich schlage vor, den Empfänger in der onResume () -Methode Ihrer Aktivität zu registrieren und die Registrierung in Ihrer onPause () -Methode aufzuheben:

@Override
protected void onPause() {
   unregisterReceiver(mReceiver);
   super.onPause();
}

@Override
protected void onResume() {
   this.mReceiver = new ConnectivityChangeReceiver();
   registerReceiver(
         this.mReceiver, 
         new IntentFilter(
               ConnectivityManager.CONNECTIVITY_ACTION));
   super.onResume();
}

Wann soll die zu registrierende Methode verwendet werden?

Welche Methode zum Registrieren Ihres BroadcastReceiver verwendet wird, hängt davon ab, was Ihre App mit dem Systemereignis macht. Ich denke, es gibt grundsätzlich zwei Gründe, warum Ihre App über systemweite Ereignisse informiert werden möchte:

  • Ihre App bietet einen Service rund um diese Ereignisse
  • Ihre App möchte freundlich auf Statusänderungen reagieren

Beispiele für die erste Kategorie sind Apps, die funktionieren müssen, sobald das Gerät gestartet wird, oder die bei jeder Installation einer App eine Arbeit starten müssen. Battery Widget Pro oder App2SD sind gute Beispiele für diese Art von Apps. Für diesen Typ müssen Sie den BroadcastReceiver in der Manifest-Datei registrieren.

Beispiele für die zweite Kategorie sind Ereignisse, die auf eine Änderung der Umstände hinweisen, auf die sich Ihre App möglicherweise stützt. Angenommen, Ihre App hängt von einer hergestellten Bluetooth-Verbindung ab. Sie müssen auf eine Statusänderung reagieren - aber nur, wenn Ihre App aktiv ist. In diesem Fall ist kein statisch registrierter Rundfunkempfänger erforderlich. Ein dynamisch registrierter wäre vernünftiger.

Es gibt auch einige Ereignisse, für die Sie sich nicht einmal statisch registrieren dürfen. Ein Beispiel hierfür ist das Ereignis Intent.ACTION_TIME_TICK, das jede Minute gesendet wird. Dies ist eine kluge Entscheidung, da ein statischer Empfänger die Batterie unnötig entladen würde.

Haythem BEN AICHA
quelle
sehr gut gesagt, Bruder.
Jay Mungara
gut erklärt.
Abhishek Kumar