Поиск сетей 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 (уровень API 26) и Android 8.1 (уровень API 27)

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

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

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

Android 9 (уровень API 28):

Для успешного вызова 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 можно отключить ограничение для локального тестирования.