אפשר להשתמש ביכולות הסריקה של Wi-Fi שמספק WifiManager API כדי לקבל רשימה של נקודות גישה ל-Wi-Fi שגלויות מהמכשיר.
תהליך הסריקה של רשתות Wi-Fi
תהליך הסריקה כולל שלושה שלבים:
רישום של מעבד אירועים של שידור עבור
SCAN_RESULTS_AVAILABLE_ACTION
, שנקרא כשבקשות הסריקה מסתיימות ומספק את סטטוס ההצלחה או הכישלון שלהן. במכשירים עם Android 10 ואילך (רמת API 29 ואילך), השידור הזה יישלח בכל סריקה מלאה של Wi-Fi שמתבצעת במכשיר על ידי הפלטפורמה או אפליקציות אחרות. אפליקציות יכולות להאזין באופן פסיבי לכל השלמות הסריקה במכשיר באמצעות השידור, בלי לבצע סריקה משלהם.מבקשים סריקה באמצעות
WifiManager.startScan()
. חשוב לבדוק את סטטוס ההחזרה של השיטה, כי הקריאה עשויה להיכשל באחת מהסיבות הבאות:- יכול להיות שבקשות הסריקה יוגבלו בגלל יותר מדי סריקות בפרק זמן קצר.
- המכשיר לא פעיל והסריקה מושבתת.
- חומרת ה-Wi-Fi מדווחת על כשל בסריקה.
הצגת תוצאות הסריקה באמצעות
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
.
ויסות נתונים (throttle)
ההגבלות הבאות חלות על תדירות הסריקה באמצעות WifiManager.startScan()
.
Android 8.0 ו-Android 8.1:
כל אפליקציה שפועלת ברקע יכולה לסרוק פעם אחת בפרק זמן של 30 דקות.
Android 9:
כל אפליקציה בחזית יכולה לסרוק ארבע פעמים בפרק זמן של 2 דקות. כך אפשר לבצע מספר רב של סריקות בזמן קצר.
כל האפליקציות ברקע יכולות לבצע סריקה אחת במצטבר בפרק זמן של 30 דקות.
Android מגרסה 10 ואילך:
חלות אותן מגבלות על צמצום הקצב מ-Android 9. יש אפשרות חדשה למפתחים להשבית את הבקרה על קצב ההעברה לצורך בדיקה מקומית (בקטע אפשרויות למפתחים > רשתות > ויסות סריקה לנקודות Wi-Fi).