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.
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?
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
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
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.
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));
}
}
}
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.
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;
}
}
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;
}
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.
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
}
}
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
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;
}
}
}
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,
- z włączonymi danymi komórkowymi wysyłane są dwie transmisje: Broadcast #1 : MOBILE data disconnected, and Broadcast # 2: WIFI connected
- 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");
}
}
}
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!
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