موقع Wi-Fi: بدءًا من ميزة "المراسلة النصية في الوقت الفعلي"

يمكنك استخدام وظيفة الموقع الجغرافي لشبكة Wi-Fi التي توفّرها واجهة برمجة التطبيقات Wi-Fi RTT (Round-Trip-Time) API لقياس المسافة بين نقاط وصول Wi-Fi القريبة التي يمكنها استخدام ميزة "مراسلة نصية في الوقت الفعلي" وأجهزة Wi-Fi Aware المشابهة.

إذا كنت تقيس المسافة إلى ثلاث نقاط وصول أو أكثر، يمكنك استخدام خوارزمية تكرار متعدد لتقدير موضع الجهاز الأنسب لهذه القياسات. عادةً ما تكون النتيجة دقيقة في نطاق متر واحد أو مترين.

وباستخدام هذه الدقة، يمكنك تطوير خدمات دقيقة تستند إلى الموقع، مثل التنقل في الأماكن المغلقة والتحكم الصوتي المميز (على سبيل المثال، "إضاءة هذا المصباح")، ومعلومات مستندة إلى الموقع (على سبيل المثال، "هل هناك عروض خاصة لهذا المنتج؟").

ولا يحتاج الجهاز الذي قدّم الطلب إلى الاتصال بنقاط الوصول لقياس المسافة باستخدام ميزة "مراسلة نصية في الوقت الفعلي" لشبكة Wi-Fi. للحفاظ على الخصوصية، يستطيع الجهاز الذي أرسل الطلب فقط تحديد المسافة إلى نقطة الوصول، ولا تحتوي نقاط الوصول على هذه المعلومات. تكون عمليات ميزة "مراسلة نصية في الوقت الفعلي" لشبكة Wi-Fi غير محدودة للتطبيقات التي تعمل في المقدّمة ولكن يتم تقييدها لاستخدامها في تطبيقات الخلفية.

يتم تحديد إمكانيات ميزة "مراسلة نصية في الوقت الفعلي" لشبكة Wi-Fi وإمكانات قياس الوقت الدقيق (FTM) ذات الصلة وفقًا لمعيار معهد الهندسة الكهربائية والإلكترونية IEEE 802.11-2016. تتطلب ميزة "مراسلة نصية في الوقت الفعلي" لشبكة Wi-Fi قياسًا دقيقًا للوقت الذي توفّره خدمة FTM لأنها تحسب المسافة بين جهازين من خلال قياس الوقت الذي تستغرقه الحزمة لنقلها ذهابًا وإيابًا بين الأجهزة وضرب هذا الوقت في سرعة الضوء.

اختلافات طريقة التنفيذ حسب إصدار Android

تم تقديم ميزة "مراسلة نصية في الوقت الفعلي" لشبكة Wi-Fi في الإصدار 9 من نظام Android (المستوى 28 من واجهة برمجة التطبيقات). عند استخدام هذا البروتوكول لتحديد موضع الجهاز باستخدام النسخ المتعددة للأجهزة التي تعمل بنظام التشغيل Android 9، يجب أن تتمكن من الوصول إلى بيانات مواقع نقطة الوصول المحددة مسبقًا في تطبيقك. والأمر متروك لك لتحديد كيفية تخزين هذه البيانات واستردادها.

على الأجهزة التي تعمل بنظام التشغيل Android 10 (مستوى واجهة برمجة التطبيقات 29) والإصدارات الأحدث، يمكن تمثيل بيانات الموقع الجغرافي في نقطة الوصول (AP) على أنّها كائنات ResponderLocation التي تشمل خطوط الطول والعرض والارتفاع. بالنسبة إلى نقاط الوصول التي تعمل في ميزة "مراسلة نصية في الوقت الفعلي" لشبكة Wi-Fi التي تتيح استخدام معلومات إعدادات الموقع الجغرافي أو التقرير المدني للموقع الجغرافي (بيانات LCI/LCR)، سيعرض البروتوكول عنصر ResponderLocation أثناء عملية تحديد النطاق الزمني.

تسمح هذه الميزة للتطبيقات بالاستعلام عن نقاط الوصول تطلب منها تحديد مكانها مباشرةً بدلاً من الحاجة إلى تخزين هذه المعلومات مسبقًا. لذلك، يمكن لتطبيقك العثور على نقاط الوصول وتحديد مواضعها حتى إذا لم تكن نقاط الوصول معروفة من قبل، مثلاً عند دخول المستخدم إلى مبنى جديد.

