البلوتوث

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

إدارة الاتصال عبر البلوتوث

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

ضبط إدارة الاتصال بالمركبات

إيقاف سياسة الهاتف التلقائية

تحافظ حِزمة Android Bluetooth على سياسة اتصال للهواتف تكون مفعّلة تلقائيًا. يجب إيقاف هذه السياسة على جهازك كي لا تتعارض مع السياسة المخصّصة للسيارات في CarBluetoothService. على الرغم من أنّ تراكب منتجات السيارات من المفترض أن يعالج ذلك نيابةً عنك، يمكنك إيقاف سياسة الهاتف في تراكب الموارد عن طريق ضبط enable_phone_policy على false في MAXIMUM_CONNECTED_DEVICES في /packages/apps/Bluetooth/res/values/config.xml.

استخدام سياسة السيارات التلقائية

تحافظ فئة CarBluetoothService على أذونات الملف الشخصي التلقائية. يمكنك العثور على قائمة الأجهزة المعروفة وأولويات إعادة ربط الملف الشخصي بها في service/src/com/android/car/BluetoothProfileDeviceManager.java.

يمكن أيضًا العثور على سياسة إدارة الاتصال عبر البلوتوث في service/src/com/android/car/BluetoothDeviceConnectionPolicy.java. بشكلٍ تلقائي، تحديد حالات اتصال البلوتوث بالأجهزة المقترنة وإلغاء ربطها ويدير أيضًا الحالات الخاصة بالسيارات التي يجب فيها تفعيل المحوِّل وإيقافه.

إنشاء سياسة مخصّصة لإدارة اتصالات المركبات

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

إيقاف السياسة التلقائية للمركبات

أولاً، لاستخدام سياسة مخصّصة، يجب إيقاف السياسة التلقائية للسيارات من خلال ضبط useDefaultBluetoothConnectionPolicy على false في تراكب الموارد. تم تحديد هذا المرجع في الأصل كجزء من MAXIMUM_CONNECTED_DEVICES في packages/services/Car/service/res/values/config.xml.

تفعيل محوِّل البلوتوث وإيقافه

إنّ إحدى الوظائف الأساسية لسياسة التطبيق هي تفعيل محوِّل البلوتوث وإيقافه في الأوقات المناسبة. يمكنك استخدام واجهات برمجة تطبيقات إطارَي العمل BluetoothAdapter.enable() و BluetoothAdapter.disable() لتفعيل المحوِّل وإيقافه. يجب أن تراعي هذه الطلبات الحالة الثابتة التي اختارها المستخدم من خلال "الإعدادات" أو أي وسيلة أخرى. في ما يلي إحدى طرق إجراء ذلك:

/**
 * Turn on the Bluetooth adapter.
 */
private void enableBluetooth() {
    BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (bluetoothAdapter == null) {
        return;
    }
    bluetoothAdapter.enable();
}

/**
 * Turn off the Bluetooth adapter.
 */
private void disableBluetooth() {
    BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (bluetoothAdapter == null) {
        return;
    }
    // Will shut down _without_ persisting the off state as the desired state
    // of the Bluetooth adapter for next start up. This does nothing if the adapter
    // is already off, keeping the existing saved desired state for next reboot.
    bluetoothAdapter.disable(false);
}

تحديد وقت تفعيل محوِّل البلوتوث وإيقافه

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

private final CarPowerStateListenerWithCompletion mCarPowerStateListener =
        new CarPowerStateListenerWithCompletion() {
    @Override
    public void onStateChanged(int state, CompletableFuture<Void> future) {
        if (state == CarPowerManager.CarPowerStateListener.ON) {
            if (isBluetoothPersistedOn()) {
                enableBluetooth();
            }
            return;
        }

        // "Shutdown Prepare" is when the user perceives the car as off
        // This is a good time to turn off Bluetooth
        if (state == CarPowerManager.CarPowerStateListener.SHUTDOWN_PREPARE) {
            disableBluetooth();

            // Let CarPowerManagerService know we're ready to shut down
            if (future != null) {
                future.complete(null);
            }
            return;
        }
    }
};

