Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BroadcastReceiver receives multiple identical messages for one event

I registered a receiver that listens to network events:

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

receiver is also very simple:

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

The problem is, when Wifi is connected I receive 3 identical messages in a row, like this:

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 

They are all "CONNECTED/CONNECTED" (Shouldn't they be something like CONNECTING/OBTAINING_IPADDR, etc.), so the problem is how do I tell when It's really connected? I have some routines that I want to make when wifi is actually connected, and I dont want them to be called three times in a row.

PS: 3G sends only one message, so no problem here.

Update:

Seems like it's device specific problem.

For test I took 2 Desire HD, and 4 random android phones(different Aquos models and some no-name chinese stuff). On both DHD and one random phone on wifi connect I got 3 messages, on remaining phones I got only one message. WTF.

like image 730
Sver Avatar asked Dec 07 '11 09:12

Sver


People also ask

What is the method name in BroadcastReceiver receive the message?

To receive SMS messages, use the onReceive() method of the BroadcastReceiver class. The Android framework sends out system broadcasts of events such as receiving an SMS message, containing intents that are meant to be received using a BroadcastReceiver.

What does a BroadcastReceiver do?

A broadcast receiver (receiver) is an Android component which allows you to register for system or application events. All registered receivers for an event are notified by the Android runtime once this event happens.

What is the life cycle of BroadcastReceiver?

1) I have an Activity. This Activity starts a service, which in turn creates and registers a BroadcastReceiver. 2) I have an Activity. This Activity creates and registers a BroadcastReceiver.

What is the limit of BroadcastReceiver in Android?

As a general rule, broadcast receivers are allowed to run for up to 10 seconds before they system will consider them non-responsive and ANR the app.


2 Answers

Receiving multiple broadcast is a device specific problem. Some phones just send one broadcast while other send 2 or 3. But there is a work around:

Assuming you get the disconnect message when the wifi is disconnected, I would guess the first one is the correct one and the other 2 are just echoes for some reason.

To know that the message has been called, you could have a static boolean that gets toggled between connect and disconnect and only call your sub-routines when you receive a connection and the boolean is true. Something like:

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;         }     } } 
like image 171
brianestey Avatar answered Sep 21 '22 20:09

brianestey


You can also cache in a static field the last handled connection type and check against the incomming broadcasts. This way you will only get one broadcast per connection type.

When connection type gets changed it will obviously work. When device gets out of connection activeNetworkInfo will be null and currentType will be NO_CONNECTION_TYPE as in default case.

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;         } } 
like image 44
Aleksandar Ilic Avatar answered Sep 20 '22 20:09

Aleksandar Ilic