ภาพรวมการสแกนหา Wi-Fi

คุณสามารถใช้ความสามารถในการสแกน Wi-Fi ที่ WifiManager API มีให้เพื่อดูรายการจุดเข้าใช้งาน Wi-Fi ที่มองเห็นได้จากอุปกรณ์

กระบวนการสแกนหา Wi-Fi

กระบวนการสแกนมี 3 ขั้นตอนดังนี้

  1. ลงทะเบียน Broadcast Listener สำหรับ 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 ...
}

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

ข้อจำกัด

Android 8.0 (ระดับ API 26) ได้เปิดตัวข้อจำกัดเกี่ยวกับสิทธิ์และความถี่ที่อนุญาตในการสแกน Wi-Fi

Android 9 (API ระดับ 28) ได้เพิ่มความเข้มงวดของข้อกำหนดด้านสิทธิ์และจำกัดความถี่ในการสแกน Wi-Fi เพิ่มเติมเพื่อปรับปรุงประสิทธิภาพเครือข่าย ความปลอดภัย และระยะเวลาการใช้งานแบตเตอรี่

สิทธิ์

Android 8.0 (ระดับ API 26) และ Android 8.1 (ระดับ API 27)

การเรียกใช้ WifiManager.getScanResults() ที่สำเร็จต้องใช้สิทธิ์อย่างใดอย่างหนึ่งต่อไปนี้

หากแอปการโทรไม่มีสิทธิ์เหล่านี้ การโทรจะดำเนินการไม่สำเร็จพร้อมข้อผิดพลาด SecurityException

หรือในอุปกรณ์ที่ใช้ Android 8.0 (ระดับ API 26) ขึ้นไป คุณสามารถใช้ CompanionDeviceManager เพื่อสแกนหาอุปกรณ์ที่ใช้ร่วมกันที่อยู่ใกล้เคียงในนามของแอปโดยไม่ต้องขอสิทธิ์เข้าถึงตำแหน่ง ดูข้อมูลเพิ่มเติมเกี่ยวกับตัวเลือกนี้ได้ที่การจับคู่อุปกรณ์ที่ใช้ร่วมกัน

Android 9 (ระดับ API 28):

การเรียกใช้ WifiManager.startScan() ที่สำเร็จต้องเป็นไปตามเงื่อนไขต่อไปนี้ทั้งหมด

  • แอปของคุณมีสิทธิ์ ACCESS_FINE_LOCATION หรือ ACCESS_COARSE_LOCATION
  • แอปของคุณมีสิทธิ์ CHANGE_WIFI_STATE
  • เปิดใช้บริการตำแหน่งในอุปกรณ์ (ในส่วนการตั้งค่า > ตำแหน่ง)

Android 10 (ระดับ API 29) ขึ้นไป:

การเรียกใช้ WifiManager.startScan() ที่ประสบความสำเร็จต้องเป็นไปตามเงื่อนไขทั้งหมดต่อไปนี้

  • หากแอปกำหนดเป้าหมายเป็น SDK ของ Android 10 (ระดับ API 29) ขึ้นไป แอปจะมีสิทธิ์ ACCESS_FINE_LOCATION
  • หากแอปของคุณกำหนดเป้าหมายเป็น SDK ที่ต่ำกว่า Android 10 (API ระดับ 29) แอปจะมีสิทธิ์ ACCESS_COARSE_LOCATION หรือ ACCESS_FINE_LOCATION
  • แอปของคุณมีสิทธิ์ CHANGE_WIFI_STATE
  • เปิดใช้บริการตำแหน่งในอุปกรณ์ (ในส่วนการตั้งค่า > ตำแหน่ง)

หากต้องการเรียกใช้ WifiManager.getScanResults() ให้สำเร็จ โปรดตรวจสอบว่าคุณมีคุณสมบัติตรงตามเงื่อนไขต่อไปนี้ทั้งหมด

  • หากแอปกำหนดเป้าหมายเป็น SDK ของ Android 10 (ระดับ API 29) ขึ้นไป แอปจะมีสิทธิ์ 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:

แอปที่ทำงานอยู่เบื้องหลังแต่ละแอปจะสแกนได้ 1 ครั้งในช่วงเวลา 30 นาที

Android 9:

แอปที่ทำงานอยู่เบื้องหน้าแต่ละแอปจะสแกนได้ 4 ครั้งในระยะเวลา 2 นาที ซึ่งจะช่วยให้สแกนได้อย่างรวดเร็วในระยะเวลาสั้นๆ

แอปที่ทำงานอยู่เบื้องหลังทั้งหมดรวมกันจะสแกนได้ 1 ครั้งในระยะเวลา 30 นาที

Android 10 ขึ้นไป:

ขีดจำกัดการควบคุมเดียวกันจาก Android 9 จะมีผล มีตัวเลือกใหม่สำหรับนักพัฒนาแอปเพื่อปิดการควบคุมปริมาณสำหรับการทดสอบในเครื่อง (ในส่วนตัวเลือกสำหรับนักพัฒนาแอป > เครือข่าย > การควบคุมปริมาณการสแกน Wi-Fi)