52 votes

CONNECTIVITY_ACTION intention reçue deux fois lorsque le Wifi est connecté

Dans mon application j'ai un BroadcastReceiver qui est lancé comme un composant par l'intermédiaire d'une balise, le filtrage android.net.conn.CONNECTIVITY_CHANGE intentions.

Mon but est simplement de savoir quand une connexion Wifi a été créé, donc ce que je fais dans onReceive() est la suivante:

NetworkInfo networkInfo = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
if(networkInfo.getType() == ConnectivityManager.TYPE_WIFI && networkInfo.isConnected()) {
    // Wifi is connected
}

Il fonctionne très bien, mais j'ai toujours l'impression d'avoir deux identiques intentions dans l'espace d'une seconde lorsque la connexion Wifi est établie. J'ai essayé de regarder les infos que j'ai pu obtenir à partir de l'intention, la ConnectivityManager et WifiManager, mais je ne peux pas trouver quelque chose qui distingue les deux modes.

En regardant le journal, il y a au moins un autre BroadcastReceiver qui reçoit également les deux identiques intentions.

Il est en cours d'exécution sur un HTC Desire avec Android 2.2

Aucune idée de pourquoi je semble pour obtenir un "doublé" intention lorsque le Wifi se connecte ou que la différence entre les deux peut être?

63voto

Torsten Römer Points 982

Après beaucoup de recherches sur google et le débogage, je crois que c'est la bonne façon de déterminer si le Wifi est connecté ou déconnecté.

L' onReceive() méthode dans le BroadcastReceiver:

public void onReceive(final Context context, final Intent intent) {

if(intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
    NetworkInfo networkInfo =
        intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
    if(networkInfo.isConnected()) {
        // Wifi is connected
        Log.d("Inetify", "Wifi is connected: " + String.valueOf(networkInfo));
    }
} else if(intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
    NetworkInfo networkInfo =
        intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
    if(networkInfo.getType() == ConnectivityManager.TYPE_WIFI &&
        ! networkInfo.isConnected()) {
        // Wifi is disconnected
        Log.d("Inetify", "Wifi is disconnected: " + String.valueOf(networkInfo));
    }
}
}

Avec les documents suivants, un élément récepteur dans AndroidManifest.xml

<receiver android:name="ConnectivityActionReceiver"
    android:enabled="true" android:label="ConnectivityActionReceiver">
    <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
        <action android:name="android.net.wifi.STATE_CHANGE"/>
    </intent-filter>
</receiver>

Quelques explications:

  • Si l'on ne regarde ConnectivityManager.CONNECTIVITY_ACTION, j'ai toujours deux intentions contenant les mêmes NetworkInfo instances (les deux getType() == TYPE_WIFI et isConnected() == true) lorsque le Wifi se connecte - le problème décrit dans cette question.

  • Vous n'utilisez WifiManager.NETWORK_STATE_CHANGED_ACTION, il n'y a pas d'intention diffusé lorsque le Wifi se déconnecte, mais deux intentions contenant différents NetworkInfo cas, ce qui permet de déterminer un événement lorsque le Wifi est connecté.

NOTE: j'ai reçu un seul rapport de crash (NPE) où l' intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO) retourné null. Donc, même si il semble être extrêmement rare de se produire, il pourrait être une bonne idée d'ajouter une valeur null vérifier.

Cheers, Torsten

12voto

Dominic Bartl Points 1934

Si vous écoutez sur WifiManager.NETWORK_STATE_CHANGED_ACTION, vous le recevrez deux fois, car il existe deux méthodes dans NetworkInfo.

  • isConnectedOrConnecting ()
  • est connecté()

IsConnectedOrConnecting () renvoie la première fois et isConnected false Deuxième fois isConnectedOrConnecting () et isConnected renvoie true

À votre santé

4voto

Mise à jour du code de Torsten, de telle sorte que lorsque WIFI est déconnecté, seule la diffusion appropriée soit activée.

Utilisé NetworkInfo.getDetailedState () == DetailedState.DISCONNECTED pour la vérification.

 public void onReceive(final Context context, final Intent intent) {
    if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
        NetworkInfo networkInfo = intent
            .getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
        if (networkInfo.isConnected()) {
            // Wifi is connected
            Log.d("Inetify","Wifi is connected: " + String.valueOf(networkInfo));
        }
    } else if (intent.getAction().equals(
        ConnectivityManager.CONNECTIVITY_ACTION)) {
        NetworkInfo networkInfo = intent
            .getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
        if (networkInfo.getDetailedState() == DetailedState.DISCONNECTED) {
            // Wifi is disconnected
            Log.d("Inetify","Wifi is disconnected: "+String.valueOf(networkInfo));
        }
    }
}
 

3voto

JoxTraex Points 7068

Si vous avez enregistré l'activité en tant qu'écouteur d'intention, vous recevrez le même message deux fois. Plus précisément, vous devez choisir d’écouter au niveau du paquet (XML) ou du niveau de la programmation.

Si vous configurez une classe pour un récepteur de diffusion et que vous associez son écoute ET que vous associez un filtre d'intention à l'activité, le message sera répliqué deux fois.

J'espère que cela résout votre problème.

2voto

Lalson Points 18

J'ai résolu deux appels en utilisant SharedPref avec Time.

 private static final Long SYNCTIME = 800L;
private static final String LASTTIMESYNC = "DATE";
SharedPreferences sharedPreferences;
private static final String TAG = "Connection";

@Override
public void onReceive(Context context, Intent intent) {
     Log.d(TAG, "Network connectivity change");
     sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);

     final ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
     final NetworkInfo ni = connectivityManager.getActiveNetworkInfo();

        if (ni != null && ni.isConnected()) {   

            if(System.currentTimeMillis()-sharedPreferences.getLong(LASTTIMESYNC, 0)>=SYNCTIME)
            {
                sharedPreferences.edit().putLong(LASTTIMESYNC, System.currentTimeMillis()).commit();
                // Your code Here.
            }
     }
     else if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, Boolean.FALSE)) {
            Log.d(TAG, "There's no network connectivity");

    }
}
 

Parce qu'il y a un petit délai entre 1.call et 2.call (environ 200 millisecondes). Donc, si avec le temps, le deuxième appel s'arrête et le premier seulement continue.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X