wake-up-neo.net

BroadcastReceiver empfängt mehrere identische Nachrichten für ein Ereignis

Ich habe einen Empfänger registriert, der Netzwerkereignisse abhört:

<receiver 
    Android:label="NetworkConnection"
    Android:name=".ConnectionChangeReceiver" >
    <intent-filter >
        <action Android:name="Android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
</receiver>

empfänger ist auch sehr einfach:

public class ConnectionChangeReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
        if (activeNetInfo != null) {
                Log.v("@@@","Receiver : " + activeNetInfo);
        } else {
            Log.v("@@@","Receiver : " + "No network");
        }
    }
}

Das Problem ist, wenn Wifi verbunden ist, erhalte ich 3 identische Nachrichten in einer Reihe, wie folgt:

Receiver : NetworkInfo: type: WIFI[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: (none), roaming: false, failover: false, isAvailable: true
Receiver : NetworkInfo: type: WIFI[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: (none), roaming: false, failover: false, isAvailable: true
Receiver : NetworkInfo: type: WIFI[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: (none), roaming: false, failover: false, isAvailable: true

Sie sind alle "CONNECTED/CONNECTED" (sollten nicht etwa CONNECTING/OBTAINING_IPADDR usw. sein). Das Problem ist, wie kann ich feststellen, wann es wirklich verbunden ist? Ich habe einige Routinen, die ich machen möchte, wenn WLAN tatsächlich verbunden ist, und ich möchte nicht, dass sie dreimal hintereinander angerufen werden. 

PS: 3G sendet nur eine Nachricht, also kein Problem.

Aktualisieren: 

Scheint, es ist ein gerätespezifisches Problem.

Zum Test nahm ich 2 Desire HD und 4 zufällige Android-Handys (verschiedene Aquos-Modelle und einige No-Name-Chinesen). Sowohl beim DHD als auch bei einem beliebigen Telefon mit WLAN-Verbindung habe ich 3 Nachrichten erhalten, bei den restlichen Telefonen nur eine Nachricht. WTF.

32
Sver

Der Empfang mehrerer Broadcasts ist ein gerätespezifisches Problem. Einige Telefone senden nur eine Sendung, während andere 2 oder 3 senden. Es gibt jedoch eine Problemlösung:

Angenommen, Sie erhalten die Trennungsnachricht, wenn das WLAN getrennt ist, würde ich vermuten, dass der erste der richtige ist und die anderen 2 nur Echos aus irgendeinem Grund sind.

Um zu wissen, dass die Nachricht aufgerufen wurde, kann ein statischer Boolean verwendet werden, der zwischen Verbinden und Trennen wechselt und Ihre Unterprogramme nur dann anruft, wenn Sie eine Verbindung erhalten und der Boolean-Wert true ist. So etwas wie:

public class ConnectionChangeReceiver extends BroadcastReceiver {
    private static boolean firstConnect = true;

    @Override
    public void onReceive(Context context, Intent intent) {
        final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        final NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
        if (activeNetInfo != null) {
            if(firstConnect) { 
                // do subroutines here
                firstConnect = false;
            }
        }
        else {
            firstConnect= true;
        }
    }
}
54
brianestey

Sie können auch den zuletzt behandelten Verbindungstyp in einem statischen Feld zwischenspeichern und mit den eingehenden Broadcasts vergleichen. Auf diese Weise erhalten Sie nur eine Übertragung pro Verbindungstyp.

Wenn der Verbindungstyp geändert wird, funktioniert das natürlich. Wenn das Gerät die Verbindung verlässt, ist activeNetworkInfo null und currentType wie im Standardfall NO_CONNECTION_TYPE.

public class ConnectivityReceiver extends BroadcastReceiver {

    /** The absence of a connection type. */
    private static final int NO_CONNECTION_TYPE = -1;

    /** The last processed network type. */
    private static int sLastType = NO_CONNECTION_TYPE;

    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager connectivityManager = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        final int currentType = activeNetworkInfo != null
                ? activeNetworkInfo.getType() : NO_CONNECTION_TYPE;

        // Avoid handling multiple broadcasts for the same connection type
        if (sLastType != currentType) {
            if (activeNetworkInfo != null) {
                boolean isConnectedOrConnecting = activeNetworkInfo.isConnectedOrConnecting();
                boolean isWiFi = ConnectivityManager.TYPE_WIFI == currentType;
                boolean isMobile = ConnectivityManager.TYPE_MOBILE == currentType;

                // TODO Connected. Do your stuff!
            } else {
                // TODO Disconnected. Do your stuff!
            }

            sLastType = currentType;
        }
}
8
Aleksandar Ilic

In meinem Fall habe ich meine BroadcastReceiver in onResume registriert und die Registrierung nur in onDestroy. aufgehoben.

Dies hat dazu geführt, dass jeder Rundfunkempfänger drei oder vier Mal registriert wurde, je nachdem, wie oft die Aktivität wieder aufgenommen wird.

Wenn Sie Ihren Rundfunkempfänger in Bezug auf den Aktivitätslebenszyklus an der richtigen Stelle einstellen, können Sie keine verwirrenden Anrufe mehr erhalten.

3
Simon

Registrieren Sie Ihren LocalBroadcastreceiver in oncreate() selbst und nicht in onResume(). nicht in onDestroy registriert

1
Sreenivasulu Y

Meine Sorge mit dem von Aleksander vorgeschlagenen Ansatz ist, dass Netzwerkänderungen des gleichen Typs nicht berücksichtigt werden, z. von einem WiFi-Netzwerk zu einem anderen.

Ich schlage vor, die extraInfo des aktiven Netzwerks zu vergleichen, das den Netzwerknamen enthält, z. WLAN-SSID oder Name des Mobilfunknetzes wie VZW

 String currentNetworkName = "";

 ConnectivityManager connectivityManager =
            ((ConnectivityManager) context.getSystemService(
                    Context.CONNECTIVITY_SERVICE));

    NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
    boolean connected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
    if (connected) {
        // prevent duplicate connect broadcasts
        String extraInfo = activeNetwork.getExtraInfo();
        if(! currentNetworkName.equals(extraInfo)) {
            // to do: handle network changes
            currentNetworkName = extraInfo;
        }
    } else {
        Log.d(TAG, "is not connected");
        isConnected = false;
        currentNetworkName = "";
    }
0
dutchman711

Ich habe eine Anwendung, die Daten hochlädt, wenn der Benutzer wieder online ist. Da mein Rundfunkempfänger die Absicht mehrmals empfangen kann, kann dies dazu führen, dass die Daten mehrmals hochgeladen werden. Um dies zu erreichen, verwende ich einen Dienst, der nichts tut, wenn er bereits läuft.

Rundfunkempfänger:

public class ConnectionChangeReceiver extends BroadcastReceiver {
    private static boolean firstConnect = true;

    @Override
    public void onReceive(Context context, Intent intent) {
        final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        final NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
        if (activeNetInfo != null) {
            startService();
        }   
    }
}

Bedienung:

public class MyService extends Service {
    private boolean mRunning;

    @Override
    public void onCreate() {
        super.onCreate();
        mRunning = false;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (!mRunning) {
            mRunning = true;
            uploadTheData();
        }
        return super.onStartCommand(intent, flags, startId);
    }
}
0
John