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

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

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

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

  1. یک شنونده‌ی پخش برای SCAN_RESULTS_AVAILABLE_ACTION ثبت کنید، که هنگام تکمیل درخواست‌های اسکن فراخوانی می‌شود و وضعیت موفقیت/شکست آنها را ارائه می‌دهد. برای دستگاه‌هایی که اندروید ۱۰ (سطح API ۲۹) و بالاتر را اجرا می‌کنند، این پخش برای هر اسکن کامل 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 ...
}

محدودیت‌ها

اندروید ۸.۰ (سطح API ۲۶) محدودیت‌هایی در مورد مجوزها و تعداد دفعات مجاز اسکن وای‌فای ایجاد کرد.

برای بهبود عملکرد شبکه، امنیت و عمر باتری، اندروید ۹ (سطح API 28) الزامات مجوز را سختگیرانه‌تر کرد و تعداد دفعات اسکن Wi-Fi را نیز محدودتر نمود.

مجوزها

اندروید ۸.۰ و اندروید ۸.۱:

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

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

از طرف دیگر، در دستگاه‌هایی که اندروید ۸.۰ (سطح API ۲۶) و بالاتر را اجرا می‌کنند، می‌توانید از CompanionDeviceManager برای انجام اسکن دستگاه‌های همراه نزدیک از طرف برنامه خود بدون نیاز به مجوز موقعیت مکانی استفاده کنید. برای اطلاعات بیشتر در مورد این گزینه، به جفت‌سازی دستگاه همراه مراجعه کنید.

اندروید ۹:

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

اندروید ۱۰ (سطح API ۲۹) و بالاتر:

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

  • اگر برنامه شما SDK اندروید ۱۰ (سطح API ۲۹) یا بالاتر را هدف قرار می‌دهد، برنامه شما مجوز ACCESS_FINE_LOCATION را دارد.
  • اگر برنامه شما SDK پایین‌تر از اندروید ۱۰ (سطح API 29) را هدف قرار می‌دهد، برنامه شما دارای مجوزهای ACCESS_COARSE_LOCATION یا ACCESS_FINE_LOCATION است.
  • برنامه شما مجوز CHANGE_WIFI_STATE را دارد.
  • سرویس‌های موقعیت مکانی روی دستگاه فعال شده‌اند (در تنظیمات > موقعیت مکانی ).

برای فراخوانی موفقیت‌آمیز WifiManager.getScanResults() ، اطمینان حاصل کنید که تمام شرایط زیر رعایت شده است:

  • اگر برنامه شما SDK اندروید ۱۰ (سطح API ۲۹) یا بالاتر را هدف قرار می‌دهد، برنامه شما مجوز ACCESS_FINE_LOCATION را دارد.
  • اگر برنامه شما SDK پایین‌تر از اندروید ۱۰ (سطح API 29) را هدف قرار می‌دهد، برنامه شما دارای مجوزهای ACCESS_COARSE_LOCATION یا ACCESS_FINE_LOCATION است.
  • برنامه شما مجوز ACCESS_WIFI_STATE را دارد.
  • سرویس‌های موقعیت مکانی روی دستگاه فعال شده‌اند (در تنظیمات > موقعیت مکانی ).

اگر برنامه‌ی فراخوانی‌کننده تمام این الزامات را برآورده نکند، تماس با خطای SecurityException با شکست مواجه می‌شود.

تنظیم سرعت

محدودیت‌های زیر در مورد تعداد دفعات اسکن با استفاده از WifiManager.startScan() اعمال می‌شود.

اندروید ۸.۰ و اندروید ۸.۱:

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

اندروید ۹:

هر برنامه پیش‌زمینه می‌تواند چهار بار در یک دوره ۲ دقیقه‌ای اسکن کند. این امکان را فراهم می‌کند که در مدت زمان کوتاهی، چندین اسکن پشت سر هم انجام شود.

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

اندروید ۱۰ و بالاتر:

همان محدودیت‌های کنترل سرعت از اندروید ۹ اعمال می‌شود. یک گزینه جدید برای توسعه‌دهندگان وجود دارد که می‌توانند کنترل سرعت را برای آزمایش محلی غیرفعال کنند (در قسمت گزینه‌های توسعه‌دهندگان > شبکه > کنترل سرعت اسکن وای‌فای ).