تحديد وقت ربط الأجهزة

وبالمثل، عند تحديد الأحداث التي يجب أن تبدأ اتصالات الأجهزة، يقدّم CarBluetoothManager طلب بيانات connectDevices() من واجهة برمجة التطبيقات الذي يواصل توصيل الأجهزة استنادًا إلى قوائم الأولوية المحدّدة لكل ملف شخصي على البلوتوث.

على سبيل المثال، يمكنك إجراء ذلك عند تفعيل محوِّل البلوتوث:

private class BluetoothBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
        if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
            int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
            if (state == BluetoothAdapter.STATE_ON) {
                // mContext should be your app's context
                Car car = Car.createCar(mContext);
                CarBluetoothManager carBluetoothManager =
                        (CarBluetoothManager) car.getCarManager(Car.BLUETOOTH_SERVICE);
                carBluetoothManager.connectDevices();
            }
        }
    }
}

التحقّق من إدارة الاتصال بالمركبات

أسهل طريقة للتحقّق من سلوك سياسة الاتصال هي تفعيل البلوتوث على جهاز IVI والتحقّق من ربطه تلقائيًا بالأجهزة الصحيحة بالترتيب المناسب. يمكنك تفعيل محوِّل البلوتوث أو إيقافه من خلال واجهة مستخدم الإعدادات، أو باستخدام أوامر adb التالية:

adb shell su u$(adb shell am get-current-user)_system svc bluetooth disable
adb shell su u$(adb shell am get-current-user)_system svc bluetooth enable

بالإضافة إلى ذلك، يمكن استخدام ناتج الأمر التالي للاطّلاع على معلومات تصحيح الأخطاء ذات الصلة بعمليات الاتصال عبر البلوتوث:

adb shell dumpsys car_service

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

ملفات البلوتوث الشخصية للسيارات

في Android، يمكن أن تتيح واجهة IVI توصيل أجهزة متعددة في الوقت نفسه عبر البلوتوث. تتيح خدمات الهاتف عبر البلوتوث المتعدّدة الأجهزة للمستخدمين ربط أجهزة منفصلة في الوقت نفسه، مثل هاتف شخصي وهاتف عمل، وإجراء مكالمات بدون لمس الجهاز من أي منهما.

يتم فرض حدود الاتصال من خلال كل ملف شخصي فردي لتقنية Bluetooth، وعادةً ما يكون ذلك ضمن تنفيذ خدمة الملف الشخصي نفسها. بشكلٍ تلقائي، لا يتخذ CarBluetoothService أيّ إجراء إضافي بشأن الحد الأقصى المسموح به لعدد الأجهزة المتصلة.

الملف الشخصي بدون لمس الجهاز

يسمح ملف "القيادة بدون استخدام اليدين" (HFP) للمركبة بإجراء مكالمات هاتفية وتلقّيها عبر جهاز تحكّم عن بُعد متصل. يسجِّل كل اتصال بالجهاز حساب هاتف منفصلاً في TelecomManager، الذي يعلن عن أي حسابات هواتف متاحة لتطبيقات IVI.

يمكن توصيل IVI بأجهزة متعددة عبر بروتوكول HFP. MAX_STATE_MACHINES_POSSIBLE MAXIMUM_CONNECTED_DEVICES في HeadsetClientService يحدِّد الحد الأقصى لعدد اتصالات HFP المتزامنة.

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

تجدر الإشارة إلى أنّ تطبيق "أداة الاتصال" التلقائي لا يتيح استخدام عدة أجهزة HFP متصلة في الوقت نفسه. لتنفيذ بروتوكول HFP على أجهزة متعددة، يجب إجراء تخصيص للسماح للمستخدمين باختيار حساب الجهاز الذي سيتم استخدامه عند إجراء مكالمة. بعد ذلك، يتصل التطبيق بـ telecomManager.placeCall باستخدام الحساب الصحيح. عليك التأكّد من أنّ وظائف الأجهزة المتعددة الأخرى تعمل على النحو المطلوب أيضًا.

