Як я можу програмно підключитися до певної мережі Wi-Fi в Android?


294

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

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

Як це зробити?



Це працює для мене WPA2 і WEP: stackoverflow.com/a/29575563/7337517
Кундан

Відповіді:


440

Вам потрібно створити такий 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);

Потім вам потрібно додати його до налаштувань Wi-Fi-менеджера Android:

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, якщо ваш пароль у шістнадцятковій формі, вам не потрібно оточувати його лапки.


5
це добре працює! дякую :) але ще одне, що я хотів би запитати. Вам не потрібно встановлювати дозволеніPairwiseCipher, allowedAuthALgorithms та allowedProtocols? І як вирішити, який саме атрибут встановити; як ви встановили WEP40 для GroupCipher для мереж WEP?
Вікрам Гупта

8
Я забув згадати одне. У випадку WEP, якщо ваш пароль у шістнадцятковій формі, вам не потрібно оточувати його лапки.
кенота

8
Дякуємо за гарне рішення, чи можете ви детальніше розглянути, як перевірити, вдале з'єднання чи ні. Наприклад, користувач може ввести неправильний пароль, і його слід повідомити про нього.
Паскаль Кляйн

3
як щодо того, якщо бажаний точок доступу Wi-Fi взагалі не використовує пароля .... Чи слід використовувати .preSharedKey = null; або ми повинні встановити .preSharedKey = ""; Який з них правильний? @kenota
gumuruh

6
Для мене це не працює: він підключається безпосередньо до попереднього запам'ятовуваного wifi замість підключення до нового.
Віртус

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 ви відключите випадок, якщо ви вже підключені до іншої мережі.
sean loyola

1
@gumuruh вам взагалі не потрібно включати об'єкт presharedkey, якщо ключ не потрібен.
sean loyola

7
згідно з javadoc enableNetwork, якщо ви використовуєте логічний boolean disabledOthers true, то вам не доведеться відключати або підключатись, це зробить і те, і інше
NikkyD

12
Напевно, слід згадати, що CHANGE_WIFI_STATEдозвіл потрібен.
ThomasW

27

Перш ніж підключити мережу WIFI, потрібно перевірити тип захисту мережі WIFI класу ScanResult. Це поле дає тип мережі

Посилання: https://developer.android.com/reference/android/net/wifi/ScanResult.html#capa sposobnosti

Існує три типи мереж 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 для wifi ScanResult
shantanu

@shantanu перевірити наступні деталі. stackoverflow.com/questions/6866153 / ...
Kalpesh Gohel

На пристроях Samsung, парольна фраза є хешованою рядком. І код не працює. Ви це перевіряєте?
Nguyen Minh Binh

Ви можете надати зразок для підключення EAP до sim-типу Wi-Fi?
Прашант Деббадвар

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

Якщо ваш пристрій знає конфігурації Wifi (вже збережені), ми можемо обійти ракетну науку. Просто проведіть конфігурацію через перевірку, чи відповідає SSID. Якщо так, підключіться та поверніться .

Встановити дозволи:

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

Підключення:

    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

Це діяльність, яку ви можете підкласирувати, щоб примусити підключитися до конкретного wifi: 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

На рівні 29 API WifiManager.enableNetwork()метод застарілий . Відповідно до документації API API (ознайомтесь тут ):

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

З рівня 29 API для підключення до мережі WiFi вам потрібно буде скористатися WifiNetworkSpecifier. Ви можете знайти приклад коду за адресою https://developer.android.com/reference/android/net/wifi/WifiNetworkSpecifier.Builder.html#build ()


Чи можливо підключитися до мережі WEP за допомогою нового WifiNetWorkSpecifier.Builder? Я не можу знайти метод додавання парольної фрази WEP до будівельника.
Dieter27

Чи не здається, що номер 1 працює? Чи є зворотний дзвінок до нього?
Faizan Mir

1

Я також намагався підключитися до мережі. Жодне із запропонованих вище рішень не працює у величезному ролику t70. Функція wifiManager.disconnect (); не відключається від поточної мережі. Отже, не можна знову підключитися до вказаної мережі. Я змінив вищевказаний код. Для мене ідеально працює код коду:

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

Я отримую помилку в 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;
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.