المتطلبات الأساسية

  • يجب أن تنفيذ معيار FTM 802.11-2016 على جهاز الجهاز الذي يطلب تحديد المدى.
  • يجب أن يعمل الجهاز الذي يقدّم طلب النطاق بالإصدار Android 9 (المستوى 28 من واجهة برمجة التطبيقات) أو بإصدار أحدث.
  • يجب أن يتم تفعيل خدمات الموقع الجغرافي في الجهاز الذي يقدّم طلب النطاق وتفعيل ميزة البحث عن شبكات Wi-Fi (ضمن الإعدادات > الموقع الجغرافي).
  • إذا كان التطبيق الذي يقدّم طلب النطاق المستهدَف يستهدف Android 13 (المستوى 33 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، يجب أن يحصل على إذن NEARBY_WIFI_DEVICES. وإذا كان هذا التطبيق يستهدف إصدارًا سابقًا من Android، يجب أن يحصل على إذن ACCESS_FINE_LOCATION بدلاً من ذلك.
  • يجب أن يستعلم التطبيق عن نطاق نقاط الوصول عندما يكون التطبيق مرئيًا أو في خدمة تعمل في المقدّمة. يتعذّر على التطبيق الوصول إلى معلومات الموقع الجغرافي من الخلفية.
  • يجب أن تنفذ نقطة الوصول معيار IEEE 802.11-2016 FTM.

إعداد

لإعداد تطبيقك لاستخدام ميزة "المراسلة النصية في الوقت الفعلي" لشبكة 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. التحقّق مما إذا كان الجهاز يتيح ميزة "المراسلة النصية في الوقت الفعلي" لشبكة Wi-Fi

للتحقّق مما إذا كان الجهاز متوافقًا مع ميزة "المراسلة النصية في الوقت الفعلي" لشبكة Wi-Fi، يمكنك استخدام واجهة برمجة التطبيقات 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 في أي وقت. يجب أن يسجّل تطبيقك جهاز 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 في طلب نطاق واحد، ويتم قياس المسافات بين جميع الأجهزة وإرجاعها.

على سبيل المثال، يمكن للطلب استخدام طريقة 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 peer) وaddWifiAwarePeer(PeerHandle peer) على التوالي. لمزيد من المعلومات حول كيفية التعرّف على الأجهزة المشابهة المزوّدة بخدمة Wi-Fi، يمكنك الاطّلاع على مستندات خدمة Wi-Fi Aware.

نطاق الطلبات

يُصدر التطبيق طلبًا متنوّعًا باستخدام الطريقة 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_Success إلى تعذُّر. يعني الإخفاق أنّ جميع الحقول الأخرى لهذه النتيجة (باستثناء تعريف الطلب أعلاه) غير صالحة، وستتعذّر طريقة get* المقابلة مع استثناء إجراء غير قانونيStateException .

3. الحصول على نتائج لكل عملية قياس ناجحة

بالنسبة إلى كل عملية قياس ناجحة، يمكنك استرداد قيم النتائج باستخدام طرق get المعنية:

أجهزة Android المتوافقة مع تقنية WiFi-RTT

تتضمّن الجداول أدناه بعض الهواتف ونقاط الوصول وأجهزة البيع بالتجزئة وأماكن التخزين والتوزيع التي تتوافق مع ميزة "المراسلة النصية في الوقت الفعلي". وهي أبعد ما تكون عن شاملة. ننصحك بالتواصل معنا لإدراج منتجاتك التي يمكنها استخدام ميزة "مراسلة نصية في الوقت الفعلي" هنا.

نقاط الوصول

الشركة المصنّعة والطراز تاريخ الدعم
Nest Wifi Pro (Wi-Fi 6E) معلومات معتمَدة
Compulab WILD AP معلومات معتمَدة
شبكة Google Wi-Fi معلومات معتمَدة
جهاز توجيه Google Nest Wi-Fi معلومات معتمَدة
نقطة اتصال Google Nest Wi-Fi معلومات معتمَدة
Aruba AP-635 معلومات معتمَدة
سيسكو 9130 معلومات معتمَدة
سيسكو 9136 معلومات معتمَدة
سيسكو 9166 معلومات معتمَدة
سيسكو 9164 معلومات معتمَدة
Aruba AP-505 معلومات معتمَدة
أروبا AP-515 معلومات معتمَدة
Aruba AP-575 معلومات معتمَدة
Aruba AP-518 معلومات معتمَدة
Aruba AP-505H معلومات معتمَدة
Aruba AP-565 معلومات معتمَدة
Aruba 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
زيبرا 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
Zebra CC600/CC6000 +10.0
Zebra MC3300x +10.0
Zebra MC330x +10.0
Zebra TC52x +10.0
Zebra TC57x +10.0
Zebra EC50 (LAN وHC) +10.0
Zebra EC55 (WAN) +10.0
حمار وحشي WT6300 +10.0
Skorpio X5 +10.0