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

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

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

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

  1. ลงทะเบียน 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 และ Android 8.1:

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

หากแอปที่เรียกใช้ไม่มีสิทธิ์เหล่านี้ ระบบจะเรียกใช้ไม่สำเร็จและแสดง SecurityException

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

Android 9:

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

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

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

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

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

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

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

หากแอปที่เรียกใช้ไม่เป็นไปตามข้อกำหนดทั้งหมด ระบบจะเรียกใช้ไม่สำเร็จและแสดง a SecurityException

การควบคุม

ข้อจำกัดต่อไปนี้มีผลกับความถี่ในการสแกนโดยใช้ WifiManager.startScan()

Android 8.0 และ Android 8.1:

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

Android 9:

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

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

Android 10 ขึ้นไป:

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