Android WifiManager.addNetwork() возвращает -1

Я пишу приложение для Android, которое будет подключаться к определенной точке доступа WPA, при подключении оно вызовет http-вызов. Это не сохранит конфигурацию сети. Я прочитал почти все сообщения о переполнении стека при подключении к сети Wi-Fi, но не могу найти ответ, который работает для меня. Вот код, который я использую для подключения..

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

Однако netId всегда -1. Я пробовал это на двух разных телефонах (ICS: HTC Rezound и GingerBread: Motorola DroidX). Оба показывают одинаковые результаты. Что я делаю не так?

Изменение: я попробовал тот же код с точкой доступа WPA2 и получил очень странные результаты. Когда этот код был запущен, в первый раз он вернул бы -1, но если я вызову тот же метод во второй раз с задержкой в 1 секунду, он вернет действительный netId. Так что вопросы

  1. почему приведенный выше код не подключается к wpa?
  2. в wpa2, почему мне нужно дважды вызывать вышеупомянутый метод для подключения? Изменение: я заметил, что мне нужно было подключиться несколько раз, чтобы подключиться. Иногда для подключения требуется 3-4 раза. Так что сейчас я зацикливаюсь, пока добавление конфигурации не вернет> 0 id.

Ответы

Ответ 1

Возможно, немного поздно, но попробуйте подключиться к защищенным сетям Open/WPA/WPA2/WEP.

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

Очевидно, вы установите свои собственные переменные для разных типов безопасности, если это применимо. Ключ (pardon the pun) к подключению к защищенной сети WEP - это метод getHexKey, как показано ниже.

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

Ответ 2

Я обнаружил, что если общий ключ меньше 8 символов, он вернет -1.

Ответ 3

У меня была та же проблема. Я узнал, что ваш Wi-Fi должен быть включен, когда вы вызываете addNetwork.

Ответ 4

У меня была такая же проблема. Казалось бы, все было хорошо, но потом - это было не так.

Я обнаружил, что это:

  • Android WifiStateMachine не позволит вам добавлять или изменять сети, если соискатель не запущен и не подключен. Это влияет на сервисы, запущенные при запуске, и сервисы, работающие даже при отключенном WIFI.

  • Android WifiConfigStore отслеживает владельцев сети Wi-Fi по UID. Это означает, что вы не сможете изменить сеть, созданную другим процессом.

добавить сеть можно следующим образом:

  1. Проверьте, включена ли сеть WIFI. Если нет, позвоните WifiManager.setWifiEnabled(true).
  2. Подождите, пока WifiManager.pingSupplicant() вернет истину.
  3. Создайте и заполните новый WifiConfiguration, затем передайте его WifiManager.addNetwork(). Убедитесь, что возвращаемое значение не (-1).
  4. (необязательно) используйте значение, возвращаемое addNetwork() в качестве аргумента для вызова WifiConfiguration.enableNetwork() (если это не -1). Обратите внимание, что логический параметр означает disableOthers и должен иметь значение false, если у вас нет права изменять все другие сети: он может выйти из строя внутри, если вы установите его в значение true.

Это должно позволить вам добавлять (и подключать) программно к новой сети Wi-Fi.

Ответ 5

Проблема в том, что вы пытаетесь добавить конфигурацию сети, которая уже существует. Когда вы звоните:

int netId = wifiManager.addNetwork(wc);

произойдет сбой (возврат -1), если сетевая конфигурация с таким же SSID уже существует. Итак, вам нужно проверить, является ли netId -1, и если это так, пройти через настроенные сети в поисках сети с тем же SSID и, как только она найдена, вернуть networkId.

Котлин:

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)