Pregunta

In my App I have a Network Selection Screen, this shows all visible networks - including Configured Hidden SSID's.

However when a user selects a visible network that is not a Hidden SSID, and associates to it using the following code.

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

}

So the method to associate to a network shown here http://developer.android.com/reference/android/net/wifi/WifiManager.html#enableNetwork(int, boolean)

mWifiManager.enableNetwork(id, true); 

Disables all other configurations. This is Okay for non-Hidden SSID's, yet this means that my Hidden SSID configuration is disabled, and is no longer included in the Scan results. Meaning that if a user is on a Hidden Network and joins another network, they can not go back to join their Hidden Network unless they launch their device Wifi Settings.

I have found that the above method for changing Wifi Network Programmatically must be different from the method used by the device Wifi Settings. For if you Associate Programmatically then go to the Wifi Settings screen you will see that all other Configured Networks have been set to "Disabled". However, If you Associate to a network from the Device Wifi Settings Screen all other Wifi Configurations stay as "Saved".

Does anyone have an alternate method for programmatically associating to a network which retains Hidden SSID configurations without Disabling them?

Thanks, this is a real pain.

¿Fue útil?

Solución

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top