CONNECTIVITY ACTION Intent odebrany dwukrotnie po podłączeniu Wifi

W mojej aplikacji mam BroadcastReceiver, który jest uruchamiany jako komponent przez znacznik <receiver>, filtrowanie intencji android.net.conn.CONNECTIVITY_CHANGE.

Moim celem jest po prostu wiedzieć, kiedy zostało ustanowione połączenie Wifi, więc to, co robię w onReceive() jest takie:

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

To działa dobrze, ale zawsze wydaje mi się, że dwie identyczne intencje w ciągu około jednej sekundy, gdy połączenie Wifi jest ustanowione. Próbowałem spojrzeć na wszelkie informacje, które mogłem uzyskać od intencji, ConnectivityManager i WifiManager, ale nie mogę znaleźć niczego, co odróżniałoby dwa zamiary.

Patrząc na log, jest co najmniej jeden inny BroadcastReceiver, który również otrzymuje dwie identyczne intencje.

[[8]}działa na HTC Desire Z Androidem 2.2

Jakiś pomysł, dlaczego wydaje mi się, że mam zamiar "zduplikowany", gdy łączy się Wifi lub jaka może być różnica między tymi dwoma?

Author: naXa, 2011-03-11

13 answers

Po wielu googling i debugowania, uważam, że jest to właściwy sposób, aby określić, czy Wifi jest podłączony lub odłączony.

Metoda onReceive() w 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));
    }
}
}

Wraz z następującym elementem odbiornika w 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>

Jakieś wyjaśnienie:

  • Gdy tylko rozważam ConnectivityManager.CONNECTIVITY_ACTION, zawsze dostaję dwa intenty zawierające identyczne instancje sieciowe (zarówno getType () = = TYPE_WIFI, jak i isConnected () = = true), Gdy Wifi łączy - problem opisany w tym pytaniu.

  • Gdy używasz tylko WifiManager.NETWORK_STATE_CHANGED_ACTION, nie ma intencji nadawanych po odłączeniu Wifi, ale dwie intencje zawierające różne instancje NetworkInfo, pozwalające określić jedno zdarzenie, gdy Wifi jest podłączone.

Uwaga: otrzymałem jeden raport o awarii (NPE), w którym intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO) zwróciło null. Tak więc, nawet jeśli wydaje się, że zdarza się to niezwykle rzadko, dobrym pomysłem może być dodanie sprawdzenia null.

Cheers, Torsten

 58
Author: Torsten Römer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-17 20:17:52

Jeśli słuchasz na WifiManager.NETWORK_STATE_CHANGED_ACTION otrzymasz to dwa razy, ponieważ są 2 metody w NetworkInfo

  • isConnectedOrConnecting()
  • isConnected()

Pierwszy raz isConnectedOrConnecting() zwraca true I isConnected() false
Second time isConnectedOrConnecting() and isConnected() return true

Cheers

 11
Author: Dominic Bartl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-28 07:33:42

Jeśli zarejestrowałeś aktywność jako intent listener, otrzymasz tę samą wiadomość dwa razy. W szczególności musisz wybrać, czy chcesz słuchać na poziomie pakietu (XML), czy na poziomie programowym.

Jeśli skonfigurujesz klasę dla odbiorcy transmisji i dołączysz do niej listen i dołączysz filtr intencyjny do aktywności, wiadomość zostanie powtórzona dwukrotnie.

Mam nadzieję, że to rozwiąże twój problem.

 3
Author: JoxTraex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-04 21:49:03

Zaktualizowano kod Torstena, tak że Gdy WIFI zostanie odłączone, działa tylko jedna odpowiednia transmisja.

Używane NetworkInfo.getDetailedState () = = DetailedState.Odłączony do sprawdzenia.

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));
        }
    }
}
 3
Author: Christopher Guray,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-13 18:59:18

Rozwiązałem dwukrotnie wywołanie używając SharedPref z czasem.

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");

    }
}

Ponieważ jest małe opóźnienie między 1.call i 2.zadzwoń (około 200 milisekund). Tak więc, jeśli z czasem drugie połączenie zostanie zatrzymane i tylko pierwsze będzie kontynuowane.

 2
Author: Lalson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-14 22:55:56

I solved if with w

onCreate()
       intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
       intentFilter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
       intentFilter.addAction("android.net.wifi.STATE_CHANGE");
       ctx.registerReceiver(outgoingReceiver, intentFilter);

W

BroadcastReceiver
 public void onReceive(Context context, Intent intent) {
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 connected
                    Log.d("Inetify", "Wifi is connected: " + String.valueOf(networkInfo));

                    Log.e("intent action", intent.getAction());
                    if (isNetworkConnected(context)){
                        Log.e("WiFi", "is Connected. Saving...");
                        try {
                            saveFilesToServer("/" + ctx.getString(R.string.app_name).replaceAll(" ", "_") + "/Temp.txt");
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }}


 boolean isNetworkConnected(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo ni = cm.getActiveNetworkInfo();
        if (ni != null) {
            Log.e("NetworkInfo", "!=null");

            try{
                //For 3G check
                boolean is3g = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE)
                        .isConnectedOrConnecting();
                //For WiFi Check
                boolean isWifi = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
                        .isConnected();

                Log.e("isWifi", "isWifi="+isWifi);
                Log.e("is3g", "is3g="+is3g);
                if (!isWifi)
                {

                    return false;
                }
                else
                {
                    return true;
                }

            }catch (Exception er){
                return false;
            }

        } else{
            Log.e("NetworkInfo", "==null");
            return false;
        }
    }
 2
Author: NickUnuchek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-26 21:16:15

Rozwiązałem ten problem używając intent extra dla NetworkInfo. W poniższym przykładzie Zdarzenie onReceive zostanie wywołane tylko raz, jeżeli wifi jest podłączone lub mobilne.

