Wie verbinde ich mich programmgesteuert mit einem bestimmten Wi-Fi-Netzwerk in Android?

294

Ich möchte eine App entwerfen, die eine Liste der verfügbaren Wi-Fi-Netzwerke anzeigt und eine Verbindung zu dem vom Benutzer ausgewählten Netzwerk herstellt.

Ich habe den Teil implementiert, der die Scanergebnisse zeigt. Jetzt möchte ich eine Verbindung zu einem bestimmten Netzwerk herstellen, das der Benutzer aus der Liste der Scanergebnisse ausgewählt hat.

Wie mache ich das?

Vikram Gupta
quelle

Antworten:

441

Sie müssen eine WifiConfigurationInstanz wie folgt erstellen :

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

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

Für das WEP-Netzwerk müssen Sie dann Folgendes tun:

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

Für ein WPA-Netzwerk müssen Sie eine Passphrase wie folgt hinzufügen:

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

Für Open Network müssen Sie Folgendes tun:

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

Dann müssen Sie es zu den Einstellungen des Android-WLAN-Managers hinzufügen:

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

Und schließlich müssen Sie es möglicherweise aktivieren, damit Android eine Verbindung dazu herstellt:

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: Wenn Ihr Passwort im Fall von WEP hexadezimal ist, müssen Sie es nicht mit Anführungszeichen umgeben.

Kenota
quelle
5
das funktioniert gut! danke :) aber noch etwas möchte ich fragen. Müssen Sie nicht die erlaubten PairwiseCipher-, erlaubtenAuthALgorithmen und erlaubten Protokolle festlegen? Und wie man entscheidet, welches Attribut gesetzt werden soll; Wie haben Sie WEP40 für GroupCipher für WEP-Netzwerke eingestellt?
Vikram Gupta
8
Ich habe vergessen, eines zu erwähnen. Wenn Ihr Passwort im Fall von WEP hexadezimal ist, müssen Sie es nicht in Anführungszeichen setzen.
Kenia
8
Vielen Dank für die nette Lösung. Können Sie erläutern, wie Sie überprüfen können, ob die Verbindung erfolgreich war oder nicht? Beispielsweise kann der Benutzer das falsche Passwort eingeben und sollte darüber informiert werden.
Pascal Klein
3
Wie wäre es, wenn der gewünschte Wifi-Hotspot überhaupt kein Passwort verwendet? Sollten wir den .preSharedKey = null verwenden? oder sollten wir .preSharedKey = "" setzen; Welches ist korrekt? @kenota
gumuruh
6
Es funktioniert bei mir nicht: Es stellt die direkte Verbindung zum zuvor gespeicherten WLAN wieder her, anstatt eine Verbindung zum neuen herzustellen.
Virthuss
138

Das frühere Antwort funktioniert , aber die Lösung kann tatsächlich einfacher sein. Das Durchlaufen der konfigurierten Netzwerkliste ist nicht erforderlich, da Sie die Netzwerk-ID erhalten, wenn Sie das Netzwerk über den WifiManager hinzufügen.

Die vollständige, vereinfachte Lösung würde also ungefähr so ​​aussehen:

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
quelle
1
wenn das Passwort nicht verwendet wird. Sollten wir .preSharedKey = null setzen; oder sollten wir einfach eine leere Zeichenfolge setzen, @seanloyola?
Gumuruh
2
@MuhammedRefaat Sie trennen die Verbindung, falls Sie bereits mit einem anderen Netzwerk verbunden sind.
Sean Loyola
1
@gumuruh Sie müssen das presharedkey-Objekt überhaupt nicht einschließen, wenn kein Schlüssel erforderlich ist.
Sean Loyola
7
Laut Javadoc von enableNetwork müssen Sie nicht trennen oder verbinden, wenn Sie boolean disableOthers true verwenden. Dies wird beides für Sie tun
NikkyD
12
Sollte wohl erwähnen, dass die CHANGE_WIFI_STATEErlaubnis benötigt wird.
ThomasW
27

Bevor Sie eine Verbindung zum WIFI-Netzwerk herstellen, müssen Sie überprüfen, ob der Sicherheitstyp der WIFI-Netzwerk-ScanResult-Klasse über Funktionen verfügt. Dieses Feld gibt Ihnen den Netzwerktyp an

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

Es gibt drei Arten von WIFI-Netzwerken.

Instanziieren Sie zunächst ein WifiConfiguration-Objekt und geben Sie die SSID des Netzwerks ein (beachten Sie, dass es in doppelte Anführungszeichen gesetzt werden muss), setzen Sie den Anfangszustand auf deaktiviert und geben Sie die Priorität des Netzwerks an (Zahlen um 40 scheinen gut zu funktionieren).

WifiConfiguration wfc = new WifiConfiguration();

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

Nun zum komplizierteren Teil: Wir müssen mehrere Mitglieder von WifiConfiguration füllen, um den Sicherheitsmodus des Netzwerks anzugeben. Für offene Netzwerke.

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

