BroadcastReceiver получает несколько идентичных сообщений для одного события

Я зарегистрировал приемник, который прослушивает сетевые события:

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

Приемник также очень прост:

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

Проблема в том, что когда Wifi подключен, я получаю 3 одинаковых сообщения подряд, например:

 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 

Все они «ПОДКЛЮЧЕНЫ / ПОДКЛЮЧЕНЫ» (не должны ли они быть чем-то вроде CONNECTING / OBTAINING_IPADDR и т. Д.), Поэтому проблема в том, как я могу сказать, когда это действительно связано? У меня есть некоторые подпрограммы, которые я хочу сделать, когда wifi действительно подключен, и я не хочу, чтобы их вызывали три раза подряд.

PS: 3G отправляет только одно сообщение, поэтому здесь нет проблем.

Обновить:

Похоже, это проблема устройства.

Для теста я взял 2 Desire HD и 4 случайных телефона Android (разные модели Aquos и некоторые китайские вещи без названия). Как на DHD, так и на одном случайном телефоне на wifi connect я получил 3 сообщения, на оставшихся телефонах я получил только одно сообщение. WTF.

Solutions Collecting From Web of "BroadcastReceiver получает несколько идентичных сообщений для одного события"

Получение нескольких широковещательных сообщений является проблемой, специфичной для устройства. Некоторые телефоны просто отправляют одну трансляцию, а другие отправляют 2 или 3. Но есть работа вокруг:

Предполагая, что вы получите сообщение об отключении, когда Wi-Fi отключен, я бы предположил, что первый из них правильный, а другой 2 – просто эхо по какой-то причине.

Чтобы знать, что сообщение было вызвано, вы можете иметь статическое логическое значение, которое переключается между подключением и отключением и вызывает вызовы подпрограмм при получении соединения, а логическое значение – true. Что-то вроде:

 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; } } } 

Вы также можете кэшировать в статическом поле последний обработанный тип подключения и проверять наличие встроенных трансляций. Таким образом, вы получите только один канал для каждого типа подключения.

Когда тип подключения будет изменен, он, очевидно, будет работать. Когда устройство выходит из соединения activeNetworkInfo будет null и currentType будет 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; } } 

В моем случае я регистрировал свои BroadcastReceivers в onResume и только незарегистрировал их в onDestroy.

Это заставило каждого трансляционного вещателя регистрироваться 3 или 4 раза в зависимости от того, сколько раз активность возобновляется.

Настройка вашего трансляционного транслятора в нужном месте с точки зрения жизненного цикла активности позволит вам перестать получать несколько запутывающих вызовов.

Зарегистрируйте свой LocalBroadcastreceiver в oncreate() сам не в onResume() . Незарегистрированный в onDestroy

У меня есть приложение, которое загружает данные, когда пользователь возвращается в Интернет. Поскольку мой широковещательный приемник может получать намерение несколько раз, это может привести к загрузке данных более одного раза. Чтобы справиться с этим, я использую службу, которая ничего не сделает, если она уже запущена.

Широковещательный приемник:

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

Обслуживание:

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