Okay I seem to have fixed it now.
Here is my revised associate logic - I have actually split this out into separate methods but for ease of reading here I will post it all in one method.
Simply put I find all the hidden networks that are visible before I perform the association, keen reference to these, then associate to the network the user has selected, then re-enable the hidden SSID configurations without disabling any others.
public boolean associate(ScanResultWrapper scanResult){
WifiConfiguration wc = getWifiConfiguration(scanResult._scanResult);
int id = -1;
if (wc == null ) {
wc = new WifiConfiguration();
wc.SSID = "\"" + scanResult._Ssid + "\"";
wc.BSSID = scanResult._scanResult.BSSID;
wc.status = WifiConfiguration.Status.ENABLED;
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
id = mWifiManager.addNetwork(wc);
if (!mWifiManager.saveConfiguration()){
return false;
}
} else{
id = wc.networkId;
}
boolean result;
//Get reference to all hidden visible networks
ArrayList<ScanResultWrapper> hiddenScanResults = new ArrayList<ScanResultWrapper>();
for (ScanResultWrapper wrapper : mScanResults){
if (wrapper._isHidden){
hiddenScanResults.add(wrapper);
}
}
try {
//Enable the user network - disabling all others
result = mWifiManager.enableNetwork(id, true);
//re-enable all hidden networks, leaving all other networks enabled
for (ScanResultWrapper wrapper : hiddenScanResults){
WifiConfiguration wcHidden = getWifiConfiguration(wrapper._scanResult);
//the false is the important part here
mWifiManager.enableNetwork(wcHidden.networkId, false);
}
return result;
} catch (Throwable t) {
t.printStackTrace();
return false;
}
}
The class ScanResultsWrapper is a simple class that allows me to keep some extra information around and accessable easily. Here is the constructor which explains what the _isHidden variable is set by.
public ScanResultWrapper(ScanResult scanResult, Context c) {
this._Ssid = scanResult.SSID;
this._scanResult = scanResult;
this.context = c;
WifiManager mWifiManager = (WifiManager) c.getSystemService(Context.WIFI_SERVICE);
List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
WifiConfiguration config = getWifiConfiguration(scanResult, configs) ;
this._isKnown = config != null;
if (config!=null){
_isHidden = config.hiddenSSID;
}else{
_isHidden = false;
}
this._isAssociated = _Ssid.equals(SSIDUtils.checkSSIDForEnclosingQuotes(mWifiManager.getConnectionInfo().getSSID()));
if (_isAssociated){
this._isAssociated = mWifiManager.getConnectionInfo().getNetworkId()!= -1 ? true : false;
}
this._isSecure = scanResult.capabilities.contains("WEP") || scanResult.capabilities.contains("PSK") || scanResult.capabilities.contains("EAP");
}
/**
* returns the wifi configuration for a given ScanResult. It compares the ssid AND the bssid
* @param ssid
* @param configs
* @return
*/
public WifiConfiguration getWifiConfiguration(ScanResult scanResult, List<WifiConfiguration> configs) { // ScanResult result) {
try {
String ssid = scanResult.SSID;
ssid = ssid.replaceAll("\"", "");
ssid = ssid.trim();
String bssid = scanResult.BSSID;
if ( bssid != null ) {
bssid = bssid.replaceAll("\"", "");
bssid = bssid.trim();
}
if (configs== null){
return null;
}
for ( WifiConfiguration config : configs ) {
String candidate = config.SSID;
if ( BSGStringUtils.isNullOrEmpty(candidate) ) {
continue;
}
candidate = candidate.replaceAll("\"", "");
candidate = candidate.trim();
if ( candidate.equals(ssid) ) {
String candidateBSSID = config.BSSID;
if ( candidateBSSID == null && bssid == null ) {
return config;
}else if (candidateBSSID == null){
return config;
} else if ( candidateBSSID != null && bssid != null && candidateBSSID.equals(bssid) ) {
return config;
} else {
}
} else {
}
}
return null;
} finally {
}
}
Hopefully this will come in handy for someone else.