Save the date! Android Dev Summit is coming to Mountain View, CA on November 7-8, 2018.

Wi-Fi scanning overview

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:

  1. Register a broadcast listener for SCAN_RESULTS_AVAILABLE_ACTION, which is called when scan requests are completed, providing their success/failure status.
  2. Request a scan using WifiManager.startScan(). Make sure to check the return status of the method, since the call may fail for any of the following reasons:

    • Scan requests may 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.
  3. Get scan results using WifiManager.getScanResults(). The returned scan results are the most recently updated results, which may be from a previous scan if your current scan has not completed or succeeded. This means that you might get older scan results if you call this method before receiving a successful SCAN_RESULTS_AVAILABLE_ACTION broadcast.

The following code provides an example of how to implement these steps:

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 and Android 8.1:

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.

Android 9 and later:

A successful call to WifiManager.startScan() requires all of the following conditions to be met:

To successfully call WifiManager.getScanResults() ensure all of the following conditions are met:

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 and later:

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.