النطاق بين الأجهزة

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

تتيح وحدة النطاق التقنيات التالية:

إمكانات النطاقات ومدى توفّرها

يوفّر فئة RangingManager للتطبيقات معلومات حول تكنولوجيات النطاق التي يتيحها الجهاز المحلي، بالإضافة إلى مدى توفّر كل تكنولوجيا وإمكاناتها. يمكن للتطبيقات التسجيل للحصول على Callback لتلقّي آخر المعلومات حول أي تغييرات تطرأ على مدى توفّر أو إمكانات أي تكنولوجيات متوافقة.

أدوار الجهاز

يجب أن يكون الجهاز المشارك في جلسة تحديد المسافة إما مشغِّلاً أو مستجيبًا. يبدأ الجهاز المُشغِّل جلسة تحديد المسافة باستخدام جهاز واحد أو أكثر من أجهزة الاستجابة. يستجيب جهاز المجيب لطلبات تحديد المسافة من بدء واحد فقط في المرة الواحدة. يمكنك تحديد دور جهاز معيّن في جلسة قياس المسافة باستخدام فئة RangingPreference.

أنواع الجلسات التي تتراوح بين

عند بدء جلسة قياس المسافة بين الأجهزة، غالبًا ما يكون من الضروري إنشاء عملية نقل بيانات خارج النطاق (OOB) لتبادل المَعلمات الخاصة بالجلسة.

يمكن أن تتعامل وحدة النطاق مع مفاوضات النطاق غير القابل للوصول (OOB) نيابةً عنك، ولكنها تتيح أيضًا عمليات تنفيذ النطاق غير القابل للوصول المخصّصة.

الشكل 1. مسار خارج نطاق الشبكة لأنواع الجلسات

التنفيذ التلقائي لميزة "الخروج من وضع التوفّر خارج نطاق المؤسسة"

في نوع الجلسة هذا (RANGING_SESSION_OOB)، تعالج وحدة النطاق مفاوضات النطاق خارج نطاق الاتصال لبدء جلسة نطاق. ويختار التطبيق المَعلمات المناسبة استنادًا إلى الإعدادات المفضّلة للاتصال التي يوفّرها، ويستخدم التكنولوجيات المناسبة استنادًا إلى الإمكانات المتاحة لكلا الجهازَين. يستخدم نوع الجلسة هذا OOB specification موحّدًا.

لا تحدِّد وحدة "تحديد النطاق" سوى تنسيق بيانات النطاق الخارجي وتسلسلها المُستخدَم للتفاعل مع جهاز مماثل. ولا يتعامل مع اكتشاف الأجهزة المشابهة أو إنشاء الاتصال.

تنفيذ مخصّص للإعلانات خارج نطاق الصفحة

في نوع الجلسة هذا (RANGING_SESSION_RAW)، يتجاوز التطبيق مسار الخروج من نطاق الشبكة (OOB) في ملف برمجي لتحديد النطاق (Ranging module) ويتولى التفاوض على الخروج من نطاق الشبكة (OOB) وإعداداته. وهذا يعني أنّه على التطبيق تحديد التكنولوجيات التي يتوافق معها الجهاز المشابه، والتفاوض على مَعلمات تحديد المسافة، وبدء جلسة تحديد المسافة.

الإعدادات المفضّلة لنطاق الأسعار

استخدِم عنصر RangingPreference لتحديد المَعلمات المطلوبة لجلسة تحديد النطاق. ويتضمن ذلك ما يلي:

  • دور الجهاز: يشير ذلك إلى ما إذا كان الجهاز سيكون المشغِّل أو المُجيب.
  • إعداد النطاق يحدِّد عنصر RangingConfig نوع جلسة القياس والمَعلمات الأخرى اللازمة لبدء جلسة قياس.
  • إعداد الجلسة: يحدِّد عنصر SessionConfig المَعلمات التي سيتم فرضها على جلسة تحديد المسافة، مثل الحد الأقصى للقياس، ودمج الاستشعار، وإعدادات السياج الجغرافي، وغير ذلك.

إذن تحديد النطاق

تتطلّب وحدة النطاق إذنًا موحّدًا جديدًا (android.permission.RANGING) للوصول إلى جميع تكنولوجيات تحديد النطاق الحالية والمستقبلية. هذا الإذن مُدرَج في قائمة NEARBY_DEVICES_PERMISSIONS.

<uses-permission android:name="android.permission.RANGING" />

القيود

قد تحدّ ميزة "تحديد النطاق" من نطاق القياس لعدة أسباب، بما في ذلك ما يلي:

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

تفرض وحدة النطاق أيضًا القيود المعروفة التالية:

  • لا تتيح وحدة النطاق إلا إرسال بيانات النطاق إلى الأجهزة المشابهة للنطاق الفائق العرض. بالنسبة إلى التقنيات الأخرى، لا تُرسِل وحدة "قياس المسافة" سوى بيانات قياس المسافة إلى الجهاز المُشغِّل.
  • لا تتيح وحدة قياس المسافة إلا إضافة الأجهزة بشكل ديناميكي في وضع قياس المسافة الأساسي، وذلك فقط للنطاق الفائق العرض.
  • لا تتوافق وحدة النطاق مع جلسات النطاق الفائق العرض من جهاز إلى عدة أجهزة في عمليات التنفيذ التلقائية للوضع خارج نطاق الرؤية. في حال تم إدخال أسماء معرِّفات أجهزة متعددة، تنشئ الوحدة جلسة بين جهازَين لكل جهاز من الأجهزة المشابهة التي تتيح استخدام تقنية النطاق الفائق العرض.

إجراء جلسة تحديد النطاق

لإجراء جلسة قياس مدى الرؤية باستخدام وحدة "قياس مدى الرؤية"، اتّبِع الخطوات التالية:

  1. تأكَّد من أنّ جميع الأجهزة تعمل بنظام التشغيل Android 16 أو إصدار أحدث.
  2. اطلب إذن android.permission.RANGING في بيان التطبيق.
  3. تقييم إمكانات تقنيات تحديد المسافة ومدى توفّرها
  4. اكتشاف جهاز نظير لإجراء عمليات تحديد المسافة
  5. أنشئ اتصالاً لتبادل خارج النطاق باستخدام أيّ من أنواع الجلسات الموضّحة في أنواع جلسات تحديد النطاق.
  6. بدء عملية تحديد المسافة والحصول على بيانات تحديد المسافة باستمرار
  7. إنهاء جلسة النطاق

يوضّح نموذج الرمز البرمجي التالي هذه الخطوات لكل من دور المُشغِّل ودور المُجيب.

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. يتناول هذا النموذج جميع تقنيات تحديد المسافة التي تتوافق مع وحدة "تحديد المسافة"، ويشمل عمليات لكل من نوعَي جلسة المتوافقَين.