Android - WiFi Association отключает скрытые настройки WiFi
В моем приложении у меня есть экран выбора сети, в котором отображаются все видимые сети, включая настроенные скрытые SSID.
Однако, когда пользователь выбирает видимую сеть, которая не является скрытым SSID, и связывается с ней, используя следующий код.
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;
try {
result = mWifiManager.enableNetwork(id, true);
return result;
} catch (Throwable t) {
t.printStackTrace();
return false;
}
}
Таким образом, метод подключения к сети показан здесь http://developer.android.com/reference/android/net/wifi/WifiManager.html, boolean)
mWifiManager.enableNetwork(id, true);
Отключает все остальные конфигурации. Это нормально для не скрытых SSID, но это означает, что моя конфигурация скрытых SSID отключена и больше не включена в результаты сканирования. Это означает, что если пользователь находится в скрытой сети и подключается к другой сети, он не может вернуться в свою скрытую сеть, пока не запустит свои настройки Wi-Fi на своем устройстве.
Я обнаружил, что описанный выше метод программного изменения сети Wifi должен отличаться от метода, используемого в настройках Wifi устройства. Например, если вы программно подключились, а затем перейдите на экран "Настройки Wi-Fi", вы увидите, что для всех остальных настроенных сетей установлено значение "Отключено". Однако, если вы подключаетесь к сети на экране настроек Wi-Fi устройства, все остальные конфигурации Wi-Fi остаются как "Сохраненные".
У кого-нибудь есть альтернативный метод для программного ассоциирования с сетью, которая сохраняет скрытые конфигурации SSID, не отключая их?
Спасибо, это настоящая боль.
1 ответ
Хорошо, я, кажется, исправил это сейчас.
Вот моя переработанная ассоциативная логика - я фактически разделил это на отдельные методы, но для простоты чтения здесь я опубликую все это в одном методе.
Проще говоря, я нахожу все скрытые сети, которые видны до того, как выполню ассоциацию, заинтересован в них, затем связываюсь с сетью, которую выбрал пользователь, затем снова включаю скрытые конфигурации SSID, не отключая другие.
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;
}
}
Класс ScanResultsWrapper - это простой класс, который позволяет хранить некоторую дополнительную информацию и быть легко доступной. Вот конструктор, который объясняет, для чего установлена переменная _isHidden.
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 {
}
}
Надеюсь, это пригодится кому-то еще.