Come posso connettermi a una specifica rete Wi-Fi in Android a livello di programmazione?


294

Voglio progettare un'app che mostri un elenco di reti Wi-Fi disponibili e connettersi a qualsiasi rete sia selezionata dall'utente.

Ho implementato la parte che mostra i risultati della scansione. Ora voglio collegarmi a una particolare rete selezionata dall'utente dall'elenco dei risultati della scansione.

Come faccio a fare questo?



Questo ha funzionato per me WPA2 e WEP: stackoverflow.com/a/29575563/7337517
— Kundan

Risposte:


441

Devi creare WifiConfigurationun'istanza come questa:

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

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

Quindi, per la rete WEP devi fare questo:

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

Per la rete WPA è necessario aggiungere passphrase in questo modo:

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

Per Open network devi fare questo:

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

Quindi, è necessario aggiungerlo alle impostazioni del gestore wifi Android:

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

Infine, potrebbe essere necessario abilitarlo, quindi Android si connette ad esso:

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: nel caso di WEP, se la password è in esadecimale, non è necessario racchiuderla tra virgolette.


5
funziona bene! grazie :) ma un'altra cosa che vorrei chiedere. Non è necessario impostare i protocolli ammessiPairwise, consentitoAuthALgorithms e consentiti? E come decidere quale particolare attributo impostare; come hai impostato WEP40 per GroupCipher per reti WEP?
— Vikram Gupta,

8
Ho dimenticato di menzionare una cosa. Nel caso di WEP, se la password è in esadecimale, non è necessario racchiuderla tra virgolette.
— Kenota,

8
Grazie per la bella soluzione, potresti approfondire come verificare se la connessione è andata a buon fine oppure no. Ad esempio, l'utente potrebbe inserire la password errata e dovrebbe esserne informato.
— Pascal Klein

3
che ne dite se l'hotspot Wifi desiderato non utilizza alcuna password .... Dovremmo usare .preSharedKey = null; o dovremmo impostare .preSharedKey = ""; Quale è corretto? @kenota
— gumuruh,

6
Per me non funziona: si ricollega direttamente al precedente wifi ricordato invece di connettersi a quello nuovo.
— Virthuss,

138

La risposta precedente funziona , ma la soluzione può effettivamente essere più semplice. Non è necessario scorrere l'elenco delle reti configurate quando si ottiene l'ID di rete quando si aggiunge la rete tramite WifiManager.

Quindi la soluzione completa e semplificata sarebbe simile a questa:

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
se la password non viene utilizzata. Dovremmo mettere .preSharedKey = null; o dovremmo semplicemente mettere una stringa vuota, @seanloyola?
— Gumuruh,

2
@MuhammedRefaat ti disconnetti se sei già connesso a un'altra rete.
— sean loyola,

1
@gumuruh non devi assolutamente includere l'oggetto presharedkey se non è richiesta alcuna chiave.
— sean loyola,

7
secondo il javadoc di enableNetwork, se si utilizza disabilita booleanaAltro vero, quindi non è necessario disconnettersi o connettersi, farà entrambe le cose per voi
— NikkyD

12
Dovrebbe probabilmente menzionare che CHANGE_WIFI_STATEè necessaria l' autorizzazione.
— ThomasW,

27

Prima di connettere la rete WIFI è necessario verificare il tipo di sicurezza della classe WIFI della rete ScanResult. Questo campo fornisce il tipo di rete

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

Esistono tre tipi di reti WIFI.

Innanzitutto, crea un'istanza di un oggetto WifiConfiguration e compila il SSID della rete (nota che deve essere racchiuso tra virgolette doppie), imposta lo stato iniziale su disabilitato e specifica la priorità della rete (i numeri intorno a 40 sembrano funzionare bene).

WifiConfiguration wfc = new WifiConfiguration();

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

Ora per la parte più complicata: dobbiamo specificare diversi membri di WifiConfiguration per specificare la modalità di sicurezza della rete. Per reti aperte.

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

