API de sugestão de Wi-Fi para conectividade com a Internet

Dispositivos com o Android 10 (API de nível 29) e versões mais recentes permitem que seu app adicione credenciais de rede para que um dispositivo se conecte automaticamente a um ponto de acesso Wi-Fi. Você pode sugerir a que rede se conectar usando WifiNetworkSuggestion. A plataforma escolhe qual ponto de acesso aceitar com base na entrada do seu app e de outros.

No Android 11 (nível 30 da API) e versões mais recentes:

  • O framework aplica requisitos de propriedade para sugestões do Enterprise baseadas em EAP-SIM (EAP-SIM, EAP-AKA, EAP-AKA-PRIME). Essas sugestões são permitidas apenas por apps assinados pela operadora.
  • Para sugestões fornecidas por um app assinado por operadora, o framework atribui automaticamente a eles um ID de operadora correspondente à assinatura da operadora do app. Essas sugestões serão desativadas automaticamente se o chip correspondente for removido do dispositivo.

No Android 12 (nível 31 da API) e versões mais recentes:

  • A privacidade extra pode ser ativada por meio de ordem aleatória de MAC não persistente, que periodicamente reorganiza aleatoriamente o endereço MAC aleatório. Use setMacRandomizationSetting para especificar o nível de randomização para sua rede.

  • isPasspointTermsAndConditionsSupported(): os Termos e Condições são um recurso do Passpoint que possibilita que as implantações de rede substituam o portal cativo não seguro, que usa redes abertas, por uma rede do Passpoint segura. O usuário recebe uma notificação quando ele for solicitado a aceitar os Termos e Condições. Os apps que sugerem redes de Passpoint controladas por Termos e Condições, precisam chamar essa API primeiro para ter certeza de que o dispositivo é compatível com a funcionalidade. Se o dispositivo não for compatível com o recurso, ele não poderá se conectar a essa rede, e será necessário sugerir uma rede alternativa ou legada.

  • isDecoratedIdentitySupported(): ao autenticar em redes com uma decoração prefixada, o prefixo de identidade decorado possibilita que os operadores de rede atualizem o identificador de acesso à rede (NAI, na sigla em inglês) para executar o roteamento explícito usando vários proxies dentro de uma rede AAA. Consulte RFC 7542 (link em inglês) para saber mais sobre isso.

    O Android 12 implementa esse recurso para estar em conformidade com as especificações da WBA para extensões PPS-MO (link em inglês). Os apps que sugerem redes do Passpoint que exigem uma identidade decorada, precisam chamar essa API primeiro para garantir que dispositivo é compatível com a funcionalidade. Se o dispositivo não for compatível com o recurso, a identidade não será decorada e a autenticação na rede pode falhar.

Para criar uma sugestão de Passpoint, os apps precisam usar as classes PasspointConfiguration, Credential e HomeSp. Essas classes descrevem o perfil do Passpoint, definido na especificação do Passpoint do Wi-Fi Alliance (em inglês).

O exemplo de código a seguir mostra como fornecer credenciais para uma rede aberta, uma WPA2, uma rede WPA3 e uma rede Passpoint:

Kotlin

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

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

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

val passpointConfig = PasspointConfiguration(); // configure passpointConfig to include a valid Passpoint configuration
val suggestion4 = WifiNetworkSuggestion.Builder()
        .setPasspointConfig(passpointConfig)
        .setIsAppInteractionRequired(true) // Optional (Needs location permission)
        .build();

val suggestionsList = listOf(suggestion1, suggestion2, suggestion3, suggestion4);

val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager;

val 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)
val intentFilter = IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);

val broadcastReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (!intent.action.equals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
            return;
        }
        // do post connect processing here
    }
};
context.registerReceiver(broadcastReceiver, intentFilter);

Java

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

Imediatamente após o app fazer uma sugestão pela primeira vez, o usuário é notificado. O tipo de notificação depende da versão do Android em execução no dispositivo:

  • No Android 11 (nível 30 da API) e versões mais recentes, o usuário vai encontrar uma caixa de diálogo se o app estiver em execução em primeiro plano e uma notificação se o app estiver sendo executado em segundo plano.
  • No Android 10 (nível 29 da API), o usuário recebe uma notificação, independente de o app estar sendo executado em primeiro ou segundo plano.

Quando a plataforma se conecta a uma das sugestões de rede, as configurações mostram o texto que atribui a conexão de rede ao app que fez a sugestão correspondente.

Processamento de desconexões do usuário

Se o usuário usar o seletor de Wi-Fi para se desconectar explicitamente de uma das sugestões de rede ao se conectar a ela, essa rede vai ser ignorada quando ainda estiver dentro do alcance. Durante esse período, essa rede não será considerada para conexão automática, mesmo que o app remova e adicione novamente a sugestão de rede correspondente à rede. Se o usuário usar o seletor de Wi-Fi para se conectar explicitamente a uma rede que foi desconectada anteriormente, essa rede será considerada para conexão automática imediatamente.

Alteração do status de aprovação para o aplicativo

Quando um usuário recusa a notificação de sugestão de rede, a permissão CHANGE_WIFI_STATE é removida do app. O usuário pode conceder essa aprovação mais tarde no menu de controle de Wi-Fi (Configurações > Apps e notificações > Acesso especial de apps > Controle de Wi-Fi > App name).