Omówienie skanowania Wi-Fi

Możesz użyć funkcji skanowania sieci Wi-Fi udostępnianych przez interfejs WifiManager API, aby uzyskać listę punktów dostępu Wi-Fi widocznych na urządzeniu.

Proces skanowania Wi-Fi

Proces skanowania składa się z 3 etapów:

  1. Zarejestruj odbiornik transmisji dla SCAN_RESULTS_AVAILABLE_ACTION, który jest wywoływany po zakończeniu żądań skanowania i zwraca stan powodzenia lub niepowodzenia. W przypadku urządzeń z Androidem 10 (poziom interfejsu API 29) lub nowszym ta transmisja będzie wysyłana w przypadku każdego pełnego skanowania sieci Wi-Fi przeprowadzonego na urządzeniu przez platformę lub inne aplikacje. Aplikacje mogą pasywnie słuchać wszystkich zakończeń skanowania na urządzeniu, korzystając z transmisji bez przeprowadzania własnego skanowania.

  2. Poproś o skanowanie, korzystając z WifiManager.startScan(). Sprawdź stan zwracania metody, ponieważ wywołanie może się nie udać z jednego z tych powodów:

    • Żądania skanowania mogą być ograniczane z powodu zbyt wielu skanowań w krótkim czasie.
    • Urządzenie jest nieaktywne, a skanowanie jest wyłączone.
    • Sprzęt Wi-Fi zgłasza błąd skanowania.
  3. Pobierz wyniki skanowania, używając WifiManager.getScanResults(). Zwrócone wyniki skanowania to najnowsze zaktualizowane wyniki. Mogą one pochodzić z poprzedniego skanowania, jeśli bieżące skanowanie nie zostało ukończone lub zakończyło się powodzeniem. Oznacza to, że jeśli wywołasz tę metodę przed otrzymaniem udanej transmisji SCAN_RESULTS_AVAILABLE_ACTION, możesz otrzymać starsze wyniki skanowania.

Poniżej znajduje się przykład implementacji tych czynności:

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

Ograniczenia

W Androidzie 8.0 (poziom interfejsu API 26) wprowadzono ograniczenia dotyczące uprawnień i dozwolonej częstotliwości skanowania sieci Wi-Fi.

Aby poprawić wydajność sieci, bezpieczeństwo i czas pracy na baterii, w Androidzie 9 (poziom API 28) zaostrzyliśmy wymagania dotyczące uprawnień i jeszcze bardziej ograniczyliśmy częstotliwość skanowania sieci Wi-Fi.

Uprawnienia

Android 8.0 i 8.1:

Aby wywołać szablon WifiManager.getScanResults(), musisz mieć co najmniej jedno z tych uprawnień:

Jeśli aplikacja do wykonywania połączeń nie ma żadnego z tych uprawnień, połączenie nie powiedzie się i zostanie wyświetlony komunikat SecurityException.

Na urządzeniach z Androidem 8.0 (poziom interfejsu API 26) lub nowszym możesz też użyć CompanionDeviceManager, aby skanować urządzenia towarzyszące w pobliżu w imieniu aplikacji bez konieczności uzyskiwania uprawnień do lokalizacji. Więcej informacji o tej opcji znajdziesz w artykule Parowanie urządzenia towarzyszącego.

Android 9:

Aby wywołanie funkcji WifiManager.startScan() zakończyło się powodzeniem, muszą być spełnione wszystkie te warunki:

Android 10 (poziom interfejsu API 29) i nowszy:

Aby wywołanie funkcji WifiManager.startScan() zakończyło się powodzeniem, muszą być spełnione wszystkie te warunki:

  • Jeśli Twoja aplikacja jest kierowana na Androida 10 (API na poziomie 29) lub nowszego, ma ona uprawnienie ACCESS_FINE_LOCATION.
  • Jeśli aplikacja jest kierowana na pakiet SDK niższy niż Android 10 (poziom interfejsu API 29), ma ona uprawnienia ACCESS_COARSE_LOCATION lub ACCESS_FINE_LOCATION.
  • Twoja aplikacja ma uprawnienie CHANGE_WIFI_STATE.
  • Usługi lokalizacyjne są włączone na urządzeniu (w sekcji Ustawienia > Lokalizacja).

Aby wywołać metodę WifiManager.getScanResults(), upewnij się, że są spełnione wszystkie te warunki:

  • Jeśli Twoja aplikacja jest kierowana na pakiet Androida 10 (API na poziomie 29) lub nowszy, ma uprawnienie ACCESS_FINE_LOCATION.
  • Jeśli Twoja aplikacja jest kierowana na SDK niższego niż Android 10 (poziom interfejsu API 29), ma uprawnienia ACCESS_COARSE_LOCATION lub ACCESS_FINE_LOCATION.
  • Twoja aplikacja ma uprawnienie ACCESS_WIFI_STATE.
  • Usługi lokalizacyjne są włączone na urządzeniu (w sekcji Ustawienia > Lokalizacja).

Jeśli aplikacja do wykonywania połączeń nie spełnia wszystkich tych wymagań, połączenie nie zostanie nawiązane i usłyszysz komunikat SecurityException.

Ograniczanie

Podane niżej ograniczenia mają zastosowanie do częstotliwości skanowania z użyciem WifiManager.startScan().

Android 8.0 i 8.1:

Każda aplikacja działająca w tle może skanować raz w ciągu 30 minut.

Android 9:

Każda aplikacja na pierwszym planie może skanować cztery razy w ciągu 2 minut. Umożliwia to skanowanie dużej liczby plików w krótkim czasie.

Wszystkie aplikacje działające w tle łącznie mogą skanować je raz w ciągu 30 minut.

Android 10 lub nowszy:

Obowiązują te same limity ograniczeń co w Androidzie 9. Dodano nową opcję dla deweloperów, która umożliwia wyłączenie ograniczania przepustowości na potrzeby testów lokalnych (w sekcji Opcje dla deweloperów > Sieć > Ograniczanie przepustowości skanowania Wi-Fi).