Użyj interfejsu Instrument Cluster API (interfejsu API Androida), aby wyświetlać aplikacje do nawigacji, w tym Mapy Google, na dodatkowym wyświetlaczu w samochodzie, np. za kierownicą na panelu wskaźników. Na tej stronie dowiesz się, jak utworzyć usługę do sterowania tym drugim wyświetlaczem i jak zintegrować ją z CarService, aby aplikacje nawigacyjne mogły wyświetlać interfejs użytkownika.
Terminologia
Na tej stronie używamy tych terminów.
CarManager, która umożliwia aplikacjom zewnętrznym uruchamianie aktywności w klastrze przyrządów i otrzymywanie wywołań zwrotnych, gdy klaster jest gotowy do wyświetlania aktywności.android:singleUser. W danym momencie w systemie Android działa maksymalnie 1 występowanie usługi.Wymagania wstępne
Zanim przejdziesz dalej, przygotuj te elementy:
- Środowisko programistyczne Androida Aby skonfigurować środowisko programistyczne Androida, zapoznaj się z artykułem Wymagania dotyczące kompilacji.
- Pobierz kod źródłowy Androida. Pobierz najnowszą wersję kodu źródłowego Androida z gałęzi pi-car-release (lub nowszej) na stronie https://android.googlesource.com.
- Główna jednostka (HU). urządzenie z Androidem w wersji 9 (lub nowszej), Urządzenie musi mieć własny wyświetlacz i możliwość flashowania wyświetlacza nowymi wersjami Androida.
- Zbiór instrumentów to:
- Fizyczny wyświetlacz dodatkowy podłączony do HU. czy sprzęt i jądro urządzenia obsługują zarządzanie wieloma wyświetlaczami.
- Niezależna jednostka. dowolna jednostka obliczeniowa połączona z HU przez połączenie sieciowe, która może odbierać i wyświetlać strumień wideo na własnym wyświetlaczu;
- Emulowany wyświetlacz Podczas tworzenia możesz korzystać z jednego z tych emulowanych środowisk:
- Symulowane wyświetlacze dodatkowe. Aby włączyć symulowany wyświetlacz pomocniczy w dowolnej dystrybucji Androida AOSP, otwórz ustawienia Opcje dla deweloperów w aplikacji systemowej Ustawienia, a następnie wybierz Symuluj wyświetlacze pomocnicze. Ta konfiguracja jest równoważna podłączeniem fizycznego wyświetlacza pomocniczego, z tym ograniczeniem, że wyświetlacz jest nakładany na wyświetlacz główny.
- Emulowany klaster instrumentów Dołączony do AAOS emulator Androida umożliwia wyświetlanie panelu sterowania z użyciem usługi ClusterRenderingService.
Architektura integracji
Komponenty integracji
Każda integracja interfejsu Instrument Cluster API składa się z tych 3 komponentów:
CarService- Aplikacje do nawigacji
- OEM Instrument Cluster Service