Für Netzwerke mit WEP; Beachten Sie, dass der WEP-Schlüssel auch in doppelte Anführungszeichen eingeschlossen ist.

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;

Für Netzwerke, die WPA und WPA2 verwenden, können wir für beide die gleichen Werte festlegen.

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

Schließlich können wir das Netzwerk zur bekannten Liste des WifiManager hinzufügen

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
quelle
Ein Hinweis zur Priorität, auf meinen Telefonnummern arbeiteten rund 4000. wahrscheinlich am besten, um diesen Teil etwas dynamischer zu gestalten (vorhandene Konfigurationen usw. wiederholen)
Sam
Wie könnte ich Netzwerksicherheitstyp von SSID für WLAN ScanResult
Shantanu
@ Shantanu überprüfen Sie die folgenden Details. stackoverflow.com/questions/6866153/…
Kalpesh Gohel
Auf Samsung-Geräten ist die Passphrase eine Hash-Zeichenfolge. Und der Code funktioniert nicht. Überprüfst du das?
Nguyen Minh Binh
Können Sie ein Beispiel für die Verbindung von EAP vom Typ SIM-WLAN bereitstellen?
Prashanth Debbadwar
19

Gutschrift an @ raji-ramamoorthi & @kenota

Die Lösung, die für mich funktioniert hat, ist die Kombination der oben genannten Mitwirkenden in diesem Thread.

Hierher zu kommen ScanResultist der Prozess.

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

Beachten Sie unregisteres auf onPause& onStopleben Sie diesunregisterReceiver(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
quelle
5

Wenn Ihr Gerät die Wifi-Konfigurationen kennt (bereits gespeichert), können wir die Raketenwissenschaft umgehen. Durchlaufen Sie einfach die Konfigurationen und prüfen Sie, ob die SSID übereinstimmt. Wenn ja, verbinden und zurückkehren .

Berechtigungen festlegen:

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

Verbinden:

    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
quelle
5

Ich habe mir den Kopf gebrochen, um zu verstehen, warum Ihre Antworten für WPA / WPA2 nicht funktionieren ... Nach stundenlangen Versuchen habe ich herausgefunden, was Ihnen fehlt:

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

ist für WPA-Netzwerke ERFORDERLICH !!!!

Jetzt gehts :)

Taras Okunev
quelle
4

Dies ist eine Aktivität, die Sie in Unterklassen unterteilen können, um die Verbindung zu einem bestimmten WLAN zu erzwingen: https://github.com/zoltanersek/android-wifi-activity/blob/master/app/src/main/java/com/zoltanersek/androidwifiactivity/ WifiActivity.java

Sie müssen diese Aktivität in Unterklassen unterteilen und ihre Methoden implementieren:

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
quelle
Link nach unten kannst du den neuen geben?
StartCoding
4

In API-Ebene 29 ist die WifiManager.enableNetwork()Methode veraltet . Gemäß Android API-Dokumentation ( hier überprüfen ):

  1. Unter WifiNetworkSpecifier.Builder # build () finden Sie einen neuen Mechanismus zum Auslösen der Verbindung zu einem Wi-Fi-Netzwerk.
  2. Unter addNetworkSuggestions (java.util.List) und removeNetworkSuggestions (java.util.List) finden Sie eine neue API zum Hinzufügen von Wi-Fi-Netzwerken, die bei der automatischen Verbindung mit WLAN berücksichtigt werden sollen. Kompatibilitätshinweis: Für Anwendungen, die auf Build.VERSION_CODES.Q oder höher abzielen, gibt diese API immer false zurück.

Ab API-Ebene 29 müssen Sie eine Verbindung zum WiFi-Netzwerk herstellen WifiNetworkSpecifier. Beispielcode finden Sie unter https://developer.android.com/reference/android/net/wifi/WifiNetworkSpecifier.Builder.html#build ()

VIjay J.
quelle
Ist es möglich, mit dem neuen WifiNetWorkSpecifier.Builder eine Verbindung zu einem WEP-Netzwerk herzustellen? Ich kann keine Methode finden, um dem Builder eine WEP-Passphrase hinzuzufügen.
Dieter27
Nummer 1 scheint nicht zu funktionieren. Gibt es einen Rückruf?
Faizan Mir
1

Ich habe auch versucht, eine Verbindung zum Netzwerk herzustellen. Keine der oben vorgeschlagenen Lösungen funktioniert für hugerock t70. Funktion wifiManager.disconnect (); trennt sich nicht vom aktuellen Netzwerk. Und kann daher keine Verbindung zum angegebenen Netzwerk herstellen. Ich habe den obigen Code geändert. Für mich funktioniert der Code bolow perfekt:

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
quelle
Ich erhalte eine Fehlermeldung in 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.
Luis A. Florit
0

Versuchen Sie diese Methode. Es ist sehr leicht:

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
quelle