API de sugerencias de Wi-Fi para la conectividad a Internet

Los dispositivos que ejecutan Android 10 (nivel de API 29) y versiones posteriores permiten que tu app agregue credenciales de red para que un dispositivo se conecte automáticamente a un punto de acceso Wi-Fi. Puedes proporcionar sugerencias para la red a la que deseas conectarte mediante WifiNetworkSuggestion. En última instancia, la plataforma elige qué punto de acceso aceptar en función de la entrada de tu app y de otras.

En Android 11 (nivel de API 30) y versiones posteriores, haz lo siguiente:

  • El framework aplica los requisitos de propiedad para las sugerencias empresariales basadas en EAP-SIM (EAP-SIM, EAP-AKA, EAP-AKA-PRIME). Solo las apps firmadas por el operador permiten estas sugerencias.
  • Para las sugerencias que proporciona una app firmada por un proveedor, el framework les asigna automáticamente un ID de operador que corresponde a la firma del proveedor de la app. Estas sugerencias se inhabilitan automáticamente si se quita la SIM correspondiente del dispositivo.

En Android 12 (nivel de API 31) y versiones posteriores, haz lo siguiente:

  • Se puede habilitar una privacidad adicional mediante la aleatorización de MAC no persistente, que periódicamente vuelve a aleatorizar la dirección MAC aleatoria. Usa setMacRandomizationSetting para especificar el nivel de aleatorización de tu red.

  • isPasspointTermsAndConditionsSupported():Términos y condiciones es una función de Passpoint que permite que las implementaciones de redes reemplacen portales cautivos no seguros, que usan redes abiertas, por una red segura de Passpoint. Se le muestra una notificación al usuario cuando debe aceptar términos y condiciones. Las apps que sugieren redes de Passpoint que están restringidas por términos y condiciones deben llamar primero a esta API para asegurarse de que el dispositivo admita la función. Si el dispositivo no la admite, no podrá conectarse a esta red, y se sugerirá una red alternativa o heredada.

  • isDecoratedIdentitySupported(): Cuando te autenticas en redes extendidas con un prefijo, el prefijo con identidad extendido permite que los operadores de red actualicen el identificador de acceso a la red (NAI) para realizar el enrutamiento explícito a través de varios proxies dentro de una red AAA (consulta RFC 7542 para obtener más información al respecto).

    Android 12 implementa esta función a fin de cumplir con la especificación de WBA para extensiones PPS-MO. Las apps que sugieren redes de Passpoint que requieren una identidad extendida deben llamar primero a esta API para asegurarse de que el dispositivo admita la función. Si el dispositivo no la admite, la identidad no se extenderá, y es posible que falle la autenticación en la red.

Para crear una sugerencia de Passpoint, las apps deben usar las clases PasspointConfiguration, Credential y HomeSp. Estas clases describen el perfil de Passpoint, que se define en la especificación de Passpoint de Wi-Fi Alliance.

En la siguiente muestra de código, se indica cómo proporcionar credenciales para una red abierta, una WPA2, una WPA3 y una de 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);

Inmediatamente después de que la app coloca una sugerencia por primera vez, se notifica al usuario. El tipo de notificación depende de la versión de Android que se ejecuta en el dispositivo:

  • En Android 11 (nivel de API 30) y versiones posteriores, el usuario ve un diálogo si la app se está ejecutando en primer plano y una notificación si se está ejecutando en segundo plano.
  • En Android 10 (nivel de API 29), el usuario ve una notificación, independientemente de si la app se está ejecutando en primer o segundo plano.

Cuando la plataforma se conecta a una de las sugerencias de red, la configuración muestra un texto que atribuye la conexión de red a la app de sugerencia correspondiente.

Cómo administrar desconexiones del usuario

Si el usuario utiliza el selector de Wi-Fi para desconectarse explícitamente de una de las sugerencias de red cuando se conecta a ella, esa red se ignora cuando aún se encuentra dentro del alcance. Durante este período, esa red no se considerará para la conexión automática, incluso si la app quita y vuelve a agregar la sugerencia de red correspondiente a la red. Si el usuario utiliza el selector de Wi-Fi para conectarse de forma explícita a una red que se desconectó anteriormente, esa red se considerará para la conexión automática de inmediato.

Cómo cambiar el estado de autorización para una app

Un usuario que rechaza la notificación de sugerencia de red quita el permiso CHANGE_WIFI_STATE de la app. Para otorgar esta aprobación más adelante, debe ir al menú de control de Wi-Fi (Configuración > Apps y notificaciones > Acceso especial de apps > Control de Wi-Fi > App name).