ב-Android 16 מוצג מודול למדידת מרחק (Ranging), שמספק ממשק מאוחד וסטנדרטי למדידת מרחק מדויקת בין מכשירים. אפשר להשתמש בממשק ה-API הזה כדי למדוד את המרחק והמיקום של מכשירים עמיתים, בלי צורך לטפל בכל טכנולוגיית מדידת המרחק בנפרד.
המודול Ranging תומך בטכנולוגיות הבאות:
- Ultra Wideband (UWB)
- בדיקת צלילים בערוץ Bluetooth
- Wi-Fi NAN RTT
- מדידת מרחק באמצעות RSSI ב-Bluetooth
יכולות וזמינות של מדידת המרחק
הכיתה RangingManager
מספקת לאפליקציות מידע על טכנולוגיות המדידת המרחק שנתמכות במכשיר המקומי, וגם על הזמינות והיכולות של כל טכנולוגיה. אפליקציות יכולות להירשם ל-Callback
כדי לקבל עדכונים על שינויים בזמינות או ביכולות של הטכנולוגיות הנתמכות.
תפקידים במכשיר
מכשיר שמשתתף בסשן למדידת המרחק חייב להיות מפעיל או משיב. מכשיר ההתחלה מתחיל את סשן המדידת המרחק עם מכשיר אחד או יותר שמגיבים. מכשיר מגיב מגיב לבקשות למדידת טווח רק מגורם מפעיל אחד בכל פעם. אפשר לציין את התפקיד של מכשיר נתון בסשן של מדידת מרחק באמצעות הכיתה RangingPreference
.
סוגי סשנים של טווחי זמן
כשמתחילים סשן מדידה בין מכשירים, לעיתים קרובות צריך ליצור העברת נתונים מחוץ למסגרת (OOB) כדי להחליף פרמטרים של הסשן.
המודול Ranging יכול לטפל בשבילכם במשא ומתן מחוץ לתהליך (OOB), אבל הוא תומך גם בהטמעות OOB בהתאמה אישית.

