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