CarService
CarService pośredniczy między aplikacjami do nawigacji a samochodem, zapewniając, że w danym momencie aktywna jest tylko jedna aplikacja do nawigacji, a tylko aplikacje z uprawnieniem android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL mogą wysyłać dane do samochodu.
CarService uruchamia wszystkie usługi związane z samochodem i zapewnia dostęp do tych usług za pomocą serii menedżerów. Aby korzystać z usług, aplikacje działające w samochodzie mogą uzyskiwać dostęp do tych menedżerów.
W przypadku implementacji tablicy rozdzielczej firmy motoryzacyjnej OEM musi utworzyć niestandardową implementację InstrumentClusterRendererService i zaktualizować ClusterRenderingService.
Podczas renderowania klastra instrumentów w trakcie procesu uruchamiania CarService odczytuje klucz InstrumentClusterRendererService usługi ClusterRenderingService, aby zlokalizować implementację InstrumentClusterService. W AOSP ten wpis wskazuje na renderowanie usługi w ramach przykładowej implementacji klastra interfejsu API stanu nawigacji:
<string name="instrumentClusterRendererService"> android.car.cluster/.ClusterRenderingService </string>
Usługa wymieniona w tym wpisie jest inicjowana i wiązana z CarService. Gdy aplikacje do nawigacji, takie jak Mapy Google, wysyłają żądanie do CarInstrumentClusterManager, CarService udostępnia menedżera, który aktualizuje stan grupy przyrządów na podstawie powiązanego elementu InstrumentClusterRenderingService.
(W tym przypadku powiązany oznacza Usługi Androida).
Usługa Instrument Cluster
Producenci OEM muszą utworzyć pakiet Androida (APK), który zawiera podklasę ClusterRenderingService.
Te zajęcia mają 2 cele:
- Udostępnia interfejs Androida i urządzenie do renderowania instrumentu (cel tej strony).
- Odbiera i wyświetla aktualizacje stanu nawigacji, takie jak wskazówki dojazdu zakręt po zakręcie.
W pierwszym przypadku implementacje OEM InstrumentClusterRendererService muszą zainicjować dodatkowy wyświetlacz używany do renderowania informacji na ekranach w kabince samochodu oraz przekazać te informacje do CarService, wywołując metody InstrumentClusterRendererService.setClusterActivityOptions() i InstrumentClusterRendererService.setClusterActivityState().
W przypadku drugiej funkcji usługa Instrument Cluster musi zapewniać implementację interfejsu ClusterRenderingService, który odbiera zdarzenia aktualizacji stanu nawigacji, które są kodowane jako eventType i dane zdarzeń zaszyfrowane w pakiecie.
Sekwencja integracji
Poniższy diagram przedstawia implementację stanu nawigacji, który renderuje aktualizacje:
Na tej ilustracji kolory oznaczają:
- Żółty.
CarServiceiCarNavigationStatusManagerudostępnione przez platformę Androida. Więcej informacji znajdziesz w usługach Car i CAR_NAVIGATION_SERVICE. - Cyjan.
InstrumentClusterRendererServicewdrożony przez producenta OEM. - Fioletowy. Aplikacja Nawigacja wdrożona przez Google i deweloperów zewnętrznych.
- Zielony.
CarAppFocusManager. Więcej informacji znajdziesz w artykule Korzystanie z interfejsu CarAppFocusManager API poniżej oraz w artykule CarAppFocusManager.
Przepływ informacji o stanie nawigacji jest zgodny z tą sekwencją:
CarServiceinicjalizujęInstrumentClusterRenderingService.- Podczas inicjowania
InstrumentClusterRenderingServiceaktualizujeCarServiceza pomocą:- Właściwości wyświetlania instrumentu klastra, takie jak nieprzejrzyste granice (więcej informacji o nieprzejrzystych granicach znajdziesz dalej).
- Opcje aktywności potrzebne do uruchamiania aktywności w wyświetlaczu klastra przyrządów. Więcej informacji znajdziesz w artykule ActivityOptions.
- Aplikacja do nawigacji (np. Mapy Google na Androida Automotive lub dowolna aplikacja do map z wymaganymi uprawnieniami):
- Uzyskuje
CarAppFocusManager, używając klasy Car z biblioteki car-lib. - Przed rozpoczęciem wskazówek dojazdu do celu wywołuje funkcję
CarAppFocusManager.requestFocus(), przekazując jako parametrCarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION.appType
- Uzyskuje
CarAppFocusManagerprzekazuje tę prośbę doCarService. Jeśli dostęp zostanie przyznany,CarServicesprawdzi pakiet aplikacji do nawigacji i odnajdzie aktywność oznaczoną kategoriąandroid.car.cluster.NAVIGATION.- Jeśli aplikacja do nawigacji znajdzie się na liście, użyje
ActivityOptionszgłoszonego przezInstrumentClusterRenderingService, aby uruchomić aktywność, i uwzględni właściwości wyświetlania wyświetlacza kokpitowego jako dodatkowe informacje w intencji.
Integracja z interfejsem API
Implementacja usługi InstrumentClusterRenderingService musi:
- być oznaczoną jako usługa pojedyncza przez dodanie tej wartości do pliku AndroidManifest.xml; Jest to konieczne, aby mieć pewność, że jedna kopia usługi Instrument Cluster działa nawet podczas inicjalizacji i przełączania użytkowników:
android:singleUser="true" - Uprawnienia systemowe
BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE. Gwarantuje to, że tylko usługa renderowania instrumentu z poziomu klastra, która jest częścią obrazu systemu Android, jest związana przezCarService:<uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
Implementacja InstrumentClusterRenderingService
Aby skompilować usługę:
- Napisz klasę rozszerzającą klasę ClusterRenderingService, a następnie dodaj odpowiedni wpis do pliku
AndroidManifest.xml. Ta klasa kontroluje wyświetlacz zestawu wskaźników i może (opcjonalnie) renderować dane interfejsu API stanu nawigacji. - Podczas
onCreate()używaj tej usługi do inicjowania komunikacji z sprzętem do renderowania. Dostępne opcje:- Określ dodatkowy wyświetlacz, który ma być używany przez zestaw wskaźników.
- Utwórz wyświetlacz wirtualny, aby aplikacja Instrument Cluster mogła renderować i przesyłać obraz do jednostki zewnętrznej (za pomocą formatu strumieniowego wideo, takiego jak H.264).
- Gdy wyświetlacz jest gotowy, usługa musi wywołać funkcję
InstrumentClusterRenderingService#setClusterActivityLaunchOptions(), aby zdefiniować dokładną wartośćActivityOptions, która musi być użyta do wyświetlania aktywności na panelu sterowania. Użyj tych parametrów:category.ClusterRenderingService.ActivityOptions.instancjaActivityOptions, która może służyć do uruchamiania aktywności w klastrze przyrządów. Na przykład z przykładowej implementacji Instrument Cluster w AOSP:getService().setClusterActivityLaunchOptions( CATEGORY_NAVIGATION, ActivityOptions.makeBasic() .setLaunchDisplayId(displayId));
- Gdy klaster instrumentów jest gotowy do wyświetlania aktywności, usługa musi wywołać
InstrumentClusterRenderingService#setClusterActivityState(). Użyj tych parametrów:categoryClusterRenderingService.statePakiet wygenerowany za pomocą usługi ClusterRenderingService. Pamiętaj, aby podać te dane:visibleOkreśla, że tablica rozdzielcza jest widoczna i gotowa do wyświetlania treści.unobscuredBoundsProstokąt określający obszar na wyświetlaczu panelu sterowania, na którym można bezpiecznie wyświetlać treści. Na przykład obszary objęte tarczami i wskaźnikami.
- Zastąpić metodę
Service#dump()i przekazać informacje o stanie, które są przydatne do debugowania (więcej informacji znajdziesz w dumpsys).
Przykładowa implementacja InstrumentClusterRenderingService
W tym przykładzie przedstawiono implementację InstrumentClusterRenderingService, która tworzy VirtualDisplay, aby wyświetlać zawartość instrumentu Cluster na zewnętrznym wyświetlaczu fizycznym.
Kod może też przekazywać displayId fizycznego dodatkowego wyświetlacza podłączonego do HU, jeśli wiadomo, że jest on dostępny.
/** * Sample {@link InstrumentClusterRenderingService} implementation */ public class SampleClusterServiceImpl extends InstrumentClusterRenderingService { // Used to retrieve or create displays private final DisplayManager mDisplayManager; // Unique identifier for the display to be used for instrument // cluster private final String mUniqueId = UUID.randomUUID().toString(); // Format of the instrument cluster display private static final int DISPLAY_WIDTH = 1280; private static final int DISPLAY_HEIGHT = 720; private static final int DISPLAY_DPI = 320; // Area not covered by instruments private static final int DISPLAY_UNOBSCURED_LEFT = 40; private static final int DISPLAY_UNOBSCURED_TOP = 0; private static final int DISPLAY_UNOBSCURED_RIGHT = 1200; private static final int DISPLAY_UNOBSCURED_BOTTOM = 680; @Override public void onCreate() { super.onCreate(); // Create a virtual display to render instrument cluster activities on mDisplayManager = getSystemService(DisplayManager.class); VirtualDisplay display = mDisplayManager.createVirtualDisplay( mUniqueId, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_DPI, null, 0 /* flags */, null, null); // Do any additional initialization (e.g.: start a video stream // based on this virtual display to present activities on a remote // display). onDisplayReady(display.getDisplay()); } private void onDisplayReady(Display display) { // Report activity options that should be used to launch activities on // the instrument cluster. String category = CarInstrumentClusterManager.CATEGORY_NAVIGATION; ActionOptions options = ActivityOptions.makeBasic() .setLaunchDisplayId(display.getDisplayId()); setClusterActivityOptions(category, options); // Report instrument cluster state. Rect unobscuredBounds = new Rect(DISPLAY_UNOBSCURED_LEFT, DISPLAY_UNOBSCURED_TOP, DISPLAY_UNOBSCURED_RIGHT, DISPLAY_UNOBSCURED_BOTTOM); boolean visible = true; ClusterActivityState state = ClusterActivityState.create(visible, unobscuredBounds); setClusterActivityState(category, options); } }
Korzystanie z interfejsu CarAppFocusManager API
Interfejs API CarAppFocusManager udostępnia metodę getAppTypeOwner(), która pozwala usłudze klastra napisanej przez producenta OEM wiedzieć, która aplikacja do nawigacji jest w danym momencie aktywna. Producenci OEM mogą korzystać z dotychczasowej metody CarAppFocusManager#addFocusListener(), a następnie z metody getAppTypeOwner(), aby dowiedzieć się, która aplikacja jest aktywna. Dzięki tym informacjom OEM może:
- Przełącz aktywność wyświetlaną w klastrze na aktywność klastra udostępnianą przez aplikację do nawigacji, która ma na celu utrzymanie fokusa.
- Może wykryć, czy aplikacja nawigacji w centrum uwagi ma aktywność skupioną. Jeśli aplikacja do nawigacji, na której skupia się użytkownik, nie ma aktywności w klastrze (lub jeśli taka aktywność jest wyłączona), producenci OEM mogą wysłać ten sygnał do DIM samochodu, aby całkowicie pominąć aspekt nawigacji w klastrze.
Użyj CarAppFocusManager, aby ustawić i słuchać bieżącego fokusa aplikacji, takiego jak aktywna nawigacja czy polecenie głosowe. Zwykle tylko jedno wystąpienie takiej aplikacji jest aktywne (lub skupione) w systemie.
Aby odbierać powiadomienia o zmianach stanu pełnej koncentracji aplikacji, używaj metody CarAppFocusManager#addFocusListener(..):
import android.car.CarAppFocusManager; ... Car car = Car.createCar(this); mAppFocusManager = (CarAppFocusManager)car.getCarManager(Car.APP_FOCUS_SERVICE); mAppFocusManager.addFocusListener(this, CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION); ... public void onAppFocusChanged(int appType, boolean active) { // Use the CarAppFocusManager#getAppTypeOwner(appType) method call // to retrieve a list of active package names }
Aby pobrać nazwy pakietów należących do bieżącego właściciela danego typu aplikacji, użyj metody CarAppFocusManager#getAppTypeOwner(..). Ta metoda może zwrócić więcej niż jedną nazwę pakietu, jeśli bieżący właściciel korzysta z funkcji android:sharedUserId.
import android.car.CarAppFocusManager; ... Car car = Car.createCar(this); mAppFocusManager = (CarAppFocusManager)car.getCarManager(Car.APP_FOCUS_SERVICE); List<String> focusOwnerPackageNames = mAppFocusManager.getAppTypeOwner( CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION); if (focusOwnerPackageNames == null || focusOwnerPackageNames.isEmpty()) { // No Navigation app has focus // OEM may choose to show their default cluster view } else { // focusOwnerPackageNames // Use the PackageManager to retrieve the cluster activity for the package(s) // returned in focusOwnerPackageNames } ...
Dodatek: korzystanie z przykładowej aplikacji
AOSP udostępnia przykładową aplikację, która implementuje interfejs Navigation State API.
Aby uruchomić tę przykładową aplikację:
- Utwórz i zainstaluj Androida Auto na obsługiwanym HU. Skorzystaj z instrukcji kompilowania i flashowania Androida na swoje urządzenie. Instrukcje znajdziesz w artykule Korzystanie z tablic referencyjnych.
- Podłącz do HU dodatkowy wyświetlacz fizyczny (jeśli jest obsługiwany) lub włącz wirtualny dodatkowy HU:
- W aplikacji Ustawienia wybierz Tryb programisty.
- Otwórz kolejno Ustawienia > System > Zaawansowane > Opcje programisty > Symuluj dodatkowe wyświetlacze.
- Zrestartuj HU
- Aby uruchomić aplikację KitchenSink:
- Otwórz panel.
- Otwórz Inst. Cluster.
- Kliknij ROZPOCZNIJ METADANY.
Funkcja KitchenSink prosi o skupienie się na NAVIGATION, co instruuje usługę DirectRenderingCluster do wyświetlenia na tablicy rozdzielczej symulowanego interfejsu użytkownika.