@@ -35,18 +35,59 @@ import androidx.lifecycle.LifecycleOwner
3535import com.google.android.gms.maps.CameraUpdateFactory
3636import com.google.android.gms.maps.GoogleMap
3737import com.google.android.gms.maps.GoogleMapOptions
38- import com.google.android.libraries.navigation.NavigationViewForAuto
38+ import com.google.android.libraries.navigation.NavigationView
39+ import com.google.android.libraries.navigation.PromptVisibilityChangedListener
3940
4041open class AndroidAutoBaseScreen (carContext : CarContext ) :
4142 Screen (carContext), SurfaceCallback , NavigationReadyListener {
43+
44+ companion object {
45+ /* *
46+ * Map options to use for Android Auto views. Can be set before the Android Auto screen is
47+ * created to customize map appearance.
48+ */
49+ var mapOptions: AutoMapViewOptions ? = null
50+ }
51+
52+ /* *
53+ * Provides the map options to use when creating the Android Auto map view.
54+ *
55+ * Override this method in your AndroidAutoBaseScreen subclass to provide custom map options from
56+ * the native layer. This is useful when you want to set map configuration (like mapId) directly
57+ * in native code instead of from Flutter, especially when the Android Auto screen may already be
58+ * open.
59+ *
60+ * The default implementation returns the value from the companion object, which can be set from
61+ * Flutter via GoogleMapsAutoViewController.setAutoMapOptions().
62+ *
63+ * @return AutoMapViewOptions containing map configuration, or null to use defaults
64+ *
65+ * Example:
66+ * ```kotlin
67+ * override fun getAutoMapOptions(): AutoMapViewOptions? {
68+ * return AutoMapViewOptions(
69+ * mapId = "your-map-id",
70+ * mapType = GoogleMap.MAP_TYPE_SATELLITE,
71+ * mapColorScheme = UIUserInterfaceStyle.DARK,
72+ * forceNightMode = NavigationView.FORCE_NIGHT_MODE_AUTO
73+ * )
74+ * }
75+ * ```
76+ */
77+ public open fun getAutoMapOptions (): AutoMapViewOptions ? {
78+ return mapOptions
79+ }
80+
4281 private val VIRTUAL_DISPLAY_NAME = " AndroidAutoNavScreen"
4382 private var mVirtualDisplay: VirtualDisplay ? = null
4483 private var mPresentation: Presentation ? = null
45- private var mNavigationView: NavigationViewForAuto ? = null
84+ private var mNavigationView: NavigationView ? = null
4685 private var mAutoMapView: GoogleMapsAutoMapView ? = null
4786 private var mViewRegistry: GoogleMapsViewRegistry ? = null
87+ private var mPromptVisibilityListener: PromptVisibilityChangedListener ? = null
4888 protected var mIsNavigationReady: Boolean = false
4989 var mGoogleMap: GoogleMap ? = null
90+ private var mIsPromptVisible: Boolean = false
5091
5192 init {
5293 initializeSurfaceCallback()
@@ -101,11 +142,43 @@ open class AndroidAutoBaseScreen(carContext: CarContext) :
101142 mPresentation = Presentation (carContext, virtualDisplay.display)
102143 val presentation = mPresentation ? : return
103144
104- mNavigationView = NavigationViewForAuto (carContext)
145+ // Get map options from overridable method (can be customized in subclasses)
146+ val autoMapOptions = getAutoMapOptions()
147+ val googleMapOptions =
148+ GoogleMapOptions ().apply {
149+ compassEnabled(false ) // Always disable compass for Android Auto
150+
151+ // Apply custom map ID if provided
152+ autoMapOptions?.mapId?.let { mapId -> mapId(mapId) }
153+
154+ // Apply map type if provided
155+ autoMapOptions?.mapType?.let { type -> mapType(type) }
156+
157+ // Apply map color scheme if provided
158+ autoMapOptions?.mapColorScheme?.let { colorScheme -> mapColorScheme(colorScheme) }
159+ }
160+
161+ // Create NavigationView with the configured options
162+ mNavigationView = NavigationView (carContext, googleMapOptions)
105163 val navigationView = mNavigationView ? : return
106- navigationView.onCreate(null )
107- navigationView.onStart()
108- navigationView.onResume()
164+
165+ // Apply force night mode if provided (separate from color scheme)
166+ autoMapOptions?.forceNightMode?.let { forceNightMode ->
167+ navigationView.setForceNightMode(forceNightMode)
168+ }
169+
170+ // Configure NavigationView for Android Auto
171+ navigationView.apply {
172+ onCreate(null )
173+ onStart()
174+ onResume()
175+ setHeaderEnabled(false )
176+ setRecenterButtonEnabled(false )
177+ setEtaCardEnabled(false )
178+ setSpeedometerEnabled(false )
179+ setTripProgressBarEnabled(false )
180+ setReportIncidentButtonEnabled(false )
181+ }
109182
110183 presentation.setContentView(navigationView)
111184 presentation.show()
@@ -116,14 +189,24 @@ open class AndroidAutoBaseScreen(carContext: CarContext) :
116189 if (viewRegistry != null && imageRegistry != null ) {
117190 mGoogleMap = googleMap
118191 mViewRegistry = viewRegistry
192+
119193 mAutoMapView =
120194 GoogleMapsAutoMapView (
121195 MapOptions (GoogleMapOptions (), null ),
122196 viewRegistry,
123197 imageRegistry,
124198 navigationView,
199+ navigationView,
125200 googleMap,
126201 )
202+
203+ // Set up prompt visibility listener with direct access to NavigationView
204+ mPromptVisibilityListener = PromptVisibilityChangedListener { promptVisible ->
205+ mIsPromptVisible = promptVisible
206+ onPromptVisibilityChanged(promptVisible)
207+ }
208+ navigationView.addPromptVisibilityChangedListener(mPromptVisibilityListener)
209+
127210 sendAutoScreenAvailabilityChangedEvent(true )
128211 invalidate()
129212 }
@@ -133,6 +216,14 @@ open class AndroidAutoBaseScreen(carContext: CarContext) :
133216 override fun onSurfaceDestroyed (surfaceContainer : SurfaceContainer ) {
134217 super .onSurfaceDestroyed(surfaceContainer)
135218 sendAutoScreenAvailabilityChangedEvent(false )
219+
220+ // Clean up prompt visibility listener
221+ if (mPromptVisibilityListener != null && mNavigationView != null ) {
222+ mNavigationView?.removePromptVisibilityChangedListener(mPromptVisibilityListener)
223+ mPromptVisibilityListener = null
224+ }
225+ mIsPromptVisible = false
226+
136227 mViewRegistry?.unregisterAndroidAutoView()
137228 mNavigationView?.onPause()
138229 mNavigationView?.onStop()
@@ -166,6 +257,14 @@ open class AndroidAutoBaseScreen(carContext: CarContext) :
166257 ) {}
167258 }
168259
260+ // Called when Flutter sends a custom event to native via sendCustomNavigationAutoEvent
261+ // Override this method in your AndroidAutoBaseScreen subclass to handle custom events from
262+ // Flutter
263+ open fun onCustomNavigationAutoEventFromFlutter (event : String , data : Any ) {
264+ // Default implementation does nothing
265+ // Subclasses can override to handle custom events
266+ }
267+
169268 private fun sendAutoScreenAvailabilityChangedEvent (isAvailable : Boolean ) {
170269 GoogleMapsNavigationPlugin .getInstance()?.autoViewEventApi?.onAutoScreenAvailabilityChanged(
171270 isAvailable
@@ -175,4 +274,57 @@ open class AndroidAutoBaseScreen(carContext: CarContext) :
175274 override fun onNavigationReady (ready : Boolean ) {
176275 mIsNavigationReady = ready
177276 }
277+
278+ /* *
279+ * Checks if a traffic prompt is currently visible on the Android Auto screen.
280+ *
281+ * This can be useful to dynamically adjust your UI based on prompt visibility, such as when
282+ * building templates or deciding whether to show custom elements.
283+ *
284+ * @return true if a prompt is currently visible, false otherwise
285+ *
286+ * Example:
287+ * ```kotlin
288+ * override fun onGetTemplate(): Template {
289+ * val builder = NavigationTemplate.Builder()
290+ *
291+ * // Only show custom actions if prompt is not visible
292+ * if (!isPromptVisible()) {
293+ * builder.setActionStrip(myCustomActionStrip)
294+ * }
295+ *
296+ * return builder.build()
297+ * }
298+ * ```
299+ */
300+ fun isPromptVisible (): Boolean {
301+ return mIsPromptVisible
302+ }
303+
304+ /* *
305+ * Called when traffic prompt visibility changes on the Android Auto screen.
306+ *
307+ * Override this method to add custom behavior when prompts appear or disappear, such as
308+ * hiding/showing your custom UI elements to avoid overlapping with system prompts.
309+ *
310+ * @param promptVisible true if the prompt is now visible, false if it's hidden
311+ *
312+ * Example:
313+ * ```kotlin
314+ * override fun onPromptVisibilityChanged(promptVisible: Boolean) {
315+ * super.onPromptVisibilityChanged(promptVisible)
316+ * if (promptVisible) {
317+ * // Hide your custom buttons or UI elements
318+ * } else {
319+ * // Show your custom buttons or UI elements
320+ * }
321+ * }
322+ * ```
323+ */
324+ open fun onPromptVisibilityChanged (promptVisible : Boolean ) {
325+ // Send event to Flutter by default
326+ GoogleMapsNavigationPlugin .getInstance()?.autoViewEventApi?.onPromptVisibilityChanged(
327+ promptVisible
328+ ) {}
329+ }
178330}
0 commit comments