Únete a ⁠ #Android11: The Beta Launch Show el 3 de junio.

Descripción general de la búsqueda Wi-Fi

Puedes utilizar las funciones de búsqueda Wi-Fi proporcionadas por la API de WifiManager para obtener una lista de puntos de acceso Wi-Fi visibles desde el dispositivo.

Proceso de búsqueda Wi-Fi

El proceso de búsqueda consta de tres pasos:

  1. Registrar un receptor de transmisiones para SCAN_RESULTS_AVAILABLE_ACTION, al que se llama cuando se completan las solicitudes de búsqueda, indicando su estado de éxito o fracaso. Para los dispositivos que ejecutan Android 10 (nivel de API 29) y versiones posteriores, se enviará esta transmisión para cualquier búsqueda Wi-Fi completa que la plataforma u otras apps realicen en el dispositivo. Las apps pueden recibir de forma pasiva todas las finalizaciones de búsqueda en el dispositivo utilizando la transmisión sin emitir una búsqueda propia.

  2. Solicitar una búsqueda usando WifiManager.startScan(). Asegúrate de comprobar el estado de resultado del método, ya que la llamada puede fallar debido a cualquiera de las siguientes razones:

    • Es posible que se limiten las solicitudes de búsqueda debido a demasiadas búsquedas en poco tiempo.
    • El dispositivo está inactivo y la búsqueda está inhabilitada.
    • El hardware Wi-Fi informa acerca de un error de búsqueda.
  3. Obtener los resultados de la búsqueda usando WifiManager.getScanResults(). Los resultados del análisis que se muestran son los actualizados más recientemente, que pueden ser de un análisis anterior si el actual no se completó o no tuvo éxito. Esto significa que puedes obtener resultados de búsqueda más antiguos si llamas a este método antes de recibir una transmisión exitosa de SCAN_RESULTS_AVAILABLE_ACTION.

El siguiente código proporciona un ejemplo de cómo implementar estos pasos:

Kotlin

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

val wifiScanReceiver = object : BroadcastReceiver() {

  override fun onReceive(context: Context, intent: Intent) {
    val success = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false)
    if (success) {
      scanSuccess()
    } else {
      scanFailure()
    }
  }
}

val intentFilter = IntentFilter()
intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
context.registerReceiver(wifiScanReceiver, intentFilter)

val success = wifiManager.startScan()
if (!success) {
  // scan failure handling
  scanFailure()
}

....

private fun scanSuccess() {
  val results = wifiManager.scanResults
  ... use new scan results ...
}

private fun scanFailure() {
  // handle failure: new scan did NOT succeed
  // consider using old scan results: these are the OLD results!
  val results = wifiManager.scanResults
  ... potentially use older scan results ...
}

Java

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

BroadcastReceiver wifiScanReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context c, Intent intent) {
    boolean success = intent.getBooleanExtra(
                       WifiManager.EXTRA_RESULTS_UPDATED, false);
    if (success) {
      scanSuccess();
    } else {
      // scan failure handling
      scanFailure();
    }
  }
};

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
context.registerReceiver(wifiScanReceiver, intentFilter);

boolean success = wifiManager.startScan();
if (!success) {
  // scan failure handling
  scanFailure();
}

....

private void scanSuccess() {
  List<ScanResult> results = wifiManager.getScanResults();
  ... use new scan results ...
}

private void scanFailure() {
  // handle failure: new scan did NOT succeed
  // consider using old scan results: these are the OLD results!
  List<ScanResult> results = wifiManager.getScanResults();
  ... potentially use older scan results ...
}

Restricciones

Android 8.0 (API nivel 26) introdujo restricciones con respecto a los permisos y la frecuencia permitida de las búsquedas Wi-Fi.

Para mejorar el rendimiento de la red, la seguridad y la duración de la batería, Android 9 (API nivel 28) endureció los requisitos de autorización y limitó aún más la frecuencia de las búsquedas Wi-Fi.

Permisos

Android 8.0 y Android 8.1:

Una llamada exitosa a WifiManager.getScanResults() requiere cualquiera de los siguientes permisos:

Si la app emisora no tiene ninguno de ellos, la llamada fallará con un error SecurityException.

Android 9:

Una llamada exitosa a WifiManager.startScan() requiere que se cumplan todas estas condiciones:

Android 10 (nivel de API 29) y versiones posteriores:

Una llamada exitosa a WifiManager.startScan() requiere que se cumplan todas estas condiciones:

  • Si tu app tiene como objetivo el SDK Android 10 (nivel de API 29) o una versión superior, significa que tiene el permiso ACCESS_FINE_LOCATION.
  • Si tu app tiene como objetivo un SDK inferior a Android 10 (nivel de API 29), significa que tiene el permiso ACCESS_COARSE_LOCATION o ACCESS_FINE_LOCATION.
  • Tu app tiene el permiso CHANGE_WIFI_STATE.
  • Los servicios de ubicación están habilitados en el dispositivo (en Configuración > Ubicación).

Para llamar con éxito a WifiManager.getScanResults(), asegúrate de que se cumplan todas estas condiciones:

  • Si tu app tiene como objetivo el SDK Android 10 (nivel de API 29) o una versión superior, significa que tiene el permiso ACCESS_FINE_LOCATION.
  • Si tu app tiene como objetivo un SDK inferior a Android 10 (nivel de API 29), significa que tiene el permiso ACCESS_COARSE_LOCATION o ACCESS_FINE_LOCATION.
  • Tu app tiene el permiso ACCESS_WIFI_STATE.
  • Los servicios de ubicación están habilitados en el dispositivo (en Configuración > Ubicación).

Para llamar con éxito a WifiManager.getScanResults(), asegúrate de que se cumplan todas estas condiciones:

Si la app emisora no cumple con todos estos requisitos, la llamada fallará con un error SecurityException.

Limitación

Las siguientes limitaciones se aplican a la frecuencia de las búsquedas que utilizan WifiManager.startScan().

Android 8.0 y Android 8.1:

Cada app que está en segundo plano puede realizar una búsqueda en un período de 30 minutos.

Android 9:

Cada app que está en primer plano puede realizar cuatro búsquedas en un período de 2 minutos. Esto permite un pico de actividad de búsquedas en poco tiempo.

Todas las apps en segundo plano combinadas pueden realizar una búsqueda en un período de 30 minutos.

Android 10 y versiones posteriores:

Se aplican los mismos límites de restricción que para Android 9. Existe una nueva opción para desarrolladores que permite desactivar el control para pruebas locales (en Opciones para desarrolladores > Redes > Limitación de búsqueda de Wi-Fi).