You can use the Wi-Fi scanning capabilities provided by the WifiManager API to get a list of Wi-Fi access points that are visible from the device.
Wi-Fi scanning process
There are three steps to the scanning process:
Register a broadcast listener for
SCAN_RESULTS_AVAILABLE_ACTION, which is sent when scan requests are completed, providing their success or failure status. For devices running Android 10 (API level 29) and higher, this broadcast will be sent for any full Wi-Fi scan performed on the device by the platform or other apps. Apps can passively listen to all scan completions on device by using the broadcast without issuing a scan of their own.Request a scan using
WifiManager.startScan(). Make sure to check the return status of the method, because the call might fail for any of the following reasons:- Scan requests might be throttled because of too many scans in a short time.
- The device is idle and scanning is disabled.
- Wi-Fi hardware reports a scan failure.
Get scan results using
WifiManager.getScanResults(). The returned scan results are the most recently updated results, which might be from a previous scan if your current scan hasn't completed or succeeded. This means that you might get older scan results if you call this method before receiving a successfulSCAN_RESULTS_AVAILABLE_ACTIONbroadcast.
The following code provides an example of how to implement these steps:
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 ...
}
Restrictions
Android 8.0 (API level 26) introduced restrictions regarding permissions and the allowed frequency of Wi-Fi scans.
To improve network performance, security, and battery life, Android 9 (API level 28) tightened permission requirements and further limited the frequency of Wi-Fi scans.
Permissions
Android 8.0 (API level 26) and Android 8.1 (API level 27):
A successful call to WifiManager.getScanResults() requires any one of the
following permissions:
If the calling app does not have any of these permissions, the call fails with a
SecurityException.
Alternatively, on devices running Android 8.0 (API level 26) and higher, you can
use the CompanionDeviceManager to perform a scan of nearby companion devices
on behalf of your app without requiring the location permission. For more on
this option, see Companion device pairing.
Android 9 (API level 28):
A successful call to WifiManager.startScan() requires all of the following
conditions to be met:
- Your app has the
ACCESS_FINE_LOCATIONorACCESS_COARSE_LOCATIONpermission. - Your app has the
CHANGE_WIFI_STATEpermission. - Location services are enabled on the device (under Settings > Location).
Android 10 (API level 29) and higher:
A successful call to WifiManager.startScan() requires all of the following
conditions to be met:
- If your app is targeting Android 10 (API level 29) SDK or higher, your app
has the
ACCESS_FINE_LOCATIONpermission. - If your app is targeting SDK lower than Android 10 (API level 29), your app
has the
ACCESS_COARSE_LOCATIONorACCESS_FINE_LOCATIONpermission. - Your app has the
CHANGE_WIFI_STATEpermission. - Location services are enabled on the device (under Settings > Location).
To successfully call WifiManager.getScanResults(), ensure all of the
following conditions are met:
- If your app is targeting Android 10 (API level 29) SDK or higher, your app
has the
ACCESS_FINE_LOCATIONpermission. - If your app is targeting SDK lower than Android 10 (API level 29), your app
has the
ACCESS_COARSE_LOCATIONorACCESS_FINE_LOCATIONpermission. - Your app has the
ACCESS_WIFI_STATEpermission. - Location services are enabled on the device (under Settings > Location).
If the calling app doesn't meet all of these requirements, the call fails with a
SecurityException.
Throttling
The following limitations apply to the frequency of scans using
WifiManager.startScan().
Android 8.0 and Android 8.1:
Each background app can scan one time in a 30-minute period.
Android 9:
Each foreground app can scan four times in a 2-minute period. This allows for a burst of scans in a short time.
All background apps combined can scan one time in a 30-minute period.
Android 10 and higher:
The same throttling limits from Android 9 apply. There is a new developer option to toggle the throttling off for local testing (under Developer Options > Networking > Wi-Fi scan throttling).