Aplikacje do nawigacji, prezentujące ciekawe miejsca i pogodowe, które korzystają z tych szablonów, mogą rysować mapy, uzyskując dostęp do Surface.
Aby używać tych szablonów, aplikacja musi zadeklarować jedno z tych uprawnień w elemencie <uses-permission> w pliku AndroidManifest.xml.
| Szablon | Uprawnienia | Wskazówki |
|---|---|---|
NavigationTemplate |
androidx.car.app.NAVIGATION_TEMPLATES |
Nawigacja |
MapWithContentTemplate |
lub
|
Nawigacja, POI, Pogoda |
|
(przestarzałe) |
androidx.car.app.NAVIGATION_TEMPLATES |
Nawigacja |
|
(przestarzałe) |
androidx.car.app.NAVIGATION_TEMPLATES |
Nawigacja |
(przestarzałe) |
androidx.car.app.NAVIGATION_TEMPLATES |
Nawigacja |
Zobacz implementację referencyjną
Pełną implementację referencyjną znajdziesz w przykładzie nawigacji.
Zadeklaruj uprawnienia do powierzchni
Oprócz uprawnień wymaganych w szablonie, z którego korzysta aplikacja, musi ona zadeklarować uprawnienia androidx.car.app.ACCESS_SURFACE w pliku AndroidManifest.xml, aby uzyskać dostęp do powierzchni:
<manifest ...>
...
<uses-permission android:name="androidx.car.app.ACCESS_SURFACE" />
...
</manifest>
Dostęp do urządzenia
Aby uzyskać dostęp do Surface udostępnianego przez hosta, musisz zaimplementować SurfaceCallback i przekazać tę implementację usłudze samochodowej AppManager. Bieżący Surface jest przekazywany do funkcji SurfaceCallback w parametrze SurfaceContainer wywołań zwrotnych onSurfaceAvailable() i onSurfaceDestroyed().
Kotlin
carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)
Java
carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);
Używanie wirtualnego wyświetlacza do renderowania treści
Oprócz renderowania bezpośrednio w Surface za pomocą interfejsu Canvas API możesz też renderować widoki w Surface za pomocą interfejsów VirtualDisplay i Presentation API, jak pokazano w tym przykładzie:
class HelloWorldSurfaceCallback(context: Context) : SurfaceCallback {
lateinit var virtualDisplay: VirtualDisplay
lateinit var presentation: Presentation
override fun onSurfaceAvailable(surfaceContainer: SurfaceContainer) {
virtualDisplay = context
.getSystemService(DisplayManager::class.java)
.createVirtualDisplay(
VIRTUAL_DISPLAY_NAME ,
surfaceContainer.width,
surfaceContainer.height,
surfaceContainer.dpi,
surfaceContainer.surface,
0
)
presentation = Presentation(context, virtualDisplay.display)
// Instantiate the view to be used as the content view
val view = ...
presentation.setContentView(view)
presentation.show()
}
override fun onSurfaceDestroyed(surfaceContainer: SurfaceContainer) {
presentation.dismiss()
// This handles releasing the Surface provided when creating the VirtualDisplay
virtualDisplay.release()
}
}
Używanie funkcji Compose do renderowania na wyświetlaczu wirtualnym
Możesz użyć ComposeView jako widoku treści Presentation. Ponieważ element
ComposeView jest używany poza aktywnością, sprawdź, czy on lub widok nadrzędny
propaguje elementy LifecycleOwner i SavedStateRegistryOwner. Aby to zrobić, użyj właściwości setViewTreeLifecycleOwner i setViewTreeSavedStateRegistryOwner.
Session już implementuje LifecycleOwner. Aby obsługiwać obie role, w implementacji możesz dodatkowo zaimplementować SavedStateRegistryOwner.
class HelloWorldSession() : Session(), SavedStateRegistryOwner { ... }
class HelloWorldSurfaceCallback(session: HelloWorldSession) : SurfaceCallback {
...
override fun onSurfaceAvailable(surfaceContainer: SurfaceContainer) {
...
val view = ComposeView(session.carContext)
view.setViewTreeLifecycleOwner(session)
view.setViewTreeSavedStateRegistryOwner(session)
view.setContent {
// Composable content
}
presentation.setContentView(view)
presentation.show()
}
...
}
Omówienie widocznego obszaru powierzchni
Host może rysować elementy interfejsu użytkownika dla szablonów na mapie.
Aplikacja hosta wywołuje metodę SurfaceCallback.onVisibleAreaChanged, aby przekazać obszar powierzchni, który najprawdopodobniej nie jest zasłonięty i jest widoczny dla użytkownika.
Aby zminimalizować liczbę zmian, host wywołuje metodę SurfaceCallback.onStableAreaChanged z najmniejszym prostokątem, który jest zawsze widoczny zgodnie z bieżącym szablonem.
Na przykład, gdy aplikacja do nawigacji używa NavigationTemplate z paskiem działań u góry, aby zwolnić więcej miejsca na ekranie, pasek działań może być ukryty, gdy użytkownik nie wchodzi w interakcję z ekranem. W tym przypadku wywołanie zwrotne jest wykonywane w funkcjach onStableAreaChanged i onVisibleAreaChanged z tym samym prostokątem.
Gdy pasek działań jest ukryty, wywoływana jest tylko funkcja onVisibleAreaChanged z większym obszarem. Jeśli użytkownik wejdzie w interakcję z ekranem, wywoływana jest tylko funkcja
onVisibleAreaChanged z pierwszym prostokątem.
Obsługa ciemnego motywu
Gdy host uzna, że warunki tego wymagają, aplikacje muszą ponownie narysować mapę na instancji Surface, używając odpowiednich ciemnych kolorów, zgodnie z opisem w wskazówkach dotyczących jakości aplikacji na Androida na potrzeby samochodów.
Aby narysować ciemną mapę, użyj metody CarContext.isDarkMode. Gdy zmieni się stan motywu ciemnego, otrzymasz połączenie na numer Session.onCarConfigurationChanged.
Rysowanie map na wyświetlaczu klastra
Oprócz rysowania map na wyświetlaczu głównym aplikacje nawigacyjne mogą też obsługiwać rysowanie map na wyświetlaczu deski rozdzielczej za kierownicą. Więcej informacji znajdziesz w artykule Rysowanie na wyświetlaczu klastra.