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

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

     

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

 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.

Получение нескольких широковещательных сообщений является проблемой, специфичной для устройства. Некоторые телефоны просто отправляют одну трансляцию, а другие отправляют 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 и только 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); } } 

Моя озабоченность по поводу предложенного Александром подхода заключается в том, что он не учитывает сетевые изменения одного и того же типа, например, из одной сети WiFi в другую.

Я предлагаю сравнить дополнительную информацию о активной сети, которая содержит имя сети, например WiFi SSID или имя мобильной сети, такое как 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 = ""; } 
Interesting Posts
Давайте будем гением компьютера.