BroadcastReceiver Lifetime - Newbiefrge

K

KurrKurr

Fortgeschrittenes Mitglied
24
Hallo Leute,

Ich hab mich erst vor kurzem begonnen, mich mit Android auseinanderzusetzen. Bitte steinigt mich nicht gleich. Ich hab auch schon die Suche beansprucht, dabei ist aber nichts herausgekommen.

Folgendes Szenario:

Ich schreibe grade ein Plug-In für Locale, welches hört, ob sich der Verindungsstatus irgendwie ändert (home, roaming, etc.). Ich hab schon einige Zeit gebraucht, bis ich überrissen habe, wie genau die Locale-Anbindung funktioniert.

Ich stehe jetzt vor folgendem Problem: Ich habe einen Receiver per XML deklaration registriert, der auf "ConnectivityManager.CONNECTIVITY_ACTION", also auf gebroadcastete "android.net.conn.CONNECTIVITY_CHANGE"-Intents reagiert.

Es funktioniert zwar alles, aber eben nur EIN EINZIGES MAL. Ich bin mittlerweile draufgekommen, dass nach dem aufruf der onReceive()-Methode die Lebenszeit des Receivers um ist.

Gibt es jetzt eine Möglichkeit, diesen Receiver wieder zu registrieren, nachdem er das Intent empfangen hat und nach onReceive() aufgehört hat zu existieren?

Ein Service wäre zwar eine Möglichkeit, aber dieser würde dann, womöglich für eine sehr lange Zeit ungenutzt im Speicher herumgammenln und nur Ressourcen vergeuden. Deshalb habe ich mir überlegt, ob ich nicht den Receiver noch einmal starten kann.

Ginge das über den umweg über eine Activity, die natürlich nicht sichtbar sein soll?

Ich stehe hier etwas an. Vielleicht könnte mir jemand einen Hinweis in die Richtige Richtung geben. Ein Link oder so würde schon reichen; Den Rest recherchiere ich dann schon.

Grüße,
Chris

[Edit]
P.S.: Könnte vl. ein Moderator den Rechtschreibfehler im Titel ausbessern? Es sollte Newbiefrage und nicht Newbiefrge heißen... (kann ich das denn nicht selbst?)
 
Der Receiver sollte eigentlich jedes mal neu feuern...was danach passiert kommt drauf an was der Entwickler vor hat. Allzu aufwendige Sachen sollte man nicht machen, weil der Receiver dann zu lange braucht um abgearbeitet zu werden. In diesem Fall empfiehlt sich dann ein Service. Außerdem kann man von einem Receiver aus sowieso nicht alle Aktionen ausführen die man vielleicht braucht.

Und wegen dem Titel: Nein, kann man leider nicht selbst ändern, und ich kann die Rechtschreibfehler in meinen Titeln auch nicht sehen ohne mich ständig zu ärgern :D

Poste doch mal bitte deinen ganzen Code, wenn es nicht zu viel oder zu geheim ist :p
 
Naja, der Receiver sollte jedesmal aufgerufen werden wenn der Broadcast kommt. Neu registrieren brauchst du ihn nicht, da er in der XML deklariert ist. Dann hängt er immer dran.

Wahrscheinlich wird dein Receiver auch aufgerufen und du machst beim 2. Mal etwas anders als beim ersten Mal. Aller Wahrscheinlichkeit nach hast du irgendwelche Objektvariablen, in denen nun schon was drin steht und die du abfragst.

Schließe mich FelixL an. Poste mal den Code, auch wenn er zu geheim ist ;)
 
Also laut android-API sieht die Sache so aus:

http://developer.android.com/reference/android/content/BroadcastReceiver.html schrieb:
[...] A BroadcastReceiver object is only valid for the duration of the call to onReceive(Context, Intent). Once your code returns from this function, the system considers the object to be finished and no longer active. [...]

Mein Code ist ganz am Ende des Posts zu finden. So geheim ist der ja nicht.

Zuerst ein paar Erklärungen:
Wundert euch nicht über die Comments. Ich hab mir nämlich das von Locale zur verfügung gestellte Beispiel einer Display-Condition (Display an/aus) genommen und das ganze geändert.

Kurze Erläuterung: Die Condition selbst funktioniert sehr gut (das ist auch ein BroadcastReceiver, der von Locale ein Intent empfängt), und auch das Bearbeiten (die Edit-Action) der zu prüfenden Bedingung, die entscheidet, ob meine Locale-Condition zutrifft, oder nicht funktioniert soweit.

Wenn ich die Variable REQUEST_REQUERY, deren Wert ein Intent "com.twofortyfouram.Intent.ACTION_REQUEST_QUERY" ist Broadcaste, dann weise ich Locale an, meine Condition wieder mal zu checken.

Die Klasse selbst reagiert auf "android.net.conn.CONNECTIVITY_CHANGE". Die wichtigsten beiden Zeilen sind eigentlich
Code:
        ContextWrapper cw = new ContextWrapper(context);
        cw.sendBroadcast(REQUEST_REQUERY);
Das meiste andere ist eigentlich nur logging, da ich auf Fehlersuche bin.

Die Methode getCarrierState() werde ich glaube ich da wieder rausnehmen, da ich sie, denke ich, nicht brauche. Darum ist sie auch auskommentiert.

Die Aufgabe selbst ist eigentlich so simpel:

  1. Höre auf "android.net.conn.CONNECTIVITY_CHANGE"
  2. Sende Broadcast "com.twofortyfouram.Intent.ACTION_REQUEST_QUERY"
