Поиск сетей Wi‑Fi

Вы можете использовать возможности сканирования Wi-Fi, предоставляемые WifiManager API, чтобы получить список точек доступа Wi-Fi, видимых с устройства.

Процесс сканирования Wi-Fi

Процесс сканирования состоит из трех этапов:

  1. Зарегистрируйте прослушиватель широковещательной рассылки для SCAN_RESULTS_AVAILABLE_ACTION. Он вызывается, когда запросы на сканирование завершены, и сообщает об их статусе (успешно или нет). На устройствах с Android 10 (уровень API 29) и более поздними версиями эта трансляция будет отправляться при любом полном сканировании Wi-Fi, выполняемом на устройстве платформой или другими приложениями. Приложения могут пассивно прослушивать все завершенные сканирования на устройстве, используя трансляцию, без необходимости запускать собственное сканирование.

  2. Запросите сканирование с помощью WifiManager.startScan(). Обязательно проверьте статус возврата метода, так как вызов может завершиться ошибкой по любой из следующих причин:

    • Запросы на сканирование могут быть ограничены из-за слишком большого количества сканирований за короткое время.
    • Устройство бездействует, и сканирование отключено.
    • Аппаратное обеспечение Wi-Fi сообщает о сбое сканирования.
  3. Получите результаты сканирования с помощью WifiManager.getScanResults(). Возвращаются результаты последнего сканирования. Если текущее сканирование не завершено или не выполнено, это могут быть результаты предыдущего сканирования. Это означает, что если вы вызовете этот метод до получения успешной трансляции SCAN_RESULTS_AVAILABLE_ACTION, то можете получить устаревшие результаты сканирования.

В следующем примере кода показано, как выполнить эти шаги:

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 ...
}

Ограничения

В Android 8.0 (уровень API 26) были введены ограничения на разрешения и частоту сканирования сетей Wi-Fi.

Чтобы повысить производительность сети, безопасность и время работы от батареи, в Android 9 (уровень API 28) были ужесточены требования к разрешениям и ограничена частота сканирования сетей Wi-Fi.

Разрешения

Android 8.0 и Android 8.1:

Для успешного вызова WifiManager.getScanResults() требуется любое из следующих разрешений:

Если у приложения для звонков нет ни одного из этих разрешений, вызов завершается ошибкой SecurityException.

На устройствах с Android 8.0 (уровень API 26) и более поздних версий можно использовать CompanionDeviceManager, чтобы сканировать находящиеся поблизости дополнительные устройства от имени приложения, не запрашивая доступ к данным о местоположении. Подробнее о подключении дополнительных устройств…

Android 9:

Чтобы вызов WifiManager.startScan() был успешным, должны быть выполнены все следующие условия:

  • В вашем приложении используется разрешение ACCESS_FINE_LOCATION или ACCESS_COARSE_LOCATION.
  • В вашем приложении используется разрешение CHANGE_WIFI_STATE.
  • На устройстве включены сервисы геолокации (Настройки > Местоположение).

Android 10 (уровень API 29) и более поздние версии:

Чтобы вызов WifiManager.startScan() был успешным, должны быть выполнены все следующие условия:

  • Если приложение предназначено для Android 10 (уровень API 29) SDK или более поздней версии, у него есть разрешение ACCESS_FINE_LOCATION.
  • Если ваше приложение предназначено для SDK ниже Android 10 (уровень API 29), у него есть разрешение ACCESS_COARSE_LOCATION или ACCESS_FINE_LOCATION.
  • В вашем приложении используется разрешение CHANGE_WIFI_STATE.
  • На устройстве включены сервисы геолокации (Настройки > Местоположение).

Чтобы успешно вызвать WifiManager.getScanResults(), убедитесь, что выполняются все следующие условия:

  • Если приложение предназначено для Android 10 (уровень API 29) SDK или более поздней версии, у него есть разрешение ACCESS_FINE_LOCATION.
  • Если целевой уровень SDK ниже, чем у Android 10 (уровень API 29), у приложения есть разрешение ACCESS_COARSE_LOCATION или ACCESS_FINE_LOCATION.
  • В вашем приложении используется разрешение ACCESS_WIFI_STATE.
  • На устройстве включены сервисы геолокации (Настройки > Местоположение).

Если приложение для звонков не соответствует всем этим требованиям, вызов завершается с ошибкой SecurityException.

Ограничение

На частоту сканирования с помощью WifiManager.startScan() накладываются следующие ограничения:

Android 8.0 и Android 8.1:

Каждое фоновое приложение может выполнять сканирование один раз в 30 минут.

Android 9:

Каждое активное приложение может выполнять сканирование четыре раза за двухминутный период. Это позволяет выполнить серию сканирований за короткое время.

Все фоновые приложения могут выполнить одно сканирование за 30 минут.

Android 10 и более поздние версии:

Применяются те же ограничения, что и в Android 9. Для локального тестирования можно отключить ограничение частоты сканирования в настройках для разработчиков (Для разработчиков > Сети > Ограничение частоты сканирования Wi-Fi).