API Android para se conectar à rede Wifi

Sep 14 2020

Estou totalmente perdido nas versões das APIs WiFi. Desejo me conectar a uma rede WiFi configurada de forma programática. Conforme descrito nesta pergunta: Conecte-se à rede wi-fi Android de maneira programática

Eu desenvolvo no Android 10 e quero escrever um código que também seja compatível com versões anteriores do Android.

No meu android 10, o código descrito não funciona. Qual código eu preciso para implementar a funcionalidade no Android 10?

O que devo fazer para escrever um aplicativo que também pode ser executado em meu outro telefone Android 9?

Atenciosamente Jürgen

Respostas

matdev Sep 14 2020 at 13:06

Aqui está uma solução que funciona a partir do Android 6 (API de nível 23)

String AP_SSID = "YourWifiNetworkSSID";
String AP_PASSWORD = "YourWifiNetworkPassword";
wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);

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

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

wifiManager.addNetwork(conf);

try {
    List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();

    for (WifiConfiguration i : list) {
        if (i.SSID != null && i.SSID.equals("\"" + AP_SSID + "\"")) {
            wifiManager.disconnect();
            wifiManager.enableNetwork(i.networkId, true);
            wifiManager.reconnect();

            break;
        }
    }
 } catch (SecurityException e) {
     Log.e(TAG, e.getMessage()); 
 }
MdImtiazHossain Nov 18 2020 at 09:17

No Android Q, a conexão com a rede Wifi mudou muito.

Primeiro de tudo o código que você está usando ou @matdev mencionado usos API public int addNetwork (WifiConfiguration config)de WifiManagerestá obsoleta no Android 10 e retornará -1 como NETWORKID.

No Android Q, duas classes são sugeridas para conexão Wifi. Mas cada um deles tem suas próprias vantagens e desvantagens.

1. WifiNetworkSpecifier

Um exemplo de código da Biblioteca WifiUtil

WifiNetworkSpecifier.Builder wifiNetworkSpecifierBuilder = new WifiNetworkSpecifier.Builder()
            .setSsid(scanResult.SSID)
            .setBssid(MacAddress.fromString(scanResult.BSSID));

    final String security = ConfigSecurities.getSecurity(scanResult);

    ConfigSecurities.setupWifiNetworkSpecifierSecurities(wifiNetworkSpecifierBuilder, security, password);


    NetworkRequest networkRequest = new NetworkRequest.Builder()
            .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
            .setNetworkSpecifier(wifiNetworkSpecifierBuilder.build())
            .build();

    // not sure, if this is needed
    if (networkCallback != null) {
        connectivityManager.unregisterNetworkCallback(networkCallback);
    }

    networkCallback = new ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(@NonNull Network network) {
            super.onAvailable(network);

            wifiLog("AndroidQ+ connected to wifi ");

            // bind so all api calls are performed over this new network
            connectivityManager.bindProcessToNetwork(network);
        }

        @Override
        public void onUnavailable() {
            super.onUnavailable();

            wifiLog("AndroidQ+ could not connect to wifi");
        }
    };

    connectivityManager.requestNetwork(networkRequest, networkCallback);

Minha observação com esta implementação é - é mais como comunicação P2P, e neste momento outro aplicativo do mesmo dispositivo não pode usar a Internet da rede WiFi conectada

2. WifiNetworkSuggestion 

Um exemplo de código de developer.android.com

final WifiNetworkSuggestion suggestion1 =
  new WifiNetworkSuggestion.Builder()
  .setSsid("test111111")
  .setIsAppInteractionRequired(true) // Optional (Needs location permission)
  .build();

final WifiNetworkSuggestion suggestion2 =
  new WifiNetworkSuggestion.Builder()
  .setSsid("test222222")
  .setWpa2Passphrase("test123456")
  .setIsAppInteractionRequired(true) // Optional (Needs location permission)
  .build();

final WifiNetworkSuggestion suggestion3 =
  new WifiNetworkSuggestion.Builder()
  .setSsid("test333333")
  .setWpa3Passphrase("test6789")
  .setIsAppInteractionRequired(true) // Optional (Needs location permission)
  .build();

final PasspointConfiguration passpointConfig = new PasspointConfiguration();
// configure passpointConfig to include a valid Passpoint configuration

final WifiNetworkSuggestion suggestion4 =
  new WifiNetworkSuggestion.Builder()
  .setPasspointConfig(passpointConfig)
  .setIsAppInteractionRequired(true) // Optional (Needs location permission)
  .build();

final List<WifiNetworkSuggestion> suggestionsList =
  new ArrayList<WifiNetworkSuggestion> {{
    add(suggestion1);
    add(suggestion2);
    add(suggestion3);
    add(suggestion4);
  }};

final WifiManager wifiManager =
  (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

final int status = wifiManager.addNetworkSuggestions(suggestionsList);
if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
// do error handling here…
}

// Optional (Wait for post connection broadcast to one of your suggestions)
final IntentFilter intentFilter =
  new IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);

final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    if (!intent.getAction().equals(
      WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
      return;
    }
    // do post connect processing here...
  }
};
context.registerReceiver(broadcastReceiver, intentFilter);

Minha observação com a implementação mencionada acima é, quando você chama o wifiManager.addNetworkSuggestionsretorno de sucesso e mostra ao usuário uma notificação para conexão. Se o usuário aceitar, o dispositivo será conectado à rede WiFi e outro aplicativo poderá usar a Internet. Mas se o usuário se desconectar da rede e você ligar wifiManager.addNetworkSuggestionsnovamente, ele retornará um WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATEerro.

Parece que esta API fornece apenas uma lista de sugestões de redes onde o dispositivo pode se conectar automaticamente. Mas a conexão será determinada pelo sistema operacional.

Mas se você realmente precisa de uma solução, use uma forma não documentada para o scanner de código QR padrão Wifi da fonte Android que pode detectar esquemas de código QR Zxing e DPP.

aqui está um exemplo de código:

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if(requestCode == REQUEST_CODE_WIFI_QR_SCANNER && resultCode == RESULT_OK)
    {
        //WIFI Connection is Successful
    }
    else
    {
        //.......
    }
}

@RequiresApi(api = Build.VERSION_CODES.Q)
private void startWifiQRCodeScanner(Context context)
{
    final String INTENT_ACTION_WIFI_QR_SCANNER = "android.settings.WIFI_DPP_ENROLLEE_QR_CODE_SCANNER";
    WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

    if(wifiManager.isEasyConnectSupported())
    {
        final Intent intent = new Intent(INTENT_ACTION_WIFI_QR_SCANNER);
        startActivityForResult(intent, REQUEST_CODE_WIFI_QR_SCANNER);
    }
}