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.
CarService
iCarNavigationStatusManager
udostępnione przez platformę Androida. Więcej informacji znajdziesz w usługach Car i CAR_NAVIGATION_SERVICE. - Cyjan.
InstrumentClusterRendererService
wdroż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ą:
CarService
inicjalizujęInstrumentClusterRenderingService
.- Podczas inicjowania
InstrumentClusterRenderingService
aktualizujeCarService
za 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
CarAppFocusManager
przekazuje tę prośbę doCarService
. Jeśli dostęp zostanie przyznany,CarService
sprawdzi 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
ActivityOptions
zgł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:category
ClusterRenderingService.state
Pakiet wygenerowany za pomocą usługi ClusterRenderingService. Pamiętaj, aby podać te dane:visible
Określa, że tablica rozdzielcza jest widoczna i gotowa do wyświetlania treści.unobscuredBounds
Prostoką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.