if (intent.getAction().equalsIgnoreCase(ConnectivityManager.CONNECTIVITY_ACTION)) {

        NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);

        boolean screenIsOn = false;
        // Prüfen ob Screen on ist
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            screenIsOn = pm.isInteractive();
        } else {
            screenIsOn = pm.isScreenOn();
        }

        if (Helper.isNetworkConnected(context)) {
            if (networkInfo.isConnected() && networkInfo.isAvailable()) {
                Log.v(logTAG + "onReceive", "connected");

                if (networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
                    Log.v(logTAG + "onReceive", "mobile connected");

                } else if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                    Log.v(logTAG + "onReceive", "wifi connected");
                }
            }
        }

I mój Pomocnik:

    public static boolean isNetworkConnected(Context ctx) {
    ConnectivityManager cm = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo ni = cm.getActiveNetworkInfo();

    return ni != null;
}
 1
Author: Scrounger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-11 14:00:56

Sposób, w jaki sobie z tym poradziłem, polegał na zapisaniu stanu sieci, a następnie porównaniu go, aby sprawdzić, czy nastąpiła zmiana.

public class ConnectivityChangedReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        boolean previouslyConnected = MyApp.getInstance().isNetworkPreviouslyConnected();
        boolean currentlyConnected = MyApp.getInstance().isNetworkConnected();

        if (previouslyConnected != currentlyConnected) {
            // do something and reset
            MyApp.getInstance().resetNetworkPreviouslyConnected();
        }
    }

}

Jeśli jest to podejście, które stosujesz, ważne jest, aby zresetować je w onResume swojego fragmentu lub aktywności, tak aby utrzymywały bieżącą wartość:

@Override
public void onResume() {
    super.onResume();
    MyApp.getInstance().resetNetworkPreviouslyConnected();
}

Zrobiłem to w moim BaseFragment, rodzicu wszystkich fragmentów w mojej aplikacji.

 0
Author: Oleksiy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-23 18:57:12

Sprawdź networkType od intent i porównaj activeNetworkInfo.getType ()

                 Bundle bundle = intent.getExtras();
                 ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
                 NetworkInfo ni = manager.getActiveNetworkInfo();

                 if(ni != null && ni.getState() == NetworkInfo.State.CONNECTED) {
                     if(bundle.getInt("networkType") == ni.getType()) {
                         // active network intent
                     }
                 }
 0
Author: Wooyeol Jung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-29 01:09:55

Znaleziono specjalny przypadek połączenia sieciowego, mówiący, że nie ma internetu, ale w rzeczywistości jest. Okazuje się, że getActiveNetworkInfo zawsze zwróci odłączony / zablokowany w konkretnym przypadku, gdy sieć zostanie zmieniona, gdy poziom baterii jest niski, a aplikacja została właśnie przełączona

Zobacz Ten post

 0
Author: Phil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-21 07:48:16

Jeśli Chcesz otrzymać go tylko raz, możesz po prostu kontrolować go za pomocą zmiennych.

 if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
                NetworkInfo activeNetwork = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
                if (activeNetwork != null) { // connected to the internet
                    if (activeNetwork.isConnected() && !isUpdated) {
                        if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
                            // connected to wifi
                        } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
                            // connected to the mobile provider's data plan
                        }

                        isUpdated = true;
                    } else {
                        isUpdated = false;
                    }
                }
            }
 0
Author: zhengcheng wang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-28 06:28:38

Podczas włączania WIFI,

  1. z włączonymi danymi komórkowymi wysyłane są dwie transmisje: Broadcast #1 : MOBILE data disconnected, and Broadcast # 2: WIFI connected
  2. przy wyłączeniu danych mobilnych wysyłana jest tylko jedna transmisja: Broadcast # 1: WIFI connected

Podobne zachowanie można zaobserwować podczas wyłączania WIFI w powyższych dwóch warunkach.

Aby odróżnić te dwa, proszę postępować zgodnie z #2 i #3 poniżej:

        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "*** Action: " + intent.getParcelableExtra("networkInfo"));

            NetworkInfo netInfo = intent.getParcelableExtra("networkInfo");

            if(intent.getAction().equalsIgnoreCase("android.net.conn.CONNECTIVITY_CHANGE")) {
                ConnectivityManager connectivityManager
                        = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
                if (activeNetInfo != null) {
                    if (netInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                        if (netInfo.getState().name().contains("DISCONNECTED")
                                && activeNetInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
                            Log.d(TAG, "WIFI disconnect created this broadcast. MOBILE data ON."); // #1
                        } else if (netInfo.getState().name().contains("CONNECTED")
                                && activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                            Log.d(TAG, "WIFI connect created this broadcast."); // #2
                        }
                    } else if (netInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
                        if (netInfo.getState().name().contains("DISCONNECTED")
                                && activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                            Log.d(TAG, "MOBILE data disconnect created this broadcast. WIFI ON."); // #3
                        } else if (netInfo.getState().name().contains("CONNECTED")
                                && activeNetInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
                            Log.d(TAG, "MOBILE data connect created this broadcast."); // #4
                        }
                    }
                } else {
                    Log.d(TAG, "No network available");
                }
            }
        }
 0
Author: FNordy Tuba68,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-14 16:29:58

Słuchaj tylko akcji "android. net. conn. CONNECTIFITY_CHANGE". jest ona nadawana zawsze, gdy połączenie zostanie nawiązane lub zniszczone.

"android.net. wifi. STATE_CHANGE" zostanie wyemitowany po nawiązaniu połączenia. Więc dostajesz dwa wyzwalacze.

Enjoy!

 -2
Author: Henry Sou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-19 02:33:57