يمكنك استخدام ميزة تحديد الموقع الجغرافي لشبكة Wi-Fi المتوفّرة من خلال واجهة برمجة التطبيقات لميزة Wi-Fi RTT (Round-Trip-Time) لقياس المسافة بين نقاط وصول Wi-Fi القريبة المتوافقة مع ميزة "المراسلة النصية في الوقت الفعلي" وأجهزة Wi-Fi Aware القريبة.
إذا كنت تقيس المسافة إلى ثلاث نقاط وصول أو أكثر، يمكنك استخدام خوارزمية المضاعفة لتقدير موضع الجهاز الأنسب لتلك القياسات. وتكون النتيجة عادةً دقيقة في نطاق مترين أو مترين.
وبهذه الدقة، يمكنك تطوير خدمات دقيقة تستند إلى الموقع الجغرافي، مثل التنقل الداخلي، والتحكم الصوتي المميز (على سبيل المثال، "تشغيل هذا المصباح")، والمعلومات المستندة إلى الموقع (على سبيل المثال، "هل هناك عروض خاصة لهذا المنتج؟").
لا يحتاج الجهاز الذي يقدّم الطلب إلى الاتصال بنقاط الوصول لقياس المسافة باستخدام ميزة "المراسلة النصية في الوقت الفعلي" عبر شبكة Wi-Fi. وللحفاظ على الخصوصية، لا يمكن تحديد المسافة إلى نقطة الوصول إلا للجهاز المطلوب، بينما لا تحتوي نقاط الوصول على هذه المعلومات. إنّ عمليات "المراسلة النصية في الوقت الفعلي عبر Wi-Fi" غير محدودة للتطبيقات التي تعمل في المقدّمة، ولكن يتم تقييدها مع تطبيقات الخلفية.
تم تحديد إمكانات ميزة "المراسلة النصية في الوقت الفعلي" باستخدام اتصال Wi-Fi وإمكانات قياس الوقت الدقيق (FTM) ذات الصلة وفقًا لمعيار IEEE 802.11-2016. تتطلب ميزة "المراسلة النصية في الوقت الفعلي" عبر Wi-Fi قياس الوقت الدقيق الذي توفّره ميزة FTM لأنها تحسب المسافة بين جهازين عن طريق قياس الوقت الذي تستغرقه الحزمة لإجراء رحلة ذهاب وعودة بين الجهازين وضرب ذلك الوقت في سرعة الضوء.
الاختلافات في التنفيذ استنادًا إلى إصدار Android
تم طرح ميزة "المراسلة النصية في الوقت الفعلي من Google" في نظام Android 9 (المستوى 28 من واجهة برمجة التطبيقات). عند استخدام هذا البروتوكول لتحديد موضع جهاز باستخدام التشغيل المتعدد مع الأجهزة التي تعمل بنظام التشغيل Android 9، يجب أن تتمكن من الوصول إلى بيانات مواقع نقاط الوصول (AP) المحددة مسبقًا في تطبيقك. والأمر متروك لك لتحديد كيفية تخزين هذه البيانات واستردادها.
على الأجهزة التي تعمل بالإصدار 10 من نظام التشغيل Android 10 (المستوى 29 لواجهة برمجة التطبيقات) والإصدارات الأحدث، يمكن تمثيل بيانات الموقع الجغرافي لنقطة الوصول (AP) كعناصر
ResponderLocation
، بما في ذلك خطوط الطول والعرض والارتفاع. بالنسبة إلى نقاط الوصول التي تستخدم ميزة "المراسلة النصية في الوقت الفعلي" عبر اتصال Wi-Fi والتي
تتوافق مع معلومات إعداد الموقع الجغرافي/التقرير المدني للموقع الجغرافي (بيانات LCI/غرفة التحكم المباشر)،
سيعرض البروتوكول عنصر ResponderLocation
أثناء
عملية تحديد الموقع الجغرافي.
تسمح هذه الميزة للتطبيقات بالاستعلام عن نقاط الوصول لتطلب منها تحديد موضعها مباشرةً بدلاً من الحاجة إلى تخزين هذه المعلومات مسبقًا. لذلك، يمكن لتطبيقك العثور على نقاط الوصول وتحديد مواضعها حتى إذا لم تكن نقاط الوصول معروفة من قبل، مثلاً عند دخول المستخدم مبنى جديد.
الشروط
- ينبغي أن تنفذ أجهزة الجهاز الذي يقدم طلب تحديد النطاق معيار 802.11-2016 FTM.
- ويجب أن يعمل الجهاز الذي يرسِل طلب تحديد النطاق بنظام التشغيل Android 9 (المستوى 28 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث.
- يجب تفعيل خدمات الموقع الجغرافي على الجهاز الذي يقدِّم طلب تحديد الموقع الجغرافي وتفعيل ميزة "البحث عن شبكات Wi-Fi" (ضمن الإعدادات > الموقع الجغرافي).
- إذا كان التطبيق الذي يُجري عملية تحديد النطاق يستهدف نظام التشغيل Android 13 (المستوى 33 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، يجب أن يحصل على إذن
NEARBY_WIFI_DEVICES
. إذا كان هذا التطبيق يستهدف إصدارًا سابقًا من Android، يجب أن يحصل التطبيق على إذنACCESS_FINE_LOCATION
بدلاً من ذلك. - يجب أن يطلب التطبيق نطاق نقاط الوصول عندما يكون التطبيق مرئيًا أو في خدمة تعمل في المقدّمة. لا يمكن للتطبيق الوصول إلى معلومات الموقع الجغرافي من الخلفية.
- يجب أن تنفّذ نقطة الوصول معيار IEEE 802.11-2016 FTM.
ضبط إعدادات
لإعداد تطبيقك لاستخدام ميزة "المراسلة النصية في الوقت الفعلي" باستخدام ميزة "المراسلة النصية في الوقت الفعلي"، عليك اتّباع الخطوات التالية:
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
هي إذنان خطيران، لذلك عليك طلبهما في وقت التشغيل في كل مرة يريد فيها المستخدم إجراء عملية فحص في ميزة "مراسلة نصية في الوقت الفعلي". سيحتاج تطبيقك إلى طلب إذن من المستخدم
إذا لم يتم منحك الإذن بعد. لمزيد من المعلومات
حول أذونات وقت التشغيل، يُرجى الاطّلاع على
طلب أذونات التطبيق.
2. التحقّق مما إذا كان الجهاز متوافقًا مع ميزة "المراسلة النصية في الوقت الفعلي" باستخدام Wi-Fi
لمعرفة ما إذا كان الجهاز يتيح استخدام ميزة Wi-Fi RTT، يمكنك استخدام واجهة برمجة التطبيقات PackageManager:
Kotlin
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)
Java
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT);
3. التحقّق مما إذا كانت ميزة "المراسلة النصية في الوقت الفعلي" متاحة عبر Wi-Fi
قد تتوفّر ميزة "المراسلة النصية في الوقت الفعلي" على الجهاز، ولكنها قد لا تكون متاحة حاليًا لأنّ المستخدم أوقف تفعيل شبكة Wi-Fi. بناءً على إمكانات الأجهزة والبرامج الثابتة، قد لا تتوافق بعض الأجهزة مع ميزة "المراسلة النصية في الوقت الفعلي عبر Wi-Fi" في حال استخدام ميزة SoftAP أو التوصيل. للتحقّق مما إذا كانت ميزة "المراسلة النصية في الوقت الفعلي" باستخدام Wi-Fi متوفّرة حاليًا، يمكنك استدعاء الدالة isAvailable().
يمكن أن يتغير مدى توفُّر ميزة "المراسلة النصية في الوقت الفعلي" عبر Wi-Fi في أي وقت. يجب أن يسجّل تطبيقك رسالة BroadcastReceivedr لتلقّي 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 في طلب واحد لتحديد النطاق، حيث يتم قياس المسافات لجميع الأجهزة وعرضها.
على سبيل المثال، يمكن أن يستخدم الطلب طريقة 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();
يتم تحديد نقطة الوصول من خلال كائن
ScanResult، والذي يمكن الحصول عليه من خلال استدعاء
WifiManager.getScanResults().
يمكنك استخدام
addAccessPoints(List
وبالمثل، يمكن لطلب تحديد النطاق إضافة نظير لخدمة Wi-Fi Aware باستخدام عنوان MAC الخاص به أو PeerHandle، باستخدام الطريقتين addWifiAwarePeer(MacAddress المشابهة) وaddWifiAwarePeer(PeerHandleّد) على التوالي. لمزيد من المعلومات حول اكتشاف التطبيقات المشابهة لخدمة Wi-Fi، يمكنك الاطّلاع على مستندات خدمة Wi-Fi.
نطاق الطلب
يصدر أحد التطبيقات طلب نطاق باستخدام طريقة WifiRttManager.startRanging() وتوفير ما يلي: RangingRequest لتحديد العملية وExecutor لتحديد سياق معاودة الاتصال و 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) { … } });
يتم تنفيذ عملية النطاق بشكل غير متزامن، ويتم عرض نتائج النطاق في إحدى عمليات الاستدعاء في RangingResultCallback:
- إذا أخفقت عملية تحديد النطاق بالكامل، يتم تشغيل معاودة الاتصال onRangingFailure برمز حالة كما هو موضح في RangingResultCallback. وقد يحدث هذا الفشل إذا لم تتمكّن الخدمة من تنفيذ عملية ضبط نطاق البيانات في الوقت الحالي، بسبب إيقاف شبكة Wi-Fi مثلاً، أو لأنّ التطبيق طلب عددًا كبيرًا جدًا من عمليات تحديد النطاق وتم تقييده، أو بسبب مشكلة في الأذونات.
- عند اكتمال عملية تحديد النطاق، يتم تشغيل معاودة الاتصال onRangingResults بقائمة من النتائج التي تطابق قائمة الطلبات، ونتيجة واحدة لكل طلب. لا يتطابق ترتيب النتائج بالضرورة مع ترتيب الطلبات. تجدر الإشارة إلى أن عملية تحديد النطاق قد تكتمل ولكن كل نتيجة قد تظل تشير إلى فشل هذا القياس المحدد.
تفسير ترتيب النتائج
ويتم تحديد كل نتيجة من النتائج التي تعرضها استدعاء onRangingResults من خلال كائن RangingResult. في كل طلب، قم بما يلي.
1. تحديد الطلب
حدِّد الطلب استنادًا إلى المعلومات المقدّمة عند إنشاء RangingRequest: في الغالب عنوان MAC المقدَّم في ScanResult
الذي يحدد نقطة الوصول. يمكن الحصول على عنوان MAC من نتيجة النطاق باستخدام طريقة
getMacAddress().
قد تكون قائمة نتائج النطاق بترتيب مختلف عن التطبيقات المشابهة (نقاط الوصول) المحددة في طلب النطاق، لذا يجب عليك استخدام عنوان MAC لتحديد التطبيقات المشابهة، وليس ترتيب النتائج.
2. تحديد ما إذا كان كل قياس ناجحًا
لتحديد ما إذا كان القياس ناجحًا أم لا، استخدم إجراء getStatus(). تشير أي قيمة بخلاف
STATUS_False إلى إخفاق. تعني الإخفاقات أن جميع الحقول الأخرى لهذه النتيجة
(باستثناء تعريف الطلب أعلاه) غير صالحة، وسيتعذّر إجراء
طريقة get*
المقابلة لها إذا كان استثناء
legalStateException .
3. الحصول على نتائج لكل عملية قياس ناجحة
لكل عملية قياس ناجحة، يمكنك استرداد قيم النتائج باستخدام طرق get
المعنية:
المسافة بالمليمتر والانحراف المعياري للقياس:
RSSI للحِزم المستخدمة في القياسات:
الوقت بالمللي ثانية الذي تم فيه إجراء القياس (مع الإشارة إلى الوقت منذ بدء التشغيل):
عدد القياسات التي تمت تجربتها وعدد القياسات التي نجحت (والتي تستند إليها قياسات المسافة):
أجهزة Android التي تتيح استخدام ميزة "المراسلة النصية في الوقت الفعلي"
تسرد الجداول أدناه بعض الهواتف ونقاط الوصول وأجهزة البيع بالتجزئة والتخزين ومركز التوزيع التي تتيح استخدام ميزة "مراسلة نصية في الوقت الفعلي" هذه ليست شاملة. ننصحك بالتواصل معنا لإدراج المنتجات التي تتيح استخدام ميزة "المراسلة النصية في الوقت الفعلي" هنا.
نقاط الوصول
الشركة المصنّعة والطراز | تاريخ الدعم |
---|---|
Nest Wifi Pro (Wi-Fi 6E) | معلومات معتمَدة |
Compulab WILD AP | معلومات معتمَدة |
شبكة Wi-Fi من Google | معلومات معتمَدة |
جهاز توجيه Wi-Fi من Google Nest | معلومات معتمَدة |
نقطة اتصال Google Nest Wi-Fi | معلومات معتمَدة |
أروبا AP-635 | معلومات معتمَدة |
سيسكو 9130 | معلومات معتمَدة |
سيسكو 9136 | معلومات معتمَدة |
سيسكو 9166 | معلومات معتمَدة |
سيسكو 9164 | معلومات معتمَدة |
أروبا AP-505 | معلومات معتمَدة |
أروبا AP-515 | معلومات معتمَدة |
أروبا AP-575 | معلومات معتمَدة |
أروبا AP-518 | معلومات معتمَدة |
أروبا AP-505H | معلومات معتمَدة |
أروبا AP-565 | معلومات معتمَدة |
أروبا AP-535 | معلومات معتمَدة |
الهواتف
الشركة المصنّعة والطراز | إصدار Android |
---|---|
Pixel 6 | +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 |
---|---|
Zebra PS20 | +10.0 |
Zebra TC52/TC52HC | +10.0 |
Zebra TC57 | +10.0 |
Zebra TC72 | +10.0 |
Zebra TC77 | +10.0 |
Zebra MC93 | +10.0 |
Zebra TC8300 | +10.0 |
Zebra VC8300 | +10.0 |
Zebra EC30 | +10.0 |
Zebra ET51 | +10.0 |
Zebra ET56 | +10.0 |
حمار الوحش L10 | +10.0 |
Zebra CC600/CC6000 | +10.0 |
Zebra MC3300x | +10.0 |
Zebra MC330x | +10.0 |
الحمار الوحشي TC52x | +10.0 |
الحمار الوحشي TC57x | +10.0 |
Zebra EC50 (LAN وHC) | +10.0 |
Zebra EC55 (WAN) | +10.0 |
Zebra WT6300 | +10.0 |
Skorpio X5 | +10.0 |