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

Puedes usar las funciones de búsqueda de Wi-Fi que proporciona la API de WifiManager para obtener una lista de los puntos de acceso Wi-Fi que son visibles desde el dispositivo.

Proceso de búsqueda Wi-Fi

El proceso de búsqueda consta de tres pasos:

  1. Registra un objeto de escucha de transmisión para SCAN_RESULTS_AVAILABLE_ACTION, que se envía cuando se completan las solicitudes de análisis, lo que proporciona su estado de éxito o falla. 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. Solicita un análisis con WifiManager.startScan(). Asegúrate de verificar el estado de devolución del método, ya que la llamada podría fallar por cualquiera de los siguientes motivos:

    • Es posible que las solicitudes de análisis se limiten debido a que se realizaron demasiados análisis en un período breve.
    • El dispositivo está inactivo y la búsqueda está inhabilitada.
    • El hardware Wi-Fi informa acerca de un error de búsqueda.
  3. Obtén los resultados del análisis con WifiManager.getScanResults(). Los resultados del análisis que se muestran son los resultados actualizados más recientemente, que pueden ser de un análisis anterior si el análisis actual no se completó o no se realizó correctamente. Esto significa que podrías obtener resultados de análisis más antiguos si llamas a este método antes de recibir una transmisión SCAN_RESULTS_AVAILABLE_ACTION correcta.

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 (nivel de API 26) y Android 8.1 (nivel de API 27):

Una llamada correcta a WifiManager.getScanResults() 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 que ejecutan Android 8.0 (nivel de API 26) y versiones posteriores, puedes usar el CompanionDeviceManager para realizar un análisis de los dispositivos complementarios cercanos en nombre de tu app sin requerir el permiso de ubicación. Para obtener más información sobre esta opción, consulta Vinculación de dispositivos complementarios.

Android 9 (nivel de API 28):

Una llamada correcta a WifiManager.startScan() requiere que se cumplan todas las siguientes condiciones:

  • Tu app tiene el permiso ACCESS_FINE_LOCATION o ACCESS_COARSE_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).

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

Para que una llamada a WifiManager.startScan() se realice correctamente, se deben cumplir todas las siguientes 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 a WifiManager.getScanResults() correctamente, asegúrate de que se cumplan todas las siguientes 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 de llamadas no cumple con todos estos requisitos, la llamada fallará con un error 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. Hay una nueva opción para desarrolladores que permite desactivar la limitación para las pruebas locales (en Opciones para desarrolladores > Redes > Limitación de búsqueda de Wi-Fi).