التحقّق من بروتوكول HFP المتوافق مع الأجهزة المتعددة

للتحقّق من عمل ميزة الاتصال بأجهزة متعددة بشكل صحيح عبر البلوتوث:

  1. باستخدام البلوتوث، يمكنك توصيل جهاز بوحدة IVI وبث الصوت من الجهاز.
  2. وصِّل هاتفَين بوحدة IVI عبر البلوتوث.
  3. اختَر هاتفًا واحدًا. إجراء مكالمة صادرة مباشرةً من الهاتف، وإجراء مكالمة صادرة باستخدام IVI
    1. في كلتا الحالتَين، تأكَّد من أنّ الصوت الذي يتم بثه يتوقّف مؤقتًا وأنّه يتم تشغيل صوت الهاتف على مكبّرات الصوت المتصلة بوحدة IVI.
  4. باستخدام الهاتف نفسه، يمكنك تلقّي مكالمة واردة على الهاتف مباشرةً، وتلقّي مكالمة واردة باستخدام شاشة IVI.
    1. في كلتا الحالتَين، تأكَّد من أنّه يتم إيقاف بث الصوت مؤقتًا ويتم تشغيل صوت الهاتف على مكبّرات الصوت المتصلة بوحدة IVI.
  5. كرِّر الخطوتَين 3 و4 مع الهاتف الآخر المتصل.

مكالمات الطوارئ

إنّ إمكانية إجراء مكالمات الطوارئ هي جانب مهم من وظائف الهاتف والبلوتوث في السيارة. هناك عدد من الطرق التي يمكن بها إجراء مكالمة طوارئ من خلال IVI، بما في ذلك:

  • حلّ مستقل لنظام eCall
  • حلّ eCall مدمج في نظام IVI
  • الاعتماد على هاتف متصل بالبلوتوث في حال عدم توفّر نظام مضمّن

ربط مكالمة طوارئ

على الرغم من أنّ معدات eCall مهمة جدًا للسلامة، إلا أنّها غير مدمجة حاليًا في Android. من الممكن استخدام ConnectionService لعرض ميزات الاتصال في حالات الطوارئ من خلال Android، ما يمنح أيضًا ميزة توفير خيارات تسهيل الاستخدام لمكالمات الطوارئ. لمزيد من المعلومات، يُرجى الاطّلاع على مقالة إنشاء تطبيق اتصال.

في ما يلي مثال على كيفية إنشاء ConnectionService في حالات الطوارئ:

public class YourEmergencyConnectionService extends ConnectionService {

    @Override
    public Connection onCreateOutgoingConnection(
            PhoneAccountHandle connectionManagerAccount,
            ConnectionRequest request) {
        // Your equipment specific procedure to make ecall
        // ...
    }

    private void onYourEcallEquipmentReady() {

        PhoneAccountHandle handle =
            new PhoneAccountHandle(new ComponentName(context, YourEmergencyConnectionService),
                    YourEmergencyConnectionId);
        PhoneAccount account =
            new PhoneAccount.Builder(handle, eCallOnlyAccount)
            .setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_TEL))
            .setCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS
                    | PhoneAccount.CAPABILITY_MULTI_USER)
            .build():
        mTelecomManager.registerPhoneAccount(account);
        mTelecomManager.enablePhoneAccount(account.getAccountHandle(), true);
    }
}

تفعيل البلوتوث لإجراء مكالمات الطوارئ

قبل الإصدار 10 من Android، كان الاتصال بخدمات الطوارئ يتطلّب الاتصال المباشر من الهاتف وتفعيل معدات خاصة إذا كانت متاحة (على سبيل المثال، التفعيل التلقائي عند رصد خطر أو عند تنفيذ إجراء من المستخدم). في الإصدار 10 من نظام التشغيل Android والإصدارات الأحدث، يمكن لتطبيق "برنامج الاتصال" في السيارة الاتصال مباشرةً بأحد أرقام الطوارئ، شرط أن يكون هذا MAXIMUM_CONNECTED_DEVICES في apps/Bluetooth/res/values/config.xml:

