Bluetooth

Android zapewnia pełną implementację Bluetooth z obsługą wielu popularnych profili Bluetooth w samochodzie. Wprowadziliśmy też wiele ulepszeń, które poprawiają wydajność i komfort korzystania z innych urządzeń i usług.

Zarządzanie połączeniami Bluetooth

W Androidzie CarBluetoothService przechowuje urządzenia Bluetooth bieżącego użytkownika i listy priorytetów dla każdego połączenia profilu z systemem IVI. Urządzenia są połączone z profilami w określonej kolejności priorytetów. Kiedy włączać i wyłączać urządzenia oraz łączyć je z profilem, określa domyślna zasada połączenia, którą w razie potrzeby można zastąpić za pomocą nakładki zasobu.

Konfigurowanie zarządzania połączeniami w przypadku samochodów

Wyłączanie domyślnych zasad dotyczących telefonów

Stos Bluetooth na Androidzie utrzymuje domyślnie włączoną zasadę połączeń dla telefonów. Ta zasada musi być wyłączona na urządzeniu, aby nie kolidowała z zasadą dotyczącą samochodów w  CarBluetoothService. Nakładka na produkt samochodowy powinna się tym zająć, ale możesz wyłączyć zasady dotyczące telefonów w  nakładce na zasób, ustawiając wartość enable_phone_policy na falseMAXIMUM_CONNECTED_DEVICES /packages/apps/Bluetooth/res/values/config.xml.

Używanie domyślnych zasad dotyczących motoryzacji

CarBluetoothService zachowuje domyślne uprawnienia profilu. Lista znanych urządzeń i ich priorytetów ponownego łączenia z profilem znajduje się w service/src/com/android/car/BluetoothProfileDeviceManager.java.

Zasady zarządzania połączeniami Bluetooth znajdziesz też w  service/src/com/android/car/BluetoothDeviceConnectionPolicy.java. Domyślnie ta zasada określa, kiedy Bluetooth powinien łączyć się z sparowanymi urządzeniami i rozłączać się z nimi. Zarządza też przypadkami związanymi z samochodem, w których adapter powinien być włączony lub wyłączony.

Tworzenie własnych zasad zarządzania połączeniami w przypadku samochodów

Jeśli domyślna polityka dotycząca motoryzacji nie spełnia Twoich potrzeb, możesz ją wyłączyć i zastąpić własną polityką niestandardową. Twoja niestandardowa zasada musi co najmniej określać, kiedy włączać i wyłączać adapter Bluetooth oraz kiedy łączyć urządzenia. Do włączania i wyłączania adaptera Bluetooth oraz inicjowania połączeń z urządzeniami można używać różnych zdarzeń, w tym zdarzeń wynikających ze zmian w określonych właściwościach samochodu.

Wyłączanie domyślnych zasad dotyczących motoryzacji

Aby użyć niestandardowej zasady, musisz najpierw wyłączyć domyślną zasadę dotyczącą motoryzacji, ustawiając useDefaultBluetoothConnectionPolicy na false nakładce zasobu. Ten zasób jest pierwotnie zdefiniowany jako część MAXIMUM_CONNECTED_DEVICES packages/services/Car/service/res/values/config.xml.

Włączanie i wyłączanie adaptera Bluetooth

Jedną z głównych funkcji zasad jest włączanie i wyłączanie adaptera Bluetooth w odpowiednich momentach. Aby włączyć i wyłączyć adapter, możesz użyć interfejsów API platform BluetoothAdapter.enable()BluetoothAdapter.disable(). Te wywołania powinny uwzględniać stan wybrany przez użytkownika w Ustawieniach lub w inny sposób. Możesz to zrobić w ten sposób:

