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

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

ขั้นตอนการสแกนหา Wi-Fi

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

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

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() ต้องใช้สิทธิ์อย่างใดอย่างหนึ่งต่อไปนี้

หากแอปการโทรไม่มีสิทธิ์ดังกล่าว จะโทรไม่สำเร็จ SecurityException

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

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 สิทธิ์
  • มีการเปิดใช้บริการตำแหน่งในอุปกรณ์ (ในส่วนการตั้งค่า > สถานที่ตั้ง)

หากแอปโทรไม่เป็นไปตามข้อกําหนดเหล่านี้ทั้งหมด จะโทรไม่สําเร็จโดยมี SecurityException

การควบคุม

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

Android 8.0 และ Android 8.1

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

Android 9

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

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

Android 10 ขึ้นไป

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