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.