Como faço para conectar-me a uma rede Wi-Fi específica no Android programaticamente?

294

Quero criar um aplicativo que mostre uma lista de redes Wi-Fi disponíveis e conecte-se à rede que for selecionada pelo usuário.

Eu implementei a parte que mostra os resultados da verificação. Agora, quero conectar-me a uma rede específica selecionada pelo usuário na lista de resultados da verificação.

Como eu faço isso?

Vikram Gupta
fonte

Respostas:

441

Você precisa criar uma WifiConfigurationinstância 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

Então, para a rede WEP, você precisa fazer o seguinte:

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

Para rede WPA, você precisa adicionar uma senha como esta:

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

Para rede aberta, você precisa fazer o seguinte:

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

Em seguida, você precisa adicioná-lo às configurações do gerenciador de wifi do Android:

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

E, finalmente, pode ser necessário ativá-lo, para que o Android se conecte a ele:

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: No caso de WEP, se sua senha estiver em hexadecimal, não será necessário cercá-la entre aspas.

kenota
fonte
5
isso funciona bem! obrigado :) mas mais uma coisa que gostaria de perguntar. Você não precisa definir o allowedPairwiseCipher, allowedAuthALgorithms e allowedProtocols? E como decidir qual atributo específico definir; como você configurou o WEP40 para GroupCipher para redes WEP?
Vikram Gupta
8
Eu esqueci de mencionar uma coisa. No caso de WEP, se sua senha estiver em hexadecimal, você não precisará cercá-la entre aspas.
Kenota
8
Obrigado pela ótima solução, você pode elaborar como verificar se a conexão foi bem-sucedida ou não. Por exemplo, o usuário pode digitar a senha incorreta e deve ser notificado sobre ela.
Pascal Klein
3
Que tal se o Hotspot Wifi desejado não usar nenhuma senha ... Devemos usar o .preSharedKey = null; ou devemos definir .preSharedKey = ""; Qual deles está correto? @kenota
gumuruh
6
Ele não funciona para mim: ele se reconecta diretamente ao wifi lembrado anterior em vez de se conectar ao novo.
precisa saber é o seguinte
138

A resposta anterior funciona , mas a solução pode realmente ser mais simples. Não é necessário fazer um loop na lista de redes configuradas, pois você obtém o ID da rede ao adicionar a rede através do WifiManager.

Portanto, a solução completa e simplificada ficaria assim:

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();
loyola sean
fonte
1
se a senha não for usada. Devemos colocar .preSharedKey = null; ou devemos simplesmente colocar uma string vazia, @seanloyola?
Gumuruh 19/07
2
@MuhammedRefaat você desconecta caso já esteja conectado a outra rede.
sean loyola
1
@ gumuruh, você não precisa incluir o objeto presharedkey se não houver uma chave necessária.
sean loyola
7
de acordo com o javadoc de enableNetwork, se você usar disableOthers boolean verdade, então você não tem que desligar ou ligar, ele vai fazer as duas coisas para você
NikkyD
12
Provavelmente deve mencionar que a CHANGE_WIFI_STATEpermissão é necessária.
ThomasW 27/05
27

Antes de conectar a rede WIFI, é necessário verificar o tipo de segurança da classe ScanResult da rede WIFI. Este campo fornece o tipo de rede

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

Existem três tipos de redes Wi-Fi.

Primeiro, instancie um objeto WifiConfiguration e preencha o SSID da rede (observe que ele deve estar entre aspas duplas), defina o estado inicial como desativado e especifique a prioridade da rede (números em torno de 40 parecem funcionar bem).

WifiConfiguration wfc = new WifiConfiguration();

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

Agora, a parte mais complicada: precisamos preencher vários membros do WifiConfiguration para especificar o modo de segurança da rede. Para redes abertas.

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 usando WEP; observe que a chave WEP também está entre aspas duplas.

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 usam WPA e WPA2, podemos definir os mesmos valores para ambos.

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 adicionar a rede à lista conhecida do 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
fonte
uma nota de prioridade, nos meus números de telefone cerca de 4000 funcionaram. provável melhor para fazer essa parte um pouco mais dinâmico (iterate existente configurações etc)
Sam
Como eu poderia obter o tipo de segurança da rede de SSID para wifi ScanResult
shantanu
@ Shantanu verifique a seguir para obter detalhes. stackoverflow.com/questions/6866153/…
Kalpesh Gohel
Nos dispositivos Samsung, a senha é uma string com hash. E o código não funciona. Você confere isso?
Nguyen Minh Binh
você pode fornecer uma amostra para conectar o EAP do tipo sim wifi?
Prashanth Debbadwar
19

Crédito para @ raji-ramamoorthi & @kenota

A solução que funcionou para mim é a combinação dos colaboradores acima neste tópico.

Chegar ScanResultaqui é o 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();
            }
        };

Aviso aos unregisterlo em onPause& onStopviver estaunregisterReceiver(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
fonte
5

Se o seu dispositivo conhece as configurações Wifi (já armazenadas), podemos ignorar a ciência dos foguetes. Basta percorrer as configurações e verificar se o SSID está correspondendo. Nesse caso, conecte e retorne .

Defina permissões:

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

Quebrei a cabeça para entender por que suas respostas para o WPA / WPA2 não funcionam ... depois de horas de tentativas, encontrei o que está faltando:

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

É NECESSÁRIO para redes WPA !!!!

Agora, funciona :)

Taras Okunev
fonte
4

Esta é uma atividade que você pode subclassificar para forçar a conexão a um wifi específico: https://github.com/zoltanersek/android-wifi-activity/blob/master/app/src/main/java/com/zoltanersek/androidwifiactivity/ WifiActivity.java

Você precisará subclassificar esta atividade e implementar seus 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
fonte
link down você pode dar o novo?
fácil
4

No nível 29 da API, o WifiManager.enableNetwork()método está obsoleto . De acordo com a documentação da API do Android (confira aqui ):

  1. Consulte WifiNetworkSpecifier.Builder # build () para obter um novo mecanismo para acionar a conexão a uma rede Wi-Fi.
  2. Consulte addNetworkSuggestions (java.util.List), removeNetworkSuggestions (java.util.List) para obter uma nova API para adicionar redes Wi-Fi para consideração ao se conectar automaticamente ao wifi. Nota de compatibilidade: Para aplicativos direcionados ao Build.VERSION_CODES.Q ou superior, essa API sempre retornará false.

No nível 29 da API, para conectar-se à rede Wi-Fi, você precisará usar WifiNetworkSpecifier. Você pode encontrar um exemplo de código em https://developer.android.com/reference/android/net/wifi/WifiNetworkSpecifier.Builder.html#build ()

VIjay J
fonte
É possível conectar-se a uma rede WEP com o novo WifiNetWorkSpecifier.Builder? Não consigo encontrar um método para adicionar uma senha WEP ao construtor.
Dieter27
O número 1 parece não funcionar. Existe algum retorno de chamada?
Faizan Mir
1

Eu também tentei me conectar à rede. Nenhuma das soluções propostas acima funciona para o hugerock t70. Função wifiManager.disconnect (); não desconecta da rede atual. Portanto, não é possível reconectar-se à rede especificada. Eu modifiquei o código acima. Para mim, o código bolow funciona perfeitamente:

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
fonte
Recebo um erro no 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

Tente este método. É muito 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
fonte