wifi – Android WifiManager.addNetwork() returns -1-ThrowExceptions

Exception or error:

I am writing an android app which will connect to a specific WPA access point, when connected, it will issue a http call. It will not save the network config.
I have read almost every post on stack overflow on connecting to wifi network but can’t find the answer which works for me. Here is the code I am using to connect..

    WifiConfiguration wc = new WifiConfiguration();
    wc.allowedAuthAlgorithms.clear();
    wc.allowedGroupCiphers.clear();
    wc.allowedPairwiseCiphers.clear();
    wc.allowedProtocols.clear();
    wc.allowedKeyManagement.clear();
    wc.SSID = "\"".concat("<ssid>").concat("\"");
    wc.preSharedKey = "\"".concat("<password>").concat("\"");
    wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
    wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
    wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
    wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
    wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
    wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
    wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
    wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN); // For WPA2
    wc.allowedProtocols.set(WifiConfiguration.Protocol.WPA); // For WPA
    wc.priority = 0;
    //wc.hiddenSSID = true;
    wc.status = WifiConfiguration.Status.ENABLED;
    // connect to and enable the connection
    WifiManager wifiManager = (WifiManager) getSystemService(this.WIFI_SERVICE);
    int netId = wifiManager.addNetwork(wc);
    boolean wifiEnabled = wifiManager.enableNetwork(netId, true);
    wifiManager.setWifiEnabled(true);
    Log.d("opener", "addNetwork returned " + netId);
    if (netId > 0) {
        wifiId = netId;
    }

However netId is always -1. I have tried it on two different phones (ICS:HTC Rezound and GingerBread:Motorola DroidX). Both show exactly same results.
What am I doing wrong?

Edit: I tried same code with WPA2 access point and got very weird results. When this code was run, first time it would return -1, but if I call same method second time with a delay of 1 second, it would return valid netId. So the questions are

  1. why does above code not connect to wpa ?
  2. in wpa2, why do I need to call above method twice to get connected ? Edit: I observed that I had to connect multiple times to get connected. Sometimes it would take 3-4 times to connect. So for now I am looping until adding config returns >0 id.
How to solve:

Possibly a bit late but try this to connect to Open/WPA/WPA2/WEP secured networks

    WifiConfiguration wifiConfig = new WifiConfiguration();
    wifiConfig.SSID = selectedNetwork.SSID();
    wifiConfig.status = WifiConfiguration.Status.DISABLED;
    wifiConfig.priority = 40;

    // Dependent on the security type of the selected network
    // we set the security settings for the configuration
    if (/*Open network*/) {
        // No security
        wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
        wifiConfig.allowedAuthAlgorithms.clear();
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
    } else if (/*WPA*/ || /*WPA2*/) {
        //WPA/WPA2 Security
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
        wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
        wifiConfig.preSharedKey = "\"".concat(password).concat("\"");
    } else if (/*WEP*/) {
        // WEP Security
        wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
        wifiConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
        wifiConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);

        if (getHexKey(password)) wifiConfig.wepKeys[0] = password;
        else wifiConfig.wepKeys[0] = "\"".concat(password).concat("\"");
        wifiConfig.wepTxKeyIndex = 0;
    }

    // Finally we add the new configuration to the managed list of networks
    int networkID = wifiMan.addNetwork(wifiConfig);

Obviously set your own variables for the different security types as applicable. The key (pardon the pun) to connecting to a WEP secured network is the getHexKey method as below.

/**
 * WEP has two kinds of password, a hex value that specifies the key or
 * a character string used to generate the real hex. This checks what kind of
 * password has been supplied. The checks correspond to WEP40, WEP104 & WEP232
 * @param s
 * @return
 */
private static boolean getHexKey(String s) {
    if (s == null) {
        return false;
    }

    int len = s.length();
    if (len != 10 && len != 26 && len != 58) {
        return false;
    }

    for (int i = 0; i < len; ++i) {
        char c = s.charAt(i);
        if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
            continue;
        }
        return false;
    }
    return true;
}

###

I have found that if the shared key is less than 8 characters, it will return -1.

###

I had the same problem. I found out that your wifi must be on while you are calling addNetwork.

###

I just had this very same problem. Seemingly everything was okay, but then – it wasn’t.

What I found is this:

  • Android WifiStateMachine will not allow you to add or modify networks unless supplicant is running and connected-to. This affects services running on start-up and services running even if WIFI is off.

  • Android WifiConfigStore tracks owners of the wifi network by UID. It means that you may not be able to modify network created by another process.

The proper way to add a network is:

  1. Check if WIFI network is enabled. If not, call WifiManager.setWifiEnabled(true).
  2. Wait until WifiManager.pingSupplicant() returns true.
  3. Create and fill a new WifiConfiguration, then pass it to WifiManager.addNetwork(). Make sure the value returned is not (-1).
  4. (optional) use value returned by addNetwork() as an argument to WifiConfiguration.enableNetwork() call (unless it’s -1). Note, that the boolean parameter means disableOthers and should be false, unless you have right to modify all other networks: it may fail internally, if you set it to true.

This should allow you to add (and connect) programmatically to a new Wifi network.

###

The problem is that you’re trying to add the network configuration that already exists. When you call:

int netId = wifiManager.addNetwork(wc);

it will fail (return -1) if the network configuration with the same SSID already exists. So, what you need to do is to check if netId is -1 and if it is, traverse through the configured networks searching for the network with same SSID and once it’s found, return the networkId.

Kotlin:

var netId = wifiManager.addNetwork(conf)
if (netId == -1) netId = wifiManager.configuredNetworks?.let {
    it.firstOrNull { it.SSID.trim('"') == ssid.trim('"') }?.networkId ?: -1
}
wifiManager.enableNetwork(netId, true)

Leave a Reply

Your email address will not be published. Required fields are marked *