نمای کلی اسکن Wi-Fi

می توانید از قابلیت های اسکن Wi-Fi ارائه شده توسط WifiManager API برای دریافت لیستی از نقاط دسترسی Wi-Fi که از دستگاه قابل مشاهده هستند استفاده کنید.

فرآیند اسکن وای فای

برای فرآیند اسکن سه مرحله وجود دارد:

  1. یک شنونده پخش را برای SCAN_RESULTS_AVAILABLE_ACTION ثبت کنید، که با تکمیل درخواست‌های اسکن فراخوانی می‌شود و وضعیت موفقیت/شکست آنها را ارائه می‌کند. برای دستگاه‌های دارای Android 10 (سطح API 29) و بالاتر، این پخش برای هر اسکن کامل Wi-Fi که توسط پلتفرم یا سایر برنامه‌ها روی دستگاه انجام می‌شود، ارسال می‌شود. برنامه‌ها می‌توانند با استفاده از پخش بدون انجام اسکن خود، به صورت غیرفعال به تمام مراحل اسکن روی دستگاه گوش دهند.

  2. درخواست اسکن با استفاده از WifiManager.startScan() . مطمئن شوید که وضعیت بازگشت متد را بررسی کرده اید، زیرا ممکن است به هر یک از دلایل زیر تماس برقرار نشود:

    • درخواست های اسکن ممکن است به دلیل اسکن های زیاد در مدت زمان کوتاهی کاهش یابد.
    • دستگاه بیکار است و اسکن غیرفعال است.
    • سخت افزار وای فای خرابی اسکن را گزارش می دهد.
  3. نتایج اسکن را با استفاده از WifiManager.getScanResults() دریافت کنید. نتایج اسکن برگشتی جدیدترین نتایج به روز شده هستند، که ممکن است از اسکن قبلی باشد، اگر اسکن فعلی شما کامل نشده یا موفقیت آمیز باشد. این بدان معنی است که اگر قبل از دریافت یک پخش موفقیت آمیز SCAN_RESULTS_AVAILABLE_ACTION با این روش تماس بگیرید، ممکن است نتایج اسکن قدیمی تری دریافت کنید.

کد زیر نمونه ای از نحوه اجرای این مراحل را ارائه می دهد:

کاتلین

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 را بیشتر محدود کرد.

مجوزها

اندروید 8.0 و اندروید 8.1:

یک فراخوان موفق به WifiManager.getScanResults() به یکی از مجوزهای زیر نیاز دارد:

اگر برنامه تماس‌گیرنده هیچ یک از این مجوزها را نداشته باشد، تماس با یک SecurityException انجام نمی‌شود.

از طرف دیگر، در دستگاه‌های دارای Android 8.0 (سطح API 26) و بالاتر، می‌توانید از CompanionDeviceManager برای انجام اسکن دستگاه‌های همراه در نزدیکی از طرف برنامه خود بدون نیاز به مجوز مکان استفاده کنید. برای اطلاعات بیشتر در مورد این گزینه، به جفت شدن دستگاه همراه مراجعه کنید.

اندروید 9:

یک فراخوان موفق به WifiManager.startScan() مستلزم رعایت همه شرایط زیر است:

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() اعمال می شود.

اندروید 8.0 و اندروید 8.1:

هر برنامه پس‌زمینه می‌تواند یک بار در مدت 30 دقیقه اسکن کند.

اندروید 9:

هر برنامه پیش زمینه می تواند چهار بار در یک دوره 2 دقیقه ای اسکن کند. این اجازه می دهد تا یک اسکن پشت سر هم در مدت زمان کوتاهی انجام شود.

همه برنامه‌های پس‌زمینه ترکیبی می‌توانند یک بار در مدت 30 دقیقه اسکن کنند.

اندروید 10 و بالاتر:

همان محدودیت‌های فشار از اندروید 9 اعمال می‌شود. یک گزینه توسعه‌دهنده جدید برای خاموش کردن throttling برای آزمایش محلی وجود دارد (در زیر Developer Options > Networking > Wi-Fi scan throttling ).