Как программно подключиться к определенной сети Wi-Fi в Android?

294

Я хочу разработать приложение, которое показывает список доступных сетей Wi-Fi и подключается к любой сети, выбранной пользователем.

Я реализовал часть, показывающую результаты сканирования. Теперь я хочу подключиться к определенной сети, выбранной пользователем из списка результатов сканирования.

Как мне это сделать?

Викрам Гупта
источник
Это работает для меня WPA2 и WEP: stackoverflow.com/a/29575563/7337517
Кундан

Ответы:

441

Вам нужно создать WifiConfigurationэкземпляр следующим образом:

String networkSSID = "test";
String networkPass = "pass";

WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + networkSSID + "\"";   // Please note the quotes. String should contain ssid in quotes

Затем для сети WEP вам нужно сделать это:

conf.wepKeys[0] = "\"" + networkPass + "\""; 
conf.wepTxKeyIndex = 0;
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); 

Для сети WPA вам нужно добавить фразу-пароль следующим образом:

conf.preSharedKey = "\""+ networkPass +"\"";

Для открытой сети вам нужно сделать это:

conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);

Затем вам нужно добавить его в настройки Android-менеджера Wi-Fi:

WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE); 
wifiManager.addNetwork(conf);

И, наконец, вам может потребоваться включить его, чтобы Android подключился к нему:

List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
for( WifiConfiguration i : list ) {
    if(i.SSID != null && i.SSID.equals("\"" + networkSSID + "\"")) {
         wifiManager.disconnect();
         wifiManager.enableNetwork(i.networkId, true);
         wifiManager.reconnect();               

         break;
    }           
 }

UPD: В случае WEP, если ваш пароль в шестнадцатеричном виде, вам не нужно заключать его в кавычки.

kenota
источник
5
это работает хорошо! спасибо :) но еще одна вещь, которую я хотел бы спросить. Вам не нужно устанавливать allowPairwiseCipher, allowAuthALgorithms и allowProtocols? И как решить, какой именно атрибут установить; как вы установили WEP40 для GroupCipher для сетей WEP?
Викрам Гупта
8
Я забыл упомянуть одну вещь. В случае WEP, если ваш пароль в шестнадцатеричном виде, вам не нужно заключать его в кавычки.
Кенота
8
Спасибо за хорошее решение, не могли бы вы рассказать, как проверить, было ли соединение успешным или нет. Например, пользователь может ввести неправильный пароль и должен быть уведомлен об этом.
Паскаль Кляйн
3
как насчет того, если желаемая точка доступа Wi-Fi вообще не использует пароль? Должны ли мы использовать .preSharedKey = null; или мы должны установить .preSharedKey = ""; Который правильный? @kenota
gumuruh
6
Он не работает для меня: он подключается напрямую к предыдущему запомненному Wi-Fi вместо подключения к новому.
Virthuss
138

Более ранний ответ работает , но решение на самом деле может быть проще. Циклический просмотр списка настроенных сетей не требуется, поскольку вы получаете идентификатор сети при добавлении сети через WifiManager.

Таким образом, полное упрощенное решение будет выглядеть примерно так:

WifiConfiguration wifiConfig = new WifiConfiguration();
wifiConfig.SSID = String.format("\"%s\"", ssid);
wifiConfig.preSharedKey = String.format("\"%s\"", key);

WifiManager wifiManager = (WifiManager)getSystemService(WIFI_SERVICE);
//remember id
int netId = wifiManager.addNetwork(wifiConfig);
wifiManager.disconnect();
wifiManager.enableNetwork(netId, true);
wifiManager.reconnect();
Шон Лойола
источник
1
если пароль не используется. Должны ли мы поставить .preSharedKey = null; или мы должны просто поставить пустую строку, @seanloyola?
gumuruh
2
@MuhammedRefaat вы отключаете, если вы уже подключены к другой сети.
Шон Лойола
1
@gumuruh вам вообще не нужно включать объект presharedkey, если ключ не требуется.
Шон Лойола
7
в соответствии с javadoc enableNetwork, если вы используете логическое значение disableOthers true, то вам не нужно отключать или подключаться, это будет делать для вас оба
NikkyD
12
Наверное, стоит упомянуть, что CHANGE_WIFI_STATEразрешение необходимо.
ThomasW
27

Перед подключением к сети WIFI необходимо проверить тип безопасности сети WIFI, который имеет класс ScanResult. В этом поле указан тип сети

См. Https://developer.android.com/reference/android/net/wifi/ScanResult.html#capabilities

Существует три типа сетей WIFI.

Во-первых, создайте экземпляр объекта WifiConfiguration и введите SSID сети (обратите внимание, что он должен быть заключен в двойные кавычки), установите начальное состояние как отключенное и укажите приоритет сети (числа около 40, кажется, работают хорошо).

WifiConfiguration wfc = new WifiConfiguration();

wfc.SSID = "\"".concat(ssid).concat("\"");
wfc.status = WifiConfiguration.Status.DISABLED;
wfc.priority = 40;

