نظرة عامة على Wi-Fi Aware

تتيح إمكانات Wi-Fi Aware للأجهزة التي تعمل بنظام التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) والإصدارات الأحدث رصد بعضها البعض والاتصال بها مباشرةً بدون أي نوع آخر من الاتصال بينها. تُعرف خدمة Wi-Fi أيضًا باسم شبكات الوعي المجاورة (NAN).

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

تتيح واجهات برمجة التطبيقات Wi-Fi Aware APIs للتطبيقات تنفيذ العمليات التالية:

  • اكتشاف الأجهزة الأخرى: تتضمّن واجهة برمجة التطبيقات آلية للعثور على الأجهزة المجاورة الأخرى. تبدأ العملية عندما ينشر جهاز واحد خدمة واحدة أو أكثر يمكن العثور عليها. وبعد ذلك، عندما يشترك أحد الأجهزة في خدمة واحدة أو أكثر ويدخل نطاق شبكة Wi-Fi للناشر، يتلقى المشترك إشعارًا باكتشاف ناشر مطابق. بعد أن يكتشف المشترك ناشرًا، يمكنه إرسال رسالة قصيرة أو إنشاء اتصال بالشبكة مع الجهاز الذي تم اكتشافه. يمكن أن تكون الأجهزة في الوقت نفسه ناشرًا ومشتركًا.

  • إنشاء اتصال بالشبكة: بعد أن يرصد جهازان بعضهما، يمكنهما إنشاء اتصال بالشبكة في اتجاهين باستخدام تقنية Wi-Fi Aware بدون نقطة وصول.

تتوافق اتصالات الشبكات الواعية بشبكة Wi-Fi مع معدلات معالجة بيانات أعلى عبر مسافات أطول مقارنةً باتصالات البلوتوث. تكون هذه الأنواع من عمليات الربط مفيدة للتطبيقات التي تشارك كميات كبيرة من البيانات بين المستخدمين، مثل تطبيقات مشاركة الصور.

تحسينات الإصدار 13 من نظام التشغيل Android (المستوى 33 لواجهة برمجة التطبيقات)

على الأجهزة التي تعمل بالإصدار 13 من نظام التشغيل Android (المستوى 33 لواجهة برمجة التطبيقات) والإصدارات الأحدث المتوافقة مع وضع التواصل الفوري، يمكن للتطبيقات استخدام الطريقتَين PublishConfig.Builder.setInstantCommunicationModeEnabled() و SubscribeConfig.Builder.setInstantCommunicationModeEnabled() لتفعيل وضع التواصل الفوري أو إيقافه في جلسة اكتشاف ناشر أو مشترك. يسرع وضع "التواصل الفوري" عملية تبادل الرسائل، واكتشاف الخدمة، وأي مسار بيانات تم إعداده كجزء من جلسة اكتشاف الناشر أو المشترك. لتحديد ما إذا كان الجهاز يتيح ميزة "التواصل الفوري"، استخدِم طريقة isInstantCommunicationModeSupported().

تحسينات Android 12 (المستوى 31)

يضيف نظام التشغيل Android 12 (المستوى 31 لواجهة برمجة التطبيقات) بعض التحسينات على ميزة "الاستشعار بشبكة Wi-Fi":

  • على الأجهزة التي تعمل بنظام Android 12 (المستوى 31 لواجهة برمجة التطبيقات) أو إصدار أحدث، يمكنك استخدام الدالة المخصّصة للرجوع onServiceLost() للتنبيه عند فقدان تطبيقك لخدمة تم رصدها بسبب stopped التوقف عن العمل أو الخروج من النطاق.
  • تم تبسيط إعداد مسارات البيانات في ميزة "الوصول إلى Wi-Fi". كانت الإصدارات السابقة تستخدم رسائل L2 لتوفير عنوان MAC للمشغِّل، ما كان يؤدي إلى إدخال وقت استجابة. على الأجهزة التي تعمل بنظام التشغيل Android 12 والإصدارات الأحدث، يمكن ضبط المجيب (الخادم) لقبول أي تطبيق مشابه، أي أنّه لا يحتاج إلى معرفة عنوان MAC الخاص ببرنامج تشغيل الرسالة. ويؤدي ذلك إلى تسريع عملية بدء مسار البيانات ويسمح بإنشاء روابط متعددة بين نقطتَين باستخدام طلب شبكة واحد فقط.
  • يمكن للتطبيقات التي تعمل بنظام التشغيل Android 12 أو إصدار أحدث استخدام الأسلوب WifiAwareManager.getAvailableAwareResources() للحصول على عدد مسارات البيانات المتاحة حاليًا وجلسات النشر وجلسات الاشتراك. ويمكن أن يساعد ذلك التطبيق في تحديد ما إذا كانت هناك موارد متوفرة بالقدر الكافي لتنفيذ الوظائف المطلوبة.

