Używaj interfejsu Instrument Cluster API (interfejsu Androida), aby wyświetlać aplikacje do nawigacji, w tym Mapy Google, na dodatkowym wyświetlaczu w samochodzie, np. za kierownicą na desce rozdzielczej. Na tej stronie dowiesz się, jak utworzyć usługę do sterowania tym dodatkowym wyświetlaczem i zintegrować ją z CarService, aby aplikacje do nawigacji mogły wyświetlać interfejs użytkownika.
Terminologia
Na tej stronie używane są te terminy:
CarManager, która umożliwia aplikacjom zewnętrznym uruchamianie aktywności w klastrze przyrządów i otrzymywanie wywołań zwrotnych, gdy klaster przyrządów jest gotowy do wyświetlania aktywności.android:singleUser. W danym momencie w systemie Android może działać co najwyżej 1 instancja usługi.Wymagania wstępne
Zanim przejdziesz dalej, przygotuj te elementy:
- Środowisko programistyczne Androida Aby skonfigurować środowisko programistyczne Androida, zapoznaj się z wymaganiami dotyczącymi 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.
- Jednostka główna (HU) urządzenie z Androidem 9 (lub nowszym), Urządzenie musi mieć własny wyświetlacz i możliwość wyświetlania nowych wersji Androida.
- Tablica wskaźników jest jednym z tych elementów:
- Fizyczny wyświetlacz dodatkowy podłączony do HU. jeśli sprzęt i jądro urządzenia obsługują zarządzanie wieloma wyświetlaczami;
- Jednostka niezależna. Każda jednostka obliczeniowa połączona z HU za pomocą połączenia sieciowego, która może odbierać i wyświetlać strumień wideo na własnym wyświetlaczu.
- Emulowany wyświetlacz. Podczas programowania możesz użyć jednego z tych emulowanych środowisk:
- Symulowane ekrany dodatkowe. Aby włączyć symulowany dodatkowy wyświetlacz w dowolnej dystrybucji Androida AOSP, otwórz Opcje programisty w aplikacji systemowej Ustawienia, a następnie wybierz Symuluj dodatkowe wyświetlacze. Ta konfiguracja jest równoważna z podłączeniem fizycznego dodatkowego wyświetlacza, z tym ograniczeniem, że ten wyświetlacz jest nałożony na wyświetlacz główny.
- Emulowana tablica wskaźników Emulator Androida dołączony do AAOS umożliwia wyświetlanie zestawu wskaźników za pomocą ClusterRenderingService.
Architektura integracji
Komponenty integracji
Każda integracja interfejsu Instrument Cluster API składa się z tych 3 komponentów:
CarService- Aplikacje do nawigacji
- Usługa tablicy wskaźników OEM

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 do nich dostęp za pomocą szeregu 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 zestawu wskaźników producenci OEM muszą utworzyć niestandardową implementację InstrumentClusterRendererService i zaktualizować ClusterRenderingService.
Podczas renderowania klastra przyrządów w trakcie procesu uruchamiania CarService odczytuje klucz InstrumentClusterRendererService usługi ClusterRenderingService, aby znaleźć implementację interfejsu InstrumentClusterService. W AOSP ten wpis
wskazuje usługę renderowania przykładowej implementacji klastra interfejsu Navigation State API:
<string name="instrumentClusterRendererService"> android.car.cluster/.ClusterRenderingService </string>
Usługa, o której mowa w tym wpisie, jest zainicjowana i powiązana z CarService. Gdy aplikacje nawigacyjne, takie jak Mapy Google, wysyłają żądanie CarInstrumentClusterManager, CarService udostępnia menedżera, który aktualizuje stan grupy przyrządów na podstawie powiązanego InstrumentClusterRenderingService.
(W tym przypadku powiązane oznacza
Usługi Androida.)
Usługa klastra przyrządów
Producenci OEM muszą utworzyć pakiet Androida (APK), który zawiera podklasę ClusterRenderingService.
Ta klasa służy 2 celom:
- Udostępnia interfejs Androida i urządzenia renderującego zestaw wskaźników (cel tej strony).
- Otrzymuje i wyświetla aktualizacje stanu nawigacji, np. szczegółowe wskazówki dojazdu.
W pierwszym przypadku implementacje OEM InstrumentClusterRendererServicemuszą zainicjować dodatkowy wyświetlacz używany do renderowania informacji na ekranach w kabinie samochodu i przekazać te informacje do CarService, wywołując metody InstrumentClusterRendererService.setClusterActivityOptions() i InstrumentClusterRendererService.setClusterActivityState().
W przypadku drugiej funkcji usługa Instrument Cluster musi udostępniać implementację interfejsu ClusterRenderingService, który odbiera zdarzenia aktualizacji stanu nawigacji zakodowane jako eventType i dane zdarzenia zakodowane w pakiecie.
Sekwencja integracji
Poniższy diagram ilustruje implementację stanu nawigacji, który renderuje aktualizacje:
Na tej ilustracji kolory oznaczają:
- Żółty
CarServiceiCarNavigationStatusManagerudostępniane przez platformę Androida. Więcej informacji znajdziesz w sekcjach Samochód i CAR_NAVIGATION_SERVICE. - Cyjan
InstrumentClusterRendererServicewdrożone przez producenta OEM. - Fioletowy. Aplikacja do nawigacji wdrożona przez Google i deweloperów zewnętrznych.
- Zielony
CarAppFocusManager. Więcej informacji znajdziesz w sekcji Korzystanie z interfejsu CarAppFocusManager API poniżej oraz w artykule CarAppFocusManager.
Przepływ informacji o stanie nawigacji przebiega w tej kolejności:
CarServiceinicjujeInstrumentClusterRenderingService.- Podczas inicjowania
InstrumentClusterRenderingServiceaktualizujeCarServiceza pomocą:- Właściwości wyświetlacza zestawu wskaźników, takie jak niezasłonięte granice (więcej informacji o niezasłoniętych granicach znajdziesz poniżej).
- Opcje aktywności potrzebne do uruchamiania aktywności na 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
CarAppFocusManagerza pomocą klasy Car z biblioteki car-lib. - Zanim rozpoczną się szczegółowe wskazówki dojazdu, wywołaj funkcję
CarAppFocusManager.requestFocus(), aby przekazaćCarAppFocusManager.APP_FOCUS_TYPE_NAVIGATIONjako parametrappType.
- Uzyskuje
CarAppFocusManagerprzekazuje tę prośbę doCarService. Jeśli uprawnienie zostanie przyznane,CarServicesprawdzi pakiet aplikacji do nawigacji i znajdzie aktywność oznaczoną kategoriąandroid.car.cluster.NAVIGATION.- Jeśli zostanie znaleziony, aplikacja do nawigacji użyje
ActivityOptionszgłoszonego przezInstrumentClusterRenderingService, aby uruchomić aktywność, i uwzględni właściwości wyświetlania na tablicy wskaźników jako dodatki w intencji.
Integracja interfejsu API
Implementacja usługi InstrumentClusterRenderingService musi:
- Oznacz usługę jako pojedynczą, dodając do pliku AndroidManifest.xml tę wartość: Jest to konieczne, aby zapewnić działanie pojedynczej kopii usługi Instrument Cluster, nawet podczas inicjowania i przełączania użytkowników:
android:singleUser="true" - mają uprawnienia systemowe
BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE; Daje to gwarancję, że tylko usługa renderowania zestawu wskaźników dołączona do obrazu systemu Android jest kiedykolwiek powiązana przezCarService:<uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
Implementowanie InstrumentClusterRenderingService
Aby skompilować usługę:
- Napisz klasę, która rozszerza ClusterRenderingService, a następnie dodaj odpowiedni wpis do pliku
AndroidManifest.xml. Ta klasa steruje wyświetlaczem grupy przyrządów i może (opcjonalnie) renderować dane interfejsu Navigation State API. - Podczas
onCreate()użyj tej usługi, aby zainicjować komunikację ze sprzętem renderującym. Dostępne opcje to:- Określ dodatkowy wyświetlacz, który ma być używany w przypadku zestawu wskaźników.
- Utwórz wirtualny wyświetlacz, aby aplikacja Instrument Cluster renderowała i przesyłała wyrenderowany obraz do urządzenia zewnętrznego (w formacie strumieniowania wideo, np. H.264).
- Gdy wyświetlacz wskazany powyżej jest gotowy, ta usługa musi wywołać
InstrumentClusterRenderingService#setClusterActivityLaunchOptions(), aby określić dokładnyActivityOptions, który musi być używany do wyświetlania aktywności na zestawie wskaźników. Użyj tych parametrów:category.ClusterRenderingServiceActivityOptions.InstancjaActivityOptions, której można użyć do uruchomienia aktywności w klastrze przyrządów. Na przykład w przykładowej implementacji zestawu wskaźników w AOSP:getService().setClusterActivityLaunchOptions( CATEGORY_NAVIGATION, ActivityOptions.makeBasic() .setLaunchDisplayId(displayId));
- Gdy zestaw wskaźników jest gotowy do wyświetlania aktywności, ta usługa musi wywołać funkcję
InstrumentClusterRenderingService#setClusterActivityState(). Użyj tych parametrów:categoryClusterRenderingServicestatePakiet wygenerowany za pomocą usługi ClusterRenderingService. Podaj te dane:visibleOkreśla, że zestaw wskaźników jest widoczny i gotowy do wyświetlania treści.unobscuredBoundsProstokąt określający obszar na wyświetlaczu zestawu wskaźników, w którym można bezpiecznie wyświetlać treści. Na przykład obszary pokryte tarczami i wskaźnikami.
- Zastąp metodę
Service#dump()i zgłoś informacje o stanie przydatne do debugowania (więcej informacji znajdziesz w artykule o dumpsys).
Przykładowa implementacja usługi InstrumentClusterRenderingService
Poniższy przykład przedstawia InstrumentClusterRenderingServiceimplementację, która tworzy VirtualDisplay do wyświetlania treści Instrument Cluster na zdalnym wyświetlaczu fizycznym.
Może też przekazywać displayId fizycznego wyświetlacza dodatkowego 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 CarAppFocusManager API udostępnia metodę o nazwie getAppTypeOwner(), która umożliwia usłudze klastra napisanej przez producentów OEM określanie, która aplikacja do nawigacji ma w danym momencie zaznaczenie nawigacji. Producenci OEM mogą używać dotychczasowej metody CarAppFocusManager#addFocusListener(), a następnie używać getAppTypeOwner(), aby dowiedzieć się, która aplikacja jest aktywna. Dzięki tym informacjom producenci OEM mogą:
- Przełącz aktywność wyświetlaną w klastrze na aktywność klastra dostarczaną przez aplikację do nawigacji, która jest aktywna.
- Może wykrywać, czy aktywna aplikacja do nawigacji ma aktywność klastra. Jeśli aplikacja nawigacyjna nie ma aktywności klastra (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 odsłuchać bieżący fokus aplikacji, np. aktywną nawigację lub polecenie głosowe. Zwykle tylko jedno wystąpienie takiej aplikacji jest aktywnie uruchomione (lub aktywne) w systemie.
Użyj metody CarAppFocusManager#addFocusListener(..), aby nasłuchiwać zmian aktywności aplikacji:
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 }
Użyj metody CarAppFocusManager#getAppTypeOwner(..), aby pobrać nazwy pakietów bieżącego właściciela danego typu aplikacji, który jest w centrum uwagi. Ta metoda może zwrócić więcej niż jedną nazwę pakietu, jeśli obecny 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 } ...
Identyfikowanie aplikacji szablonowych
W przypadku aplikacji do nawigacji opartych na szablonach, które korzystają z biblioteki aplikacji do samochodu, funkcja
CarAppFocusManager#getAppTypeOwner() zwraca nazwę pakietu hosta
(np. com.google.android.apps.automotive.templates.host)
, ponieważ host utrzymuje fokus systemu w imieniu aplikacji klienta.
Aby zidentyfikować aplikację kliencką, która inicjuje nawigację, producenci OEM mogą wyodrębnić nazwę pakietu z pakietu stanu nawigacji wysyłanego z CarNavigationStatusManager. Nazwa pakietu jest przechowywana pod kluczem active_app_package_name w pakiecie otrzymanym przez NavigationRenderer#onNavigationStateChanged(Bundle):
// In your NavigationRenderer implementation @Override public void onNavigationStateChanged(Bundle bundle) { if (bundle.containsKey("active_app_package_name")) { String activeAppPackage = bundle.getString("active_app_package_name"); // Use the package name to identify the navigating app (e.g., com.waze) } }
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ę:
- Skompiluj i zainstaluj Androida Auto na obsługiwanym panelu. Postępuj zgodnie z instrukcjami kompilacji i flashowania Androida dla konkretnego urządzenia. Instrukcje znajdziesz w artykule Korzystanie z tablic referencyjnych.
- Podłącz fizyczny wyświetlacz dodatkowy do HU (jeśli jest obsługiwany) lub włącz wirtualny wyświetlacz dodatkowy:
- W aplikacji Ustawienia wybierz Tryb programisty.
- Otwórz kolejno Ustawienia > System > Zaawansowane > Opcje programisty > Symuluj wyświetlacze dodatkowe.
- Uruchom ponownie HU
- Aby uruchomić aplikację KitchenSink:
- Otwórz szufladę.
- Otwórz Inst. Cluster (Klaster instancji).
- Kliknij ROZPOCZNIJ METADANE.
Usługa KitchenSink wysyła żądanie NAVIGATION focus, które nakazuje DirectRenderingClusterwyświetlenie w zestawie wskaźników makiety interfejsu.