¿Cómo me conecto a una red Wi-Fi específica en Android mediante programación?

294

Quiero diseñar una aplicación que muestre una lista de redes Wi-Fi disponibles y conectarse a la red que seleccione el usuario.

He implementado la parte que muestra los resultados del escaneo. Ahora quiero conectarme a una red particular seleccionada por el usuario de la lista de resultados de escaneo.

¿Cómo hago esto?

Vikram Gupta
fuente

Respuestas:

441

Necesita crear una WifiConfigurationinstancia como esta:

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

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

Luego, para la red WEP, debe hacer esto:

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

Para la red WPA, debe agregar una frase de contraseña como esta:

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

Para la red abierta, debe hacer esto:

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

Luego, debe agregarlo a la configuración del administrador de wifi de Android:

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

Y finalmente, es posible que deba habilitarlo, por lo que Android se conecta a él:

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: en el caso de WEP, si su contraseña está en hexadecimal, no necesita rodearla con comillas.

kenota
fuente
55
eso funciona bien! gracias :) pero una cosa más que me gustaría preguntar. ¿No necesita establecer el valor de PairPairwise enabled, allowAuthALgorithms y allowProtocols? Y cómo decidir qué atributo particular establecer; ¿Cómo configurar WEP40 para GroupCipher para redes WEP?
Vikram Gupta
8
Olvidé mencionar una cosa. En el caso de WEP, si su contraseña está en hexadecimal, no necesita rodearla con comillas.
kenota
8
Gracias por la buena solución, ¿podría explicar cómo verificar si la conexión fue exitosa o no? Por ejemplo, el usuario puede ingresar la contraseña incorrecta y se le debe notificar al respecto.
Pascal Klein
3
¿qué tal si el punto de acceso Wifi deseado no usa ninguna contraseña en absoluto ... ¿Deberíamos usar .preSharedKey = null; o deberíamos establecer .preSharedKey = ""; ¿Cuál es el correcto? @kenota
gumuruh
66
No funciona para mí: se conecta de nuevo directamente al wifi recordado anterior en lugar de conectarse al nuevo.
Virthuss
138

La respuesta anterior funciona , pero la solución en realidad puede ser más simple. No es necesario recorrer la lista de redes configuradas ya que obtiene la identificación de red cuando agrega la red a través del WifiManager.

Entonces, la solución completa y simplificada se vería así:

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
fuente
1
si no se usa la contraseña ¿Deberíamos poner .preSharedKey = null; ¿O deberíamos poner una cadena vacía, @seanloyola?
gumuruh
2
@MuhammedRefaat se desconecta en caso de que ya esté conectado a otra red.
sean loyola
1
@gumuruh no tiene que incluir el objeto presharedkey si no se requiere una clave.
sean loyola
77
De acuerdo con el javadoc de enableNetwork, si usa boolean disableOthers true, entonces no tiene que desconectarse o conectarse, lo hará por usted
NikkyD
12
Probablemente debería mencionar que CHANGE_WIFI_STATEse necesita el permiso.
ThomasW
27

Antes de conectar la red WIFI, debe verificar el tipo de seguridad de la red WIFI. La clase ScanResult tiene capacidades. Este campo te da el tipo de red

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

Hay tres tipos de redes WIFI.

Primero, cree una instancia de un objeto WifiConfiguration y complete el SSID de la red (tenga en cuenta que debe estar entre comillas dobles), configure el estado inicial en deshabilitado y especifique la prioridad de la red (los números alrededor de 40 parecen funcionar bien).

WifiConfiguration wfc = new WifiConfiguration();

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

Ahora para la parte más complicada: necesitamos llenar varios miembros de WifiConfiguration para especificar el modo de seguridad de la red. Para redes abiertas.

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

Para redes que utilizan WEP; tenga en cuenta que la clave WEP también se incluye entre comillas dobles.

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;

Para redes que usan WPA y WPA2, podemos establecer los mismos valores para cualquiera.

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

Finalmente, podemos agregar la red a la lista conocida de 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
fuente
Una nota sobre la prioridad, en mis números de teléfono alrededor de 4000 funcionó. probablemente lo mejor para hacer que esa parte sea un poco más dinámica (iterar configuraciones existentes, etc.)
Sam
¿Cómo podría obtener el tipo de seguridad de red de SSID para wifi ScanResult
Shantanu
@shantanu revise lo siguiente para más detalles. stackoverflow.com/questions/6866153/…
Kalpesh Gohel el
En los dispositivos Samsung, la frase de contraseña es una cadena hash. Y el código no funciona. ¿Lo revisas?
Nguyen Minh Binh
¿Puede proporcionar una muestra para conectar EAP de wifi tipo sim?
Prashanth Debbadwar
19

Crédito a @ raji-ramamoorthi y @kenota

La solución que funcionó para mí es la combinación de los contribuyentes anteriores en este hilo.

Llegar ScanResultaquí es el proceso.

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

Aviso para unregisterello onPausey onStopvive estounregisterReceiver(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
fuente
5

Si su dispositivo conoce las configuraciones de Wifi (ya almacenadas), podemos evitar la ciencia de cohetes. Simplemente recorra las configuraciones y verifique si el SSID coincide. Si es así, conéctese y regrese .

Establecer permisos:

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

Conectar:

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

Me rompí la cabeza para entender por qué sus respuestas para WPA / WPA2 no funcionan ... después de horas de intentos encontré lo que se está perdiendo:

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

se REQUIERE para redes WPA !!!!

Ahora funciona :)

Taras Okunev
fuente
4

Esta es una actividad que puede subclasificar para forzar la conexión a un wifi específico: https://github.com/zoltanersek/android-wifi-activity/blob/master/app/src/main/java/com/zoltanersek/androidwifiactivity/ WifiActivity.java

Deberá subclasificar esta actividad e implementar sus métodos:

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
fuente
enlace abajo ¿puedes dar el nuevo?
StartCoding
4

En el nivel de API 29, el WifiManager.enableNetwork()método está en desuso . Según la documentación de la API de Android (marque aquí ):

  1. Consulte WifiNetworkSpecifier.Builder # build () para conocer el nuevo mecanismo para activar la conexión a una red Wi-Fi.
  2. Consulte addNetworkSuggestions (java.util.List), removeNetworkSuggestions (java.util.List) para obtener una nueva API para agregar redes Wi-Fi para su consideración al conectarse automáticamente a wifi. Nota de compatibilidad: para aplicaciones dirigidas a Build.VERSION_CODES.Q o superior, esta API siempre devolverá false.

Desde el nivel de API 29, para conectarse a la red WiFi, deberá usar WifiNetworkSpecifier. Puede encontrar un código de ejemplo en https://developer.android.com/reference/android/net/wifi/WifiNetworkSpecifier.Builder.html#build ()

VIjay J
fuente
¿Es posible conectarse a una red WEP con el nuevo WifiNetWorkSpecifier.Builder? No puedo encontrar un método para agregar una frase de contraseña WEP al generador.
Dieter27
El número 1 no parece funcionar, ¿hay alguna devolución de llamada?
Faizan Mir
1

También intenté conectarme a la red. Ninguna de las soluciones propuestas anteriormente funciona para hugerock t70. Función wifiManager.disconnect (); no se desconecta de la red actual. Por lo tanto, no puede volver a conectarse a la red especificada. He modificado el código anterior. Para mí, el código bolow funciona perfectamente:

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);
usuario1277317
fuente
Me sale un error en 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

Prueba este método. Es muy fácil:

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
fuente