Jak połączyć się programowo z określoną siecią Wi-Fi w systemie Android?

294

Chcę zaprojektować aplikację, która pokazuje listę dostępnych sieci Wi-Fi i połączyć się z dowolną siecią wybraną przez użytkownika.

Zaimplementowałem część pokazującą wyniki skanowania. Teraz chcę połączyć się z określoną siecią wybraną przez użytkownika z listy wyników skanowania.

Jak mam to zrobic?

Vikram Gupta
źródło

Odpowiedzi:

440

Musisz utworzyć WifiConfigurationtaką instancję:

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

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

Następnie w przypadku sieci WEP musisz to zrobić:

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

W przypadku sieci WPA musisz dodać hasło w następujący sposób:

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

W przypadku sieci otwartej musisz to zrobić:

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

Następnie musisz dodać go do ustawień menedżera Wi-Fi Android:

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

Na koniec może być konieczne włączenie go, aby system Android się z nim łączył:

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: W przypadku WEP, jeśli twoje hasło jest szesnastkowe, nie musisz otaczać go cudzysłowami.

Kenota
źródło
5
to działa dobrze! dziękuję :) ale jeszcze jedno chciałbym zapytać. Czy nie musisz ustawić dozwolonych algorytmów, dozwolonych algorytmów i dozwolonych protokołów? I jak zdecydować, który konkretny atrybut ustawić; jak ustawiłeś WEP40 dla GroupCipher dla sieci WEP?
Vikram Gupta
8
Zapomniałem wspomnieć o jednej rzeczy. W przypadku WEP, jeśli twoje hasło jest w postaci szesnastkowej, nie musisz otaczać go cudzysłowami.
kenota,
8
Dzięki za fajne rozwiązanie, czy możesz opracować sposób sprawdzenia, czy połączenie zakończyło się powodzeniem, czy nie. Na przykład użytkownik może wprowadzić nieprawidłowe hasło i powinien zostać o tym powiadomiony.
Pascal Klein
3
co powiesz, jeśli żądany hotspot Wi-Fi w ogóle nie używa hasła ... Czy powinniśmy użyć .preSharedKey = null; lub powinniśmy ustawić .preSharedKey = ""; Który jest prawidłowy? @kenota
gumuruh
6
Dla mnie to nie działa: łączy się ponownie z poprzednio zapamiętanym Wi-Fi zamiast łączyć się z nowym.
Virthuss
138

Wcześniej odpowiedź działa , ale rozwiązanie w rzeczywistości może być prostsze. Zapętlanie listy skonfigurowanych sieci nie jest wymagane, ponieważ identyfikator sieci jest dodawany po dodaniu sieci za pomocą WifiManager.

Kompletne, uproszczone rozwiązanie wyglądałoby mniej więcej tak:

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();
Sean Loyola
źródło
1
jeśli hasło nie jest używane. Powinniśmy umieścić .preSharedKey = null; czy powinniśmy po prostu umieścić pusty ciąg @seanloyola?
gumuruh
2
@MuhammedRefaat rozłączasz, ponieważ jesteś już podłączony do innej sieci.
sean loyola
1
@ gumuruh nie musisz w ogóle uwzględniać obiektu wstępnego klucza, jeśli nie jest wymagany klucz.
sean loyola
7
zgodnie z javadoc z enableNetwork, jeśli użyjesz boolean disableInne są prawdziwe, to nie musisz się rozłączać ani łączyć, zrobi to dla ciebie oba
NikkyD
12
Powinien prawdopodobnie wspomnieć, że CHANGE_WIFI_STATEzezwolenie jest potrzebne.
ThomasW
27

Przed podłączeniem sieci WIFI należy sprawdzić rodzaj zabezpieczeń sieci WIFI Klasa ScanResult ma możliwości. To pole podaje typ sieci

Patrz: https://developer.android.com/reference/android/net/wifi/ScanResult.html#capabilities

Istnieją trzy rodzaje sieci WIFI.

Najpierw utwórz instancję obiektu WifiConfiguration i wypełnij identyfikator SSID sieci (zwróć uwagę, że musi on być zawarty w podwójnych cudzysłowach), ustaw stan początkowy na wyłączony i określ priorytet sieci (liczby około 40 wydają się działać dobrze).

WifiConfiguration wfc = new WifiConfiguration();

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

Teraz bardziej skomplikowana część: musimy wypełnić kilku członków konfiguracji Wi-Fi, aby określić tryb bezpieczeństwa sieci. Dla otwartych sieci.

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