/**
 * 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);
}

Określanie, kiedy włączać i wyłączać adapter Bluetooth

W ramach zasad niestandardowych możesz określić, które zdarzenia wskazują najlepszy czas na włączenie i wyłączenie adaptera. Jednym ze sposobów na to jest użycie stanów zasilaniaMAXIMUM_CONNECTED_DEVICES wCarPowerManager:

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;
        }
    }
};

Określanie, kiedy połączyć urządzenia

Podobnie, gdy określisz zdarzenia, które powinny uruchamiać połączenia urządzeń, CarBluetoothManager udostępnia wywołanie interfejsu API connectDevices(), które umożliwia łączenie urządzeń na podstawie list priorytetów zdefiniowanych dla każdego profilu Bluetooth.

Możesz to zrobić na przykład za każdym razem, gdy włączasz adapter Bluetooth:

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();
            }
        }
    }
}

Weryfikowanie zarządzania połączeniami w samochodzie

Najprostszym sposobem sprawdzenia działania zasad połączenia jest włączenie Bluetootha w systemie IVI i sprawdzenie, czy automatycznie łączy się on z odpowiednimi urządzeniami we właściwej kolejności. Adapter Bluetooth możesz włączyć lub wyłączyć w interfejsie ustawień albo za pomocą tych poleceń 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

Dodatkowo możesz użyć wyniku tego polecenia, aby wyświetlić informacje o debugowaniu związane z połączeniami Bluetooth:

adb shell dumpsys car_service

Jeśli masz własną politykę dotyczącą samochodów, weryfikacja niestandardowego zachowania połączenia wymaga kontrolowania zdarzeń, które mają wywoływać połączenia z urządzeniem.

Profile Bluetooth w samochodzie

W Androidzie system IVI może obsługiwać wiele urządzeń połączonych jednocześnie przez Bluetooth. Usługi telefoniczne Bluetooth na wielu urządzeniach umożliwiają użytkownikom jednoczesne łączenie się z osobnymi urządzeniami, np. telefonem prywatnym i służbowym, oraz prowadzenie rozmów w trybie głośnomówiącym na każdym z nich.

Limity połączeń są egzekwowane przez poszczególne profile Bluetooth, zwykle w ramach implementacji samej usługi profilu. Domyślnie usługa CarBluetoothService nie podejmuje dalszych decyzji dotyczących maksymalnej liczby dozwolonych połączonych urządzeń.

Profil zestawu słuchawkowego

Profil zestawu głośnomówiącego Bluetooth (HFP) umożliwia wykonywanie i odbieranie połączeń telefonicznych w pojeździe za pomocą połączonego urządzenia zdalnego. Każde połączenie urządzenia rejestruje oddzielne konto telefoniczne w usłudze TelecomManager, która udostępnia wszystkie dostępne konta telefoniczne aplikacjom IVI.

System IVI może łączyć się z wieloma urządzeniami za pomocą profilu HFP. MAX_STATE_MACHINES_POSSIBLE MAXIMUM_CONNECTED_DEVICES HeadsetClientService określa maksymalną liczbę jednoczesnych połączeń HFP.

Gdy użytkownik nawiązuje lub odbiera połączenie telefoniczne na urządzeniu, odpowiednie konto telefoniczne tworzy obiekt HfpClientConnection. Aplikacja Telefon współdziała z obiektem HfpClientConnection, aby zarządzać funkcjami połączeń, takimi jak odbieranie i rozłączanie połączeń.

Warto pamiętać, że domyślna aplikacja Telefon nie obsługuje wielu jednocześnie połączonych urządzeń HFP. Aby wdrożyć HFP na wielu urządzeniach, konieczne jest dostosowanie, które umożliwi użytkownikom wybór konta urządzenia, z którego będą korzystać podczas nawiązywania połączeń. Aplikacja wywołuje wtedy telecomManager.placeCall z użyciem właściwego konta. Musisz też sprawdzić, czy inne funkcje na wielu urządzeniach działają zgodnie z oczekiwaniami.

Weryfikacja HFP na wielu urządzeniach

Aby sprawdzić, czy łączność z wieloma urządzeniami działa prawidłowo przez Bluetooth:

  1. Połącz urządzenie z systemem IVI przez Bluetooth i przesyłaj strumieniowo dźwięk z urządzenia.
  2. Połącz 2 telefony z systemem IVI przez Bluetooth.
  3. Wybierz jeden telefon. wykonywać połączenia wychodzące bezpośrednio z telefonu i za pomocą systemu IVI;
    1. Za każdym razem sprawdź, czy strumieniowany dźwięk jest wstrzymywany, a dźwięk z telefonu jest odtwarzany przez głośniki podłączone do IVI.
  4. Odbieranie połączeń przychodzących bezpośrednio na telefonie i za pomocą systemu IVI na tym samym telefonie.
    1. Za każdym razem sprawdź, czy strumieniowe odtwarzanie dźwięku zostało wstrzymane, a dźwięk z telefonu jest odtwarzany przez głośniki połączone z IVI.
  5. Powtórz kroki 3 i 4 w przypadku drugiego połączonego telefonu.

Połączenia alarmowe

Możliwość nawiązywania połączeń alarmowych jest ważnym aspektem funkcji telefonicznych i Bluetooth w samochodzie. Połączenie alarmowe można zainicjować z systemu IVI na kilka sposobów, m.in.:

  • Samodzielne rozwiązanie eCall
  • Rozwiązanie eCall zintegrowane z systemem IVI
  • korzystanie z połączonego telefonu Bluetooth, gdy nie jest dostępny wbudowany system;

Nawiązywanie połączenia alarmowego

Urządzenia eCall mają kluczowe znaczenie dla bezpieczeństwa, ale obecnie nie są zintegrowane z Androidem. Za pomocą ConnectionService można udostępniać funkcje połączeń alarmowych w Androidzie, co ma też tę zaletę, że wprowadza opcje ułatwień dostępu dla połączeń alarmowych. Więcej informacji znajdziesz w artykule Tworzenie aplikacji do dzwonienia.

Oto przykład nawiązywania połączenia alarmowego za pomocą usługi :

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);
    }
}

Włączanie Bluetootha na potrzeby połączeń alarmowych

W przypadku Androida w wersji starszej niż 10 dzwonienie na numer alarmowy wymagało bezpośredniego wybrania numeru na telefonie i użycia specjalnego sprzętu, jeśli był dostępny (np. automatyczne uruchomienie po wykryciu zagrożenia lub działania użytkownika). Na urządzeniach z Androidem 10 lub nowszym aplikacja Telefon w samochodzie może bezpośrednio dzwonić pod numer alarmowy, pod warunkiem że 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>

Dzięki takiemu wdrożeniu połączeń alarmowych inne aplikacje, np. rozpoznawanie głosu, również mogą dzwonić pod numer alarmowy.

Profil dostępu do książki telefonicznej

Profil dostępu do książki telefonicznej Bluetooth (PBAP) pobiera kontakty i historię połączeń z połączonego urządzenia zdalnego. PBAP prowadzi zagregowaną listę kontaktów z możliwością wyszukiwania, która jest aktualizowana przez automat stanowy klienta PBAP. Każde połączone urządzenie wchodzi w interakcję z osobnym automatem stanu klienta PBAP, dzięki czemu kontakty są powiązane z odpowiednim urządzeniem podczas nawiązywania połączenia.

PBAP jest jednokierunkowy, dlatego IVI musi tworzyć połączenia z dowolnym urządzeniem MAXIMUM_CONNECTED_DEVICES. Wartość PbapClientService określa maksymalną liczbę jednoczesnych połączeń urządzeń PBAP dozwolonych w przypadku IVI. Klient PBAP przechowuje kontakty dla każdego podłączonego urządzenia w  dostawcy kontaktów, do którego aplikacja może uzyskać dostęp, aby pobrać książkę telefoniczną dla każdego urządzenia.

Dodatkowo połączenie profilu musi być autoryzowane zarówno przez IVI, jak i urządzenie mobilne, aby można było nawiązać połączenie. Gdy klient PBAP rozłączy się, wewnętrzna baza danych usunie wszystkie kontakty i historię połączeń powiązane z wcześniej połączonym urządzeniem.

Profil dostępu do wiadomości

Profil dostępu do wiadomości Bluetooth (MAP) umożliwia pojazdowi wysyłanie i odbieranie SMS-ów za pomocą połączonego urządzenia zdalnego. Obecnie wiadomości nie są przechowywane lokalnie w systemie IVI. Zamiast tego, gdy połączone urządzenie zdalne otrzyma wiadomość, IVI odbiera i analizuje wiadomość oraz rozgłasza jej zawartość w instancji Intent, którą może następnie odebrać aplikacja.

Aby połączyć się z urządzeniem mobilnym w celu wysyłania i odbierania wiadomości, system IVI musi zainicjować połączenie MAP. MAXIMUM_CONNECTED_DEVICES MapClientService określa maksymalną liczbę jednoczesnych połączeń urządzenia MAP z systemem IVI. Przed przeniesieniem wiadomości każde połączenie musi zostać autoryzowane przez system IVI i urządzenie mobilne.

Profil zaawansowanej dystrybucji audio

Profil zaawansowanej dystrybucji audio (A2DP) umożliwia pojazdowi odbieranie strumieni audio z połączonego urządzenia zdalnego.

W przeciwieństwie do innych profili maksymalna liczba połączonych urządzeń A2DP jest wymuszana w natywnym stosie, a nie w Javie. Wartość jest obecnie na stałe ustawiona na 1 przy użyciu zmiennej kDefaultMaxConnectedAudioDevices packages/modules/Bluetooth/system/btif/src/btif_av.cc.

Profil zdalnego sterowania audio/wideo

Profil zdalnego sterowania dźwiękiem/obrazem Bluetooth (AVRCP) umożliwia pojazdowi sterowanie odtwarzaczami multimediów na podłączonym urządzeniu zdalnym i przeglądanie ich zawartości. Ponieważ system IVI pełni rolę kontrolera AVRCP, wszystkie wywoływane elementy sterujące, które wpływają na odtwarzanie dźwięku, opierają się na połączeniu A2DP z urządzeniem docelowym.

Aby konkretny odtwarzacz multimediów na telefonie z Androidem był dostępny dla IVI za pomocą AVRCP, aplikacja multimedialna na telefonie musi udostępniać MediaBrowserService i umożliwiać com.android.bluetooth dostęp do tej usługi. Więcej informacji znajdziesz w artykule Tworzenie usługi przeglądarki multimediów.