Теперь о более сложной части: нам нужно заполнить несколько членов WifiConfiguration, чтобы указать режим безопасности сети. Для открытых сетей.

wfc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wfc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wfc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wfc.allowedAuthAlgorithms.clear();
wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);

Для сетей, использующих WEP; обратите внимание, что ключ WEP также заключен в двойные кавычки.

wfc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wfc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wfc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wfc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
wfc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);

if (isHexString(password)) wfc.wepKeys[0] = password;
else wfc.wepKeys[0] = "\"".concat(password).concat("\"");
wfc.wepTxKeyIndex = 0;

Для сетей, использующих WPA и WPA2, мы можем установить одинаковые значения для обоих.

wfc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wfc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wfc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);

wfc.preSharedKey = "\"".concat(password).concat("\"");

Наконец, мы можем добавить сеть в известный список WifiManager

WifiManager wfMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
int networkId = wfMgr.addNetwork(wfc);
if (networkId != -1) {
 // success, can call wfMgr.enableNetwork(networkId, true) to connect
} 
Раджи Рамамурти
источник
записка о приоритете, на моих телефонах около 4000 сработало. Вероятно, лучше всего сделать эту часть более динамичной (повторять существующие конфиги и т. д.)
Сэм
Как я могу получить тип безопасности сети от SSID для Wi-Fi ScanResult
shantanu
@shantanu проверьте следующие детали. stackoverflow.com/questions/6866153/…
Kalpesh Gohel
На устройствах Samsung, пароль является хэшированной строкой. И код не работает. Вы это проверяете?
Нгуен Минь Бинь
Можете ли вы предоставить образец для подключения EAP типа WiFi?
Прашант Деббадвар
19

Кредит @ raji-ramamoorthi & @kenota

Решение, которое сработало для меня, - это сочетание перечисленных выше участников в этой теме.

Чтобы попасть ScanResultсюда, это процесс.

WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if (wifi.isWifiEnabled() == false) {
            Toast.makeText(getApplicationContext(), "wifi is disabled..making it enabled", Toast.LENGTH_LONG).show();
            wifi.setWifiEnabled(true);
        }

BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context c, Intent intent) {
                 wifi.getScanResults();
            }
        };

Обратите внимание на unregisterэто onPauseи onStopживи этимunregisterReceiver(broadcastReceiver);

public void connectWiFi(ScanResult scanResult) {
        try {

            Log.v("rht", "Item clicked, SSID " + scanResult.SSID + " Security : " + scanResult.capabilities);

            String networkSSID = scanResult.SSID;
            String networkPass = "12345678";

            WifiConfiguration conf = new WifiConfiguration();
            conf.SSID = "\"" + networkSSID + "\"";   // Please note the quotes. String should contain ssid in quotes
            conf.status = WifiConfiguration.Status.ENABLED;
            conf.priority = 40;

            if (scanResult.capabilities.toUpperCase().contains("WEP")) {
                Log.v("rht", "Configuring WEP");    
                conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
                conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
                conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);

                if (networkPass.matches("^[0-9a-fA-F]+$")) {
                    conf.wepKeys[0] = networkPass;
                } else {
                    conf.wepKeys[0] = "\"".concat(networkPass).concat("\"");
                }

                conf.wepTxKeyIndex = 0;

            } else if (scanResult.capabilities.toUpperCase().contains("WPA")) {
                Log.v("rht", "Configuring WPA");

                conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
                conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);

                conf.preSharedKey = "\"" + networkPass + "\"";

            } else {
                Log.v("rht", "Configuring OPEN network");
                conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
                conf.allowedAuthAlgorithms.clear();
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            }

            WifiManager wifiManager = (WifiManager) WiFiApplicationCore.getAppContext().getSystemService(Context.WIFI_SERVICE);
            int networkId = wifiManager.addNetwork(conf);

            Log.v("rht", "Add result " + networkId);

            List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
            for (WifiConfiguration i : list) {
                if (i.SSID != null && i.SSID.equals("\"" + networkSSID + "\"")) {
                    Log.v("rht", "WifiConfiguration SSID " + i.SSID);

                    boolean isDisconnected = wifiManager.disconnect();
                    Log.v("rht", "isDisconnected : " + isDisconnected);

                    boolean isEnabled = wifiManager.enableNetwork(i.networkId, true);
                    Log.v("rht", "isEnabled : " + isEnabled);

                    boolean isReconnected = wifiManager.reconnect();
                    Log.v("rht", "isReconnected : " + isReconnected);

                    break;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
Рохит Мандивал
источник
5

Если ваше устройство знает настройки Wi-Fi (уже сохранены), мы можем обойти ракетостроение. Просто прокрутите конфиги и проверьте, совпадает ли SSID. Если так, подключитесь и вернитесь .

Установить разрешения:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

Connect:

    try {
    String ssid = null;
    if (wifi == Wifi.PCAN_WIRELESS_GATEWAY) {
        ssid = AesPrefs.get(AesConst.PCAN_WIRELESS_SSID,
                context.getString(R.string.pcan_wireless_ssid_default));
    } else if (wifi == Wifi.KJ_WIFI) {
        ssid = context.getString(R.string.remote_wifi_ssid_default);
    }

    WifiManager wifiManager = (WifiManager) context.getApplicationContext()
            .getSystemService(Context.WIFI_SERVICE);

    List<WifiConfiguration> wifiConfigurations = wifiManager.getConfiguredNetworks();

    for (WifiConfiguration wifiConfiguration : wifiConfigurations) {
        if (wifiConfiguration.SSID.equals("\"" + ssid + "\"")) {
            wifiManager.enableNetwork(wifiConfiguration.networkId, true);
            Log.i(TAG, "connectToWifi: will enable " + wifiConfiguration.SSID);
            wifiManager.reconnect();
            return null; // return! (sometimes logcat showed me network-entries twice,
            // which may will end in bugs)
        }
    }
} catch (NullPointerException | IllegalStateException e) {
    Log.e(TAG, "connectToWifi: Missing network configuration.");
}
return null;
Мартин Пфеффер
источник
5

Я сломал голову, чтобы понять, почему ваши ответы на WPA / WPA2 не работают ... после нескольких часов попыток я нашел то, что вам не хватает:

conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);

ТРЕБУЕТСЯ для сетей WPA !!!!

Теперь это работает :)

