סקירה כללית של חיפוש נקודות Wi-Fi

אפשר להשתמש ביכולות חיפוש נקודות ה-Wi-Fi שמסופקות על ידי Wi-FiManager API כדי לקבל רשימה של נקודות גישה ל-Wi-Fi שגלויות במכשיר.

תהליך חיפוש נקודות Wi-Fi

תהליך הסריקה כולל שלושה שלבים:

  1. רישום של מאזין שידור למשך SCAN_RESULTS_AVAILABLE_ACTION, נקרא כשבקשות סריקה מסתיימות, ומספקים את סטטוס הצלחה/כישלון. במכשירים עם Android בגרסה 10 (רמת API 29) ואילך, ההגדרה הזו השידור יישלח בכל סריקת Wi-Fi מלאה שתבוצע במכשיר על ידי בפלטפורמה או באפליקציות אחרות. אפליקציות יכולות להאזין באופן פסיבי לכל הסריקה שהושלמו במכשיר על ידי שימוש בשידור בלי לבצע סריקה של שלו.

  2. מבקשים סריקה באמצעות WifiManager.startScan(). חשוב לבדוק את סטטוס ההחזרה של השיטה, כי יכול להיות שהקריאה תיכשל מכל אחת מהסיבות הבאות:

    • יכול להיות שבקשות סריקה יעברו ויסות נתונים (throttle) עקב יותר מדי סריקות בפרק זמן קצר.
    • המכשיר לא פעיל והסריקה מושבתת.
    • חומרת ה-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() מחייב את כל התנאים הבאים:

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.

ויסות נתונים (throttle)

המגבלות הבאות חלות על תדירות הסריקות שמשתמשות WifiManager.startScan()

Android 8.0 ו-Android 8.1:

כל אפליקציה ברקע יכולה לסרוק פעם אחת בפרק זמן של 30 דקות.

Android 9:

כל אפליקציה שפועלת בחזית יכולה לסרוק ארבע פעמים בפרק זמן של 2 דקות. כך אפשר רצף של סריקות בפרק זמן קצר.

שילוב של כל האפליקציות ברקע יכול לסרוק פעם אחת בפרק זמן של 30 דקות.

Android מגרסה 10 ואילך:

אותן מגבלות של ויסות נתונים (throttle) ב-Android 9 חלות. יש אפשרות חדשה למפתחים כדי להשבית את ויסות הנתונים (throttle) לבדיקה מקומית (בקטע אפשרויות למפתחים >) רשתות > ויסות נתונים (throttling) של סריקת Wi-Fi).