الإعداد الأولي

لإعداد تطبيقك من أجل استخدام ميزة الاكتشاف والاتصال بشبكة Wi-Fi Aware، يُرجى اتّباع الخطوات التالية:

  1. اطلب الأذونات التالية في ملف بيان تطبيقك:

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- 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" />
  2. تحقَّق مما إذا كان الجهاز متوافقًا مع ميزة Wi-Fi Aware باستخدام واجهة برمجة التطبيقات PackageManager ، كما هو موضّح أدناه:

    Kotlin

    context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)

    Java

    context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE);
  3. تحقَّق ممّا إذا كانت ميزة "الوصول الواعي بشبكة Wi-Fi" متاحة حاليًا. قد يكون لديك ميزة "الوصول الواعي إلى شبكة Wi-Fi" على الجهاز، ولكن قد لا تكون متاحة حاليًا لأنّ المستخدم أوقف شبكة Wi-Fi أو الموقع الجغرافي. استنادًا إلى إمكانات الأجهزة والبرامج الثابتة، قد لا تتوافق بعض الأجهزة مع ميزة "الاستشعار عبر Wi-Fi" في حال استخدام Wi-Fi Direct أو SoftAP أو ربط الجهاز بجهاز آخر. للتحقّق مما إذا كانت ميزة "الاستشعار بالشبكات Wi-Fi" متاحة حاليًا، يُرجى الاتصال بالرقم isAvailable().

    يمكن أن يتغيّر مدى توفّر ميزة "الاستشعار بالشبكات Wi-Fi" في أي وقت. يجب أن يُسجِّل تطبيقك BroadcastReceiver لتلقّي ACTION_WIFI_AWARE_STATE_CHANGED، الذي يتم إرساله عند تغيُّر مدى التوفّر. عندما يتلقّى تطبيقك intent بث المحتوى، من المفترض أن يتخلّص من جميع الجلسات الحالية (على افتراض أنّه تم إيقاف خدمة Wi-Fi Aware)، ثم يتحقّق من الحالة الحالية للمدى المتوفّر ويضبط سلوكه وفقًا لذلك. مثلاً:

    Kotlin

    val wifiAwareManager = context.getSystemService(Context.WIFI_AWARE_SERVICE) as WifiAwareManager?
    val filter = IntentFilter(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED)
    val myReceiver = object : BroadcastReceiver() {
    
        override fun onReceive(context: Context, intent: Intent) {
            // discard current sessions
            if (wifiAwareManager?.isAvailable) {
                ...
            } else {
                ...
            }
        }
    }
    context.registerReceiver(myReceiver, filter)

    Java

    WifiAwareManager wifiAwareManager = 
            (WifiAwareManager)context.getSystemService(Context.WIFI_AWARE_SERVICE)
    IntentFilter filter =
            new IntentFilter(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED);
    BroadcastReceiver myReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // discard current sessions
            if (wifiAwareManager.isAvailable()) {
                ...
            } else {
                ...
            }
        }
    };
    context.registerReceiver(myReceiver, filter);

لمزيد من المعلومات، يُرجى الاطّلاع على البثّ.

الحصول على جلسة

لبدء استخدام خدمة Wi-Fi Aware، يجب أن يحصل تطبيقك على WifiAwareSession من خلال الاتصال بـ attach(). تؤدي هذه الطريقة المهام التالية:

  • يؤدي هذا الخيار إلى تفعيل أجهزة Wi-Fi Aware.
  • الانضمام إلى مجموعة Wi-Fi Aware أو تشكيلها
  • تنشئ جلسة Wi-Fi Aware باستخدام مساحة اسم فريدة تعمل كأحد حاويات جميع جلسات الاكتشاف التي تم إنشاؤها فيها.

إذا تم إرفاق التطبيق بنجاح، ينفذ النظام عملية callback لتطبيق onAttached(). يوفّر هذا المرجع المرجعي عنصرًا من النوع WifiAwareSession يجب أن يستخدمه تطبيقك لجميع عمليات الجلسة الأخرى. يمكن للتطبيق استخدام الجلسة من أجل نشر خدمة أو الاشتراك في خدمة.

يُفترَض أن يتصل تطبيقك بـ attach() مرة واحدة فقط. إذا كان تطبيقك يستدعي attach() عدة مرات، يتلقّى التطبيق جلسة مختلفة لكل طلب، ولكل جلسة مساحة اسم خاصة بها. قد يكون هذا مفيدًا في سيناريوهات معقدة، ولكن يجب تجنبه بشكل عام.