<!-- For supporting emergency call through the hfp client connection service --> <bool name=”hfp_client_connection_service_support_emergency_call”>true</bool>

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

الملف الشخصي للوصول إلى دفتر الهاتف

ينزِّل ملف الوصول إلى دفتر العناوين عبر البلوتوث (PBAP) جهات الاتصال وسجلّات المكالمات من جهاز بعيد متصل. يحافظ بروتوكول PBAP على قائمة مجمّعة وقابلة للبحث من الجهات التي يُجري تعديلها أسلوب حالة عميل PBAP. يتفاعل كل جهاز متصل مع آلة حالة عميل PBAP منفصلة، ما يؤدي إلى ربط جهات الاتصال بالجهاز المناسب عند إجراء مكالمة.

‫PBAP أحادي الاتجاه، وبالتالي يتطلب من IVI إنشاء اتصالات بأي MAXIMUM_CONNECTED_DEVICES في PbapClientService يحدِّد الحد الأقصى لعدد اتصالات PBAP المتزامنة المسموح بها مع IVI. يخزِّن برنامج PBAP جهات الاتصال لكل جهاز متصل في موفِّر جهات الاتصال الذي يمكن للتطبيق الوصول إليه بعد ذلك لاستخراج دفتر الهاتف لكل جهاز.

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

الملف الشخصي للوصول إلى الرسائل

يسمح ملف الوصول إلى الرسائل (MAP) عبر البلوتوث للمركبة بإرسال وتلقّي رسائل SMS عبر جهاز عن بُعد متصل. لا يتم حاليًا تخزين الرسائل على جهاز IVI. بدلاً من ذلك، عندما يتلقّى الجهاز البعيد المتصل رسالة، يتلقّى واجهة برمجة التطبيقات لعرض الفيديوهات التفاعلية الرسالة ويحلّلها ويبثّ محتواها في مثيل Intent، ويمكن للتطبيق تلقّيها بعد ذلك.

للاتصال بجهاز جوّال بغرض إرسال الرسائل واستلامها، يجب أن يبدأ IVI عملية الاتصال بـ MAP. يحدِّد MAXIMUM_CONNECTED_DEVICES في MapClientService الحد الأقصى لعدد اتصالات جهاز MAP المتزامنة المسموح بها مع IVI. يجب أن يحصل كل اتصال على إذن من IVI و جهاز الجوّال قبل نقل الرسائل.

نمط توزيع الصوت المتقدّم

يسمح ملف A2DP (المعروف باسم "ملف توزيع الصوت المتقدّم") عبر البلوتوث للسيارة بتلقّي مصادر صوت من جهاز عن بُعد متصل.

على عكس الملفات الشخصية الأخرى، يتم فرض الحد الأقصى لعدد أجهزة A2DP المتصلة في الحزمة الأصلية وليس في Java. تمّ ضبط القيمة حاليًا بشكلٍ ثابت على 1 باستخدام متغيّر kDefaultMaxConnectedAudioDevices في packages/modules/Bluetooth/system/btif/src/btif_av.cc.

نمط التحكم عن بُعد في الصوت/الفيديو

يتيح ملف التحكم عن بُعد في الصوت/الفيديو عبر البلوتوث (AVRCP) للمركبة التحكّم في مشغّلات الوسائط والتصفّح عليها على جهاز عن بُعد متصل. بما أنّ IVI يلعب دور وحدة تحكّم في AVRCP، فإنّ أي عناصر تحكّم يتم تفعيلها وتؤثر في تشغيل الصوت تعتمد على اتصال A2DP بالجهاز المستهدَف.

لكي يتمكّن جهاز IVI من تصفُّح مشغّل وسائط معيّن على هاتف Android من خلال بروتوكول AVRCP، يجب أن يقدّم تطبيق الوسائط على الهاتف MediaBrowserService وأن يسمح لجهاز com.android.bluetooth بالوصول إلى هذه الخدمة. توضّح المقالة إنشاء خدمة تصفّح وسائط كيفية إجراء ذلك بالتفصيل.