detecting disconnection from a WiFi access point

eshayne picture eshayne · Feb 18, 2011 · Viewed 9.5k times · Source

I am trying to use a BroadcastReceiver to detect when the phone has disconnected from a WiFi access point. To do this, I registered my BroadcastReceiver in the manifest:

<receiver android:name="com.eshayne.android.WiFiBroadcastReceiver">
    <intent-filter>
        <action android:name="android.net.wifi.STATE_CHANGE" />
    </intent-filter>
</receiver>

In my WiFiBroadcastReceiver class, I am checking for a NETWORK_STATE_CHANGED_ACTION action and looking at the NetworkInfo's detailed state:

if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
    NetworkInfo info = (NetworkInfo)intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
    android.util.Log.d("com.eshayne.android.WiFiBroadcastReceiver", "network state change - detailedState=" + info.getDetailedState() + ": " + info.toString());
    if (info.getDetailedState() == DetailedState.DISCONNECTED) {
        ...
    }
    else if (info.getDetailedState() == DetailedState.CONNECTED) {
        ...
    }

The problem I'm seeing is that when the phone leaves the WiFi access point's range, my "disconnected" callback gets called 6 times - pretty regularly at about once every 15 seconds - before it stops. So far I haven't been able to find any distinguishing characteristics between each callback's NetworkInfo. Each NetworkInfo object being written to the log looks like this:

02-18 10:16:51.918 D/com.eshayne.android.WiFiBroadcastReceiver( 1511): network state change - detailedState=DISCONNECTED: NetworkInfo: type: WIFI[], state: DISCONNECTED/DISCONNECTED, reason: (unspecified), extra: (none), roaming: false, failover: false, isAvailable: true

It's also not an issue of the phone wandering in and out of WiFi range, as my "connected" callback is not called in between "disconnected" callbacks. Nor are any other states being triggered in between. Just a rapid series of 6 callbacks each with a detailedState of DISCONNECTED.

Is there a better way for me to detect when the phone has lost its WiFi connection, so that my callback only gets called once per disconnect? Or any way to detect which of the 6 callbacks I'm seeing is the "final" one?

Answer

Alexander Lucas picture Alexander Lucas · Feb 18, 2011

You say it's a "rapid series of 6 disconnected callbacks", but your if/else-if only checks for DISCONNECTED and CONNECTED, with what looks like no default block to handle all other cases. From the NetworkInfo.DetailedState api page, there's 10 possible states that could be returned by NetworkInfo.getDetailedState(), including "connecting", "scanning", "disconnecting", all of which would be plausible behavior for a phone that just got disconnected from a network.

Throw down a default case that alerts you to any change in wifi state, not just "CONNECTED" and "DISCONNECTED". You might find that the phone is rotating between several different states, and not just shotgunning the same one at you six times. Hopefully from there, how to proceed in your code will be a little clearer.