نشر خدمة

لجعل الخدمة قابلة للاكتشاف، يمكنك استدعاء الأسلوب publish() الذي يأخذ المَعلمات التالية:

  • تحدّد السمة PublishConfig اسم الخدمة وخصائص الإعداد الأخرى، مثل فلتر المطابقة.
  • DiscoverySessionCallback لتحديد الإجراءات التي سيتم تنفيذها عند حدوث الأحداث، مثل عندما يتلقّى المشترك رسالة

وفي ما يلي مثال لذلك:

Kotlin

val config: PublishConfig = PublishConfig.Builder()
        .setServiceName(AWARE_FILE_SHARE_SERVICE_NAME)
        .build()
awareSession.publish(config, object : DiscoverySessionCallback() {

    override fun onPublishStarted(session: PublishDiscoverySession) {
        ...
    }

    override fun onMessageReceived(peerHandle: PeerHandle, message: ByteArray) {
        ...
    }
})

Java

PublishConfig config = new PublishConfig.Builder()
    .setServiceName(Aware_File_Share_Service_Name)
    .build();

awareSession.publish(config, new DiscoverySessionCallback() {
    @Override
    public void onPublishStarted(PublishDiscoverySession session) {
        ...
    }
    @Override
    public void onMessageReceived(PeerHandle peerHandle, byte[] message) {
        ...
    }
}, null);

في حال نجاح النشر، يتم استدعاء دالّة ردّ الاتصال onPublishStarted().

بعد النشر، عندما تنتقل الأجهزة التي تشغل تطبيقات المشتركين المطابقة إلى نطاق Wi-Fi لجهاز النشر، يكتشف المشتركون الخدمة. عندما يكتشف أحد المشتركين ناشرًا، لا يتلقّى الناشر إشعارًا. ولكن إذا أرسل المشترك رسالة إلى الناشر، سيتلقّى الناشر إشعارًا. وعند حدوث ذلك، يتم استدعاء طريقة معاودة الاتصال onMessageReceived(). يمكنك استخدام الوسيطة PeerHandle من هذه الطريقة ل إرسال رسالة إلى المشترك أو إنشاء اتصال به.

لإيقاف نشر الخدمة، يُرجى الاتصال بـ DiscoverySession.close(). ترتبط جلسات "الاقتراحات" بجلسة الوالد WifiAwareSession. إذا كانت الجلسة الرئيسية مغلقة، فسيتم أيضًا إغلاق جلسات الاكتشاف المرتبطة بها. وفي حين أنّه يتم إغلاق العناصر المهملة أيضًا، لا يضمن النظام إغلاق جلسات خارج النطاق، لذا ننصحك باستدعاء close() methods بشكل صريح.

الاشتراك في خدمة

للاشتراك في خدمة، يمكنك استدعاء الأسلوب subscribe()، الذي يأخذ المَعلمات التالية:

  • SubscribeConfig يحدِّد اسم الخدمة المطلوب الاشتراك فيها وخصائص الضبط الأخرى، مثل فلتر المطابقة.
  • DiscoverySessionCallback تحدّد الإجراءات التي يجب تنفيذها عند وقوع الأحداث، مثل اكتشاف ناشر.

وفي ما يلي مثال لذلك:

Kotlin

val config: SubscribeConfig = SubscribeConfig.Builder()
        .setServiceName(AWARE_FILE_SHARE_SERVICE_NAME)
        .build()
awareSession.subscribe(config, object : DiscoverySessionCallback() {

    override fun onSubscribeStarted(session: SubscribeDiscoverySession) {
        ...
    }

    override fun onServiceDiscovered(
            peerHandle: PeerHandle,
            serviceSpecificInfo: ByteArray,
            matchFilter: List<ByteArray>
    ) {
        ...
    }
}, null)

Java

SubscribeConfig config = new SubscribeConfig.Builder()
    .setServiceName("Aware_File_Share_Service_Name")
    .build();

awareSession.subscribe(config, new DiscoverySessionCallback() {
    @Override
    public void onSubscribeStarted(SubscribeDiscoverySession session) {
        ...
    }

    @Override
    public void onServiceDiscovered(PeerHandle peerHandle,
            byte[] serviceSpecificInfo, List<byte[]> matchFilter) {
        ...
    }
}, null);