Per reti che utilizzano WEP; si noti che anche la chiave WEP è racchiusa tra virgolette doppie.

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;

Per le reti che utilizzano WPA e WPA2, possiamo impostare gli stessi valori per entrambi.

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

Infine, possiamo aggiungere la rete all'elenco noto di 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
} 

una nota sulla priorità, sui miei numeri di telefono circa 4000 ha funzionato. probabilmente meglio per rendere quella parte un po 'più dinamica (iterare le configurazioni esistenti ecc.)
— Sam

Come posso ottenere il tipo di sicurezza della rete da SSID per wifi ScanResult
— shantanu

@shantanu controlla quanto segue per i dettagli. stackoverflow.com/questions/6866153/...
— Kalpesh Gohel

Sui dispositivi Samsung, la passphrase è una stringa con hash. E il codice non funziona. Lo controlli?
— Nguyen Minh Binh,

puoi fornire un esempio per connettere EAP di tipo sim wifi?
— Prashanth Debbadwar,

19

Ringraziamo @ raji-ramamoorthi e @kenota

La soluzione che ha funzionato per me è la combinazione dei precedenti collaboratori in questo thread.

Per arrivare ScanResultqui è il processo.

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

Avviso per il unregistersu onPausee onStopvivere questounregisterReceiver(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

Se il tuo dispositivo conosce le configurazioni Wifi (già memorizzate), possiamo ignorare la scienza missilistica. Basta scorrere attraverso le configurazioni per verificare se l'SSID è corrispondente. In tal caso, connettiti e ritorna .

Imposta autorizzazioni:

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

Collegare:

    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

Mi sono rotto la testa per capire perché le tue risposte per WPA / WPA2 non funzionano ... dopo ore di tentativi ho trovato quello che ti perdi:

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

è RICHIESTO per le reti WPA !!!!

Ora funziona :)


4

Questa è un'attività che puoi sottoclassare per forzare la connessione a un wifi specifico: https://github.com/zoltanersek/android-wifi-activity/blob/master/app/src/main/java/com/zoltanersek/androidwifiactivity/ WifiActivity.java

Dovrai sottoclassare questa attività e implementarne i metodi:

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 in basso puoi dare quello nuovo?
— Inizia la codifica il

4

Nel livello API 29, il WifiManager.enableNetwork()metodo è obsoleto . Come da documentazione API Android (controlla qui ):

  1. Vedi WifiNetworkSpecifier.Builder # build () per un nuovo meccanismo per attivare la connessione a una rete Wi-Fi.
  2. Vedi addNetworkSuggestions (java.util.List), removeNetworkSuggestions (java.util.List) per la nuova API per aggiungere reti Wi-Fi da tenere in considerazione durante la connessione automatica al wifi. Nota di compatibilità: per le applicazioni destinate a Build.VERSION_CODES.Q o versioni successive, questa API restituirà sempre false.

Dal livello API 29, per collegarti alla rete WiFi, dovrai utilizzare WifiNetworkSpecifier. Puoi trovare il codice di esempio su https://developer.android.com/reference/android/net/wifi/WifiNetworkSpecifier.Builder.html#build ()


È possibile connettersi a una rete WEP con il nuovo WifiNetWorkSpecifier.Builder? Non riesco a trovare un metodo per aggiungere una passphrase WEP al builder.
— Dieter27

Il numero 1 sembra non funzionare c'è qualche richiamata ad esso?
— Faizan Mir,

1

Ho anche provato a connettermi alla rete. Nessuna delle soluzioni proposte sopra funziona per hugerock t70. Funzione wifiManager.disconnect (); non si disconnette dalla rete corrente. Pertanto, non è possibile riconnettersi alla rete specificata. Ho modificato il codice sopra. Per me il codice bolow funziona perfettamente:

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

Ottengo un errore 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

Prova questo metodo. È molto facile:

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;
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.