אפשר להשתמש בפונקציונליות המיקום ב-Wi-Fi שמסופקת על ידי API של Wi-Fi RTT (Round-Trip-Time) כדי למדוד את המרחק בין נקודות גישה ל-Wi-Fi ולעמיתים קרובים עם RTT מכשירי Wi-Fi Aware.
אם מודדים את המרחק לשלוש נקודות גישה או יותר, אפשר להשתמש אלגוריתם רב-שלבי להערכת מיקום המכשיר המתאים ביותר מדידות. בדרך כלל התוצאה מדויקת בטווח של 1-2 מטר.
הדיוק הזה מאפשר לך לפתח שירותים פרטניים מבוססי מיקום, כמו כמו ניווט בתוך מבנים, שליטה קולית חד-משמעית (לדוגמה, "אני רוצה להפעיל את התכונה הזו) קל) ומידע מבוסס-מיקום (לדוגמה, "האם יש מבצעים מיוחדים?" של המוצר הזה?").
המכשיר ששלח את הבקשה לא צריך להתחבר לנקודות הגישה כדי לבצע מדידה מרחק באמצעות Wi-Fi RTT. כדי לשמור על הפרטיות, רק המכשיר ששלח את הבקשה יכול כדי לקבוע את המרחק לנקודת הגישה, נקודות הגישה מידע זה. אין הגבלה על פעולות RTT ב-Wi-Fi באפליקציות שפועלות בחזית, אבל מוגבלת לאפליקציות ברקע.
תכונות RTT ב-Wi-Fi והיכולות שקשורות למדידה בזמן אמת (FTM) הן שצוין בתקן IEEE 802.11-2016. נדרש זמן מדויק לשימוש ב-RTT ב-Wi-Fi מדידה שמסופקת על ידי FTM כי היא מחשבת את המרחק בין מכשירים על ידי מדידת הזמן שלוקח לחבילה לבצע טיסה הלוך ושוב בין ולהכפיל את הזמן הזה במהירות האור.
הבדלים בהטמעה בהתאם לגרסת Android
התחלנו להשתמש ב-RTT ב-Wi-Fi ב-Android 9 (רמת API 28). כשמשתמשים בפרוטוקול הזה כדי לקבוע את מיקום המכשיר באמצעות ריבוי שורות עם מכשירים פועלים ב-Android 9, נדרשת גישה למיקומים של נקודות גישה שהוגדרו מראש (AP) בתוך האפליקציה. אתם מחליטים איך לאחסן ולאחזר את הנתונים האלה.
במכשירים שמותקנת בהם גרסת Android 10 (API ברמה 29) ואילך, נתוני המיקום של AP יכולים להיות
מיוצג בתור
ResponderLocation
אובייקטים, כולל קו רוחב, קו אורך וגובה. עבור נקודות AP של RTT ב-Wi-Fi
תמיכה במידע על תצורת המיקום/בדוח האזרחי של המיקום (נתוני LCI/LCR),
הפרוטוקול יחזיר אובייקט ResponderLocation
במהלך
תהליך הטווח.
התכונה הזו מאפשרת לאפליקציות לשלוח שאילתות ל-AP כדי לבקש את המיקום שלהן ישירות במקום לאחסן את המידע הזה מראש. לכן, האפליקציה למצוא נקודות AP ולקבוע את המיקום שלהן גם אם הן לא היו ידועות לפני כן, למשל, כשמשתמש נכנס לבניין חדש.
הדרישות
- החומרה של המכשיר שמבצע את בקשת הטווח חייבת להטמיע את תקן FTM 802.11-2016.
- במכשיר המבצע את בקשת הטווח צריכה לפעול מערכת Android 9 (רמת API 28) ואילך.
- צריך להפעיל שירותי מיקום במכשיר שממנו נשלחה בקשת הטווח וסריקת נקודות ה-Wi-Fi מופעלת (בקטע הגדרות > מיקום).
- אם האפליקציה שמבצעת את הטווחים של הבקשות לטירגוט
מערכת Android 13 (רמת API 33) ואילך, חייבת להיות בה גרסת
NEARBY_WIFI_DEVICES
הרשאה. אם אפליקציה כזו מטרגטת גרסה קודמת של Android, היא חייבת כולליםACCESS_FINE_LOCATION
במקום זאת. - האפליקציה צריכה לשלוח שאילתה על טווח נקודות הגישה בזמן שהיא גלויה או נמצאת בתוך האפליקציה שירות שפועל בחזית. האפליקציה לא יכולה לגשת לפרטי המיקום דרך רקע.
- נקודת הגישה חייבת להטמיע את תקן IEEE 802.11-2016 FTM.
הגדרה
כדי להגדיר באפליקציה שימוש ב-RTT ב-Wi-Fi, מבצעים את השלבים הבאים.
1. בקשת הרשאות
צריך לבקש את ההרשאות הבאות במניפסט של האפליקציה:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!-- If your app targets Android 13 (API level 33)
or higher, you must declare the NEARBY_WIFI_DEVICES permission. -->
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES"
<!-- If your app derives location information from Wi-Fi APIs,
don't include the "usesPermissionFlags" attribute. -->
android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
<!-- If any feature in your app relies on precise location
information, don't include the "maxSdkVersion"
attribute. -->
android:maxSdkVersion="32" />
ההרשאות NEARBY_WIFI_DEVICES
ו-ACCESS_FINE_LOCATION
מסוכנות
עליך לבקש אותן בזמן הריצה בכל פעם שהמשתמש רוצה
ביצוע פעולת סריקת RTT. האפליקציה שלך תצטרך לבקש מהמשתמש
אם ההרשאה עדיין לא ניתנה. אפשר לקבל מידע נוסף
על הרשאות סביבת זמן ריצה,
מבקשים הרשאות לאפליקציה.
2. בדיקה אם המכשיר תומך ב-RTT ב-Wi-Fi
כדי לבדוק אם המכשיר תומך ב-RTT ב-Wi-Fi, משתמשים API של PackageManager:
Kotlin
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)
Java
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT);
3. איך בודקים אם התכונה RTT ב-Wi-Fi זמינה
יכול להיות שיש במכשיר RTT Wi-Fi, אבל הוא לא זמין כרגע כי המשתמש השבית את ה-Wi-Fi. בהתאם לחומרה ולקושחה של המכשירים יכולות. ייתכן שחלק מהמכשירים לא תומכים ב-RTT ב-Wi-Fi אם התכונה SoftAP או שיתוף אינטרנט בין מכשירים ניידים בשימוש. כדי לבדוק אם התכונה RTT ב-Wi-Fi זמינה כרגע, צריך להתקשר isAvailable().
הזמינות של RTT ב-Wi-Fi עשויה להשתנות בכל שלב. האפליקציה שלך צריכה לרשום BroadcastReceiver לקבל ACTION_WIFI_RTT_STATE_CHANGED, שנשלח כשהזמינות משתנה. מתי האפליקציה מקבלת את השידור כוונה, האפליקציה צריכה לבדוק את מצב הזמינות הנוכחי ולשנות את בהתאם.
לדוגמה:
Kotlin
val filter = IntentFilter(WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED) val myReceiver = object: BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (wifiRttManager.isAvailable) { … } else { … } } } context.registerReceiver(myReceiver, filter)
Java
IntentFilter filter = new IntentFilter(WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED); BroadcastReceiver myReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (wifiRttManager.isAvailable()) { … } else { … } } }; context.registerReceiver(myReceiver, filter);
למידע נוסף, ראו שידורים.
יצירת בקשה בטווח
בקשה בטווח (RangingRequest) נוצר על ידי ציון רשימה של נקודות AP או אפליקציות להשוואה ל-Wi-Fi שאליהן טווח נדרש. אפשר לציין כמה נקודות גישה או רשתות Wi-Fi Aware במסגרת בקשה בטווח יחיד; המערכת מודדת ומחזירה את המרחקים בין כל המכשירים.
לדוגמה, בקשה יכולה להשתמש addAccessPoint() כדי לציין נקודת גישה שאליה מודדים את המרחק:
Kotlin
val req: RangingRequest = RangingRequest.Builder().run { addAccessPoint(ap1ScanResult) addAccessPoint(ap2ScanResult) build() }
Java
RangingRequest.Builder builder = new RangingRequest.Builder(); builder.addAccessPoint(ap1ScanResult); builder.addAccessPoint(ap2ScanResult); RangingRequest req = builder.build();
נקודת גישה מזוהה לפי
אובייקט Scanresults, שיכול להיות
שמתקבלת באמצעות התקשרות
Wi-FiManager.getScanresults().
אפשר להשתמש
addAccessPoints(List
באופן דומה, בקשה טווח יכולה להוסיף אפליקציה להשוואה ל-Wi-Fi באמצעות ה-MAC או ה-PeerHandle שלה, באמצעות ה addWi-FiAwarePeer(MacAddress peer) ו-addWifiAwarePeer(PeerHandle peer) שיטות, בהתאמה. לקבלת מידע נוסף על איתור אפליקציות להשוואה של Wi-Fi, עיין בתיעוד של Wi-Fi Aware.
טווח בקשות
אפליקציה מנפיקה בקשה טווח באמצעות Wi-FiRttManager.startRanging() ולציין את הפרטים הבאים: RangingRequest כדי לציין את פעולה, מפעיל שיציין את ההקשר של הקריאה החוזרת RangingresultCallback כדי לקבל את התוצאות.
לדוגמה:
Kotlin
val mgr = context.getSystemService(Context.WIFI_RTT_RANGING_SERVICE) as WifiRttManager val request: RangingRequest = myRequest mgr.startRanging(request, executor, object : RangingResultCallback() { override fun onRangingResults(results: List<RangingResult>) { … } override fun onRangingFailure(code: Int) { … } })
Java
WifiRttManager mgr = (WifiRttManager) Context.getSystemService(Context.WIFI_RTT_RANGING_SERVICE); RangingRequest request ...; mgr.startRanging(request, executor, new RangingResultCallback() { @Override public void onRangingFailure(int code) { … } @Override public void onRangingResults(List<RangingResult> results) { … } });
פעולת הטווח מתבצעת באופן אסינכרוני, ותוצאות הטווח שהוחזרה באחד מהקריאות החוזרות של Ranging resultCallback:
- אם כל הפעולה של הטווח נכשלת, onRangingFailure הקריאה החוזרת מופעלת באמצעות קוד סטטוס שמתואר בשדה Ranging resultCallback. כשל כזה עשוי להתרחש אם השירות לא יכול לבצע פעולת טווח באותו זמן - לדוגמה, בגלל שה-Wi-Fi מושבת, כי האפליקציה ביקש יותר מדי פעולות טווח וחסומות, או בגלל בעיית הרשאה.
- בסיום פעולת הטווח, תוצאות onRanging הקריאה החוזרת (callback) מופעלת עם רשימה של תוצאות שתואמות לרשימה בקשות – תוצאה אחת לכל בקשה. סדר התוצאות לא תואמות בהכרח לסדר של הבקשות. חשוב לשים לב שפעולת טווח עשויה הושלם, אך כל תוצאה עדיין עשויה להעיד על כשל מדידה.
פרשו תוצאות בטווח
כל אחת מהתוצאות שהוחזרו על ידי תוצאות onRanging הקריאה החוזרת (callback) מצוינת באמצעות RangingAmount לאובייקט. מבצעים את הפעולות הבאות בכל בקשה.
1. זיהוי הבקשה
לזהות את הבקשה על סמך המידע שסופק כשיצרתם את
RangingRequest:
בדרך כלל כתובת MAC שניתנה בScanResult
שמזהה גישה
לנקודה. ניתן לקבל את כתובת ה-MAC מתוצאת הטווח באמצעות הפרמטר
getMacAddress()
.
רשימת התוצאות עשויה להיות בסדר שונה מזה של האפליקציות להשוואה (גישה נקודות) שצוינו בבקשת הטווח, לכן עליך להשתמש בכתובת MAC כדי אנחנו מזהים את האפליקציה להשוואה, לא את סדר התוצאות.
2. בודקים אם כל מדידה הצליחה
כדי לקבוע אם המדידה הצליחה,
getStatus()
. כל ערך מלבד
STATUS_PROGRESS
מציין כישלון. המשמעות של כשל היא שכל שאר השדות בתוצאה הזו
(חוץ מזיהוי הבקשה שלמעלה) לא תקינים, והפרמטרים המתאימים
השיטה get*
תיכשל עם
חריג DisallowStateError .
3. קבלת תוצאות לכל מדידה מוצלחת
לכל מדידה מוצלחת, אפשר לאחזר את ערכי התוצאות עם
get
השיטות המתאימות:
מרחק, במ"מ וסטיית תקן של המדידה:
RSSI של המנות המשמשות למדידות:
הזמן באלפיות השנייה שבו בוצעה המדידה (מציין זמן מאז האתחול):
מספר המדידות שניסינו לבצע ומספר המדידות שהצליחו (ועליהן מבוססות מדידות המרחק):
מכשירי Android שתומכים ב-Wi-RTT
בטבלאות שבהמשך מפורטות כמה טלפונים, נקודות גישה ומכשירים קמעונאיים, אחסון ומרכז הפצה שתומכים ב-Wi-Fi-RTT. הדוגמאות האלה רחוקות מלהיות מקיף. מומלץ ליצור איתנו קשר כדי לפרט כאן את המוצרים שיכולים להשתמש ב-RTT.
נקודות גישה
יצרן ודגם | תאריך התמיכה |
---|---|
Nest Wifi Pro (Wi-Fi 6E) | נתמך |
Compulab WILD AP | נתמך |
Google Wi-Fi | נתמך |
נתב Wi-Fi של Google Nest | נתמך |
נקודת Wi-Fi של Google Nest | נתמך |
ארובה AP-635 | נתמך |
Cisco 9130 | נתמך |
Cisco 9136 | נתמך |
Cisco 9166 | נתמך |
Cisco 9164 | נתמך |
ארובה AP-505 | נתמך |
ארובה AP-515 | נתמך |
ארובה AP-575 | נתמך |
ארובה AP-518 | נתמך |
ארובה AP-505H | נתמך |
ארובה AP-565 | נתמך |
ארובה AP-535 | נתמך |
טלפונים
יצרן ודגם | גרסת Android |
---|---|
6 Pixel | 9.0 ואילך |
Pixel 6 Pro | 9.0 ואילך |
Pixel 5 | 9.0 ואילך |
Pixel 5a | 9.0 ואילך |
Pixel 5a (5G) | 9.0 ואילך |
Xiaomi Mi 10 Pro | 9.0 ואילך |
Xiaomi Mi 10 | 9.0 ואילך |
Xiaomi Redmi Mi 9T Pro | 9.0 ואילך |
Xiaomi Mi 9T | 9.0 ואילך |
Xiaomi Mi 9 | 9.0 ואילך |
Xiaomi Mi Note 10 | 9.0 ואילך |
Xiaomi Mi Note 10 Lite | 9.0 ואילך |
Xiaomi Redmi Note 9S | 9.0 ואילך |
Xiaomi Redmi Note 9 Pro | 9.0 ואילך |
Xiaomi Redmi Note 8T | 9.0 ואילך |
Xiaomi Redmi Note 8 | 9.0 ואילך |
Xiaomi Redmi K30 Pro | 9.0 ואילך |
Xiaomi Redmi K20 Pro | 9.0 ואילך |
Xiaomi Redmi K20 | 9.0 ואילך |
Xiaomi Redmi Note 5 Pro | 9.0 ואילך |
Xiaomi Mi CC9 Pro | 9.0 ואילך |
LG G8X ThinQ | 9.0 ואילך |
LG V50S ThinQ | 9.0 ואילך |
LG V60 ThinQ | 9.0 ואילך |
LG V30 | 9.0 ואילך |
Samsung Galaxy Note 10+ 5G | 9.0 ואילך |
Samsung Galaxy S20+ 5G | 9.0 ואילך |
טלפונים מדגם Samsung Galaxy S20 ואילך | 9.0 ואילך |
Samsung Galaxy S20 5G | 9.0 ואילך |
Samsung Galaxy S20 Ultra 5G | 9.0 ואילך |
Samsung Galaxy S20 | 9.0 ואילך |
Samsung Galaxy Note 10+ | 9.0 ואילך |
Samsung Galaxy Note 10 5G | 9.0 ואילך |
Samsung Galaxy Note 10 | 9.0 ואילך |
Samsung A9 Pro | 9.0 ואילך |
Google Pixel 4 XL | 9.0 ואילך |
Google Pixel 4 | 9.0 ואילך |
Google Pixel 4a | 9.0 ואילך |
Google Pixel 3 XL | 9.0 ואילך |
Google Pixel 3 | 9.0 ואילך |
Google Pixel 3a XL | 9.0 ואילך |
Google Pixel 3a | 9.0 ואילך |
Google Pixel 2 XL | 9.0 ואילך |
Google Pixel 2 | 9.0 ואילך |
Google Pixel 1 XL | 9.0 ואילך |
Google Pixel 1 | 9.0 ואילך |
Poco X2 | 9.0 ואילך |
Sharp Aquos R3 SH-04L | 9.0 ואילך |
מכשירים של מרכז הקמעונאות, האחסון וההפצה
יצרן ודגם | גרסת Android |
---|---|
זברה PS20 | 10.0 ומעלה |
זברה TC52/TC52HC | 10.0 ומעלה |
זברה TC57 | 10.0 ומעלה |
זברה TC72 | 10.0 ומעלה |
זברה TC77 | 10.0 ומעלה |
זברה MC93 | 10.0 ומעלה |
זברה TC8300 | 10.0 ומעלה |
זברה VC8300 | 10.0 ומעלה |
זברה EC30 | 10.0 ומעלה |
זברה ET51 | 10.0 ומעלה |
זברה ET56 | 10.0 ומעלה |
זברה L10 | 10.0 ומעלה |
זברה CC600/CC6000 | 10.0 ומעלה |
זברה MC3300x | 10.0 ומעלה |
זברה MC330x | 10.0 ומעלה |
זברה TC52x | 10.0 ומעלה |
זברה TC57x | 10.0 ומעלה |
זברה EC50 (LAN ו-HC) | 10.0 ומעלה |
Zebra EC55 (WAN) | 10.0 ומעלה |
זברה WT6300 | 10.0 ומעלה |
Skorpio X5 | 10.0 ומעלה |