Nur leider funtkioniert das nur ein EINZIGES Mal...

Chris

P.S.: Hier der Code:

Code:
package com.schmeisserweb.carrierstring;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;

/**
 * {@code Service} for monitoring the {@code REGISTERED_RECEIVER_ONLY}
 * {@code Intent}s {@link Intent#ACTION_SCREEN_ON} and
 * {@link Intent#ACTION_SCREEN_OFF}.
 */
public final class NetworkConnectivityReceiver extends BroadcastReceiver {

    private static final Intent REQUEST_REQUERY = new Intent(
            com.twofortyfouram.Intent.ACTION_REQUEST_QUERY);

    static {
        REQUEST_REQUERY.putExtra(com.twofortyfouram.Intent.EXTRA_ACTIVITY,
                EditActivity.class.getName());
    }
    //private static String carrier;
    
    @Override
    public void onReceive(final Context c, final Intent i) {
        startReception(c, i);
    }

    private void startReception(final Context context, final Intent intent) {
        String action = intent.getAction();
        Log.d("CarrierCondition", "Action Received: " + action + " From intent: " + intent);
        Bundle extras = intent.getExtras();
        for (String key : extras.keySet()) {
            Log.d("CarrierCondition", key + "::" + extras.get(key));
        }
        //carrier = getCarrierState(context);
        ContextWrapper cw = new ContextWrapper(context);
        Log.d("CarrierCondition","Broadcast sent");
        cw.sendBroadcast(REQUEST_REQUERY);
        
        /*final IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        cw.registerReceiver(this, filter);*/
        

    }

/*    public static String getCarrierState(final Context c) {
        if (carrier == null) {
            try {
                final ContextWrapper cw = new ContextWrapper(c);
                final TelephonyManager tm = (TelephonyManager) cw
                        .getSystemService(Context.TELEPHONY_SERVICE);
                final String carrier = tm.getNetworkOperatorName();

                Log.d("CarrierCondition", "State is " + carrier); //$NON-NLS-1$ //$NON-NLS-2$

                return carrier;
            } catch (final Exception e) {
                Log.e("CarrierCondition", "Error", e); //$NON-NLS-1$ //$NON-NLS-2$
            }
        }

        return carrier;
    }
*/
}
 
Hmmmm.... sehr schräg: Jetzt gehts irgendwie... Also zumindest das Broadcasten.

Jetzt spinnt die Bedingung selbst wieder...

Bald ist es soweit: Ich hab zwar schon ein Einsteigerbuch zu Android gelesen und mich mit diversen Tutorials beschäftigt, aber jetzt gehe ich bald in die nächste Buchhandlung und kaufe mir ein richtig dickes Android-Buch...

Aber noch mal zurück zu meinem Problem:

Also ein über Java-Code registrierter Receiver lebt einen Aufruf lang und ein über XML deklarierter, lungert immer herum. Habe ich das richtig verstanden?

Chris
 
Ich glaub die über Java-Code registrierten leben solange bis der Service der das Ding registriert hat nicht mehr da ist. Kann also sein das man damit nie was empfängt, aber auch vielleicht für immer ;)

Die xml-Dinger sind meiner Meinung nach wenn möglich vorzuziehen.
Ich ärgere mich z.B. ohne Ende darüber das das für ACTION_HEADSET_PLUG nicht geht -.-
 
Darüber hab ich denke ich schon Mal was aus StackOverflow gelesen... denke ich.

Ich bin zZt. der Ansicht, dass die Requestverwaltung von Locale wahrscheinlich daran schuld ist, dass mein Broadcast nicht immer zu einer Überprüfung der Condition führt.

Es steht in deren API:
Locale API schrieb:
Locale makes no guarantees as to how often or if your plug-in will be queried. Typically, a plug-in will be queried once when Locale first starts up, and additional queries may happen somewhere on the order of every 10 minutes. If a situation in Locale contains multiple conditions, the order in which conditions are queried is unspecified. Locale may choose to stop evaluating conditions in a situation if one condition is not satisfied, at which point a plug-in may never be queried.

Wahrscheinlich ist es besser, das ganze selbst zu Implementieren und sich nicht auf das Framework von Locale zu verlassen...

Hat eigentlich schon jemand Erfahrung im Umgang mit Locale gemacht? Also aus Developersicht?

MfG, Chris
 
FelixL schrieb:
Ich glaub die über Java-Code registrierten leben solange bis der Service der das Ding registriert hat nicht mehr da ist. Kann also sein das man damit nie was empfängt, aber auch vielleicht für immer ;)

Die xml-Dinger sind meiner Meinung nach wenn möglich vorzuziehen.
Ich ärgere mich z.B. ohne Ende darüber das das für ACTION_HEADSET_PLUG nicht geht -.-

So steht es in meinem Buch.
 
  • Danke
Reaktionen: FelixL
Kranki schrieb:
So steht es in meinem Buch.

Welches hast du denn? Ich möchte nämlich nicht länger im Android-Nebel herumdümpeln, sondern mit fundiertem Hintergrundwissen an die Sache herangehen.

Chris
 

Ähnliche Themen

J
Antworten
2
Aufrufe
1.047
JonasSchmietzer
J
znieh99
Antworten
9
Aufrufe
1.146
znieh99
znieh99
N
Antworten
1
Aufrufe
1.309
Nonsens
N
Zurück
Oben Unten