BroadcastReceiver odbiera wiele identycznych wiadomości dla jednego zdarzenia
Zarejestrowałem odbiornik, który nasłuchuje zdarzeń sieciowych:
<receiver
android:label="NetworkConnection"
android:name=".ConnectionChangeReceiver" >
<intent-filter >
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
Odbiornik jest również bardzo prosty:
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");
}
}
}
Problem polega na tym, że po podłączeniu Wifi otrzymuję 3 identyczne wiadomości pod rząd, jak to:
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
Wszystkie są "CONNECTED/CONNECTED" (nie powinny być czymś w rodzaju CONNECTING/OBTAINING_IPADDR, itp.), więc problem polega na tym, jak rozpoznać, że jest naprawdę podłączony? Mam kilka procedur, które chcę zrobić, gdy wifi jest rzeczywiście podłączony, i nie chcę będą wywoływane trzy razy z rzędu.
PS: 3G wysyła tylko jedną wiadomość, więc nie ma problemu.
Aktualizacja:
Wygląda na to, że to problem specyficzny dla urządzenia.Do testu wziąłem 2 Desire HD i 4 losowe telefony z Androidem(różne modele Aquos i trochę chińskich rzeczy bez nazwy). Na obu DHD i jeden losowy telefon na wifi connect dostałem 3 wiadomości, na pozostałych telefonach dostałem tylko jedną wiadomość. WTF.
6 answers
Odbieranie wielu transmisji jest problemem specyficznym dla urządzenia. Niektóre telefony wysyłają tylko jedną transmisję, podczas gdy inne wysyłają 2 lub 3. Ale jest praca wokół:
Zakładając, że otrzymasz komunikat o odłączeniu, Gdy wifi jest odłączony, domyślam się, że pierwszy jest prawidłowy, a pozostałe 2 są tylko echem z jakiegoś powodu.
Aby wiedzieć, że wiadomość została wywołana, możesz mieć statyczny boolean, który zostanie przełączony między connect i disconnect i tylko wywoła Twój podprogramy, gdy otrzymasz połączenie i wartość logiczna jest true. Coś w stylu:
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;
}
}
}
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-05-13 10:03:37
Możesz również buforować w polu statycznym ostatni Obsługiwany typ połączenia i sprawdzić przed nadchodzącymi transmisjami. W ten sposób otrzymasz tylko jedną transmisję na każdy typ połączenia.
Gdy typ połączenia zostanie zmieniony, będzie to oczywiście działać. Gdy urządzenie zostanie wyłączone z połączenia, activeNetworkInfo
będzie równe null, a currentType
będzie równe NO_CONNECTION_TYPE
jak w przypadku domyślnym.
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;
}
}
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-06-16 15:32:06
W moim przypadku rejestrowałem swoje Broadcastreceivery w onResume
i tylko je wyrejestrowywałem w onDestroy.
To spowodowało, że każdy broadcastreceiver został zarejestrowany 3 lub 4 razy, w zależności od tego, ile razy aktywność zostanie wznowiona.
Ustawienie broadcastreceiver we właściwym miejscu pod względem cyklu życia aktywności pozwoli Ci przestać uzyskiwać wiele mylących połączeń.
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-03-19 10:16:42
Zarejestruj swój LocalBroadcastreceiver w oncreate()
nie w onResume()
. Niezarejestrowana Strona onDestroy
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-12-22 14:11:30
Mam aplikację, która przesyła dane, gdy użytkownik wróci online. Ponieważ mój odbiornik może odbierać intencję wiele razy, może to prowadzić do przesłania danych więcej niż raz. Aby sobie z tym poradzić, korzystam z usługi, która nic nie zrobi, jeśli jest już uruchomiona.
Odbiornik Transmisji:
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();
}
}
}
Usługa:
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);
}
}
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-06 18:54:21
Moje zaniepokojenie podejściem zaproponowanym przez Aleksandra polega na tym, że nie uwzględnia on zmian sieci tego samego typu, np. z jednej sieci WiFi na drugą.
Proponuję porównać extraInfo aktywnej sieci, która zawiera nazwę sieci, np. WiFi SSID lub nazwę sieci komórkowej jak 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 = "";
}
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-08-07 14:18:23