Вы можете использовать возможности сканирования Wi-Fi, предоставляемые API WifiManager, чтобы получить список точек доступа Wi-Fi, которые видны с устройства.
Процесс сканирования Wi-Fi
Процесс сканирования состоит из трех этапов:
Зарегистрируйте прослушиватель трансляции для
SCAN_RESULTS_AVAILABLE_ACTION
, который вызывается при завершении запросов сканирования, предоставляя их статус успеха/неудачи. Для устройств под управлением Android 10 (уровень API 29) и выше эта трансляция будет отправляться для любого полного сканирования Wi-Fi, выполняемого на устройстве платформой или другими приложениями. Приложения могут пассивно прослушивать все завершения сканирования на устройстве, используя трансляцию, не запуская собственное сканирование.Запросите сканирование с помощью
WifiManager.startScan()
. Обязательно проверьте возвращаемый статус метода, так как вызов может завершиться неудачей по любой из следующих причин:- Запросы на сканирование могут быть ограничены из-за слишком большого количества сканирований за короткий промежуток времени.
- Устройство находится в режиме ожидания, сканирование отключено.
- Оборудование Wi-Fi сообщает об ошибке сканирования.
Получите результаты сканирования с помощью
WifiManager.getScanResults()
. Возвращенные результаты сканирования являются последними обновленными результатами, которые могут быть из предыдущего сканирования, если ваше текущее сканирование не было завершено или прошло успешно. Это означает, что вы можете получить более старые результаты сканирования, если вызовете этот метод до получения успешной трансляцииSCAN_RESULTS_AVAILABLE_ACTION
.
Следующий код демонстрирует пример реализации этих шагов:
Котлин
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 ... }
Ява
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
для сканирования близлежащих сопутствующих устройств от имени вашего приложения без запроса разрешения на местоположение. Подробнее об этой опции см. в разделе Сопряжение сопутствующих устройств .
Андроид 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 минут.
Андроид 9:
Каждое фоновое приложение может сканировать четыре раза в течение 2-минутного периода. Это позволяет проводить серию сканирований за короткое время.
Все фоновые приложения вместе взятые могут выполнять сканирование один раз в 30 минут.
Android 10 и выше:
Действуют те же ограничения по регулированию, что и в Android 9. Появилась новая опция разработчика, позволяющая отключить регулирование для локального тестирования (в разделе «Параметры разработчика» > «Сеть» > «Регулирование сканирования Wi-Fi» ).