Rysuj mapy

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

androidx.car.app.NAVIGATION_TEMPLATES

lub

androidx.car.app.MAP_TEMPLATES

Nawigacja, POI, Pogoda

MapTemplate

(przestarzałe)

androidx.car.app.NAVIGATION_TEMPLATES Nawigacja

PlaceListNavigationTemplate

(przestarzałe)

androidx.car.app.NAVIGATION_TEMPLATES Nawigacja

RoutePreviewNavigationTemplate

(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()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 VirtualDisplayPresentation 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 LifecycleOwnerSavedStateRegistryOwner. Aby to zrobić, użyj właściwości setViewTreeLifecycleOwnersetViewTreeSavedStateRegistryOwner.

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 NavigationTemplatepaskiem 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 onStableAreaChangedonVisibleAreaChanged 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.