إذا نجحت عملية الاشتراك، يستدعي النظام دالّة callback الخاصة بالوسيطonSubscribeStarted() في تطبيقك. وبما أنّه يمكنك استخدام الوسيطةSubscribeDiscoverySession في دالّة callback للتواصل مع ناشر بعد أن يعثر عليه تطبيقك، يجب حفظ هذا المرجع. ويمكنك تعديل جلسة الاشتراك متى شئت من خلال النقر على updateSubscribe() في جلسة الاكتشاف.

في هذه المرحلة، ينتظر اشتراكك وصول الناشرين المطابقين إلى نطاق شبكة Wi-Fi. عند حدوث ذلك، ينفذ النظام أسلوب callback onServiceDiscovered(). يمكنك استخدام الوسيطة PeerHandle من ردّ الاتصال هذا لإرسال رسالة أو إنشاء ربط بهذا الناشر.

لإيقاف الاشتراك في خدمة، يُرجى الاتصال DiscoverySession.close(). ترتبط جلسات "الاقتراحات" بجلسة الوالد WifiAwareSession. في حال إغلاق الجلسة الرئيسية، يتم أيضًا إغلاق جلسات الاستكشاف المرتبطة بها. وفي حين أنّه يتم إغلاق العناصر المهملة أيضًا، لا يضمن النظام إغلاق جلسات خارج النطاق، لذا ننصحك باستدعاء close() methods بشكل صريح.

إرسال رسالة

لإرسال رسالة إلى جهاز آخر، تحتاج إلى العناصر التالية:

لإرسال رسالة، اتصل بالرقم sendMessage(). قد تحدث بعد ذلك عمليات معاودة الاتصال التالية:

  • عندما يستلم المستخدم الرسالة بنجاح، يطلب النظام onMessageSendSucceeded() معاودة الاتصال في تطبيق الإرسال.
  • عندما يتلقّى المستخدم الآخر رسالة إلكترونية، يطلب النظام onMessageReceived() معاودة الاتصال في تطبيق الاستلام.

على الرغم من أنّ PeerHandle مطلوب للتواصل مع التطبيقات المشابهة، يجب ألّا تعتمد عليه كمعرّف دائم للتطبيقات المشابهة. يمكن للتطبيق استخدام معرّفات من مستوى أعلى، تكون مضمّنة في خدمة الاكتشاف نفسها أو في الرسائل اللاحقة. يمكنك تضمين معرّف في خدمة الاكتشاف باستخدام طريقة setMatchFilter() أو setServiceSpecificInfo() PublishConfig أو SubscribeConfig. تؤثر الطريقة setMatchFilter() في ميزة "اقتراحات"، في حين لا تؤثر الطريقة setServiceSpecificInfo() في هذه الميزة.

يشير تضمين معرّف في رسالة إلى تعديل صفيف وحدات البايت للرسالة بهدف تضمين معرّف (على سبيل المثال، كأول زوج من وحدات البايت).

إنشاء اتصال

تتيح تقنية Wi-Fi Aware إمكانية التواصل بين جهازَين مزوّدين بتقنية Wi-Fi Aware.

