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 {
    }
}

Надеюсь, это пригодится кому-то еще.

Другие вопросы по тегам