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

Puedes utilizar las funciones de búsqueda de 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 de 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. En el caso de los dispositivos con Android 10 (API nivel 29) y versiones posteriores, se enviará esta transmisión para cualquier búsqueda de 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 mediante WifiManager.startScan(). Asegúrate de comprobar el estado 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 resultados de la búsqueda con WifiManager.getScanResults(). Los resultados de la búsqueda que se muestran son los actualizados más recientemente, que pueden ser de una búsqueda anterior si la actual no se completó o no se realizó correctamente. Esto significa que puedes obtener resultados de búsqueda más antiguos si llamas a este método antes de recibir una transmisión de SCAN_RESULTS_AVAILABLE_ACTION que se realizó correctamente.

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 de Wi-Fi.

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

Permisos

Android 8.0 y Android 8.1:

Para que una llamada a WifiManager.getScanResults() se realice correctamente, se requiere cualquiera de los siguientes permisos:

Si la app de llamada no tiene ninguno de estos permisos, la llamada falla con una SecurityException.

Como alternativa, en los dispositivos con Android 8.0 (API nivel 26) y versiones posteriores, puedes usar el CompanionDeviceManager para realizar una búsqueda de los dispositivos complementarios cercanos en nombre de tu app sin solicitar permiso de ubicación. Para obtener más información sobre esta opción, consulta Dispositivo complementario de la configuración.

Android 9:

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

Android 10 (API nivel 29) y versiones posteriores:

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

  • Si tu app se orienta al SDK de Android 10 (API nivel 29) o versiones posteriores, tiene el permiso ACCESS_FINE_LOCATION.
  • Si tu app se orienta a un SDK inferior a Android 10 (API nivel 29), 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 correctamente a WifiManager.getScanResults(), asegúrate de que se cumplan todas estas condiciones:

  • Si tu app se orienta al SDK de Android 10 (API nivel 29) o versiones posteriores, tiene el permiso ACCESS_FINE_LOCATION.
  • Si tu app se orienta a un SDK inferior a Android 10 (API nivel 29), 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).

Si la app que realiza la llamada no cumple con todos estos requisitos, la llamada falla con una SecurityException.

Limitación

Se aplican las siguientes limitaciones a la frecuencia de búsquedas mediante WifiManager.startScan().

Android 8.0 y Android 8.1:

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

Android 9:

Cada app 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).