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?



To zadziałało dla mnie WPA2 i WEP: stackoverflow.com/a/29575563/7337517
Kundan

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.


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

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
} 

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

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;

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


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

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


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

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;
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.