لإعداد اتصال العميل بالخادم:

  1. استخدِم ميزة "الاستكشاف باستخدام تقنية Wi-Fi Aware" من أجل نشر خدمة (على الخادم) والاشتراك في خدمة (على العميل).

  2. بعد أن يعثر المشترك على الناشر، أرسِل رسالة من المشترك إلى الناشر.

  3. ابدأ تشغيل ServerSocket على جهاز الناشر وعليك ضبط المنفذ الخاص به أو الحصول عليه:

    Kotlin

    val ss = ServerSocket(0)
    val port = ss.localPort

    Java

    ServerSocket ss = new ServerSocket(0);
    int port = ss.getLocalPort();
  4. استخدِم ConnectivityManager لطلب شبكة Wi-Fi Aware على الناشر باستخدام WifiAwareNetworkSpecifier، مع تحديد جلسة الاكتشاف وPeerHandle للمشترك، والتي حصلت عليها من الرسالة التي أرسلها المشترك:

    Kotlin

    val networkSpecifier = WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle)
        .setPskPassphrase("somePassword")
        .setPort(port)
        .build()
    val myNetworkRequest = NetworkRequest.Builder()
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
        .setNetworkSpecifier(networkSpecifier)
        .build()
    val callback = object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) {
            ...
        }
    
        override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
            ...
        }
    
        override fun onLost(network: Network) {
            ...
        }
    }
    
    connMgr.requestNetwork(myNetworkRequest, callback);

    Java

    NetworkSpecifier networkSpecifier = new WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle)
        .setPskPassphrase("somePassword")
        .setPort(port)
        .build();
    NetworkRequest myNetworkRequest = new NetworkRequest.Builder()
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
        .setNetworkSpecifier(networkSpecifier)
        .build();
    ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(Network network) {
            ...
        }
    
        @Override
        public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
            ...
        }
    
        @Override
        public void onLost(Network network) {
            ...
        }
    };
    
    ConnectivityManager connMgr.requestNetwork(myNetworkRequest, callback);
  5. بعد أن يطلب الناشر شبكة، عليه إرسال رسالة إلى المشترك.

  6. بعد أن يتلقّى المشترك الرسالة من الناشر، يُرجى طلب شبكة Wi-Fi Aware على جهاز المشترك باستخدام الطريقة نفسها المستخدَمة على جهاز الناشر. لا تحدِّد منفذًا عند إنشاء NetworkSpecifier. يتم استدعاء methods المناسبة للرجوع عند توفُّر اتصال الشبكة أو تغييره أو فقدانه.

  7. بعد استدعاء طريقة onAvailable() في الاشتراك، يتوفّر عنصر Network الذي يمكنك من خلاله فتح Socket للتواصل مع ServerSocket في الناشر، ولكن عليك معرفة عنوان IPv6 ومينفذ ServerSocket. وتحصل على هذه القيم من الكائن NetworkCapabilities المقدَّم في معاودة الاتصال onCapabilitiesChanged():

    Kotlin

    val peerAwareInfo = networkCapabilities.transportInfo as WifiAwareNetworkInfo
    val peerIpv6 = peerAwareInfo.peerIpv6Addr
    val peerPort = peerAwareInfo.port
    ...
    val socket = network.getSocketFactory().createSocket(peerIpv6, peerPort)

    Java

    WifiAwareNetworkInfo peerAwareInfo = (WifiAwareNetworkInfo) networkCapabilities.getTransportInfo();
    Inet6Address peerIpv6 = peerAwareInfo.getPeerIpv6Addr();
    int peerPort = peerAwareInfo.getPort();
    ...
    Socket socket = network.getSocketFactory().createSocket(peerIpv6, peerPort);
  8. عند الانتهاء من الاتصال بالشبكة، اتصل بالرقم unregisterNetworkCallback().

رصد الأجهزة المجاورة واكتشاف الأجهزة بالاستناد إلى الموقع الجغرافي

يمكن للجهاز الذي يتضمّن إمكانات تحديد الموقع الجغرافي باستخدام تقنية RTT في Wi-Fi قياس المسافة إلى الأجهزة المشابهة مباشرةً واستخدام هذه المعلومات لتحديد حدود عملية اكتشاف الخدمات التي تستخدم تقنية Wi-Fi Aware.

تسمح واجهة برمجة التطبيقات Wi-Fi RTT بقياس المسافة مباشرةً إلى جهاز متوافق مع Wi-Fi Aware باستخدام إما عنوان MAC أو PeerHandle.

يمكن تقييد ميزة "الاستشعار بالشبكات Wi-Fi" لاكتشاف الخدمات ضمن حدود جغرافية معيّنة فقط. على سبيل المثال، يمكنك إعداد حدود جغرافية تسمح باكتشاف جهاز ينشر خدمة "Aware_File_Share_Service_Name" على مسافة لا تقل عن 3 أمتار (يتم تحديدها على أنّها 3,000 مم) ولا تزيد عن 10 أمتار (يتم تحديدها على أنّها 10,000 مم).

لتفعيل ميزة تحديد حدود جغرافية، على كل من الناشر والمشترك اتّخاذ إجراء:

  • يجب أن يفعّل الناشر النطاقات على الخدمة المنشورة باستخدام setRangingEnabled(true).

    وإذا لم يفعّل الناشر النطاق، يتم تجاهل أي قيود على الحدود الجغرافية يحدّدها المشترك ويتم تنفيذ الاكتشاف الطبيعي، مع تجاهل المسافة.

  • على المشترك تحديد حدود جغرافية باستخدام بعض المجموعات من setMinDistanceMm و setMaxDistanceMm.

    بالنسبة لأي من القيمتين، لا تعني المسافة غير المحددة أي حد. ولا يتضمن تحديد الحد الأقصى للمسافة إلا أن تكون المسافة الأدنى 0. إنّ تحديد الحد الأدنى للمسافة فقط لا يعني عدم وجود حدّ أقصى.

عند اكتشاف خدمة نظير داخل سياج جغرافي، يتم تشغيل استدعاء onServiceDiscoveredWithinRange الذي يوفر المسافة التي تم قياسها للنظير. يمكن بعد ذلك استخدام واجهة برمجة التطبيقات Wi-Fi RTT المباشرة حسب الحاجة لقياس المسافة في مواعيد لاحقة.