Тарас Окунев
источник
4

Это действие, которое вы можете создать подклассом для принудительного подключения к определенному Wi-Fi: https://github.com/zoltanersek/android-wifi-activity/blob/master/app/src/main/java/com/zoltanersek/androidwifiactivity/ WifiActivity.java

Вам нужно будет создать подкласс этого действия и реализовать его методы:

public class SampleActivity extends WifiBaseActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
  }

  @Override
  protected int getSecondsTimeout() {
      return 10;
  }

  @Override
  protected String getWifiSSID() {
      return "WifiNetwork";
  }

  @Override
  protected String getWifiPass() {
      return "123456";
  }
}
Золтан Эрсек
источник
ссылку вниз можешь дать новый?
StartCoding
4

На уровне API 29 WifiManager.enableNetwork()метод устарел . Согласно документации Android API (проверьте здесь ):

  1. См. WifiNetworkSpecifier.Builder # build () для нового механизма запуска соединения с сетью Wi-Fi.
  2. См. AddNetworkSuggestions (java.util.List), removeNetworkSuggestions (java.util.List) для нового API для добавления сетей Wi-Fi для рассмотрения при автоматическом подключении к Wi-Fi. Примечание о совместимости: для приложений, нацеленных на Build.VERSION_CODES.Q или выше, этот API всегда будет возвращать false.

Начиная с уровня API 29, для подключения к сети Wi-Fi вам необходимо будет использовать WifiNetworkSpecifier. Пример кода можно найти по адресу https://developer.android.com/reference/android/net/wifi/WifiNetworkSpecifier.Builder.html#build ().

Виджай Дж
источник
Можно ли подключиться к сети WEP с помощью нового WifiNetWorkSpecifier.Builder? Я не могу найти способ добавить WEP-пароль в сборщик.
Dieter27
Номер 1, кажется, не работает, есть ли обратный вызов к нему?
Файзан Мир
1

Я также пытался подключиться к сети. Ни одно из предложенных выше решений не работает для hugerock t70. Функция wifiManager.disconnect (); не отключается от текущей сети. И поэтому не может переподключиться к указанной сети. Я изменил приведенный выше код. Для меня код bolow работает отлично:

String networkSSID = "test";
String networkPass = "pass";

WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + networkSSID + "\"";   
conf.wepKeys[0] = "\"" + networkPass + "\""; 
conf.wepTxKeyIndex = 0;
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); 
conf.preSharedKey = "\""+ networkPass +"\"";

WifiManager wifiManager =         
(WifiManager)context.getSystemService(Context.WIFI_SERVICE);    

int networkId = wifiManager.addNetwork(conf);
wifi_inf = wifiManager.getConnectionInfo();

/////important!!!
wifiManager.disableNetwork(wifi_inf.getNetworkId());
/////////////////

wifiManager.enableNetwork(networkId, true);
user1277317
источник
Я получаю сообщение об ошибке в Android 10:UID nnnnn does not have permission to update configuration xxxx. MD_START_CONNECT but no requests and connected, but app does not have sufficient permissions, bailing.
Луис А. Флорит
0

Попробуйте этот метод. Это очень просто:

public static boolean setSsidAndPassword(Context context, String ssid, String ssidPassword) {
    try {
        WifiManager wifiManager = (WifiManager) context.getSystemService(context.WIFI_SERVICE);
        Method getConfigMethod = wifiManager.getClass().getMethod("getWifiApConfiguration");
        WifiConfiguration wifiConfig = (WifiConfiguration) getConfigMethod.invoke(wifiManager);

        wifiConfig.SSID = ssid;
        wifiConfig.preSharedKey = ssidPassword;

        Method setConfigMethod = wifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
        setConfigMethod.invoke(wifiManager, wifiConfig);

        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}
Хирен Вагела
источник