يقدّم Android 16 وحدة Ranging التي توفّر واجهة موحّدة وموحّدة لإجراء عملية تحديد دقيقة للمسافة بين الأجهزة. يمكنك استخدام واجهة برمجة التطبيقات هذه لقياس المسافة وموضع الأجهزة النظيرة بدون الحاجة إلى التعامل مع كل تكنولوجيا من تكنولوجيات تحديد المسافة على حدة.
تتوافق وحدة Ranging مع التكنولوجيات التالية:
- النطاق الفائق العرض
- قياس قوة إشارة البلوتوث
- Wi-Fi NAN RTT
- تحديد المسافة باستخدام RSSI للبلوتوث
إمكانات تحديد المسافة وتوفّرها
توفّر الفئة RangingManager للتطبيقات معلومات عن تكنولوجيات تحديد المسافة
التي يتيحها الجهاز المحلي، بالإضافة إلى توفّر كل تكنولوجيا وإمكاناتها. يمكن للتطبيقات تسجيل Callback لتلقّي إشعارات بأي تغييرات تطرأ على توفّر أي من التكنولوجيات المتوافقة أو إمكاناتها.
أدوار الأجهزة
يجب أن يكون الجهاز المشارك في جلسة تحديد المسافة إما جهازًا مبادرًا أو جهازًا مستجيبًا. يبدأ الجهاز المبادر جلسة تحديد المسافة مع جهاز واحد أو أكثر من الأجهزة المستجيبة. يستجيب الجهاز المستجيب لطلبات تحديد المسافة من جهاز مبادر واحد فقط في كل مرة. يمكنك تحديد دور جهاز معيّن في جلسة تحديد المسافة
باستخدام الفئة RangingPreference.
أنواع جلسات تحديد المسافة
عند بدء جلسة تحديد المسافة بين الأجهزة، غالبًا ما يكون من الضروري إنشاء عملية نقل بيانات خارج النطاق (OOB) لتبادل مَعلمات الجلسة.
يمكن لوحدة Ranging التعامل مع عمليات التفاوض خارج النطاق نيابةً عنك، ولكنها تتيح أيضًا عمليات التنفيذ المخصّصة خارج النطاق.
عملية التنفيذ التلقائية خارج النطاق
في هذا النوع من الجلسات (RANGING_SESSION_OOB)، تتعامل وحدة Ranging مع
عمليات التفاوض خارج النطاق لبدء جلسة تحديد المسافة. تختار الوحدة مَعلمات مناسبة استنادًا إلى الإعدادات المفضّلة لتحديد المسافة التي يقدّمها التطبيق، وتستخدم التكنولوجيات المناسبة استنادًا إلى ما يتيحه كلا الجهازَين. يستخدم هذا النوع من الجلسات
مواصفات موحّدة OOB specification.
لا تحدّد وحدة Ranging سوى تنسيق البيانات خارج النطاق والتسلسل الذي سيتم استخدامه للتفاعل مع جهاز نظير. ولا تتعامل الوحدة مع عملية اكتشاف الجهاز النظير أو إنشاء الاتصال.
عملية التنفيذ المخصّصة خارج النطاق
في هذا النوع من الجلسات (RANGING_SESSION_RAW)، يتجاوز التطبيق عملية نقل البيانات خارج النطاق في وحدة Ranging
ويتعامل مع عمليات التفاوض خارج النطاق والمَعلمات الخاصة به. يعني ذلك أنّه على التطبيق تحديد التكنولوجيات التي يتيحها الجهاز النظير، والتفاوض على مَعلمات تحديد المسافة، وبدء جلسة تحديد المسافة.
الإعدادات المفضّلة لتحديد المسافة
استخدِم كائن RangingPreference لتحديد المَعلمات المختارة لـ
جلسة تحديد المسافة. ويتضمن ذلك ما يلي:
- دور الجهاز: يشير هذا الإعداد إلى ما إذا كان الجهاز سيكون الجهاز المبادر أو الجهاز المستجيب.
- إعدادات تحديد المسافة: يحدّد كائن
RangingConfigنوع جلسة تحديد المسافة والمَعلمات الأخرى اللازمة لبدء جلسة تحديد المسافة. - إعدادات الجلسة: يحدّد كائن
SessionConfigالمَعلمات التي سيتم فرضها على جلسة تحديد المسافة، مثل حد القياس ودمج أجهزة الاستشعار وإعدادات السياج الجغرافي وغير ذلك.
إذن تحديد المسافة
تتطلب وحدة Ranging إذنًا موحّدًا جديدًا (android.permission.RANGING) للوصول إلى جميع تكنولوجيات تحديد المسافة الحالية والمستقبلية. يظهر هذا الإذن في قائمة NEARBY_DEVICES_PERMISSIONS.
<uses-permission android:name="android.permission.RANGING" />
القيود والأحكام
قد تقيّد وحدة Ranging عملية تحديد المسافة لعدة أسباب، بما في ذلك ما يلي:
- لا يُسمح للتطبيقات التابعة لجهات خارجية بإجراء عملية تحديد المسافة في الخلفية إلا باستخدام النطاق الفائق العرض ، وعلى الأجهزة المتوافقة فقط. لا يُسمح بتحديد المسافة في الخلفية باستخدام تكنولوجيات أخرى.
- لا يُسمح بتحديد المسافة عند بلوغ الحد الأقصى لعدد جلسات تحديد المسافة المتزامنة لكل جهاز.
- قد يتم تقييد عملية تحديد المسافة بسبب مشاكل في سلامة النظام، مثل البطارية أو الأداء أو الذاكرة.
تفرض وحدة Ranging أيضًا القيود المعروفة التالية:
- لا تتيح وحدة Ranging إرسال بيانات تحديد المسافة إلى الأجهزة النظيرة إلا باستخدام النطاق الفائق العرض. بالنسبة إلى التكنولوجيات الأخرى، لا ترسل وحدة Ranging بيانات تحديد المسافة إلا إلى الجهاز المبادر.
- لا تتيح وحدة Ranging إضافة الأجهزة بشكل ديناميكي في وضع تحديد المسافة الأولي mode، وذلك باستخدام النطاق الفائق العرض فقط.
- لا تتيح وحدة Ranging جلسات النطاق الفائق العرض من جهاز واحد إلى أجهزة متعددة لـ عمليات التنفيذ التلقائية خارج النطاق. إذا مرّرت عدة مقابض للأجهزة، تنشئ الوحدة جلسة من جهاز واحد إلى جهاز واحد لكل جهاز نظير يتيح النطاق الفائق العرض.
إجراء جلسة تحديد المسافة
لإجراء جلسة تحديد المسافة باستخدام وحدة Ranging، اتّبِع الخطوات التالية:
- تأكَّد من أنّ جميع الأجهزة تعمل بنظام التشغيل 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();
}
}
التوافق التشغيلي للنطاق الفائق العرض مع أجهزة iOS
تتيح وحدة Ranging إمكانية التشغيل التفاعلي مع أجهزة iOS باستخدام النطاق الفائق العرض (UWB). لتحديد المسافة باستخدام جهاز iOS، يجب استخدام عملية تنفيذ مخصّصة خارج النطاق وضبط جلسة تحديد المسافة باستخدام مَعلمات معيّنة تتطابق مع بروتوكول Apple Nearby Interaction Accessory Protocol. يُرجى الرجوع إلى نموذج التطبيق كمرجع.
عند إنشاء RangingPreference، استخدِم RawRangingDevice وUwbRangingParams لتحديد الإعدادات. تُعدّ المَعلمات التالية ضرورية للتوافق التشغيلي مع أجهزة iOS:
- رقم تعريف الإعدادات: استخدِم
UwbRangingParams.CONFIG_UNICAST_DS_TWR. - معلومات مفتاح الجلسة: قدِّم مصفوفة بايت تحتوي على رقم تعريف المورّد وStatic STS IV.
- القناة المعقّدة: اضبط رقم القناة وفهرس التمهيد ليطابقا إعدادات جهاز iOS.
يوضّح مقتطف الرمز التالي كيفية إنشاء RangingPreference لجهاز مبادر يحدّد المسافة مع جهاز مستجيب يعمل بنظام التشغيل iOS:
Kotlin
// Create UwbRangingParams with iOS-specific configuration
val uwbRangingParams = UwbRangingParams.Builder(
sessionId,
UwbRangingParams.CONFIG_UNICAST_DS_TWR,
sourceAddress,
destinationAddress
)
.setComplexChannel(
UwbComplexChannel.Builder()
.setChannel(channelNumber)
.setPreambleIndex(preambleIndex)
.build()
)
.setRangingUpdateRate(updateRate)
.setSessionKeyInfo(sessionKeyInfo) // Vendor ID + STS IV
.setSlotDuration(slotDuration)
.build()
// Create RawRangingDevice
val rawRangingDevice = RawRangingDevice.Builder()
.setRangingDevice(RangingDevice.Builder().build())
.setUwbRangingParams(uwbRangingParams)
.build()
// Create SessionConfig
val sessionConfig = SessionConfig.Builder()
.setAngleOfArrivalNeeded(true)
.setDataNotificationConfig(DataNotificationConfig.Builder()
.setNotificationConfigType(DataNotificationConfig.NOTIFICATION_CONFIG_ENABLE)
.build())
.build()
// Create RangingPreference for the initiator
val preference = RangingPreference.Builder(
RangingPreference.DEVICE_ROLE_INITIATOR,
RawInitiatorRangingConfig.Builder()
.addRawRangingDevice(rawRangingDevice)
.build()
)
.setSessionConfig(sessionConfig)
.build()
Java
// Create UwbRangingParams with iOS-specific configuration
UwbRangingParams uwbRangingParams = new UwbRangingParams.Builder(
sessionId,
UwbRangingParams.CONFIG_UNICAST_DS_TWR,
sourceAddress,
destinationAddress)
.setComplexChannel(new UwbComplexChannel.Builder()
.setChannel(channelNumber)
.setPreambleIndex(preambleIndex)
.build())
.setRangingUpdateRate(updateRate)
.setSessionKeyInfo(sessionKeyInfo) // Vendor ID + STS IV
.setSlotDuration(slotDuration)
.build();
// Create RawRangingDevice
RawRangingDevice rawRangingDevice = new RawRangingDevice.Builder()
.setRangingDevice(new RangingDevice.Builder().build())
.setUwbRangingParams(uwbRangingParams)
.build();
// Create SessionConfig
SessionConfig sessionConfig = new SessionConfig.Builder()
.setAngleOfArrivalNeeded(true)
.setDataNotificationConfig(new DataNotificationConfig.Builder()
.setNotificationConfigType(DataNotificationConfig.NOTIFICATION_CONFIG_ENABLE)
.build())
.build();
// Create RangingPreference for the initiator
RangingPreference preference = new RangingPreference.Builder(
RangingPreference.DEVICE_ROLE_INITIATOR,
new RawInitiatorRangingConfig.Builder()
.addRawRangingDevice(rawRangingDevice)
.build())
.setSessionConfig(sessionConfig)
.build();
واجهة برمجة التطبيقات UWB Downlink-TDoA
بالنسبة إلى واجهة برمجة التطبيقات UWB DL-TDoA، يُرجى الاطّلاع على الميزات الجديدة في Android 17.
نموذج التطبيق
للاطّلاع على مثال شامل حول كيفية استخدام وحدة Ranging، يُرجى الاطّلاع على نموذج التطبيق في AOSP. يغطّي نموذج التطبيق هذا جميع تكنولوجيات تحديد المسافة التي تتيحها وحدة Ranging ويتضمّن عمليات نقل البيانات لكلا نوعَي الجلسات المتوافقَين.
التوافق التشغيلي للنطاق الفائق العرض مع أجهزة iOS
يتيح نموذج تطبيق Android بدء جلسة تحديد المسافة باستخدام النطاق الفائق العرض مع نموذج تطبيق iOS.