Dla sieci korzystających z WEP; zwróć uwagę, że klucz WEP jest również ujęty w podwójne cudzysłowy.

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;

W przypadku sieci korzystających z WPA i WPA2 możemy ustawić te same wartości dla obu.

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("\"");

Wreszcie możemy dodać sieć do znanej listy 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
} 
raji ramamoorthi
źródło
uwaga na priorytet, na moich numerach telefonów działało około 4000. prawdopodobnie najlepiej uczynić tę część nieco bardziej dynamiczną (iteruj istniejące konfiguracje itp.)
Sam
Jak mogę uzyskać typ zabezpieczenia sieci z SSID dla Wi-Fi ScanResult
shantanu
@shantanu sprawdź następujące szczegóły. stackoverflow.com/questions/6866153/…
Kalpesh Gohel
Na urządzeniach Samsung hasło jest hashowane. Kod nie działa. Sprawdzasz to?
Nguyen Minh Binh
czy możesz podać próbkę połączenia EAP Wi-Fi typu SIM?
Prashanth Debbadwar
19

Podziękowania dla @ raji-ramamoorthi & @kenota

Rozwiązaniem, które działało dla mnie, jest połączenie powyższych autorów w tym wątku.

Dotarcie ScanResulttutaj jest procesem.

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

Zwróć na unregisterto uwagę onPausei onStopżyj tymunregisterReceiver(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();
        }
    }
Rohit Mandiwal
źródło
5

Jeśli twoje urządzenie zna konfiguracje Wi-Fi (już zapisane), możemy ominąć naukę o rakietach. Wystarczy, że przejdziesz do konfiguracji i sprawdzisz, czy identyfikator SSID jest zgodny. Jeśli tak, połącz się i wróć .

Ustaw uprawnienia:

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

Połączyć:

    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;
Martin Pfeffer
źródło
5

Złamałem głowę, aby zrozumieć, dlaczego twoje odpowiedzi na WPA / WPA2 nie działają ... po wielu godzinach prób znalazłem to, czego brakuje:

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

jest WYMAGANY dla sieci WPA !!!!

Teraz działa :)

Taras Okunev
źródło
4

Jest to czynność, którą możesz podklasować, aby wymusić połączenie z określonym Wi-Fi: https://github.com/zoltanersek/android-wifi-activity/blob/master/app/src/main/java/com/zoltanersek/androidwifiactivity/ WifiActivity.java

Będziesz musiał podklasować to działanie i zaimplementować jego metody:

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";
  }
}
Zoltan Ersek
źródło
link w dół, czy możesz podać nowy?
Rozpocznij kodowanie
4

Na poziomie API 29 WifiManager.enableNetwork()metoda jest przestarzała . Zgodnie z dokumentacją interfejsu API Androida (sprawdź tutaj ):

  1. Zobacz WifiNetworkSpecifier.Builder # build (), aby poznać nowy mechanizm wyzwalania połączenia z siecią Wi-Fi.
  2. Zobacz addNetworkSuggestions (java.util.List), removeNetworkSuggestions (java.util.List), aby uzyskać nowe API do dodawania sieci Wi-Fi do rozważenia przy automatycznym połączeniu z Wi-Fi. Uwaga dotycząca zgodności: w przypadku aplikacji kierowanych na Build.VERSION_CODES.Q lub nowszy ten interfejs API zawsze zwróci false.

Z poziomu interfejsu API 29, aby połączyć się z siecią Wi-Fi, musisz użyć WifiNetworkSpecifier. Przykładowy kod można znaleźć na https://developer.android.com/reference/android/net/wifi/WifiNetworkSpecifier.Builder.html#build ()

VIjay J
źródło
Czy można połączyć się z siecią WEP za pomocą nowego WifiNetWorkSpecifier.Builder? Nie mogę znaleźć metody dodania hasła WEP do konstruktora.
Dieter27
Wydaje się, że numer 1 nie działa. Czy jest jakiś oddzwonienie?
Faizan Mir
1

Próbowałem także połączyć się z siecią. Żadne z powyższych rozwiązań nie działa dla hugerocka t70. Funkcja wifiManager.disconnect (); nie odłącza się od bieżącej sieci. Dlatego nie można ponownie połączyć się z określoną siecią. Zmodyfikowałem powyższy kod. Dla mnie kod bolow działa idealnie:

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);
użytkownik1277317
źródło
Pojawia się błąd w Androidzie 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.
Luis A. Florit
0

Wypróbuj tę metodę. To jest bardzo łatwe:

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;
    }
}
Hiren Vaghela
źródło