Silex Silex - 6 months ago 31
Android Question

Connecting to specific wifi sometimes fails in android

I am creating an app, which can list out all the available wifi's in a ListView. If I select one of the wifi's in the list, which was cached before in

List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
then it should connect to it. If the
WifiConfiguration
list doesn't contain the selected wifi, then nothing happens. My problem is, that sometimes I select a wifi from the list (which I know for sure is in the
WifiConfiguration
list), but it doesn't connects to it. Instead it connects back to the previously connected wifi. After some attempts (selecting again and again the same wifi) it connects to it finally. This doesn't happen always, just sometimes. What can be the problem? Here is my code snippet:

// Go through all the cached wifis and check if the selected GoPro was cached before
for (WifiConfiguration config : configurations) {
// If it was cached connect to it and that's all
if (config.SSID != null && config.SSID.equals("\"" + mDrawerListView.getAdapter().getItem(position) + "\"")) {
// Log
Log.i("onReceive", "Connecting to: " + config.SSID);
mWifiManager.disconnect();
mWifiManager.enableNetwork(config.networkId, true);
mWifiManager.reconnect();
break;
}
}

Answer

This is what's going on. Basically, you can tell the OS to disable a network, and you can tell the OS to enable a network, but it's not possible to tell the OS what network to connect to.

If there are multiple WiFi access points in range that are both configured on the device (and both are in the enabled state), the OS will decide which one to connect to.

The only way to force the OS to connect to one of the networks in range instead of the other one is to call disableNetwork() on the network that is in range that you don't want to connect to.

Let's go through your code line by line:

mWifiManager.disconnect();

The line above tells the OS to disconnect from the currently connected WiFi access point.

mWifiManager.enableNetwork(config.networkId, true);

The line above tells the device to set the network to the enabled state if it was previously in the disabled state.

mWifiManager.reconnect(); 

From the documentation:

Reconnect to the currently active access point, if we are currently disconnected. This may result in the asynchronous delivery of state change events.

So, when you say Instead it connects back to the previously connected wifi., it's working exactly as expected, as the OS is re-connecting to what it considers the currently active access point.

If you really want to disable the other network so that the OS will connect to the one you just clicked on, you could do something like this:

// Go through all the cached wifis and check if the selected GoPro was cached before

WifiInfo info = mWifiManager.getConnectionInfo(); //get WifiInfo
int id = info.getNetworkId(); //get id of currently connected network

for (WifiConfiguration config : configurations) {
    // If it was cached connect to it and that's all
    if (config.SSID != null && config.SSID.equals("\"" + mDrawerListView.getAdapter().getItem(position) + "\"")) {
        // Log
        Log.i("onReceive", "Connecting to: " + config.SSID);

        mWifiManager.disconnect();

        mWifiManager.disableNetwork(id); //disable current network

        mWifiManager.enableNetwork(config.networkId, true);
        mWifiManager.reconnect();
        break;
     }
}