Wi-Fi 검색 개요

WifiManager API가 제공하는 Wi-Fi 검색 기능을 사용하여 기기에 보이는 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 ...
}

자바

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 를 사용하여 위치 정보 액세스 권한을 요구하는 대신 앱을 대신하여 근처 호환 기기를 스캔할 수 있습니다. 이 옵션에 대한 자세한 내용은 호환 기기 페어링을 선택합니다.

Android 9:

WifiManager.startScan()을 성공적으로 호출하려면 다음 모든 조건에 부합해야 합니다.

Android 10(API 수준 29) 이상:

WifiManager.startScan()을 성공적으로 호출하려면 다음 모든 조건에 부합해야 합니다.

  • 앱이 Android 10(API 수준 29) SDK 이상을 타겟팅할 경우 ACCESS_FINE_LOCATION 권한이 있어야 합니다.
  • 앱이 Android 10(API 수준 29) 미만의 SDK를 타겟팅하는 경우 ACCESS_COARSE_LOCATION 또는 ACCESS_FINE_LOCATION 권한이 필요합니다.
  • 앱에 CHANGE_WIFI_STATE 권한이 있어야 합니다.
  • 기기에서 위치 서비스가 활성화되어야 합니다(설정 > 위치 아래).

WifiManager.getScanResults()를 호출하려면 다음 조건을 모두 충족해야 합니다.

  • 앱이 Android 10(API 수준 29) SDK 이상을 타겟팅할 경우 ACCESS_FINE_LOCATION 권한이 있어야 합니다.
  • 앱이 Android 10(API 수준 29) 미만인 SDK를 타겟팅할 경우 ACCESS_COARSE_LOCATION 또는 ACCESS_FINE_LOCATION 권한이 있어야 합니다.
  • 앱에 ACCESS_WIFI_STATE 권한이 있어야 합니다.
  • 기기에서 위치 서비스가 활성화되어야 합니다(설정 > 위치 아래).

호출하는 앱이 이러한 조건을 모두 충족하지 못하면 SecurityException과 함께 호출이 실패합니다.

사용 제한

WifiManager.startScan()을 사용하는 스캔 빈도에 다음과 같은 제한이 적용됩니다.

Android 8.0 및 Android 8.1:

각 백그라운드 앱은 30분 간격으로 1회 스캔할 수 있습니다.

Android 9:

각 포그라운드 앱은 2분 간격으로 4회 스캔할 수 있습니다. 이 경우, 단시간에 여러 번의 스캔이 가능하게 됩니다.

백그라운드 앱은 모두 합쳐서 30분 간격으로 1회 스캔할 수 있습니다.

Android 10 이상:

Android 9와 동일한 사용 제한이 적용됩니다. 로컬 테스트를 위해 사용 제한을 해제하는 새로운 개발자 옵션이 추가되었습니다(Developer Options > Networking > Wi-Fi scan throttling).