הטמעה ברירת המחדל של OOB
בסוג הסשן הזה (RANGING_SESSION_OOB
), מודול הטווח מטפל במשא ומתן מחוץ לתהליך (OOB) כדי להתחיל סשן טווח. הוא בוחר פרמטרים מתאימים על סמך העדפות הטווח שסופקו על ידי האפליקציה, ומשתמש בטכנולוגיות המתאימות על סמך מה ששני המכשירים תומכים בו. בסוג הסשן הזה נעשה שימוש ב-OOB specification
סטנדרטי.
מודול הטווח מגדיר רק את הפורמט והרצף של נתוני ה-OOB שישמשו לאינטראקציה עם מכשיר עמית. הוא לא מטפל בגילוי של מכשירי עמיתים או ביצירת חיבורים.
הטמעה בהתאמה אישית מחוץ לארגון
בסוג הסשן הזה (RANGING_SESSION_RAW
), האפליקציה עוקפת את תהליך ה-OOB של מודול הטווח ומטפלת בפרמטרים ובמשא ומתן שלה מחוץ למסגרת.
המשמעות היא שהאפליקציה צריכה לקבוע אילו טכנולוגיות המכשיר השני תומך בהן, לנהל משא ומתן על פרמטרים של מדידת המרחק ולהתחיל את סשן מדידת המרחק.
העדפות למדידת טווח
משתמשים באובייקט RangingPreference
כדי לציין את הפרמטרים הרצויים לסשן סריקה. בין היתר, אסור:
- תפקיד המכשיר ההגדרה הזו מציינת אם המכשיר יהיה זה שיתחיל את הקריאה או זה שישיב לה.
- הגדרת טווח אובייקט
RangingConfig
מציין את סוג סשן הטווח ופרמטרים אחרים שנדרשים כדי להתחיל סשן טווח. - הגדרת סשן אובייקט
SessionConfig
מציין פרמטרים שיחולו על סשן המדידות, כמו מגבלת מדידה, מיזוג חיישנים, הגדרת גדר גיאוגרפית ועוד.
הרשאת טווח
מודול המדידת המרחק דורש הרשאה מאוחדת חדשה (android.permission.RANGING
) כדי לגשת לכל טכנולוגיות המדידה הקיימות והעתידיות. ההרשאה הזו נמצאת ברשימה NEARBY_DEVICES_PERMISSIONS
.
<uses-permission android:name="android.permission.RANGING" />
הגבלות ומגבלות
מודול הטווח עשוי להגביל את הטווח מכמה סיבות, כולל:
- אפליקציות צד שלישי יכולות לבצע מדידת מרחק ברקע באמצעות Ultra Wideband רק במכשירים נתמכים. אסור לבצע מדידת מרחק ברקע באמצעות טכנולוגיות אחרות.
- אי אפשר לבצע מדידת מרחק כשמגיעים למספר המקסימלי של סשנים בו-זמניים למדידת מרחק לכל מכשיר.
- יכול להיות שהטווח יהיה מוגבל בגלל בעיות בבריאות המערכת, כמו בעיות בסוללה, בביצועים או בזיכרון.
למודול הטווח יש גם את המגבלות הידועות הבאות:
- המודול של מדידת המרחק תומך רק בהעברת נתוני מדידת המרחק למכשירים אחרים בטכנולוגיית Ultra Wideband. בטכנולוגיות אחרות, מודול המדידת מרחק מעביר את נתוני המדידת מרחק רק למכשיר המבצע את הקריאה.
- המודול למדידת המרחק תומך בהוספה דינמית של מכשירים רק במצב מדידת מרחק גולמי, ורק לתדר רחב במיוחד.
- מודול הטווח לא תומך בסשנים של תדר רחב במיוחד מסוג 'אחד לרבים' בהטמעות ברירת המחדל של OOB. אם מעבירים כמה מזהי מכשירים, המודול יוצר סשן אחד על אחד לכל מכשיר עמית שתומך ב-UWB.
ביצוע סשן למדידת טווח
כדי לנהל סשן מדידת מרחק באמצעות מודול המדידה:
- מוודאים שכל המכשירים פועלים עם Android מגרסה 16 ואילך.
- מבקשים את ההרשאה
android.permission.RANGING
במניפסט של האפליקציה. - הערכת היכולות והזמינות של טכנולוגיות למדידת מרחק.
- חיפוש מכשיר עמית לפעולות מדידת מרחק.
- יוצרים חיבור לצורך החלפה מחוץ למסגרת, באמצעות אחד מסוגי הסשנים שמתוארים בקטע סוגי סשנים של טווח.
- הפעלת מדידת המרחק ואיסוף נתוני מדידת המרחק באופן רציף.
- סיום סשן הטווח.
דוגמת הקוד הבאה מדגימה את השלבים האלה גם לתפקיד המבצע וגם לתפקיד המגיב.
Kotlin
class RangingApp {
// Starts a ranging session on the initiator side.
fun startRangingInitiator(
context: Context,
deviceHandle: DeviceHandle,
executor: Executor,
callback: RangingSessionCallback
) {
// Get the RangingManager which is the entry point for ranging module.
val manager = context.getSystemService(RangingManager::class.java)
// Create a new RangingSession using the provided executor and callback.
val session = manager.createRangingSession(executor, callback)
// Create an OobInitiatorRangingConfig, which specifies the ranging parameters for
// the initiator role.
val config = OobInitiatorRangingConfig.Builder()
.setFastestRangingInterval(Duration.ofMillis(100))
.setSlowestRangingInterval(Duration.ofMillis(5000))
.setRangingMode(RANGING_MODE_AUTO)
.setSecurityLevel(SECURITY_LEVEL_BASIC)
.addDeviceHandle(deviceHandle)
.build()
// Create a RangingPreference, which specifies the role (initiator) and
// configuration for the ranging session.
val preference =
RangingPreference.Builder(DEVICE_ROLE_INITIATOR, config).build()
// Start ranging session.
session.start(preference)
// If successful, the ranging data will be sent through callback#onResults
// Stop ranging session
session.stop()
}
// Starts a ranging session on the responder side.
fun startRangingResponder(
context: Context,
deviceHandle: DeviceHandle,
executor: Executor,
callback: RangingSessionCallback
) {
// Get the RangingManager which is the entry point for ranging module.
val manager = context.getSystemService(RangingManager::class.java)
// Create a new RangingSession using the provided executor and callback.
val session = manager.createRangingSession(executor, callback)
// Create an OobResponderRangingConfig, which specifies the ranging parameters for
// the responder role.
val config = OobResponderRangingConfig.Builder(deviceHandle).build()
// Create a RangingPreference, which specifies the role (responder) and
// configuration for the ranging session.
val preference =
RangingPreference.Builder(DEVICE_ROLE_RESPONDER, config).build()
// Start the ranging session.
session.start(preference)
// Stop the ranging session
session.stop()
}
}
Java
public class RangingApp {
// Starts a ranging session on the initiator side.
void startRangingInitiator(Context context, DeviceHandle deviceHandle, Executor executor, RangingSessionCallback callback) {
// Get the RangingManager which is the entry point for ranging module.
RangingManager manager = context.getSystemService(RangingManager.class);
// Create a new RangingSession using the provided executor and callback.
RangingSession session = manager.createRangingSession(executor, callback);
// Create an OobInitiatorRangingConfig, which specifies the ranging parameters for
// the initiator role.
OobInitiatorRangingConfig config = new OobInitiatorRangingConfig.Builder()
.setFastestRangingInterval(Duration.ofMillis(100))
.setSlowestRangingInterval(Duration.ofMillis(5000))
.setRangingMode(RANGING_MODE_AUTO)
.setSecurityLevel(SECURITY_LEVEL_BASIC)
.addDeviceHandle(deviceHandle)
.build();
// Create a RangingPreference, which specifies the role (initiator) and
// configuration for the ranging session.
RangingPreference preference =
new RangingPreference.Builder(DEVICE_ROLE_INITIATOR, config).build();
// Start ranging session.
session.start(preference);
// If successful, the ranging data will be sent through callback#onResults
// Stop ranging session
session.stop();
}
// Starts a ranging session on the responder side.
void startRangingResponder(Context context, DeviceHandle deviceHandle, Executor executor, RangingSessionCallback callback) {
// Get the RangingManager which is the entry point for ranging module.
RangingManager manager = context.getSystemService(RangingManager.class);
// Create a new RangingSession using the provided executor and callback.
RangingSession session = manager.createRangingSession(executor, callback);
// Create an OobResponderRangingConfig, which specifies the ranging parameters for
// the responder role.
OobResponderRangingConfig config = new OobResponderRangingConfig.Builder( deviceHandle).build();
// Create a RangingPreference, which specifies the role (responder) and
// configuration for the ranging session.
RangingPreference preference =
new RangingPreference.Builder(DEVICE_ROLE_RESPONDER, config).build();
// Start the ranging session.
session.start(preference);
// Stop the ranging session
session.stop();
}
}
אפליקציה לדוגמה
דוגמה מקצה לקצה לשימוש במודול הטווח זמינה באפליקציה לדוגמה ב-AOSP. האפליקציה לדוגמה הזו כוללת את כל טכנולוגיות הטווח שנתמכות על ידי מודול הטווח, וגם תהליכים לשני סוגי הסשנים הנתמכים.