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 korzystać z tych szablonów, aplikacja musi zadeklarować jedno z tych uprawnień w elemencie <uses-permission> w pliku AndroidManifest.xml.

Szablon Uprawnienie Wskazówki
NavigationTemplate androidx.car.app.NAVIGATION_TEMPLATES Nawigacja
MapWithContentTemplate

androidx.car.app.NAVIGATION_TEMPLATES

lub

androidx.car.app.MAP_TEMPLATES

Nawigacja, ciekawe miejsca, pogoda

MapTemplate

(wycofany)

androidx.car.app.NAVIGATION_TEMPLATES Nawigacja

PlaceListNavigationTemplate

(wycofany)

androidx.car.app.NAVIGATION_TEMPLATES Nawigacja

RoutePreviewNavigationTemplate

(wycofany)

androidx.car.app.NAVIGATION_TEMPLATES Nawigacja

Zobacz implementację referencyjną

Aby zobaczyć pełną implementację referencyjną, zapoznaj się z przykładem nawigacji.

Zadeklaruj uprawnienie do powierzchni

Oprócz uprawnienia wymaganego przez szablon, którego używa Twoja aplikacja, musi ona też zadeklarować uprawnienie 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 powierzchni

Aby uzyskać dostęp do Surface udostępnianej przez hosta, musisz zaimplementować SurfaceCallback i przekazać tę implementację do AppManager usługi samochodowej. Bieżąca Surface jest przekazywana do 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 na Surface za pomocą interfejsu API Canvas możesz też renderować widoki na Surface za pomocą interfejsów API VirtualDisplay i Presentation, 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 Compose do renderowania na wirtualnym wyświetlaczu

Możesz użyć ComposeView jako widoku treści Presentation. Ponieważ ComposeView jest używany poza aktywnością, upewnij się, że on lub widok rodzica propaguje LifecycleOwner i SavedStateRegistryOwner. Aby to zrobić, użyj setViewTreeLifecycleOwner i setViewTreeSavedStateRegistryOwner.

Session implementuje już LifecycleOwner. Aby pełnić obie role, implementacja może dodatkowo implementować 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()
  }

  ...
}

Poznawanie widocznego obszaru powierzchni

Host może rysować elementy interfejsu użytkownika dla szablonów na mapie. Host wywołuje metodę SurfaceCallback.onVisibleAreaChanged , aby przekazać obszar powierzchni, który najprawdopodobniej nie będzie zasłonięty i będzie 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 takim przypadku wywołanie zwrotne onStableAreaChanged i onVisibleAreaChanged jest wywoływane 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

Aplikacje muszą ponownie narysować mapę na instancji Surface z odpowiednimi ciemnymi kolorami, gdy host stwierdzi, że jest to konieczne, zgodnie z opisem w artykule Jakość aplikacji na Androida w samochodach.

Aby narysować ciemną mapę, użyj metody CarContext.isDarkMode. Gdy zmieni się stan ciemnego motywu, otrzymasz wywołanie Session.onCarConfigurationChanged.

Rysowanie map na wyświetlaczu deski rozdzielczej

Oprócz rysowania map na wyświetlaczu głównym aplikacje do nawigacji mogą też obsługiwać rysowanie map na wyświetlaczu deski rozdzielczej za kierownicą. Więcej informacji znajdziesz w artykule Rysowanie na wyświetlaczu deski rozdzielczej.