From 3a5c18c41dfd89973722200e03108b82a7f6bc47 Mon Sep 17 00:00:00 2001 From: Joonas Kerttula Date: Tue, 23 Dec 2025 18:40:05 +0200 Subject: [PATCH] feat: support prompt visibility handling on Android Auto and CarPlay views --- .../navigation/AndroidAutoBaseScreen.kt | 164 ++++- .../flutter/navigation/AutoMapViewOptions.kt | 38 ++ .../navigation/GoogleMapsAutoMapView.kt | 49 +- .../GoogleMapsAutoViewMessageHandler.kt | 70 ++ .../navigation/GoogleMapsBaseMapView.kt | 146 ++++ .../navigation/GoogleMapsNavigationView.kt | 50 +- .../maps/flutter/navigation/messages.g.kt | 539 ++++++++++++--- .../SampleAndroidAutoScreen.kt | 36 + example/ios/Podfile | 1 + example/ios/README.md | 121 ++++ example/ios/Runner.xcodeproj/project.pbxproj | 192 +++++- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- .../xcschemes/RunnerCarPlay.xcscheme | 50 +- example/ios/Runner/CarSceneDelegate.swift | 49 ++ example/lib/main.dart | 25 +- example/lib/pages/navigation.dart | 16 + .../AutoMapViewOptions.swift | 47 ++ .../BaseCarSceneDelegate.swift | 118 +++- .../GoogleMapsAutoViewMessageHandler.swift | 72 ++ .../GoogleMapsNavigationView.swift | 32 +- .../messages.g.swift | 468 ++++++++++--- lib/src/google_maps_auto_view_controller.dart | 250 +++++++ lib/src/method_channel/auto_view_api.dart | 80 ++- lib/src/method_channel/convert/camera.dart | 2 +- lib/src/method_channel/map_view_api.dart | 4 +- lib/src/method_channel/messages.g.dart | 646 +++++++++++++++--- lib/src/types/auto_map_options.dart | 68 ++ lib/src/types/navigation_view_types.dart | 6 + lib/src/types/types.dart | 1 + pigeons/messages.dart | 45 ++ test/messages_test.g.dart | 171 ++--- 31 files changed, 3141 insertions(+), 417 deletions(-) create mode 100644 android/src/main/kotlin/com/google/maps/flutter/navigation/AutoMapViewOptions.kt create mode 100644 example/ios/README.md create mode 100644 ios/google_navigation_flutter/Sources/google_navigation_flutter/AutoMapViewOptions.swift create mode 100644 lib/src/types/auto_map_options.dart diff --git a/android/src/main/kotlin/com/google/maps/flutter/navigation/AndroidAutoBaseScreen.kt b/android/src/main/kotlin/com/google/maps/flutter/navigation/AndroidAutoBaseScreen.kt index 3892c324..e58805c3 100644 --- a/android/src/main/kotlin/com/google/maps/flutter/navigation/AndroidAutoBaseScreen.kt +++ b/android/src/main/kotlin/com/google/maps/flutter/navigation/AndroidAutoBaseScreen.kt @@ -35,18 +35,59 @@ import androidx.lifecycle.LifecycleOwner import com.google.android.gms.maps.CameraUpdateFactory import com.google.android.gms.maps.GoogleMap import com.google.android.gms.maps.GoogleMapOptions -import com.google.android.libraries.navigation.NavigationViewForAuto +import com.google.android.libraries.navigation.NavigationView +import com.google.android.libraries.navigation.PromptVisibilityChangedListener open class AndroidAutoBaseScreen(carContext: CarContext) : Screen(carContext), SurfaceCallback, NavigationReadyListener { + + companion object { + /** + * Map options to use for Android Auto views. Can be set before the Android Auto screen is + * created to customize map appearance. + */ + var mapOptions: AutoMapViewOptions? = null + } + + /** + * Provides the map options to use when creating the Android Auto map view. + * + * Override this method in your AndroidAutoBaseScreen subclass to provide custom map options from + * the native layer. This is useful when you want to set map configuration (like mapId) directly + * in native code instead of from Flutter, especially when the Android Auto screen may already be + * open. + * + * The default implementation returns the value from the companion object, which can be set from + * Flutter via GoogleMapsAutoViewController.setAutoMapOptions(). + * + * @return AutoMapViewOptions containing map configuration, or null to use defaults + * + * Example: + * ```kotlin + * override fun getAutoMapOptions(): AutoMapViewOptions? { + * return AutoMapViewOptions( + * mapId = "your-map-id", + * mapType = GoogleMap.MAP_TYPE_SATELLITE, + * mapColorScheme = UIUserInterfaceStyle.DARK, + * forceNightMode = NavigationView.FORCE_NIGHT_MODE_AUTO + * ) + * } + * ``` + */ + public open fun getAutoMapOptions(): AutoMapViewOptions? { + return mapOptions + } + private val VIRTUAL_DISPLAY_NAME = "AndroidAutoNavScreen" private var mVirtualDisplay: VirtualDisplay? = null private var mPresentation: Presentation? = null - private var mNavigationView: NavigationViewForAuto? = null + private var mNavigationView: NavigationView? = null private var mAutoMapView: GoogleMapsAutoMapView? = null private var mViewRegistry: GoogleMapsViewRegistry? = null + private var mPromptVisibilityListener: PromptVisibilityChangedListener? = null protected var mIsNavigationReady: Boolean = false var mGoogleMap: GoogleMap? = null + private var mIsPromptVisible: Boolean = false init { initializeSurfaceCallback() @@ -101,11 +142,43 @@ open class AndroidAutoBaseScreen(carContext: CarContext) : mPresentation = Presentation(carContext, virtualDisplay.display) val presentation = mPresentation ?: return - mNavigationView = NavigationViewForAuto(carContext) + // Get map options from overridable method (can be customized in subclasses) + val autoMapOptions = getAutoMapOptions() + val googleMapOptions = + GoogleMapOptions().apply { + compassEnabled(false) // Always disable compass for Android Auto + + // Apply custom map ID if provided + autoMapOptions?.mapId?.let { mapId -> mapId(mapId) } + + // Apply map type if provided + autoMapOptions?.mapType?.let { type -> mapType(type) } + + // Apply map color scheme if provided + autoMapOptions?.mapColorScheme?.let { colorScheme -> mapColorScheme(colorScheme) } + } + + // Create NavigationView with the configured options + mNavigationView = NavigationView(carContext, googleMapOptions) val navigationView = mNavigationView ?: return - navigationView.onCreate(null) - navigationView.onStart() - navigationView.onResume() + + // Apply force night mode if provided (separate from color scheme) + autoMapOptions?.forceNightMode?.let { forceNightMode -> + navigationView.setForceNightMode(forceNightMode) + } + + // Configure NavigationView for Android Auto + navigationView.apply { + onCreate(null) + onStart() + onResume() + setHeaderEnabled(false) + setRecenterButtonEnabled(false) + setEtaCardEnabled(false) + setSpeedometerEnabled(false) + setTripProgressBarEnabled(false) + setReportIncidentButtonEnabled(false) + } presentation.setContentView(navigationView) presentation.show() @@ -116,14 +189,24 @@ open class AndroidAutoBaseScreen(carContext: CarContext) : if (viewRegistry != null && imageRegistry != null) { mGoogleMap = googleMap mViewRegistry = viewRegistry + mAutoMapView = GoogleMapsAutoMapView( MapOptions(GoogleMapOptions(), null), viewRegistry, imageRegistry, navigationView, + navigationView, googleMap, ) + + // Set up prompt visibility listener with direct access to NavigationView + mPromptVisibilityListener = PromptVisibilityChangedListener { promptVisible -> + mIsPromptVisible = promptVisible + onPromptVisibilityChanged(promptVisible) + } + navigationView.addPromptVisibilityChangedListener(mPromptVisibilityListener) + sendAutoScreenAvailabilityChangedEvent(true) invalidate() } @@ -133,6 +216,14 @@ open class AndroidAutoBaseScreen(carContext: CarContext) : override fun onSurfaceDestroyed(surfaceContainer: SurfaceContainer) { super.onSurfaceDestroyed(surfaceContainer) sendAutoScreenAvailabilityChangedEvent(false) + + // Clean up prompt visibility listener + if (mPromptVisibilityListener != null && mNavigationView != null) { + mNavigationView?.removePromptVisibilityChangedListener(mPromptVisibilityListener) + mPromptVisibilityListener = null + } + mIsPromptVisible = false + mViewRegistry?.unregisterAndroidAutoView() mNavigationView?.onPause() mNavigationView?.onStop() @@ -166,6 +257,14 @@ open class AndroidAutoBaseScreen(carContext: CarContext) : ) {} } + // Called when Flutter sends a custom event to native via sendCustomNavigationAutoEvent + // Override this method in your AndroidAutoBaseScreen subclass to handle custom events from + // Flutter + open fun onCustomNavigationAutoEventFromFlutter(event: String, data: Any) { + // Default implementation does nothing + // Subclasses can override to handle custom events + } + private fun sendAutoScreenAvailabilityChangedEvent(isAvailable: Boolean) { GoogleMapsNavigationPlugin.getInstance()?.autoViewEventApi?.onAutoScreenAvailabilityChanged( isAvailable @@ -175,4 +274,57 @@ open class AndroidAutoBaseScreen(carContext: CarContext) : override fun onNavigationReady(ready: Boolean) { mIsNavigationReady = ready } + + /** + * Checks if a traffic prompt is currently visible on the Android Auto screen. + * + * This can be useful to dynamically adjust your UI based on prompt visibility, such as when + * building templates or deciding whether to show custom elements. + * + * @return true if a prompt is currently visible, false otherwise + * + * Example: + * ```kotlin + * override fun onGetTemplate(): Template { + * val builder = NavigationTemplate.Builder() + * + * // Only show custom actions if prompt is not visible + * if (!isPromptVisible()) { + * builder.setActionStrip(myCustomActionStrip) + * } + * + * return builder.build() + * } + * ``` + */ + fun isPromptVisible(): Boolean { + return mIsPromptVisible + } + + /** + * Called when traffic prompt visibility changes on the Android Auto screen. + * + * Override this method to add custom behavior when prompts appear or disappear, such as + * hiding/showing your custom UI elements to avoid overlapping with system prompts. + * + * @param promptVisible true if the prompt is now visible, false if it's hidden + * + * Example: + * ```kotlin + * override fun onPromptVisibilityChanged(promptVisible: Boolean) { + * super.onPromptVisibilityChanged(promptVisible) + * if (promptVisible) { + * // Hide your custom buttons or UI elements + * } else { + * // Show your custom buttons or UI elements + * } + * } + * ``` + */ + open fun onPromptVisibilityChanged(promptVisible: Boolean) { + // Send event to Flutter by default + GoogleMapsNavigationPlugin.getInstance()?.autoViewEventApi?.onPromptVisibilityChanged( + promptVisible + ) {} + } } diff --git a/android/src/main/kotlin/com/google/maps/flutter/navigation/AutoMapViewOptions.kt b/android/src/main/kotlin/com/google/maps/flutter/navigation/AutoMapViewOptions.kt new file mode 100644 index 00000000..3909df5e --- /dev/null +++ b/android/src/main/kotlin/com/google/maps/flutter/navigation/AutoMapViewOptions.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.maps.flutter.navigation + +/** + * Options for configuring Android Auto map views. Contains only settings relevant for Android Auto + * views. + */ +public data class AutoMapViewOptions( + /** The initial camera position for the map view. */ + val cameraPosition: CameraPositionDto? = null, + + /** Cloud-based map ID for custom styling. */ + val mapId: String? = null, + + /** The type of map to display. */ + val mapType: Int? = null, + + /** The color scheme for the map. */ + val mapColorScheme: Int? = null, + + /** Forces night mode regardless of system settings. */ + val forceNightMode: Int? = null, +) diff --git a/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsAutoMapView.kt b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsAutoMapView.kt index c50429db..e1540c48 100644 --- a/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsAutoMapView.kt +++ b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsAutoMapView.kt @@ -17,19 +17,26 @@ package com.google.maps.flutter.navigation import android.view.View +import android.view.ViewGroup import com.google.android.gms.maps.GoogleMap -import com.google.android.libraries.navigation.NavigationViewForAuto +import com.google.android.libraries.navigation.NavigationView class GoogleMapsAutoMapView internal constructor( mapOptions: MapOptions, viewRegistry: GoogleMapsViewRegistry, imageRegistry: ImageRegistry, - private val mapView: NavigationViewForAuto, + private val navigationView: NavigationView, + private val viewGroup: ViewGroup, map: GoogleMap, ) : GoogleMapsBaseMapView(null, mapOptions, null, imageRegistry) { + private var _isTrafficPromptsEnabled: Boolean = true + private var _isTrafficIncidentCardsEnabled: Boolean = true + private var _isReportIncidentButtonEnabled: Boolean = true + private var _forceNightMode: Int = 0 + override fun getView(): View { - return mapView + return viewGroup } init { @@ -40,6 +47,42 @@ internal constructor( mapReady() } + override fun setTrafficPromptsEnabled(enabled: Boolean) { + navigationView.setTrafficPromptsEnabled(enabled) + _isTrafficPromptsEnabled = enabled + } + + override fun isTrafficPromptsEnabled(): Boolean { + return _isTrafficPromptsEnabled + } + + override fun setTrafficIncidentCardsEnabled(enabled: Boolean) { + navigationView.setTrafficIncidentCardsEnabled(enabled) + _isTrafficIncidentCardsEnabled = enabled + } + + override fun isTrafficIncidentCardsEnabled(): Boolean { + return _isTrafficIncidentCardsEnabled + } + + override fun setReportIncidentButtonEnabled(enabled: Boolean) { + navigationView.setReportIncidentButtonEnabled(enabled) + _isReportIncidentButtonEnabled = enabled + } + + override fun isReportIncidentButtonEnabled(): Boolean { + return _isReportIncidentButtonEnabled + } + + override fun getForceNightMode(): Int { + return _forceNightMode + } + + override fun setForceNightMode(forceNightMode: Int) { + navigationView.setForceNightMode(forceNightMode) + _forceNightMode = forceNightMode + } + // Handled by AndroidAutoBaseScreen. override fun onStart(): Boolean { return super.onStart() diff --git a/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsAutoViewMessageHandler.kt b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsAutoViewMessageHandler.kt index b0ec13ab..7a4cfa4c 100644 --- a/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsAutoViewMessageHandler.kt +++ b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsAutoViewMessageHandler.kt @@ -31,6 +31,22 @@ class GoogleMapsAutoViewMessageHandler(private val viewRegistry: GoogleMapsViewR } } + override fun setAutoMapOptions(mapOptions: AutoMapOptionsDto) { + // Store the map options in AndroidAutoBaseScreen companion object + // Convert DTO to a simple data holder + val options = + AutoMapViewOptions( + cameraPosition = mapOptions.cameraPosition, + mapId = mapOptions.mapId, + mapType = mapOptions.mapType?.let { Convert.convertMapTypeFromDto(it) }, + mapColorScheme = + mapOptions.mapColorScheme?.let { Convert.convertMapColorSchemeFromDto(it) }, + forceNightMode = + mapOptions.forceNightMode?.let { Convert.convertNavigationForceNightModeFromDto(it) }, + ) + AndroidAutoBaseScreen.mapOptions = options + } + override fun isMyLocationEnabled(): Boolean { return getView().isMyLocationEnabled() } @@ -99,6 +115,18 @@ class GoogleMapsAutoViewMessageHandler(private val viewRegistry: GoogleMapsViewR getView().setTrafficEnabled(enabled) } + override fun setTrafficPromptsEnabled(enabled: Boolean) { + getView().setTrafficPromptsEnabled(enabled) + } + + override fun setTrafficIncidentCardsEnabled(enabled: Boolean) { + getView().setTrafficIncidentCardsEnabled(enabled) + } + + override fun setReportIncidentButtonEnabled(enabled: Boolean) { + getView().setReportIncidentButtonEnabled(enabled) + } + override fun isMyLocationButtonEnabled(): Boolean { return getView().isMyLocationButtonEnabled() } @@ -143,6 +171,18 @@ class GoogleMapsAutoViewMessageHandler(private val viewRegistry: GoogleMapsViewR return getView().isTrafficEnabled() } + override fun isTrafficPromptsEnabled(): Boolean { + return getView().isTrafficPromptsEnabled() + } + + override fun isTrafficIncidentCardsEnabled(): Boolean { + return getView().isTrafficIncidentCardsEnabled() + } + + override fun isReportIncidentButtonEnabled(): Boolean { + return getView().isReportIncidentButtonEnabled() + } + override fun getMyLocation(): LatLngDto? { val location = getView().getMyLocation() ?: return null return LatLngDto(location.latitude, location.longitude) @@ -393,4 +433,34 @@ class GoogleMapsAutoViewMessageHandler(private val viewRegistry: GoogleMapsViewR override fun getPadding(): MapPaddingDto { return getView().getPadding() } + + override fun getMapColorScheme(): MapColorSchemeDto { + val colorScheme = getView().getMapColorScheme() + return Convert.convertMapColorSchemeToDto(colorScheme) + } + + override fun setMapColorScheme(mapColorScheme: MapColorSchemeDto) { + val colorScheme = Convert.convertMapColorSchemeFromDto(mapColorScheme) + getView().setMapColorScheme(colorScheme) + } + + override fun getForceNightMode(): NavigationForceNightModeDto { + val forceNightMode = getView().getForceNightMode() + return Convert.convertNavigationForceNightModeToDto(forceNightMode) + } + + override fun setForceNightMode(forceNightMode: NavigationForceNightModeDto) { + val nightMode = Convert.convertNavigationForceNightModeFromDto(forceNightMode) + getView().setForceNightMode(nightMode) + } + + override fun sendCustomNavigationAutoEvent(event: String, data: Any) { + // This method receives custom events from Flutter. + // The implementation is left empty by design, as developers should handle + // custom events in their AndroidAutoBaseScreen subclass by overriding + // onCustomNavigationAutoEventFromFlutter method. + // + // Note: If you need to handle events here, you would need to maintain a reference + // to your AndroidAutoBaseScreen instance and call a method on it. + } } diff --git a/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsBaseMapView.kt b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsBaseMapView.kt index d364e377..6c1afa5f 100644 --- a/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsBaseMapView.kt +++ b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsBaseMapView.kt @@ -541,6 +541,152 @@ abstract class GoogleMapsBaseMapView( return getMap().isTrafficEnabled } + open fun setTrafficPromptsEnabled(enabled: Boolean) { + throw FlutterError( + "notSupported", + "setTrafficPromptsEnabled is not supported on this view type", + ) + } + + open fun isTrafficPromptsEnabled(): Boolean { + throw FlutterError("notSupported", "isTrafficPromptsEnabled is not supported on this view type") + } + + // Navigation UI methods - only supported on NavigationView + open fun isNavigationTripProgressBarEnabled(): Boolean { + throw FlutterError( + "notSupported", + "isNavigationTripProgressBarEnabled is not supported on this view type", + ) + } + + open fun setNavigationTripProgressBarEnabled(enabled: Boolean) { + throw FlutterError( + "notSupported", + "setNavigationTripProgressBarEnabled is not supported on this view type", + ) + } + + open fun isNavigationHeaderEnabled(): Boolean { + throw FlutterError( + "notSupported", + "isNavigationHeaderEnabled is not supported on this view type", + ) + } + + open fun setNavigationHeaderEnabled(enabled: Boolean) { + throw FlutterError( + "notSupported", + "setNavigationHeaderEnabled is not supported on this view type", + ) + } + + open fun isNavigationFooterEnabled(): Boolean { + throw FlutterError( + "notSupported", + "isNavigationFooterEnabled is not supported on this view type", + ) + } + + open fun setNavigationFooterEnabled(enabled: Boolean) { + throw FlutterError( + "notSupported", + "setNavigationFooterEnabled is not supported on this view type", + ) + } + + open fun isRecenterButtonEnabled(): Boolean { + throw FlutterError("notSupported", "isRecenterButtonEnabled is not supported on this view type") + } + + open fun setRecenterButtonEnabled(enabled: Boolean) { + throw FlutterError( + "notSupported", + "setRecenterButtonEnabled is not supported on this view type", + ) + } + + open fun isSpeedLimitIconEnabled(): Boolean { + throw FlutterError("notSupported", "isSpeedLimitIconEnabled is not supported on this view type") + } + + open fun setSpeedLimitIconEnabled(enabled: Boolean) { + throw FlutterError( + "notSupported", + "setSpeedLimitIconEnabled is not supported on this view type", + ) + } + + open fun isSpeedometerEnabled(): Boolean { + throw FlutterError("notSupported", "isSpeedometerEnabled is not supported on this view type") + } + + open fun setSpeedometerEnabled(enabled: Boolean) { + throw FlutterError("notSupported", "setSpeedometerEnabled is not supported on this view type") + } + + open fun isTrafficIncidentCardsEnabled(): Boolean { + throw FlutterError( + "notSupported", + "isTrafficIncidentCardsEnabled is not supported on this view type", + ) + } + + open fun setTrafficIncidentCardsEnabled(enabled: Boolean) { + throw FlutterError( + "notSupported", + "setTrafficIncidentCardsEnabled is not supported on this view type", + ) + } + + open fun isReportIncidentButtonEnabled(): Boolean { + throw FlutterError( + "notSupported", + "isReportIncidentButtonEnabled is not supported on this view type", + ) + } + + open fun setReportIncidentButtonEnabled(enabled: Boolean) { + throw FlutterError( + "notSupported", + "setReportIncidentButtonEnabled is not supported on this view type", + ) + } + + open fun isIncidentReportingAvailable(): Boolean { + throw FlutterError( + "notSupported", + "isIncidentReportingAvailable is not supported on this view type", + ) + } + + open fun showReportIncidentsPanel() { + throw FlutterError( + "notSupported", + "showReportIncidentsPanel is not supported on this view type", + ) + } + + open fun isNavigationUIEnabled(): Boolean { + throw FlutterError("notSupported", "isNavigationUIEnabled is not supported on this view type") + } + + open fun setNavigationUIEnabled(enabled: Boolean) { + throw FlutterError("notSupported", "setNavigationUIEnabled is not supported on this view type") + } + + open fun showRouteOverview() { + throw FlutterError("notSupported", "showRouteOverview is not supported on this view type") + } + + open fun getForceNightMode(): Int { + throw FlutterError("notSupported", "getForceNightMode is not supported on this view type") + } + + open fun setForceNightMode(forceNightMode: Int) { + throw FlutterError("notSupported", "setForceNightMode is not supported on this view type") + } + fun isBuildingsEnabled(): Boolean { return getMap().isBuildingsEnabled } diff --git a/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsNavigationView.kt b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsNavigationView.kt index 7f4e0f9d..fbb0cda3 100644 --- a/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsNavigationView.kt +++ b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsNavigationView.kt @@ -194,114 +194,114 @@ internal constructor( super.initListeners() } - fun isNavigationTripProgressBarEnabled(): Boolean { + override fun isNavigationTripProgressBarEnabled(): Boolean { return _isNavigationTripProgressBarEnabled } - fun setNavigationTripProgressBarEnabled(enabled: Boolean) { + override fun setNavigationTripProgressBarEnabled(enabled: Boolean) { _navigationView.setTripProgressBarEnabled(enabled) _isNavigationTripProgressBarEnabled = enabled } - fun isNavigationHeaderEnabled(): Boolean { + override fun isNavigationHeaderEnabled(): Boolean { return _isNavigationHeaderEnabled } - fun setNavigationHeaderEnabled(enabled: Boolean) { + override fun setNavigationHeaderEnabled(enabled: Boolean) { _navigationView.setHeaderEnabled(enabled) _isNavigationHeaderEnabled = enabled } - fun isNavigationFooterEnabled(): Boolean { + override fun isNavigationFooterEnabled(): Boolean { return _isNavigationFooterEnabled } - fun setNavigationFooterEnabled(enabled: Boolean) { + override fun setNavigationFooterEnabled(enabled: Boolean) { _navigationView.setEtaCardEnabled(enabled) _isNavigationFooterEnabled = enabled } - fun isRecenterButtonEnabled(): Boolean { + override fun isRecenterButtonEnabled(): Boolean { return _isRecenterButtonEnabled } - fun setRecenterButtonEnabled(enabled: Boolean) { + override fun setRecenterButtonEnabled(enabled: Boolean) { _navigationView.setRecenterButtonEnabled(enabled) _isRecenterButtonEnabled = enabled } - fun isSpeedLimitIconEnabled(): Boolean { + override fun isSpeedLimitIconEnabled(): Boolean { return _isSpeedLimitIconEnabled } - fun setSpeedLimitIconEnabled(enabled: Boolean) { + override fun setSpeedLimitIconEnabled(enabled: Boolean) { _navigationView.setSpeedLimitIconEnabled(enabled) _isSpeedLimitIconEnabled = enabled } - fun isSpeedometerEnabled(): Boolean { + override fun isSpeedometerEnabled(): Boolean { return _isSpeedometerEnabled } - fun setSpeedometerEnabled(enabled: Boolean) { + override fun setSpeedometerEnabled(enabled: Boolean) { _navigationView.setSpeedometerEnabled(enabled) _isSpeedometerEnabled = enabled } - fun isTrafficIncidentCardsEnabled(): Boolean { + override fun isTrafficIncidentCardsEnabled(): Boolean { return _isTrafficIncidentCardsEnabled } - fun setTrafficIncidentCardsEnabled(enabled: Boolean) { + override fun setTrafficIncidentCardsEnabled(enabled: Boolean) { _navigationView.setTrafficIncidentCardsEnabled(enabled) _isTrafficIncidentCardsEnabled = enabled } - fun isReportIncidentButtonEnabled(): Boolean { + override fun isReportIncidentButtonEnabled(): Boolean { return _isReportIncidentButtonEnabled } - fun setReportIncidentButtonEnabled(enabled: Boolean) { + override fun setReportIncidentButtonEnabled(enabled: Boolean) { _navigationView.setReportIncidentButtonEnabled(enabled) _isReportIncidentButtonEnabled = enabled } - fun isIncidentReportingAvailable(): Boolean { + override fun isIncidentReportingAvailable(): Boolean { return _navigationView.isIncidentReportingAvailable() } - fun showReportIncidentsPanel() { + override fun showReportIncidentsPanel() { _navigationView.showReportIncidentsPanel() } - fun isTrafficPromptsEnabled(): Boolean { + override fun isTrafficPromptsEnabled(): Boolean { return _isTrafficPromptsEnabled } - fun setTrafficPromptsEnabled(enabled: Boolean) { + override fun setTrafficPromptsEnabled(enabled: Boolean) { _navigationView.setTrafficPromptsEnabled(enabled) _isTrafficPromptsEnabled = enabled } - fun isNavigationUIEnabled(): Boolean { + override fun isNavigationUIEnabled(): Boolean { return _navigationView.isNavigationUiEnabled } - fun setNavigationUIEnabled(enabled: Boolean) { + override fun setNavigationUIEnabled(enabled: Boolean) { if (_navigationView.isNavigationUiEnabled != enabled) { _navigationView.isNavigationUiEnabled = enabled } } - fun showRouteOverview() { + override fun showRouteOverview() { _navigationView.showRouteOverview() } - fun getForceNightMode(): Int { + override fun getForceNightMode(): Int { return _forceNightMode } - fun setForceNightMode(forceNightMode: Int) { + override fun setForceNightMode(forceNightMode: Int) { _forceNightMode = forceNightMode _navigationView.setForceNightMode(forceNightMode) } diff --git a/android/src/main/kotlin/com/google/maps/flutter/navigation/messages.g.kt b/android/src/main/kotlin/com/google/maps/flutter/navigation/messages.g.kt index 20d72d9d..b5e7ea33 100644 --- a/android/src/main/kotlin/com/google/maps/flutter/navigation/messages.g.kt +++ b/android/src/main/kotlin/com/google/maps/flutter/navigation/messages.g.kt @@ -602,6 +602,51 @@ enum class TaskRemovedBehaviorDto(val raw: Int) { } } +/** + * Object containing auto/carplay map options. + * + * Generated class from Pigeon that represents data sent in messages. + */ +data class AutoMapOptionsDto( + /** The initial positioning of the camera in the map view. */ + val cameraPosition: CameraPositionDto? = null, + /** Cloud-based map ID for custom styling. */ + val mapId: String? = null, + /** The type of map to display (e.g., satellite, terrain, hybrid, etc.). */ + val mapType: MapTypeDto? = null, + /** The color scheme for the map (light, dark, or follow system). */ + val mapColorScheme: MapColorSchemeDto? = null, + /** Forces night mode (dark theme) regardless of system settings. */ + val forceNightMode: NavigationForceNightModeDto? = null, +) { + companion object { + fun fromList(pigeonVar_list: List): AutoMapOptionsDto { + val cameraPosition = pigeonVar_list[0] as CameraPositionDto? + val mapId = pigeonVar_list[1] as String? + val mapType = pigeonVar_list[2] as MapTypeDto? + val mapColorScheme = pigeonVar_list[3] as MapColorSchemeDto? + val forceNightMode = pigeonVar_list[4] as NavigationForceNightModeDto? + return AutoMapOptionsDto(cameraPosition, mapId, mapType, mapColorScheme, forceNightMode) + } + } + + fun toList(): List { + return listOf(cameraPosition, mapId, mapType, mapColorScheme, forceNightMode) + } + + override fun equals(other: Any?): Boolean { + if (other !is AutoMapOptionsDto) { + return false + } + if (this === other) { + return true + } + return MessagesPigeonUtils.deepEquals(toList(), other.toList()) + } + + override fun hashCode(): Int = toList().hashCode() +} + /** * Object containing map options used to initialize Google Map view. * @@ -2408,137 +2453,140 @@ private open class messagesPigeonCodec : StandardMessageCodec() { return (readValue(buffer) as Long?)?.let { TaskRemovedBehaviorDto.ofRaw(it.toInt()) } } 154.toByte() -> { - return (readValue(buffer) as? List)?.let { MapOptionsDto.fromList(it) } + return (readValue(buffer) as? List)?.let { AutoMapOptionsDto.fromList(it) } } 155.toByte() -> { - return (readValue(buffer) as? List)?.let { NavigationViewOptionsDto.fromList(it) } + return (readValue(buffer) as? List)?.let { MapOptionsDto.fromList(it) } } 156.toByte() -> { - return (readValue(buffer) as? List)?.let { ViewCreationOptionsDto.fromList(it) } + return (readValue(buffer) as? List)?.let { NavigationViewOptionsDto.fromList(it) } } 157.toByte() -> { - return (readValue(buffer) as? List)?.let { CameraPositionDto.fromList(it) } + return (readValue(buffer) as? List)?.let { ViewCreationOptionsDto.fromList(it) } } 158.toByte() -> { - return (readValue(buffer) as? List)?.let { MarkerDto.fromList(it) } + return (readValue(buffer) as? List)?.let { CameraPositionDto.fromList(it) } } 159.toByte() -> { - return (readValue(buffer) as? List)?.let { MarkerOptionsDto.fromList(it) } + return (readValue(buffer) as? List)?.let { MarkerDto.fromList(it) } } 160.toByte() -> { - return (readValue(buffer) as? List)?.let { ImageDescriptorDto.fromList(it) } + return (readValue(buffer) as? List)?.let { MarkerOptionsDto.fromList(it) } } 161.toByte() -> { - return (readValue(buffer) as? List)?.let { InfoWindowDto.fromList(it) } + return (readValue(buffer) as? List)?.let { ImageDescriptorDto.fromList(it) } } 162.toByte() -> { - return (readValue(buffer) as? List)?.let { MarkerAnchorDto.fromList(it) } + return (readValue(buffer) as? List)?.let { InfoWindowDto.fromList(it) } } 163.toByte() -> { - return (readValue(buffer) as? List)?.let { PointOfInterestDto.fromList(it) } + return (readValue(buffer) as? List)?.let { MarkerAnchorDto.fromList(it) } } 164.toByte() -> { - return (readValue(buffer) as? List)?.let { PolygonDto.fromList(it) } + return (readValue(buffer) as? List)?.let { PointOfInterestDto.fromList(it) } } 165.toByte() -> { - return (readValue(buffer) as? List)?.let { PolygonOptionsDto.fromList(it) } + return (readValue(buffer) as? List)?.let { PolygonDto.fromList(it) } } 166.toByte() -> { - return (readValue(buffer) as? List)?.let { PolygonHoleDto.fromList(it) } + return (readValue(buffer) as? List)?.let { PolygonOptionsDto.fromList(it) } } 167.toByte() -> { - return (readValue(buffer) as? List)?.let { StyleSpanStrokeStyleDto.fromList(it) } + return (readValue(buffer) as? List)?.let { PolygonHoleDto.fromList(it) } } 168.toByte() -> { - return (readValue(buffer) as? List)?.let { StyleSpanDto.fromList(it) } + return (readValue(buffer) as? List)?.let { StyleSpanStrokeStyleDto.fromList(it) } } 169.toByte() -> { - return (readValue(buffer) as? List)?.let { PolylineDto.fromList(it) } + return (readValue(buffer) as? List)?.let { StyleSpanDto.fromList(it) } } 170.toByte() -> { - return (readValue(buffer) as? List)?.let { PatternItemDto.fromList(it) } + return (readValue(buffer) as? List)?.let { PolylineDto.fromList(it) } } 171.toByte() -> { - return (readValue(buffer) as? List)?.let { PolylineOptionsDto.fromList(it) } + return (readValue(buffer) as? List)?.let { PatternItemDto.fromList(it) } } 172.toByte() -> { - return (readValue(buffer) as? List)?.let { CircleDto.fromList(it) } + return (readValue(buffer) as? List)?.let { PolylineOptionsDto.fromList(it) } } 173.toByte() -> { - return (readValue(buffer) as? List)?.let { CircleOptionsDto.fromList(it) } + return (readValue(buffer) as? List)?.let { CircleDto.fromList(it) } } 174.toByte() -> { - return (readValue(buffer) as? List)?.let { MapPaddingDto.fromList(it) } + return (readValue(buffer) as? List)?.let { CircleOptionsDto.fromList(it) } } 175.toByte() -> { - return (readValue(buffer) as? List)?.let { RouteTokenOptionsDto.fromList(it) } + return (readValue(buffer) as? List)?.let { MapPaddingDto.fromList(it) } } 176.toByte() -> { - return (readValue(buffer) as? List)?.let { DestinationsDto.fromList(it) } + return (readValue(buffer) as? List)?.let { RouteTokenOptionsDto.fromList(it) } } 177.toByte() -> { - return (readValue(buffer) as? List)?.let { RoutingOptionsDto.fromList(it) } + return (readValue(buffer) as? List)?.let { DestinationsDto.fromList(it) } } 178.toByte() -> { - return (readValue(buffer) as? List)?.let { NavigationDisplayOptionsDto.fromList(it) } + return (readValue(buffer) as? List)?.let { RoutingOptionsDto.fromList(it) } } 179.toByte() -> { - return (readValue(buffer) as? List)?.let { NavigationWaypointDto.fromList(it) } + return (readValue(buffer) as? List)?.let { NavigationDisplayOptionsDto.fromList(it) } } 180.toByte() -> { - return (readValue(buffer) as? List)?.let { NavigationTimeAndDistanceDto.fromList(it) } + return (readValue(buffer) as? List)?.let { NavigationWaypointDto.fromList(it) } } 181.toByte() -> { + return (readValue(buffer) as? List)?.let { NavigationTimeAndDistanceDto.fromList(it) } + } + 182.toByte() -> { return (readValue(buffer) as? List)?.let { NavigationAudioGuidanceSettingsDto.fromList(it) } } - 182.toByte() -> { + 183.toByte() -> { return (readValue(buffer) as? List)?.let { SimulationOptionsDto.fromList(it) } } - 183.toByte() -> { + 184.toByte() -> { return (readValue(buffer) as? List)?.let { LatLngDto.fromList(it) } } - 184.toByte() -> { + 185.toByte() -> { return (readValue(buffer) as? List)?.let { LatLngBoundsDto.fromList(it) } } - 185.toByte() -> { + 186.toByte() -> { return (readValue(buffer) as? List)?.let { SpeedingUpdatedEventDto.fromList(it) } } - 186.toByte() -> { + 187.toByte() -> { return (readValue(buffer) as? List)?.let { GpsAvailabilityChangeEventDto.fromList(it) } } - 187.toByte() -> { + 188.toByte() -> { return (readValue(buffer) as? List)?.let { SpeedAlertOptionsThresholdPercentageDto.fromList(it) } } - 188.toByte() -> { + 189.toByte() -> { return (readValue(buffer) as? List)?.let { SpeedAlertOptionsDto.fromList(it) } } - 189.toByte() -> { + 190.toByte() -> { return (readValue(buffer) as? List)?.let { RouteSegmentTrafficDataRoadStretchRenderingDataDto.fromList(it) } } - 190.toByte() -> { + 191.toByte() -> { return (readValue(buffer) as? List)?.let { RouteSegmentTrafficDataDto.fromList(it) } } - 191.toByte() -> { + 192.toByte() -> { return (readValue(buffer) as? List)?.let { RouteSegmentDto.fromList(it) } } - 192.toByte() -> { + 193.toByte() -> { return (readValue(buffer) as? List)?.let { LaneDirectionDto.fromList(it) } } - 193.toByte() -> { + 194.toByte() -> { return (readValue(buffer) as? List)?.let { LaneDto.fromList(it) } } - 194.toByte() -> { + 195.toByte() -> { return (readValue(buffer) as? List)?.let { StepInfoDto.fromList(it) } } - 195.toByte() -> { + 196.toByte() -> { return (readValue(buffer) as? List)?.let { NavInfoDto.fromList(it) } } else -> super.readValueOfType(type, buffer) @@ -2647,174 +2695,178 @@ private open class messagesPigeonCodec : StandardMessageCodec() { stream.write(153) writeValue(stream, value.raw) } - is MapOptionsDto -> { + is AutoMapOptionsDto -> { stream.write(154) writeValue(stream, value.toList()) } - is NavigationViewOptionsDto -> { + is MapOptionsDto -> { stream.write(155) writeValue(stream, value.toList()) } - is ViewCreationOptionsDto -> { + is NavigationViewOptionsDto -> { stream.write(156) writeValue(stream, value.toList()) } - is CameraPositionDto -> { + is ViewCreationOptionsDto -> { stream.write(157) writeValue(stream, value.toList()) } - is MarkerDto -> { + is CameraPositionDto -> { stream.write(158) writeValue(stream, value.toList()) } - is MarkerOptionsDto -> { + is MarkerDto -> { stream.write(159) writeValue(stream, value.toList()) } - is ImageDescriptorDto -> { + is MarkerOptionsDto -> { stream.write(160) writeValue(stream, value.toList()) } - is InfoWindowDto -> { + is ImageDescriptorDto -> { stream.write(161) writeValue(stream, value.toList()) } - is MarkerAnchorDto -> { + is InfoWindowDto -> { stream.write(162) writeValue(stream, value.toList()) } - is PointOfInterestDto -> { + is MarkerAnchorDto -> { stream.write(163) writeValue(stream, value.toList()) } - is PolygonDto -> { + is PointOfInterestDto -> { stream.write(164) writeValue(stream, value.toList()) } - is PolygonOptionsDto -> { + is PolygonDto -> { stream.write(165) writeValue(stream, value.toList()) } - is PolygonHoleDto -> { + is PolygonOptionsDto -> { stream.write(166) writeValue(stream, value.toList()) } - is StyleSpanStrokeStyleDto -> { + is PolygonHoleDto -> { stream.write(167) writeValue(stream, value.toList()) } - is StyleSpanDto -> { + is StyleSpanStrokeStyleDto -> { stream.write(168) writeValue(stream, value.toList()) } - is PolylineDto -> { + is StyleSpanDto -> { stream.write(169) writeValue(stream, value.toList()) } - is PatternItemDto -> { + is PolylineDto -> { stream.write(170) writeValue(stream, value.toList()) } - is PolylineOptionsDto -> { + is PatternItemDto -> { stream.write(171) writeValue(stream, value.toList()) } - is CircleDto -> { + is PolylineOptionsDto -> { stream.write(172) writeValue(stream, value.toList()) } - is CircleOptionsDto -> { + is CircleDto -> { stream.write(173) writeValue(stream, value.toList()) } - is MapPaddingDto -> { + is CircleOptionsDto -> { stream.write(174) writeValue(stream, value.toList()) } - is RouteTokenOptionsDto -> { + is MapPaddingDto -> { stream.write(175) writeValue(stream, value.toList()) } - is DestinationsDto -> { + is RouteTokenOptionsDto -> { stream.write(176) writeValue(stream, value.toList()) } - is RoutingOptionsDto -> { + is DestinationsDto -> { stream.write(177) writeValue(stream, value.toList()) } - is NavigationDisplayOptionsDto -> { + is RoutingOptionsDto -> { stream.write(178) writeValue(stream, value.toList()) } - is NavigationWaypointDto -> { + is NavigationDisplayOptionsDto -> { stream.write(179) writeValue(stream, value.toList()) } - is NavigationTimeAndDistanceDto -> { + is NavigationWaypointDto -> { stream.write(180) writeValue(stream, value.toList()) } - is NavigationAudioGuidanceSettingsDto -> { + is NavigationTimeAndDistanceDto -> { stream.write(181) writeValue(stream, value.toList()) } - is SimulationOptionsDto -> { + is NavigationAudioGuidanceSettingsDto -> { stream.write(182) writeValue(stream, value.toList()) } - is LatLngDto -> { + is SimulationOptionsDto -> { stream.write(183) writeValue(stream, value.toList()) } - is LatLngBoundsDto -> { + is LatLngDto -> { stream.write(184) writeValue(stream, value.toList()) } - is SpeedingUpdatedEventDto -> { + is LatLngBoundsDto -> { stream.write(185) writeValue(stream, value.toList()) } - is GpsAvailabilityChangeEventDto -> { + is SpeedingUpdatedEventDto -> { stream.write(186) writeValue(stream, value.toList()) } - is SpeedAlertOptionsThresholdPercentageDto -> { + is GpsAvailabilityChangeEventDto -> { stream.write(187) writeValue(stream, value.toList()) } - is SpeedAlertOptionsDto -> { + is SpeedAlertOptionsThresholdPercentageDto -> { stream.write(188) writeValue(stream, value.toList()) } - is RouteSegmentTrafficDataRoadStretchRenderingDataDto -> { + is SpeedAlertOptionsDto -> { stream.write(189) writeValue(stream, value.toList()) } - is RouteSegmentTrafficDataDto -> { + is RouteSegmentTrafficDataRoadStretchRenderingDataDto -> { stream.write(190) writeValue(stream, value.toList()) } - is RouteSegmentDto -> { + is RouteSegmentTrafficDataDto -> { stream.write(191) writeValue(stream, value.toList()) } - is LaneDirectionDto -> { + is RouteSegmentDto -> { stream.write(192) writeValue(stream, value.toList()) } - is LaneDto -> { + is LaneDirectionDto -> { stream.write(193) writeValue(stream, value.toList()) } - is StepInfoDto -> { + is LaneDto -> { stream.write(194) writeValue(stream, value.toList()) } - is NavInfoDto -> { + is StepInfoDto -> { stream.write(195) writeValue(stream, value.toList()) } + is NavInfoDto -> { + stream.write(196) + writeValue(stream, value.toList()) + } else -> super.writeValue(stream, value) } } @@ -7284,6 +7336,12 @@ class NavigationSessionEventApi( /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface AutoMapViewApi { + /** + * Sets the map options to be used for Android Auto and CarPlay views. Should be called before the + * Auto/CarPlay screen is created. This allows customization of mapId and basic map settings. + */ + fun setAutoMapOptions(mapOptions: AutoMapOptionsDto) + fun isMyLocationEnabled(): Boolean fun setMyLocationEnabled(enabled: Boolean) @@ -7387,6 +7445,12 @@ interface AutoMapViewApi { fun setTrafficEnabled(enabled: Boolean) + fun setTrafficPromptsEnabled(enabled: Boolean) + + fun setTrafficIncidentCardsEnabled(enabled: Boolean) + + fun setReportIncidentButtonEnabled(enabled: Boolean) + fun isMyLocationButtonEnabled(): Boolean fun isConsumeMyLocationButtonClickEventsEnabled(): Boolean @@ -7409,6 +7473,12 @@ interface AutoMapViewApi { fun isTrafficEnabled(): Boolean + fun isTrafficPromptsEnabled(): Boolean + + fun isTrafficIncidentCardsEnabled(): Boolean + + fun isReportIncidentButtonEnabled(): Boolean + fun getMarkers(): List fun addMarkers(markers: List): List @@ -7459,6 +7529,16 @@ interface AutoMapViewApi { fun getPadding(): MapPaddingDto + fun getMapColorScheme(): MapColorSchemeDto + + fun setMapColorScheme(mapColorScheme: MapColorSchemeDto) + + fun getForceNightMode(): NavigationForceNightModeDto + + fun setForceNightMode(forceNightMode: NavigationForceNightModeDto) + + fun sendCustomNavigationAutoEvent(event: String, data: Any) + companion object { /** The codec used by AutoMapViewApi. */ val codec: MessageCodec by lazy { messagesPigeonCodec() } @@ -7472,6 +7552,30 @@ interface AutoMapViewApi { ) { val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setAutoMapOptions$separatedMessageChannelSuffix", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val mapOptionsArg = args[0] as AutoMapOptionsDto + val wrapped: List = + try { + api.setAutoMapOptions(mapOptionsArg) + listOf(null) + } catch (exception: Throwable) { + MessagesPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } run { val channel = BasicMessageChannel( @@ -8415,6 +8519,78 @@ interface AutoMapViewApi { channel.setMessageHandler(null) } } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setTrafficPromptsEnabled$separatedMessageChannelSuffix", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val enabledArg = args[0] as Boolean + val wrapped: List = + try { + api.setTrafficPromptsEnabled(enabledArg) + listOf(null) + } catch (exception: Throwable) { + MessagesPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setTrafficIncidentCardsEnabled$separatedMessageChannelSuffix", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val enabledArg = args[0] as Boolean + val wrapped: List = + try { + api.setTrafficIncidentCardsEnabled(enabledArg) + listOf(null) + } catch (exception: Throwable) { + MessagesPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setReportIncidentButtonEnabled$separatedMessageChannelSuffix", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val enabledArg = args[0] as Boolean + val wrapped: List = + try { + api.setReportIncidentButtonEnabled(enabledArg) + listOf(null) + } catch (exception: Throwable) { + MessagesPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } run { val channel = BasicMessageChannel( @@ -8646,6 +8822,69 @@ interface AutoMapViewApi { channel.setMessageHandler(null) } } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isTrafficPromptsEnabled$separatedMessageChannelSuffix", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = + try { + listOf(api.isTrafficPromptsEnabled()) + } catch (exception: Throwable) { + MessagesPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isTrafficIncidentCardsEnabled$separatedMessageChannelSuffix", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = + try { + listOf(api.isTrafficIncidentCardsEnabled()) + } catch (exception: Throwable) { + MessagesPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isReportIncidentButtonEnabled$separatedMessageChannelSuffix", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = + try { + listOf(api.isReportIncidentButtonEnabled()) + } catch (exception: Throwable) { + MessagesPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } run { val channel = BasicMessageChannel( @@ -9208,6 +9447,121 @@ interface AutoMapViewApi { channel.setMessageHandler(null) } } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMapColorScheme$separatedMessageChannelSuffix", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = + try { + listOf(api.getMapColorScheme()) + } catch (exception: Throwable) { + MessagesPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMapColorScheme$separatedMessageChannelSuffix", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val mapColorSchemeArg = args[0] as MapColorSchemeDto + val wrapped: List = + try { + api.setMapColorScheme(mapColorSchemeArg) + listOf(null) + } catch (exception: Throwable) { + MessagesPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getForceNightMode$separatedMessageChannelSuffix", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = + try { + listOf(api.getForceNightMode()) + } catch (exception: Throwable) { + MessagesPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setForceNightMode$separatedMessageChannelSuffix", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val forceNightModeArg = args[0] as NavigationForceNightModeDto + val wrapped: List = + try { + api.setForceNightMode(forceNightModeArg) + listOf(null) + } catch (exception: Throwable) { + MessagesPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.sendCustomNavigationAutoEvent$separatedMessageChannelSuffix", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val eventArg = args[0] as String + val dataArg = args[1] as Any + val wrapped: List = + try { + api.sendCustomNavigationAutoEvent(eventArg, dataArg) + listOf(null) + } catch (exception: Throwable) { + MessagesPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } } } } @@ -9263,6 +9617,25 @@ class AutoViewEventApi( } } } + + fun onPromptVisibilityChanged(promptVisibleArg: Boolean, callback: (Result) -> Unit) { + val separatedMessageChannelSuffix = + if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + val channelName = + "dev.flutter.pigeon.google_navigation_flutter.AutoViewEventApi.onPromptVisibilityChanged$separatedMessageChannelSuffix" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(promptVisibleArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(MessagesPigeonUtils.createConnectionError(channelName))) + } + } + } } /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ diff --git a/example/android/app/src/main/kotlin/com/google/maps/flutter/navigation_example/SampleAndroidAutoScreen.kt b/example/android/app/src/main/kotlin/com/google/maps/flutter/navigation_example/SampleAndroidAutoScreen.kt index 447a585c..eb6a6a6f 100644 --- a/example/android/app/src/main/kotlin/com/google/maps/flutter/navigation_example/SampleAndroidAutoScreen.kt +++ b/example/android/app/src/main/kotlin/com/google/maps/flutter/navigation_example/SampleAndroidAutoScreen.kt @@ -17,6 +17,7 @@ package com.google.maps.flutter.navigation_example import android.annotation.SuppressLint +import android.util.Log import androidx.car.app.CarContext import androidx.car.app.model.Action import androidx.car.app.model.ActionStrip @@ -97,6 +98,41 @@ class SampleAndroidAutoScreen(carContext: CarContext): AndroidAutoBaseScreen(car invalidate() } + // Example of handling prompt visibility changes + // This is called when traffic prompts appear/disappear on the Android Auto screen + override fun onPromptVisibilityChanged(promptVisible: Boolean) { + super.onPromptVisibilityChanged(promptVisible) // This sends the event to Flutter + Log.d("SampleAndroidAutoScreen", "Prompt visibility changed to: $promptVisible") + + // You can add custom logic here, such as: + // - Hiding/showing custom action buttons when prompts appear + // - Adjusting your template layout + // - Updating custom UI elements + + // For example, you might want to refresh the template: + // invalidate() + } + + // Example of handling custom events from Flutter + override fun onCustomNavigationAutoEventFromFlutter(event: String, data: Any) { + super.onCustomNavigationAutoEventFromFlutter(event, data) + Log.d("SampleAndroidAutoScreen", "Received custom event from Flutter: event=$event, data=$data") + } + + // Example of providing custom map options from native code + override fun getAutoMapOptions(): AutoMapViewOptions? { + // Call super to use Flutter-provided options + return super.getAutoMapOptions() + + // Or provide your own custom options: + // return AutoMapViewOptions( + // mapId = "your-custom-map-id", + // mapType = GoogleMap.MAP_TYPE_SATELLITE, + // mapColorScheme = MapColorScheme.DARK, + // forceNightMode = NavigationForceNightMode.FORCE_NIGHT + // ) + } + override fun onGetTemplate(): Template { if (!mIsNavigationReady) { return PaneTemplate.Builder( diff --git a/example/ios/Podfile b/example/ios/Podfile index f47daa68..00eb4e50 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -52,6 +52,7 @@ post_install do |installer| flutter_additional_ios_build_settings(target) # Start of the permission_handler configuration target.build_configurations.each do |config| + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '16.0' # You can enable the permissions needed here. For example to enable camera # permission, just remove the `#` character in front so it looks like this: diff --git a/example/ios/README.md b/example/ios/README.md new file mode 100644 index 00000000..130e4a3c --- /dev/null +++ b/example/ios/README.md @@ -0,0 +1,121 @@ +# iOS Example Apps + +This directory contains two iOS example apps to demonstrate different use cases of the Google Maps Navigation SDK: + +## 1. Runner (Standard iOS App) +**Bundle ID:** `com.google.maps.flutter.navigationExample` + +A standard iOS app without CarPlay support. + +### Running from Command Line: +```bash +# From example/ directory +flutter run -d -t lib/main.dart --flavor Runner +``` + +### Running from Xcode: +1. Open `ios/Runner.xcworkspace` +2. Select the **Runner** scheme +3. Build and run + +--- + +## 2. RunnerCarPlay (CarPlay-Enabled App) +**Bundle ID:** `com.google.maps.flutter.navigationExample.carplay` + +An iOS app with full CarPlay support, including: +- Multi-scene setup (phone + car scenes) +- CarPlay entitlements +- CarPlay-specific delegate (`AppDelegateCarPlay`) +- Conditional compilation with `#if CARPLAY` + +### Running from Command Line: +```bash +# From example/ directory +flutter run -d -t lib/main.dart --flavor RunnerCarPlay +``` + +### Running from Xcode: +1. Open `ios/Runner.xcworkspace` +2. Select the **RunnerCarPlay** scheme +3. Build and run + +--- + +## Technical Details + +### Key Differences + +| Feature | Runner | RunnerCarPlay | +| ------------- | -------------------- | ---------------------------- | +| Bundle ID | `.navigationExample` | `.navigationExample.carplay` | +| Info.plist | `Info.plist` | `Info-CarPlay.plist` | +| Entitlements | None | `RunnerCarPlay.entitlements` | +| App Delegate | `AppDelegate` | `AppDelegateCarPlay` | +| Scene Support | Single scene | Multi-scene (phone + car) | +| Swift Flags | Default | `-D CARPLAY` | + +### How main.swift Selects the Delegate + +The `main.swift` uses conditional compilation: + +```swift +#if CARPLAY + UIApplicationMain( + CommandLine.argc, + CommandLine.unsafeArgv, + nil, + NSStringFromClass(AppDelegateCarPlay.self) + ) +#else + UIApplicationMain( + CommandLine.argc, + CommandLine.unsafeArgv, + nil, + NSStringFromClass(AppDelegate.self) + ) +#endif +``` + +The `CARPLAY` flag is set via `OTHER_SWIFT_FLAGS` in the RunnerCarPlay target's build settings. + +### Swift Package Manager (SPM) Support + +Both targets support SPM. The shared scheme files are located in: +``` +ios/Runner.xcodeproj/xcshareddata/xcschemes/ +├── Runner.xcscheme +└── RunnerCarPlay.xcscheme +``` + +These schemes are version-controlled and shared across all developers. + +### CocoaPods Configuration + +The `Podfile` configures both targets: +- `Runner` target - standard iOS app +- `RunnerCarPlay` target - with CarPlay support + +All pods have their deployment target set to iOS 16.0 minimum in the `post_install` hook. + +--- + +## Troubleshooting + +### Error: "requires minimum platform version 16.0" +Run `pod install` from the `ios/` directory. The Podfile's `post_install` hook sets all pods to iOS 16.0. + +### Error: "You must specify a --flavor option" +Don't use `--flavor`. Use `--scheme` instead: +```bash +flutter run --scheme RunnerCarPlay +``` + +### Error: "Unable to get scheme file for RunnerCarPlay" +Remove any duplicate user-specific schemes: +```bash +rm -rf ios/Runner.xcodeproj/xcuserdata/*/xcschemes/RunnerCarPlay.xcscheme +``` + +### Both Apps Can't Be Installed at the Same Time +This is expected! They have different bundle IDs, so both apps can be installed simultaneously on the same device for testing purposes. diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index babaf9c3..eb615e7a 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 506F574D2AD8012C004AC70F /* RunnerUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 506F574C2AD8012C004AC70F /* RunnerUITests.m */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; 9622089A4166ECC03B433965 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 054752A3C68A7FF5D59CC247 /* Pods_RunnerTests.framework */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; @@ -30,7 +31,6 @@ C9CBB6602AD89694007C737E /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 506F57582AD8055D004AC70F /* XCTest.framework */; platformFilter = ios; }; D3A3B5ED895816BDF2A70351 /* Pods_RunnerCarPlay.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B269F01B5CD151328AA7F8EB /* Pods_RunnerCarPlay.framework */; }; EDFE577D2F64CF5D3712A4E9 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 64B801515FD75D36D58A86FE /* Pods_Runner.framework */; }; - 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -77,6 +77,7 @@ 054752A3C68A7FF5D59CC247 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 255E7806BEC9998D7DACC806 /* Pods-Runner-RunnerUITests.debug-runnercarplay.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner-RunnerUITests.debug-runnercarplay.xcconfig"; path = "Target Support Files/Pods-Runner-RunnerUITests/Pods-Runner-RunnerUITests.debug-runnercarplay.xcconfig"; sourceTree = ""; }; 2A18B9192AB17E8000172055 /* ConvertTests.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = ConvertTests.swift; sourceTree = ""; }; 2A8C4ACD2CC646F200168311 /* RunnerCarPlay.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RunnerCarPlay.app; sourceTree = BUILT_PRODUCTS_DIR; }; 2A8C4ACF2CC64A8500168311 /* AppDelegateCarPlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegateCarPlay.swift; sourceTree = ""; }; @@ -87,15 +88,18 @@ 2A8C4ADE2CC656E800168311 /* CarSceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarSceneDelegate.swift; sourceTree = ""; }; 2EAF2B705FB6C39F7F5344DA /* Pods-Runner-RunnerUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner-RunnerUITests.debug.xcconfig"; path = "Target Support Files/Pods-Runner-RunnerUITests/Pods-Runner-RunnerUITests.debug.xcconfig"; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 35E5AF4EA16C287D705B54B3 /* Pods-RunnerTests.debug-runnercarplay.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug-runnercarplay.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug-runnercarplay.xcconfig"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 3D757C86B3AF1A2A14538F73 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 506F574A2AD8012C004AC70F /* RunnerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 506F574C2AD8012C004AC70F /* RunnerUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RunnerUITests.m; sourceTree = ""; }; 506F57582AD8055D004AC70F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + 510AA50DE75FAE82EC03E97C /* Pods-Runner.debug-runnercarplay.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug-runnercarplay.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug-runnercarplay.xcconfig"; sourceTree = ""; }; 64B801515FD75D36D58A86FE /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6E64AED9A2F8E776988CC405 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 8A1462748CBFF934FB9BF87A /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; @@ -113,9 +117,9 @@ B7C92A3F95B466A95C6F8F82 /* Pods-RunnerCarPlay.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerCarPlay.profile.xcconfig"; path = "Target Support Files/Pods-RunnerCarPlay/Pods-RunnerCarPlay.profile.xcconfig"; sourceTree = ""; }; C8406E69EBE45F2EF856A867 /* Pods-RunnerCarPlay.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerCarPlay.debug.xcconfig"; path = "Target Support Files/Pods-RunnerCarPlay/Pods-RunnerCarPlay.debug.xcconfig"; sourceTree = ""; }; D775A5369CBCF55F2213A29D /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + DB233621323BD5B8EBB431E5 /* Pods-RunnerCarPlay.debug-runnercarplay.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerCarPlay.debug-runnercarplay.xcconfig"; path = "Target Support Files/Pods-RunnerCarPlay/Pods-RunnerCarPlay.debug-runnercarplay.xcconfig"; sourceTree = ""; }; F66F7193CD255958326CC224 /* Pods-RunnerCarPlay.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerCarPlay.release.xcconfig"; path = "Target Support Files/Pods-RunnerCarPlay/Pods-RunnerCarPlay.release.xcconfig"; sourceTree = ""; }; FD0B54A81651AC7754FA8D08 /* Pods-Runner-RunnerUITests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner-RunnerUITests.profile.xcconfig"; path = "Target Support Files/Pods-Runner-RunnerUITests/Pods-Runner-RunnerUITests.profile.xcconfig"; sourceTree = ""; }; - 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -244,6 +248,10 @@ C8406E69EBE45F2EF856A867 /* Pods-RunnerCarPlay.debug.xcconfig */, F66F7193CD255958326CC224 /* Pods-RunnerCarPlay.release.xcconfig */, B7C92A3F95B466A95C6F8F82 /* Pods-RunnerCarPlay.profile.xcconfig */, + 510AA50DE75FAE82EC03E97C /* Pods-Runner.debug-runnercarplay.xcconfig */, + 255E7806BEC9998D7DACC806 /* Pods-Runner-RunnerUITests.debug-runnercarplay.xcconfig */, + DB233621323BD5B8EBB431E5 /* Pods-RunnerCarPlay.debug-runnercarplay.xcconfig */, + 35E5AF4EA16C287D705B54B3 /* Pods-RunnerTests.debug-runnercarplay.xcconfig */, ); path = Pods; sourceTree = ""; @@ -282,6 +290,9 @@ dependencies = ( ); name = RunnerCarPlay; + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); productName = Runner; productReference = 2A8C4ACD2CC646F200168311 /* RunnerCarPlay.app */; productType = "com.apple.product-type.application"; @@ -329,9 +340,6 @@ productType = "com.apple.product-type.bundle.ui-testing"; }; 97C146ED1CF9000F007C117D /* Runner */ = { - packageProductDependencies = ( - 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, - ); isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( @@ -350,6 +358,9 @@ dependencies = ( ); name = Runner; + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); productName = Runner; productReference = 97C146EE1CF9000F007C117D /* Runner.app */; productType = "com.apple.product-type.application"; @@ -358,9 +369,6 @@ /* Begin PBXProject section */ 97C146E61CF9000F007C117D /* Project object */ = { - packageReferences = ( - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, - ); isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; @@ -390,6 +398,9 @@ Base, ); mainGroup = 97C146E51CF9000F007C117D; + packageReferences = ( + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + ); productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; projectRoot = ""; @@ -808,6 +819,7 @@ /* Begin XCBuildConfiguration section */ 249021D3217E4FDB00AE95B9 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB31CF90195004384FC /* Generated.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -1093,6 +1105,160 @@ }; name = Profile; }; + 52C24CA52EF59E8F003F5A8C /* Debug-RunnerCarPlay */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB31CF90195004384FC /* Generated.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = "Debug-RunnerCarPlay"; + }; + 52C24CA62EF59E8F003F5A8C /* Debug-RunnerCarPlay */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 5LUR69Y2U9; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.google.maps.flutter.navigationExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = "Debug-RunnerCarPlay"; + }; + 52C24CA72EF59E8F003F5A8C /* Debug-RunnerCarPlay */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/RunnerCarPlay.entitlements; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 5LUR69Y2U9; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = "Runner/Info-CarPlay.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -D CARPLAY"; + PRODUCT_BUNDLE_IDENTIFIER = com.google.maps.flutter.navigationExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = "Debug-RunnerCarPlay"; + }; + 52C24CA82EF59E8F003F5A8C /* Debug-RunnerCarPlay */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 35E5AF4EA16C287D705B54B3 /* Pods-RunnerTests.debug-runnercarplay.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.google.maps.flutter.navigationExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = "Debug-RunnerCarPlay"; + }; + 52C24CA92EF59E8F003F5A8C /* Debug-RunnerCarPlay */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 255E7806BEC9998D7DACC806 /* Pods-Runner-RunnerUITests.debug-runnercarplay.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.google.maps.flutter.navigation-example.RunnerUITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = Runner; + }; + name = "Debug-RunnerCarPlay"; + }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 9740EEB31CF90195004384FC /* Generated.xcconfig */; @@ -1151,6 +1317,7 @@ }; 97C147041CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB31CF90195004384FC /* Generated.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -1255,6 +1422,7 @@ isa = XCConfigurationList; buildConfigurations = ( 2A8C4ACA2CC646F200168311 /* Debug */, + 52C24CA72EF59E8F003F5A8C /* Debug-RunnerCarPlay */, 2A8C4ACB2CC646F200168311 /* Release */, 2A8C4ACC2CC646F200168311 /* Profile */, ); @@ -1265,6 +1433,7 @@ isa = XCConfigurationList; buildConfigurations = ( 331C8088294A63A400263BE5 /* Debug */, + 52C24CA82EF59E8F003F5A8C /* Debug-RunnerCarPlay */, 331C8089294A63A400263BE5 /* Release */, 331C808A294A63A400263BE5 /* Profile */, ); @@ -1275,6 +1444,7 @@ isa = XCConfigurationList; buildConfigurations = ( 506F57522AD8012C004AC70F /* Debug */, + 52C24CA92EF59E8F003F5A8C /* Debug-RunnerCarPlay */, 506F57532AD8012C004AC70F /* Release */, 506F57542AD8012C004AC70F /* Profile */, ); @@ -1285,6 +1455,7 @@ isa = XCConfigurationList; buildConfigurations = ( 97C147031CF9000F007C117D /* Debug */, + 52C24CA52EF59E8F003F5A8C /* Debug-RunnerCarPlay */, 97C147041CF9000F007C117D /* Release */, 249021D3217E4FDB00AE95B9 /* Profile */, ); @@ -1295,6 +1466,7 @@ isa = XCConfigurationList; buildConfigurations = ( 97C147061CF9000F007C117D /* Debug */, + 52C24CA62EF59E8F003F5A8C /* Debug-RunnerCarPlay */, 97C147071CF9000F007C117D /* Release */, 249021D4217E4FDB00AE95B9 /* Profile */, ); @@ -1302,12 +1474,14 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + /* Begin XCLocalSwiftPackageReference section */ - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { isa = XCLocalSwiftPackageReference; relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; }; /* End XCLocalSwiftPackageReference section */ + /* Begin XCSwiftPackageProductDependency section */ 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = { isa = XCSwiftPackageProductDependency; diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 49b7aacd..d2d01f75 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,7 +1,7 @@ + version = "1.7"> diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/RunnerCarPlay.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/RunnerCarPlay.xcscheme index 46eef0f5..eb6c4b7c 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/RunnerCarPlay.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/RunnerCarPlay.xcscheme @@ -1,11 +1,28 @@ + buildImplicitDependencies = "YES"> + + + + + + + + + + + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" + shouldUseLaunchSchemeArgsEnv = "YES"> + + + + + + @@ -52,7 +82,7 @@ + buildConfiguration = "Debug-RunnerCarPlay"> diff --git a/example/ios/Runner/CarSceneDelegate.swift b/example/ios/Runner/CarSceneDelegate.swift index dfc2451b..0dd4dc93 100644 --- a/example/ios/Runner/CarSceneDelegate.swift +++ b/example/ios/Runner/CarSceneDelegate.swift @@ -35,4 +35,53 @@ class CarSceneDelegate: BaseCarSceneDelegate { template.leadingNavigationBarButtons = [customEventButton, recenterButton] return template } + + // Example of handling custom events from Flutter + override func onCustomNavigationAutoEventFromFlutter(event: String, data: Any) { + NSLog("CarSceneDelegate: Received custom event from Flutter: event=\(event), data=\(data)") + } + + // Example of providing custom map options from native code + // Override this method to provide custom map configuration + override func getAutoMapOptions() -> AutoMapViewOptions? { + // Call super to use Flutter-provided options + return super.getAutoMapOptions() + + // Or provide your own custom options: + // let cameraPosition = GMSCameraPosition(latitude: 37.7749, longitude: -122.4194, zoom: 14) + // return AutoMapViewOptions( + // cameraPosition: cameraPosition, + // mapId: "your-custom-map-id", + // mapType: .satellite, + // mapColorScheme: .dark, + // forceNightMode: .lowLight + // ) + } + + // Example of handling prompt visibility changes + override func onPromptVisibilityChanged(promptVisible: Bool) { + // Call super to ensure Flutter receives the event + super.onPromptVisibilityChanged(promptVisible: promptVisible) + + NSLog("CarSceneDelegate: onPromptVisibilityChanged called with promptVisible=\(promptVisible)") + + // Example: Hide custom UI when prompt appears, show it when prompt disappears + // Uncomment to enable this behavior: + // if promptVisible { + // mapTemplate?.leadingNavigationBarButtons = [] + // } else { + // // Restore your custom buttons + // let customEventButton = CPBarButton(title: "Custom Event") { [weak self] _ in + // let data = ["sampleDataKey": "sampleDataContent"] + // self?.sendCustomNavigationAutoEvent(event: "CustomCarPlayEvent", data: data) + // } + // let recenterButton = CPBarButton(title: "Re-center") { [weak self] _ in + // self?.getNavView()?.followMyLocation( + // perspective: GMSNavigationCameraPerspective.tilted, + // zoomLevel: nil + // ) + // } + // mapTemplate?.leadingNavigationBarButtons = [customEventButton, recenterButton] + // } + } } diff --git a/example/lib/main.dart b/example/lib/main.dart index 2faf656b..b4d9a11a 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -69,6 +69,7 @@ class _NavigationDemoState extends State { _requestPermissions(); super.initState(); unawaited(_checkSDKVersion()); + _updateAutoMapOptions(); } Future _checkSDKVersion() async { @@ -76,6 +77,21 @@ class _NavigationDemoState extends State { _navSDKVersion = await GoogleMapsNavigator.getNavSDKVersion(); } + /// Updates AutoMapOptions for Android Auto and CarPlay views. + Future _updateAutoMapOptions() async { + final String? mapId = MapIdManager.instance.mapId; + + // Configure AutoMapOptions with current map ID + await GoogleMapsAutoViewController.setAutoMapOptions( + AutoMapOptions( + mapId: mapId, + // You can add more options here as needed: + // mapType: MapType.normal, + // mapColorScheme: MapColorScheme.followSystem, + ), + ); + } + Future _pushPage(BuildContext context, ExamplePage page) async { await Navigator.of( context, @@ -147,8 +163,13 @@ class _NavigationDemoState extends State { Padding( padding: const EdgeInsets.all(8.0), child: ElevatedButton( - onPressed: - () => showMapIdDialog(context, () => setState(() {})), + onPressed: () async { + await showMapIdDialog(context, () { + setState(() {}); + // Update AutoMapOptions when map ID changes + unawaited(_updateAutoMapOptions()); + }); + }, child: const Text('Set Map ID'), ), ), diff --git a/example/lib/pages/navigation.dart b/example/lib/pages/navigation.dart index 2ce12d6c..bd49c75c 100644 --- a/example/lib/pages/navigation.dart +++ b/example/lib/pages/navigation.dart @@ -215,6 +215,22 @@ class _NavigationPageState extends ExamplePageState { _isAutoScreenAvailable = event.isAvailable; }); }); + + // Listen for prompt visibility changes on Android Auto / CarPlay + _autoViewController.listenForPromptVisibilityChangedEvent((event) { + debugPrint( + event.promptVisible + ? "Traffic prompt is now visible on auto screen" + : "Traffic prompt is now hidden on auto screen", + ); + + // Example: Send a custom event back to native to adjust UI + _autoViewController + .sendCustomNavigationAutoEvent('PromptVisibilityChanged', { + 'promptVisible': event.promptVisible, + 'timestamp': DateTime.now().millisecondsSinceEpoch, + }); + }); } Future _setRouteTokensEnabled(bool value) async { diff --git a/ios/google_navigation_flutter/Sources/google_navigation_flutter/AutoMapViewOptions.swift b/ios/google_navigation_flutter/Sources/google_navigation_flutter/AutoMapViewOptions.swift new file mode 100644 index 00000000..853b2130 --- /dev/null +++ b/ios/google_navigation_flutter/Sources/google_navigation_flutter/AutoMapViewOptions.swift @@ -0,0 +1,47 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Foundation +import GoogleMaps +import GoogleNavigation + +/// Options for configuring CarPlay map views. +/// Contains only settings relevant for CarPlay views. +public struct AutoMapViewOptions { + /// The initial camera position for the map view. + public let cameraPosition: GMSCameraPosition? + + /// Cloud-based map ID for custom styling. + public let mapId: String? + + /// The type of map to display. + public let mapType: GMSMapViewType? + + /// The color scheme for the map. + public let mapColorScheme: UIUserInterfaceStyle? + + /// Forces night mode regardless of system settings. + public let forceNightMode: GMSNavigationLightingMode? + + public init( + cameraPosition: GMSCameraPosition? = nil, mapId: String? = nil, mapType: GMSMapViewType? = nil, + mapColorScheme: UIUserInterfaceStyle? = nil, forceNightMode: GMSNavigationLightingMode? = nil + ) { + self.cameraPosition = cameraPosition + self.mapId = mapId + self.mapType = mapType + self.mapColorScheme = mapColorScheme + self.forceNightMode = forceNightMode + } +} diff --git a/ios/google_navigation_flutter/Sources/google_navigation_flutter/BaseCarSceneDelegate.swift b/ios/google_navigation_flutter/Sources/google_navigation_flutter/BaseCarSceneDelegate.swift index 577ea77a..150fe2b2 100644 --- a/ios/google_navigation_flutter/Sources/google_navigation_flutter/BaseCarSceneDelegate.swift +++ b/ios/google_navigation_flutter/Sources/google_navigation_flutter/BaseCarSceneDelegate.swift @@ -19,6 +19,37 @@ import GoogleMaps open class BaseCarSceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate, CPMapTemplateDelegate { + /// Map options to use for CarPlay views. + /// Can be set before the CarPlay scene is created to customize map appearance. + public static var mapOptions: AutoMapViewOptions? + + /// Provides the map options to use when creating the CarPlay map view. + /// + /// Override this method in your BaseCarSceneDelegate subclass to provide custom map options + /// from the native layer. This is useful when you want to set map configuration (like mapId) + /// directly in native code instead of from Flutter, especially when the CarPlay screen + /// may already be open. + /// + /// The default implementation returns the value from the static property, which can be set + /// from Flutter via GoogleMapsAutoViewController.setAutoMapOptions(). + /// + /// - Returns: AutoMapViewOptions containing map configuration, or nil to use defaults + /// + /// Example: + /// ```swift + /// override func getAutoMapOptions() -> AutoMapViewOptions? { + /// return AutoMapViewOptions( + /// mapId: "your-map-id", + /// mapType: .satellite, + /// mapColorScheme: .dark, + /// forceNightMode: NavigationView.ForceNightMode.auto.rawValue + /// ) + /// } + /// ``` + open func getAutoMapOptions() -> AutoMapViewOptions? { + BaseCarSceneDelegate.mapOptions + } + private var interfaceController: CPInterfaceController? private var carWindow: CPWindow? private var mapTemplate: CPMapTemplate? @@ -79,6 +110,10 @@ open class BaseCarSceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate guard let self else { return } self.viewRegistry = viewRegistry self.autoViewEventApi = autoViewEventApi + + // Get map options from overridable method (can be customized in subclasses) + let autoMapOptions = self.getAutoMapOptions() + self.navView = GoogleMapsNavigationView( frame: templateApplicationScene.carWindow.screen.bounds, viewIdentifier: nil, @@ -86,21 +121,32 @@ open class BaseCarSceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate viewRegistry: viewRegistry, viewEventApi: nil, navigationUIEnabledPreference: NavigationUIEnabledPreference.automatic, - forceNightMode: nil, + forceNightMode: autoMapOptions?.forceNightMode, mapConfiguration: MapConfiguration( - cameraPosition: nil, - mapType: .normal, - compassEnabled: true, + cameraPosition: autoMapOptions?.cameraPosition, + mapType: autoMapOptions?.mapType ?? .normal, + compassEnabled: false, rotateGesturesEnabled: false, scrollGesturesEnabled: true, tiltGesturesEnabled: false, zoomGesturesEnabled: true, scrollGesturesEnabledDuringRotateOrZoom: false, - mapColorScheme: .unspecified + cameraTargetBounds: nil, + minZoomPreference: nil, + maxZoomPreference: nil, + padding: nil, + mapId: autoMapOptions?.mapId, + mapColorScheme: autoMapOptions?.mapColorScheme ?? .unspecified ), imageRegistry: imageRegistry, isCarPlayView: true ) + + // Set up prompt visibility callback to allow override + self.navView?.promptVisibilityCallback = { [weak self] promptVisible in + self?.onPromptVisibilityChanged(promptVisible: promptVisible) + } + self.navView?.setNavigationHeaderEnabled(false) self.navView?.setRecenterButtonEnabled(false) self.navView?.setNavigationFooterEnabled(false) @@ -152,10 +198,72 @@ open class BaseCarSceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate return scrollAmount } + /// Checks if a traffic prompt is currently visible on the CarPlay screen. + /// + /// This can be useful to dynamically adjust your UI based on prompt visibility, + /// such as when deciding whether to show custom buttons or adjust your template. + /// + /// - Returns: true if a prompt is currently visible, false otherwise + /// + /// Example: + /// ```swift + /// override func getTemplate() -> CPMapTemplate { + /// let template = CPMapTemplate() + /// + /// // Only show custom buttons if prompt is not visible + /// if !isPromptVisible() { + /// template.leadingNavigationBarButtons = [customButton] + /// } + /// + /// return template + /// } + /// ``` + open func isPromptVisible() -> Bool { + return navView?.isPromptVisible() ?? false + } + + /// Called when traffic prompt visibility changes on the CarPlay screen. + /// + /// Override this method to customize behavior when prompts appear or disappear, + /// such as hiding custom UI elements or adjusting your template. + /// + /// The default implementation sends the event to Flutter via AutoViewEventApi. + /// + /// - Parameter promptVisible: true when a prompt becomes visible, false when it disappears + /// + /// Example: + /// ```swift + /// override func onPromptVisibilityChanged(promptVisible: Bool) { + /// super.onPromptVisibilityChanged(promptVisible: promptVisible) + /// + /// if promptVisible { + /// // Hide custom UI when prompt appears + /// mapTemplate?.leadingNavigationBarButtons = [] + /// } else { + /// // Restore custom UI when prompt disappears + /// mapTemplate?.leadingNavigationBarButtons = [customButton] + /// } + /// } + /// ``` + open func onPromptVisibilityChanged(promptVisible: Bool) { + // Default implementation: send event to Flutter + autoViewEventApi?.onPromptVisibilityChanged( + promptVisible: promptVisible, + completion: { _ in } + ) + } + open func sendCustomNavigationAutoEvent(event: String, data: Any) { autoViewEventApi?.onCustomNavigationAutoEvent(event: event, data: data) { _ in } } + // Called when Flutter sends a custom event to native via sendCustomNavigationAutoEvent + // Override this method in your CarSceneDelegate subclass to handle custom events from Flutter + open func onCustomNavigationAutoEventFromFlutter(event: String, data: Any) { + // Default implementation does nothing + // Subclasses can override to handle custom events + } + func sendAutoScreenAvailabilityChangedEvent(isAvailable: Bool) { autoViewEventApi?.onAutoScreenAvailabilityChanged(isAvailable: isAvailable) { _ in } } diff --git a/ios/google_navigation_flutter/Sources/google_navigation_flutter/GoogleMapsAutoViewMessageHandler.swift b/ios/google_navigation_flutter/Sources/google_navigation_flutter/GoogleMapsAutoViewMessageHandler.swift index fd1499c6..553a8057 100644 --- a/ios/google_navigation_flutter/Sources/google_navigation_flutter/GoogleMapsAutoViewMessageHandler.swift +++ b/ios/google_navigation_flutter/Sources/google_navigation_flutter/GoogleMapsAutoViewMessageHandler.swift @@ -105,6 +105,34 @@ class GoogleMapsAutoViewMessageHandler: AutoMapViewApi { try getView().setTrafficEnabled(enabled) } + func setTrafficPromptsEnabled(enabled: Bool) throws { + try getView().setTrafficPromptsEnabled(enabled) + } + + func setTrafficIncidentCardsEnabled(enabled: Bool) throws { + try getView().setTrafficIncidentCardsEnabled(enabled) + } + + func setReportIncidentButtonEnabled(enabled: Bool) throws { + try getView().setReportIncidentButtonEnabled(enabled) + } + + func setAutoMapOptions(mapOptions: AutoMapOptionsDto) throws { + // Store the map options in BaseCarSceneDelegate static property + let options = AutoMapViewOptions( + cameraPosition: mapOptions.cameraPosition != nil + ? Convert.convertCameraPosition(position: mapOptions.cameraPosition!) : nil, + mapId: mapOptions.mapId, + mapType: mapOptions.mapType != nil + ? Convert.convertMapType(mapType: mapOptions.mapType!) : nil, + mapColorScheme: mapOptions.mapColorScheme != nil + ? Convert.convertMapColorScheme(mapColorScheme: mapOptions.mapColorScheme!) : nil, + forceNightMode: mapOptions.forceNightMode != nil + ? Convert.convertNavigationForceNightMode(forceNightMode: mapOptions.forceNightMode!) : nil + ) + BaseCarSceneDelegate.mapOptions = options + } + func isMyLocationEnabled() throws -> Bool { try getView().isMyLocationEnabled() } @@ -149,6 +177,18 @@ class GoogleMapsAutoViewMessageHandler: AutoMapViewApi { try getView().isTrafficEnabled() } + func isTrafficPromptsEnabled() throws -> Bool { + try getView().isTrafficPromptsEnabled() + } + + func isTrafficIncidentCardsEnabled() throws -> Bool { + try getView().isTrafficIncidentCardsEnabled() + } + + func isReportIncidentButtonEnabled() throws -> Bool { + try getView().isReportIncidentButtonEnabled() + } + func getMyLocation() throws -> LatLngDto? { do { guard let myLocation = try getView().getMyLocation() else { @@ -481,4 +521,36 @@ class GoogleMapsAutoViewMessageHandler: AutoMapViewApi { func getPadding() throws -> MapPaddingDto { try getView().getPadding() } + + func getMapColorScheme() throws -> MapColorSchemeDto { + try Convert.convertMapColorScheme(uiUserInterfaceStyle: getView().getMapColorScheme()) + } + + func setMapColorScheme(mapColorScheme: MapColorSchemeDto) throws { + let colorScheme = Convert.convertMapColorScheme(mapColorScheme: mapColorScheme) + try getView().setMapColorScheme(colorScheme: colorScheme) + } + + func getForceNightMode() throws -> NavigationForceNightModeDto { + try Convert.convertNavigationForceNightMode( + gmsNavigationLightingMode: getView().getForceNightMode() + ) + } + + func setForceNightMode(forceNightMode: NavigationForceNightModeDto) throws { + let nightMode = Convert.convertNavigationForceNightMode( + forceNightMode: forceNightMode + ) + try getView().setForceNightMode(nightMode) + } + + func sendCustomNavigationAutoEvent(event: String, data: Any) throws { + // This method receives custom events from Flutter. + // The implementation is left empty by design, as developers should handle + // custom events in their BaseCarSceneDelegate subclass by overriding + // onCustomNavigationAutoEventFromFlutter method. + // + // Note: If you need to handle events here, you would need to maintain a reference + // to your CarSceneDelegate instance and call a method on it. + } } diff --git a/ios/google_navigation_flutter/Sources/google_navigation_flutter/GoogleMapsNavigationView.swift b/ios/google_navigation_flutter/Sources/google_navigation_flutter/GoogleMapsNavigationView.swift index 0a63ca60..fa190a2e 100644 --- a/ios/google_navigation_flutter/Sources/google_navigation_flutter/GoogleMapsNavigationView.swift +++ b/ios/google_navigation_flutter/Sources/google_navigation_flutter/GoogleMapsNavigationView.swift @@ -56,6 +56,13 @@ public class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettle // is handled by the view. private var _isTrafficPromptsEnabled: Bool = true + // Track current prompt visibility state + private var _isPromptVisible: Bool = false + + // Callback for CarPlay views to handle prompt visibility changes + // This allows BaseCarSceneDelegate to intercept and handle the event + var promptVisibilityCallback: ((Bool) -> Void)? + public func view() -> UIView { _mapView } @@ -618,6 +625,10 @@ public class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettle } } + func isPromptVisible() -> Bool { + return _isPromptVisible + } + func isNavigationUIEnabled() -> Bool { _mapView.isNavigationEnabled } @@ -1111,11 +1122,22 @@ extension GoogleMapsNavigationView: GMSMapViewDelegate { } func sendPromptVisibilityChangedEvent(promptVisible: Bool) { - getViewEventApi()?.onPromptVisibilityChanged( - viewId: _viewId!, - promptVisible: promptVisible, - completion: { _ in } - ) + // Update the prompt visibility state + _isPromptVisible = promptVisible + + // For CarPlay views, use callback if set (allows override in BaseCarSceneDelegate) + // Otherwise send to regular ViewEventApi + if _isCarPlayView { + if let callback = promptVisibilityCallback { + callback(promptVisible) + } + } else { + getViewEventApi()?.onPromptVisibilityChanged( + viewId: _viewId!, + promptVisible: promptVisible, + completion: { _ in } + ) + } } } diff --git a/ios/google_navigation_flutter/Sources/google_navigation_flutter/messages.g.swift b/ios/google_navigation_flutter/Sources/google_navigation_flutter/messages.g.swift index 9e4878b2..306d70cf 100644 --- a/ios/google_navigation_flutter/Sources/google_navigation_flutter/messages.g.swift +++ b/ios/google_navigation_flutter/Sources/google_navigation_flutter/messages.g.swift @@ -491,6 +491,54 @@ enum TaskRemovedBehaviorDto: Int { case quitService = 1 } +/// Object containing auto/carplay map options. +/// +/// Generated class from Pigeon that represents data sent in messages. +struct AutoMapOptionsDto: Hashable { + /// The initial positioning of the camera in the map view. + var cameraPosition: CameraPositionDto? = nil + /// Cloud-based map ID for custom styling. + var mapId: String? = nil + /// The type of map to display (e.g., satellite, terrain, hybrid, etc.). + var mapType: MapTypeDto? = nil + /// The color scheme for the map (light, dark, or follow system). + var mapColorScheme: MapColorSchemeDto? = nil + /// Forces night mode (dark theme) regardless of system settings. + var forceNightMode: NavigationForceNightModeDto? = nil + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> AutoMapOptionsDto? { + let cameraPosition: CameraPositionDto? = nilOrValue(pigeonVar_list[0]) + let mapId: String? = nilOrValue(pigeonVar_list[1]) + let mapType: MapTypeDto? = nilOrValue(pigeonVar_list[2]) + let mapColorScheme: MapColorSchemeDto? = nilOrValue(pigeonVar_list[3]) + let forceNightMode: NavigationForceNightModeDto? = nilOrValue(pigeonVar_list[4]) + + return AutoMapOptionsDto( + cameraPosition: cameraPosition, + mapId: mapId, + mapType: mapType, + mapColorScheme: mapColorScheme, + forceNightMode: forceNightMode + ) + } + func toList() -> [Any?] { + return [ + cameraPosition, + mapId, + mapType, + mapColorScheme, + forceNightMode, + ] + } + static func == (lhs: AutoMapOptionsDto, rhs: AutoMapOptionsDto) -> Bool { + return deepEqualsmessages(lhs.toList(), rhs.toList()) + } + func hash(into hasher: inout Hasher) { + deepHashmessages(value: toList(), hasher: &hasher) + } +} + /// Object containing map options used to initialize Google Map view. /// /// Generated class from Pigeon that represents data sent in messages. @@ -2305,89 +2353,91 @@ private class MessagesPigeonCodecReader: FlutterStandardReader { } return nil case 154: - return MapOptionsDto.fromList(self.readValue() as! [Any?]) + return AutoMapOptionsDto.fromList(self.readValue() as! [Any?]) case 155: - return NavigationViewOptionsDto.fromList(self.readValue() as! [Any?]) + return MapOptionsDto.fromList(self.readValue() as! [Any?]) case 156: - return ViewCreationOptionsDto.fromList(self.readValue() as! [Any?]) + return NavigationViewOptionsDto.fromList(self.readValue() as! [Any?]) case 157: - return CameraPositionDto.fromList(self.readValue() as! [Any?]) + return ViewCreationOptionsDto.fromList(self.readValue() as! [Any?]) case 158: - return MarkerDto.fromList(self.readValue() as! [Any?]) + return CameraPositionDto.fromList(self.readValue() as! [Any?]) case 159: - return MarkerOptionsDto.fromList(self.readValue() as! [Any?]) + return MarkerDto.fromList(self.readValue() as! [Any?]) case 160: - return ImageDescriptorDto.fromList(self.readValue() as! [Any?]) + return MarkerOptionsDto.fromList(self.readValue() as! [Any?]) case 161: - return InfoWindowDto.fromList(self.readValue() as! [Any?]) + return ImageDescriptorDto.fromList(self.readValue() as! [Any?]) case 162: - return MarkerAnchorDto.fromList(self.readValue() as! [Any?]) + return InfoWindowDto.fromList(self.readValue() as! [Any?]) case 163: - return PointOfInterestDto.fromList(self.readValue() as! [Any?]) + return MarkerAnchorDto.fromList(self.readValue() as! [Any?]) case 164: - return PolygonDto.fromList(self.readValue() as! [Any?]) + return PointOfInterestDto.fromList(self.readValue() as! [Any?]) case 165: - return PolygonOptionsDto.fromList(self.readValue() as! [Any?]) + return PolygonDto.fromList(self.readValue() as! [Any?]) case 166: - return PolygonHoleDto.fromList(self.readValue() as! [Any?]) + return PolygonOptionsDto.fromList(self.readValue() as! [Any?]) case 167: - return StyleSpanStrokeStyleDto.fromList(self.readValue() as! [Any?]) + return PolygonHoleDto.fromList(self.readValue() as! [Any?]) case 168: - return StyleSpanDto.fromList(self.readValue() as! [Any?]) + return StyleSpanStrokeStyleDto.fromList(self.readValue() as! [Any?]) case 169: - return PolylineDto.fromList(self.readValue() as! [Any?]) + return StyleSpanDto.fromList(self.readValue() as! [Any?]) case 170: - return PatternItemDto.fromList(self.readValue() as! [Any?]) + return PolylineDto.fromList(self.readValue() as! [Any?]) case 171: - return PolylineOptionsDto.fromList(self.readValue() as! [Any?]) + return PatternItemDto.fromList(self.readValue() as! [Any?]) case 172: - return CircleDto.fromList(self.readValue() as! [Any?]) + return PolylineOptionsDto.fromList(self.readValue() as! [Any?]) case 173: - return CircleOptionsDto.fromList(self.readValue() as! [Any?]) + return CircleDto.fromList(self.readValue() as! [Any?]) case 174: - return MapPaddingDto.fromList(self.readValue() as! [Any?]) + return CircleOptionsDto.fromList(self.readValue() as! [Any?]) case 175: - return RouteTokenOptionsDto.fromList(self.readValue() as! [Any?]) + return MapPaddingDto.fromList(self.readValue() as! [Any?]) case 176: - return DestinationsDto.fromList(self.readValue() as! [Any?]) + return RouteTokenOptionsDto.fromList(self.readValue() as! [Any?]) case 177: - return RoutingOptionsDto.fromList(self.readValue() as! [Any?]) + return DestinationsDto.fromList(self.readValue() as! [Any?]) case 178: - return NavigationDisplayOptionsDto.fromList(self.readValue() as! [Any?]) + return RoutingOptionsDto.fromList(self.readValue() as! [Any?]) case 179: - return NavigationWaypointDto.fromList(self.readValue() as! [Any?]) + return NavigationDisplayOptionsDto.fromList(self.readValue() as! [Any?]) case 180: - return NavigationTimeAndDistanceDto.fromList(self.readValue() as! [Any?]) + return NavigationWaypointDto.fromList(self.readValue() as! [Any?]) case 181: - return NavigationAudioGuidanceSettingsDto.fromList(self.readValue() as! [Any?]) + return NavigationTimeAndDistanceDto.fromList(self.readValue() as! [Any?]) case 182: - return SimulationOptionsDto.fromList(self.readValue() as! [Any?]) + return NavigationAudioGuidanceSettingsDto.fromList(self.readValue() as! [Any?]) case 183: - return LatLngDto.fromList(self.readValue() as! [Any?]) + return SimulationOptionsDto.fromList(self.readValue() as! [Any?]) case 184: - return LatLngBoundsDto.fromList(self.readValue() as! [Any?]) + return LatLngDto.fromList(self.readValue() as! [Any?]) case 185: - return SpeedingUpdatedEventDto.fromList(self.readValue() as! [Any?]) + return LatLngBoundsDto.fromList(self.readValue() as! [Any?]) case 186: - return GpsAvailabilityChangeEventDto.fromList(self.readValue() as! [Any?]) + return SpeedingUpdatedEventDto.fromList(self.readValue() as! [Any?]) case 187: - return SpeedAlertOptionsThresholdPercentageDto.fromList(self.readValue() as! [Any?]) + return GpsAvailabilityChangeEventDto.fromList(self.readValue() as! [Any?]) case 188: - return SpeedAlertOptionsDto.fromList(self.readValue() as! [Any?]) + return SpeedAlertOptionsThresholdPercentageDto.fromList(self.readValue() as! [Any?]) case 189: + return SpeedAlertOptionsDto.fromList(self.readValue() as! [Any?]) + case 190: return RouteSegmentTrafficDataRoadStretchRenderingDataDto.fromList( self.readValue() as! [Any?]) - case 190: - return RouteSegmentTrafficDataDto.fromList(self.readValue() as! [Any?]) case 191: - return RouteSegmentDto.fromList(self.readValue() as! [Any?]) + return RouteSegmentTrafficDataDto.fromList(self.readValue() as! [Any?]) case 192: - return LaneDirectionDto.fromList(self.readValue() as! [Any?]) + return RouteSegmentDto.fromList(self.readValue() as! [Any?]) case 193: - return LaneDto.fromList(self.readValue() as! [Any?]) + return LaneDirectionDto.fromList(self.readValue() as! [Any?]) case 194: - return StepInfoDto.fromList(self.readValue() as! [Any?]) + return LaneDto.fromList(self.readValue() as! [Any?]) case 195: + return StepInfoDto.fromList(self.readValue() as! [Any?]) + case 196: return NavInfoDto.fromList(self.readValue() as! [Any?]) default: return super.readValue(ofType: type) @@ -2472,132 +2522,135 @@ private class MessagesPigeonCodecWriter: FlutterStandardWriter { } else if let value = value as? TaskRemovedBehaviorDto { super.writeByte(153) super.writeValue(value.rawValue) - } else if let value = value as? MapOptionsDto { + } else if let value = value as? AutoMapOptionsDto { super.writeByte(154) super.writeValue(value.toList()) - } else if let value = value as? NavigationViewOptionsDto { + } else if let value = value as? MapOptionsDto { super.writeByte(155) super.writeValue(value.toList()) - } else if let value = value as? ViewCreationOptionsDto { + } else if let value = value as? NavigationViewOptionsDto { super.writeByte(156) super.writeValue(value.toList()) - } else if let value = value as? CameraPositionDto { + } else if let value = value as? ViewCreationOptionsDto { super.writeByte(157) super.writeValue(value.toList()) - } else if let value = value as? MarkerDto { + } else if let value = value as? CameraPositionDto { super.writeByte(158) super.writeValue(value.toList()) - } else if let value = value as? MarkerOptionsDto { + } else if let value = value as? MarkerDto { super.writeByte(159) super.writeValue(value.toList()) - } else if let value = value as? ImageDescriptorDto { + } else if let value = value as? MarkerOptionsDto { super.writeByte(160) super.writeValue(value.toList()) - } else if let value = value as? InfoWindowDto { + } else if let value = value as? ImageDescriptorDto { super.writeByte(161) super.writeValue(value.toList()) - } else if let value = value as? MarkerAnchorDto { + } else if let value = value as? InfoWindowDto { super.writeByte(162) super.writeValue(value.toList()) - } else if let value = value as? PointOfInterestDto { + } else if let value = value as? MarkerAnchorDto { super.writeByte(163) super.writeValue(value.toList()) - } else if let value = value as? PolygonDto { + } else if let value = value as? PointOfInterestDto { super.writeByte(164) super.writeValue(value.toList()) - } else if let value = value as? PolygonOptionsDto { + } else if let value = value as? PolygonDto { super.writeByte(165) super.writeValue(value.toList()) - } else if let value = value as? PolygonHoleDto { + } else if let value = value as? PolygonOptionsDto { super.writeByte(166) super.writeValue(value.toList()) - } else if let value = value as? StyleSpanStrokeStyleDto { + } else if let value = value as? PolygonHoleDto { super.writeByte(167) super.writeValue(value.toList()) - } else if let value = value as? StyleSpanDto { + } else if let value = value as? StyleSpanStrokeStyleDto { super.writeByte(168) super.writeValue(value.toList()) - } else if let value = value as? PolylineDto { + } else if let value = value as? StyleSpanDto { super.writeByte(169) super.writeValue(value.toList()) - } else if let value = value as? PatternItemDto { + } else if let value = value as? PolylineDto { super.writeByte(170) super.writeValue(value.toList()) - } else if let value = value as? PolylineOptionsDto { + } else if let value = value as? PatternItemDto { super.writeByte(171) super.writeValue(value.toList()) - } else if let value = value as? CircleDto { + } else if let value = value as? PolylineOptionsDto { super.writeByte(172) super.writeValue(value.toList()) - } else if let value = value as? CircleOptionsDto { + } else if let value = value as? CircleDto { super.writeByte(173) super.writeValue(value.toList()) - } else if let value = value as? MapPaddingDto { + } else if let value = value as? CircleOptionsDto { super.writeByte(174) super.writeValue(value.toList()) - } else if let value = value as? RouteTokenOptionsDto { + } else if let value = value as? MapPaddingDto { super.writeByte(175) super.writeValue(value.toList()) - } else if let value = value as? DestinationsDto { + } else if let value = value as? RouteTokenOptionsDto { super.writeByte(176) super.writeValue(value.toList()) - } else if let value = value as? RoutingOptionsDto { + } else if let value = value as? DestinationsDto { super.writeByte(177) super.writeValue(value.toList()) - } else if let value = value as? NavigationDisplayOptionsDto { + } else if let value = value as? RoutingOptionsDto { super.writeByte(178) super.writeValue(value.toList()) - } else if let value = value as? NavigationWaypointDto { + } else if let value = value as? NavigationDisplayOptionsDto { super.writeByte(179) super.writeValue(value.toList()) - } else if let value = value as? NavigationTimeAndDistanceDto { + } else if let value = value as? NavigationWaypointDto { super.writeByte(180) super.writeValue(value.toList()) - } else if let value = value as? NavigationAudioGuidanceSettingsDto { + } else if let value = value as? NavigationTimeAndDistanceDto { super.writeByte(181) super.writeValue(value.toList()) - } else if let value = value as? SimulationOptionsDto { + } else if let value = value as? NavigationAudioGuidanceSettingsDto { super.writeByte(182) super.writeValue(value.toList()) - } else if let value = value as? LatLngDto { + } else if let value = value as? SimulationOptionsDto { super.writeByte(183) super.writeValue(value.toList()) - } else if let value = value as? LatLngBoundsDto { + } else if let value = value as? LatLngDto { super.writeByte(184) super.writeValue(value.toList()) - } else if let value = value as? SpeedingUpdatedEventDto { + } else if let value = value as? LatLngBoundsDto { super.writeByte(185) super.writeValue(value.toList()) - } else if let value = value as? GpsAvailabilityChangeEventDto { + } else if let value = value as? SpeedingUpdatedEventDto { super.writeByte(186) super.writeValue(value.toList()) - } else if let value = value as? SpeedAlertOptionsThresholdPercentageDto { + } else if let value = value as? GpsAvailabilityChangeEventDto { super.writeByte(187) super.writeValue(value.toList()) - } else if let value = value as? SpeedAlertOptionsDto { + } else if let value = value as? SpeedAlertOptionsThresholdPercentageDto { super.writeByte(188) super.writeValue(value.toList()) - } else if let value = value as? RouteSegmentTrafficDataRoadStretchRenderingDataDto { + } else if let value = value as? SpeedAlertOptionsDto { super.writeByte(189) super.writeValue(value.toList()) - } else if let value = value as? RouteSegmentTrafficDataDto { + } else if let value = value as? RouteSegmentTrafficDataRoadStretchRenderingDataDto { super.writeByte(190) super.writeValue(value.toList()) - } else if let value = value as? RouteSegmentDto { + } else if let value = value as? RouteSegmentTrafficDataDto { super.writeByte(191) super.writeValue(value.toList()) - } else if let value = value as? LaneDirectionDto { + } else if let value = value as? RouteSegmentDto { super.writeByte(192) super.writeValue(value.toList()) - } else if let value = value as? LaneDto { + } else if let value = value as? LaneDirectionDto { super.writeByte(193) super.writeValue(value.toList()) - } else if let value = value as? StepInfoDto { + } else if let value = value as? LaneDto { super.writeByte(194) super.writeValue(value.toList()) - } else if let value = value as? NavInfoDto { + } else if let value = value as? StepInfoDto { super.writeByte(195) super.writeValue(value.toList()) + } else if let value = value as? NavInfoDto { + super.writeByte(196) + super.writeValue(value.toList()) } else { super.writeValue(value) } @@ -6207,6 +6260,10 @@ class NavigationSessionEventApi: NavigationSessionEventApiProtocol { } /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol AutoMapViewApi { + /// Sets the map options to be used for Android Auto and CarPlay views. + /// Should be called before the Auto/CarPlay screen is created. + /// This allows customization of mapId and basic map settings. + func setAutoMapOptions(mapOptions: AutoMapOptionsDto) throws func isMyLocationEnabled() throws -> Bool func setMyLocationEnabled(enabled: Bool) throws func getMyLocation() throws -> LatLngDto? @@ -6258,6 +6315,9 @@ protocol AutoMapViewApi { func setTiltGesturesEnabled(enabled: Bool) throws func setMapToolbarEnabled(enabled: Bool) throws func setTrafficEnabled(enabled: Bool) throws + func setTrafficPromptsEnabled(enabled: Bool) throws + func setTrafficIncidentCardsEnabled(enabled: Bool) throws + func setReportIncidentButtonEnabled(enabled: Bool) throws func isMyLocationButtonEnabled() throws -> Bool func isConsumeMyLocationButtonClickEventsEnabled() throws -> Bool func isZoomGesturesEnabled() throws -> Bool @@ -6269,6 +6329,9 @@ protocol AutoMapViewApi { func isTiltGesturesEnabled() throws -> Bool func isMapToolbarEnabled() throws -> Bool func isTrafficEnabled() throws -> Bool + func isTrafficPromptsEnabled() throws -> Bool + func isTrafficIncidentCardsEnabled() throws -> Bool + func isReportIncidentButtonEnabled() throws -> Bool func getMarkers() throws -> [MarkerDto] func addMarkers(markers: [MarkerDto]) throws -> [MarkerDto] func updateMarkers(markers: [MarkerDto]) throws -> [MarkerDto] @@ -6294,6 +6357,11 @@ protocol AutoMapViewApi { func isAutoScreenAvailable() throws -> Bool func setPadding(padding: MapPaddingDto) throws func getPadding() throws -> MapPaddingDto + func getMapColorScheme() throws -> MapColorSchemeDto + func setMapColorScheme(mapColorScheme: MapColorSchemeDto) throws + func getForceNightMode() throws -> NavigationForceNightModeDto + func setForceNightMode(forceNightMode: NavigationForceNightModeDto) throws + func sendCustomNavigationAutoEvent(event: String, data: Any) throws } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. @@ -6304,6 +6372,27 @@ class AutoMapViewApiSetup { binaryMessenger: FlutterBinaryMessenger, api: AutoMapViewApi?, messageChannelSuffix: String = "" ) { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" + /// Sets the map options to be used for Android Auto and CarPlay views. + /// Should be called before the Auto/CarPlay screen is created. + /// This allows customization of mapId and basic map settings. + let setAutoMapOptionsChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setAutoMapOptions\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + setAutoMapOptionsChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let mapOptionsArg = args[0] as! AutoMapOptionsDto + do { + try api.setAutoMapOptions(mapOptions: mapOptionsArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setAutoMapOptionsChannel.setMessageHandler(nil) + } let isMyLocationEnabledChannel = FlutterBasicMessageChannel( name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isMyLocationEnabled\(channelSuffix)", @@ -7030,6 +7119,60 @@ class AutoMapViewApiSetup { } else { setTrafficEnabledChannel.setMessageHandler(nil) } + let setTrafficPromptsEnabledChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setTrafficPromptsEnabled\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + setTrafficPromptsEnabledChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let enabledArg = args[0] as! Bool + do { + try api.setTrafficPromptsEnabled(enabled: enabledArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setTrafficPromptsEnabledChannel.setMessageHandler(nil) + } + let setTrafficIncidentCardsEnabledChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setTrafficIncidentCardsEnabled\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + setTrafficIncidentCardsEnabledChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let enabledArg = args[0] as! Bool + do { + try api.setTrafficIncidentCardsEnabled(enabled: enabledArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setTrafficIncidentCardsEnabledChannel.setMessageHandler(nil) + } + let setReportIncidentButtonEnabledChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setReportIncidentButtonEnabled\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + setReportIncidentButtonEnabledChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let enabledArg = args[0] as! Bool + do { + try api.setReportIncidentButtonEnabled(enabled: enabledArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setReportIncidentButtonEnabledChannel.setMessageHandler(nil) + } let isMyLocationButtonEnabledChannel = FlutterBasicMessageChannel( name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isMyLocationButtonEnabled\(channelSuffix)", @@ -7206,6 +7349,54 @@ class AutoMapViewApiSetup { } else { isTrafficEnabledChannel.setMessageHandler(nil) } + let isTrafficPromptsEnabledChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isTrafficPromptsEnabled\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + isTrafficPromptsEnabledChannel.setMessageHandler { _, reply in + do { + let result = try api.isTrafficPromptsEnabled() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isTrafficPromptsEnabledChannel.setMessageHandler(nil) + } + let isTrafficIncidentCardsEnabledChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isTrafficIncidentCardsEnabled\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + isTrafficIncidentCardsEnabledChannel.setMessageHandler { _, reply in + do { + let result = try api.isTrafficIncidentCardsEnabled() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isTrafficIncidentCardsEnabledChannel.setMessageHandler(nil) + } + let isReportIncidentButtonEnabledChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isReportIncidentButtonEnabled\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + isReportIncidentButtonEnabledChannel.setMessageHandler { _, reply in + do { + let result = try api.isReportIncidentButtonEnabled() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isReportIncidentButtonEnabledChannel.setMessageHandler(nil) + } let getMarkersChannel = FlutterBasicMessageChannel( name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMarkers\(channelSuffix)", @@ -7631,6 +7822,93 @@ class AutoMapViewApiSetup { } else { getPaddingChannel.setMessageHandler(nil) } + let getMapColorSchemeChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMapColorScheme\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + getMapColorSchemeChannel.setMessageHandler { _, reply in + do { + let result = try api.getMapColorScheme() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + getMapColorSchemeChannel.setMessageHandler(nil) + } + let setMapColorSchemeChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMapColorScheme\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + setMapColorSchemeChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let mapColorSchemeArg = args[0] as! MapColorSchemeDto + do { + try api.setMapColorScheme(mapColorScheme: mapColorSchemeArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setMapColorSchemeChannel.setMessageHandler(nil) + } + let getForceNightModeChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getForceNightMode\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + getForceNightModeChannel.setMessageHandler { _, reply in + do { + let result = try api.getForceNightMode() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + getForceNightModeChannel.setMessageHandler(nil) + } + let setForceNightModeChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setForceNightMode\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + setForceNightModeChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let forceNightModeArg = args[0] as! NavigationForceNightModeDto + do { + try api.setForceNightMode(forceNightMode: forceNightModeArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setForceNightModeChannel.setMessageHandler(nil) + } + let sendCustomNavigationAutoEventChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.sendCustomNavigationAutoEvent\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + sendCustomNavigationAutoEventChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let eventArg = args[0] as! String + let dataArg = args[1]! + do { + try api.sendCustomNavigationAutoEvent(event: eventArg, data: dataArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + sendCustomNavigationAutoEventChannel.setMessageHandler(nil) + } } } /// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift. @@ -7640,6 +7918,8 @@ protocol AutoViewEventApiProtocol { completion: @escaping (Result) -> Void) func onAutoScreenAvailabilityChanged( isAvailable isAvailableArg: Bool, completion: @escaping (Result) -> Void) + func onPromptVisibilityChanged( + promptVisible promptVisibleArg: Bool, completion: @escaping (Result) -> Void) } class AutoViewEventApi: AutoViewEventApiProtocol { private let binaryMessenger: FlutterBinaryMessenger @@ -7696,6 +7976,28 @@ class AutoViewEventApi: AutoViewEventApiProtocol { } } } + func onPromptVisibilityChanged( + promptVisible promptVisibleArg: Bool, completion: @escaping (Result) -> Void + ) { + let channelName: String = + "dev.flutter.pigeon.google_navigation_flutter.AutoViewEventApi.onPromptVisibilityChanged\(messageChannelSuffix)" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([promptVisibleArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(())) + } + } + } } /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol NavigationInspector { diff --git a/lib/src/google_maps_auto_view_controller.dart b/lib/src/google_maps_auto_view_controller.dart index f69cdac1..f1f4f749 100644 --- a/lib/src/google_maps_auto_view_controller.dart +++ b/lib/src/google_maps_auto_view_controller.dart @@ -24,6 +24,48 @@ class GoogleMapsAutoViewController { GoogleMapsNavigationPlatform.instance.autoAPI.ensureAutoViewApiSetUp(); } + /// Sets the map options to be used for Android Auto and CarPlay views. + /// + /// This method should be called before the Android Auto or CarPlay screen is created + /// to customize the map appearance. + /// + /// The [mapOptions] parameter allows you to specify: + /// - cameraPosition: The initial positioning of the camera (target, zoom, bearing, tilt) + /// - mapId: A cloud-based map ID for custom styling + /// - mapType: The type of map to display (normal, satellite, terrain, hybrid) + /// - mapColorScheme: Color scheme affecting map colors, roads, and labels (light, dark, or follow system) + /// - forceNightMode: Controls light/dark mode for navigation UI when navigation is running + /// + /// Note: mapColorScheme and forceNightMode are independent settings: + /// - mapColorScheme controls the map's visual appearance (roads, labels, terrain colors) + /// - forceNightMode controls the navigation UI mode (light/dark) when navigation is active + /// + /// This is a static configuration that affects all auto/carplay views. + /// Gesture controls and other UI elements are not configurable as they are + /// handled by the Android Auto and CarPlay systems. + /// + /// Example usage: + /// ```dart + /// // Set before Android Auto or CarPlay screen is created + /// await GoogleMapsAutoViewController.setAutoMapOptions( + /// AutoMapOptions( + /// cameraPosition: CameraPosition( + /// target: LatLng(37.7749, -122.4194), + /// zoom: 14.0, + /// ), + /// mapId: 'your-cloud-based-map-id', + /// mapType: MapType.hybrid, + /// mapColorScheme: MapColorScheme.dark, + /// forceNightMode: NavigationForceNightMode.forceNight, + /// ), + /// ); + /// ``` + static Future setAutoMapOptions(AutoMapOptions mapOptions) { + return GoogleMapsNavigationPlatform.instance.autoAPI.setAutoMapOptions( + mapOptions: mapOptions, + ); + } + /// Change status of my location enabled. Future setMyLocationEnabled(bool enabled) { return GoogleMapsNavigationPlatform.instance.autoAPI.setMyLocationEnabled( @@ -364,11 +406,169 @@ class GoogleMapsAutoViewController { return GoogleMapsNavigationPlatform.instance.autoAPI.getPadding(); } + /// Returns whether the Android Auto or CarPlay map view is currently available. Future isAutoScreenAvailable() { return GoogleMapsNavigationPlatform.instance.autoAPI .isAutoScreenAvailable(); } + /// Enable or disable traffic prompts on the Android Auto or CarPlay map view. + /// + /// When enabled, traffic prompts are displayed on the map during navigation + /// to inform the driver about traffic conditions along the route. + /// + /// This setting persists across navigation sessions. + /// + /// Example: + /// ```dart + /// await autoViewController.setTrafficPromptsEnabled(true); + /// ``` + Future setTrafficPromptsEnabled(bool enabled) { + return GoogleMapsNavigationPlatform.instance.autoAPI + .setTrafficPromptsEnabled(enabled: enabled); + } + + /// Returns whether traffic prompts are currently enabled on the + /// Android Auto or CarPlay map view. + Future isTrafficPromptsEnabled() { + return GoogleMapsNavigationPlatform.instance.autoAPI + .isTrafficPromptsEnabled(); + } + + /// Sets whether traffic incident cards are enabled on the Android Auto or CarPlay view. + /// + /// Traffic incident cards display information about accidents, construction, + /// road closures, and other incidents along the route. + /// + /// Example: + /// ```dart + /// await autoViewController.setTrafficIncidentCardsEnabled(true); + /// ``` + Future setTrafficIncidentCardsEnabled(bool enabled) { + return GoogleMapsNavigationPlatform.instance.autoAPI + .setTrafficIncidentCardsEnabled(enabled: enabled); + } + + /// Returns whether traffic incident cards are currently enabled on the + /// Android Auto or CarPlay map view. + Future isTrafficIncidentCardsEnabled() { + return GoogleMapsNavigationPlatform.instance.autoAPI + .isTrafficIncidentCardsEnabled(); + } + + /// Sets whether the report incident button is enabled on the Android Auto or CarPlay view. + /// + /// The report incident button allows users to report traffic incidents they encounter. + /// + /// Example: + /// ```dart + /// await autoViewController.setReportIncidentButtonEnabled(true); + /// ``` + Future setReportIncidentButtonEnabled(bool enabled) { + return GoogleMapsNavigationPlatform.instance.autoAPI + .setReportIncidentButtonEnabled(enabled: enabled); + } + + /// Returns whether the report incident button is currently enabled on the + /// Android Auto or CarPlay map view. + Future isReportIncidentButtonEnabled() { + return GoogleMapsNavigationPlatform.instance.autoAPI + .isReportIncidentButtonEnabled(); + } + + /// Gets the current map color scheme for the Android Auto or CarPlay view. + /// + /// Returns the map color scheme (light, dark, or follow system). + /// + /// Example: + /// ```dart + /// final scheme = await autoViewController.getMapColorScheme(); + /// print('Current scheme: $scheme'); + /// ``` + Future getMapColorScheme() { + return GoogleMapsNavigationPlatform.instance.autoAPI.getMapColorScheme(); + } + + /// Sets the map color scheme for the Android Auto or CarPlay view. + /// + /// The color scheme affects how map tiles are rendered. + /// + /// Example: + /// ```dart + /// await autoViewController.setMapColorScheme(MapColorScheme.dark); + /// ``` + Future setMapColorScheme(MapColorScheme mapColorScheme) { + return GoogleMapsNavigationPlatform.instance.autoAPI.setMapColorScheme( + mapColorScheme: mapColorScheme, + ); + } + + /// Gets the current force night mode setting for the Android Auto or CarPlay navigation view. + /// + /// Returns the force night mode setting. + /// + /// Example: + /// ```dart + /// final mode = await autoViewController.getForceNightMode(); + /// print('Current night mode: $mode'); + /// ``` + Future getForceNightMode() { + return GoogleMapsNavigationPlatform.instance.autoAPI.getForceNightMode(); + } + + /// Sets the force night mode for the Android Auto or CarPlay navigation view. + /// + /// This controls whether the navigation UI uses night mode styling. + /// + /// Example: + /// ```dart + /// await autoViewController.setForceNightMode(NavigationForceNightMode.forceNight); + /// ``` + Future setForceNightMode(NavigationForceNightMode forceNightMode) { + return GoogleMapsNavigationPlatform.instance.autoAPI.setForceNightMode( + forceNightMode: forceNightMode, + ); + } + + /// Sends a custom event from Flutter to the native Android Auto or CarPlay implementation. + /// + /// This allows you to communicate custom data from your Flutter app to your native + /// Android Auto screen or CarPlay scene delegate implementations. + /// + /// The [event] parameter identifies the type of event being sent. + /// The [data] parameter contains the event payload, which can be any serializable type. + /// + /// Note: You must handle this event in your native implementation: + /// - Android: Override the event handling in your `AndroidAutoBaseScreen` subclass + /// - iOS: Override the event handling in your `BaseCarSceneDelegate` subclass + /// + /// Example: + /// ```dart + /// await autoViewController.sendCustomNavigationAutoEvent( + /// 'showMenu', + /// {'menuId': 'myMenu'} + /// ); + /// ``` + Future sendCustomNavigationAutoEvent(String event, Object data) { + return GoogleMapsNavigationPlatform.instance.autoAPI + .sendCustomNavigationAutoEvent(event: event, data: data); + } + + /// Listens for custom navigation events sent from the native Android Auto or CarPlay code. + /// + /// This allows your native Android Auto or CarPlay implementation to send + /// custom events back to your Flutter application. + /// + /// The [func] callback will be invoked whenever a custom event is received from + /// the native layer. + /// + /// Example: + /// ```dart + /// autoViewController.listenForCustomNavigationAutoEvents((event) { + /// print('Received event: ${event.event}'); + /// print('Event data: ${event.data}'); + /// }); + /// ``` void listenForCustomNavigationAutoEvents( void Function(CustomNavigationAutoEvent event) func, ) { @@ -379,6 +579,22 @@ class GoogleMapsAutoViewController { }); } + /// Listens for changes in Android Auto or CarPlay screen availability. + /// + /// The [func] callback will be invoked whenever the auto screen becomes + /// available or unavailable (e.g., when user connects/disconnects from + /// Android Auto or CarPlay). + /// + /// Example: + /// ```dart + /// autoViewController.listenForAutoScreenAvailibilityChangedEvent((event) { + /// if (event.isAvailable) { + /// print('Auto screen is now available'); + /// } else { + /// print('Auto screen is no longer available'); + /// } + /// }); + /// ``` void listenForAutoScreenAvailibilityChangedEvent( void Function(AutoScreenAvailabilityChangedEvent event) func, ) { @@ -388,4 +604,38 @@ class GoogleMapsAutoViewController { func(event); }); } + + /// Listens for prompt visibility changes on Android Auto or CarPlay. + /// + /// The [func] callback will be invoked whenever traffic prompts become + /// visible or hidden on the auto screen. This is useful for adjusting + /// your custom UI elements to avoid overlapping with system prompts. + /// + /// Note: You can also override the prompt visibility detection in your native + /// implementation: + /// - Android: Override the detection in your `AndroidAutoBaseScreen` subclass + /// - iOS: Override the detection in your `BaseCarSceneDelegate` subclass + /// This listener provides additional control from the Flutter side. + /// + /// Example: + /// ```dart + /// autoViewController.listenForPromptVisibilityChangedEvent((event) { + /// if (event.promptVisible) { + /// // Hide custom buttons or UI elements + /// print('Prompt is now visible, hiding custom UI'); + /// } else { + /// // Show custom buttons or UI elements + /// print('Prompt is hidden, showing custom UI'); + /// } + /// }); + /// ``` + void listenForPromptVisibilityChangedEvent( + void Function(PromptVisibilityChangedEvent event) func, + ) { + GoogleMapsNavigationPlatform.instance.autoAPI + .getPromptVisibilityChangedEventStream() + .listen((PromptVisibilityChangedEvent event) { + func(event); + }); + } } diff --git a/lib/src/method_channel/auto_view_api.dart b/lib/src/method_channel/auto_view_api.dart index 176f7418..7915e4e0 100644 --- a/lib/src/method_channel/auto_view_api.dart +++ b/lib/src/method_channel/auto_view_api.dart @@ -87,6 +87,18 @@ class AutoMapViewAPIImpl { } } + /// Sets the map options to be used for Android Auto and CarPlay views. + Future setAutoMapOptions({required AutoMapOptions mapOptions}) { + final AutoMapOptionsDto mapOptionsDto = AutoMapOptionsDto( + cameraPosition: mapOptions.cameraPosition?.toDto(), + mapId: mapOptions.mapId, + mapType: mapOptions.mapType?.toDto(), + mapColorScheme: mapOptions.mapColorScheme?.toDto(), + forceNightMode: mapOptions.forceNightMode?.toDto(), + ); + return _viewApi.setAutoMapOptions(mapOptionsDto); + } + /// Get the preference for whether the my location should be enabled or disabled. Future isMyLocationEnabled() { return _viewApi.isMyLocationEnabled(); @@ -312,7 +324,7 @@ class AutoMapViewAPIImpl { unawaited( _viewApi .animateCameraToCameraPosition( - cameraUpdate.cameraPosition!.toCameraPosition(), + cameraUpdate.cameraPosition!.toDto(), duration, ) .then( @@ -407,7 +419,7 @@ class AutoMapViewAPIImpl { case CameraUpdateType.cameraPosition: assert(cameraUpdate.cameraPosition != null, 'Camera position is null'); return _viewApi.moveCameraToCameraPosition( - cameraUpdate.cameraPosition!.toCameraPosition(), + cameraUpdate.cameraPosition!.toDto(), ); case CameraUpdateType.latLng: return _viewApi.moveCameraToLatLng(cameraUpdate.latLng!.toDto()); @@ -868,6 +880,63 @@ class AutoMapViewAPIImpl { getAutoScreenAvailabilityChangedEventStream() { return _unwrapEventStream(); } + + /// Get prompt visibility changed event stream from the auto view. + Stream getPromptVisibilityChangedEventStream() { + return _unwrapEventStream(); + } + + Future setTrafficPromptsEnabled({required bool enabled}) { + return _viewApi.setTrafficPromptsEnabled(enabled); + } + + Future isTrafficPromptsEnabled() { + return _viewApi.isTrafficPromptsEnabled(); + } + + Future setTrafficIncidentCardsEnabled({required bool enabled}) { + return _viewApi.setTrafficIncidentCardsEnabled(enabled); + } + + Future isTrafficIncidentCardsEnabled() { + return _viewApi.isTrafficIncidentCardsEnabled(); + } + + Future setReportIncidentButtonEnabled({required bool enabled}) { + return _viewApi.setReportIncidentButtonEnabled(enabled); + } + + Future isReportIncidentButtonEnabled() { + return _viewApi.isReportIncidentButtonEnabled(); + } + + Future getMapColorScheme() async { + final MapColorSchemeDto colorScheme = await _viewApi.getMapColorScheme(); + return colorScheme.toMapColorScheme(); + } + + Future setMapColorScheme({required MapColorScheme mapColorScheme}) { + return _viewApi.setMapColorScheme(mapColorScheme.toDto()); + } + + Future getForceNightMode() async { + final NavigationForceNightModeDto forceNightMode = await _viewApi + .getForceNightMode(); + return forceNightMode.toNavigationForceNightMode(); + } + + Future setForceNightMode({ + required NavigationForceNightMode forceNightMode, + }) { + return _viewApi.setForceNightMode(forceNightMode.toDto()); + } + + Future sendCustomNavigationAutoEvent({ + required String event, + required Object data, + }) { + return _viewApi.sendCustomNavigationAutoEvent(event, data); + } } class AutoViewEventApiImpl implements AutoViewEventApi { @@ -893,6 +962,13 @@ class AutoViewEventApiImpl implements AutoViewEventApi { ), ); } + + @override + void onPromptVisibilityChanged(bool promptVisible) { + _viewEventStreamController.add( + _AutoEventWrapper(PromptVisibilityChangedEvent(promptVisible)), + ); + } } class _AutoEventWrapper { diff --git a/lib/src/method_channel/convert/camera.dart b/lib/src/method_channel/convert/camera.dart index d0dd1b0e..b3409abf 100644 --- a/lib/src/method_channel/convert/camera.dart +++ b/lib/src/method_channel/convert/camera.dart @@ -31,7 +31,7 @@ extension ConvertCameraPositionDto on CameraPositionDto { /// @nodoc extension ConvertCameraPosition on CameraPosition { /// Convert [CameraPosition] to [CameraPositionDto]. - CameraPositionDto toCameraPosition() => CameraPositionDto( + CameraPositionDto toDto() => CameraPositionDto( bearing: bearing, target: target.toDto(), tilt: tilt, diff --git a/lib/src/method_channel/map_view_api.dart b/lib/src/method_channel/map_view_api.dart index 6c548d18..97af4006 100644 --- a/lib/src/method_channel/map_view_api.dart +++ b/lib/src/method_channel/map_view_api.dart @@ -413,7 +413,7 @@ class MapViewAPIImpl { _viewApi .animateCameraToCameraPosition( viewId, - cameraUpdate.cameraPosition!.toCameraPosition(), + cameraUpdate.cameraPosition!.toDto(), duration, ) .then( @@ -520,7 +520,7 @@ class MapViewAPIImpl { assert(cameraUpdate.cameraPosition != null, 'Camera position is null'); return _viewApi.moveCameraToCameraPosition( viewId, - cameraUpdate.cameraPosition!.toCameraPosition(), + cameraUpdate.cameraPosition!.toDto(), ); case CameraUpdateType.latLng: return _viewApi.moveCameraToLatLng( diff --git a/lib/src/method_channel/messages.g.dart b/lib/src/method_channel/messages.g.dart index 3b1560e7..7457ce33 100644 --- a/lib/src/method_channel/messages.g.dart +++ b/lib/src/method_channel/messages.g.dart @@ -439,6 +439,73 @@ enum TaskRemovedBehaviorDto { quitService, } +/// Object containing auto/carplay map options. +class AutoMapOptionsDto { + AutoMapOptionsDto({ + this.cameraPosition, + this.mapId, + this.mapType, + this.mapColorScheme, + this.forceNightMode, + }); + + /// The initial positioning of the camera in the map view. + CameraPositionDto? cameraPosition; + + /// Cloud-based map ID for custom styling. + String? mapId; + + /// The type of map to display (e.g., satellite, terrain, hybrid, etc.). + MapTypeDto? mapType; + + /// The color scheme for the map (light, dark, or follow system). + MapColorSchemeDto? mapColorScheme; + + /// Forces night mode (dark theme) regardless of system settings. + NavigationForceNightModeDto? forceNightMode; + + List _toList() { + return [ + cameraPosition, + mapId, + mapType, + mapColorScheme, + forceNightMode, + ]; + } + + Object encode() { + return _toList(); + } + + static AutoMapOptionsDto decode(Object result) { + result as List; + return AutoMapOptionsDto( + cameraPosition: result[0] as CameraPositionDto?, + mapId: result[1] as String?, + mapType: result[2] as MapTypeDto?, + mapColorScheme: result[3] as MapColorSchemeDto?, + forceNightMode: result[4] as NavigationForceNightModeDto?, + ); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! AutoMapOptionsDto || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(encode(), other.encode()); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => Object.hashAll(_toList()); +} + /// Object containing map options used to initialize Google Map view. class MapOptionsDto { MapOptionsDto({ @@ -2826,132 +2893,135 @@ class _PigeonCodec extends StandardMessageCodec { } else if (value is TaskRemovedBehaviorDto) { buffer.putUint8(153); writeValue(buffer, value.index); - } else if (value is MapOptionsDto) { + } else if (value is AutoMapOptionsDto) { buffer.putUint8(154); writeValue(buffer, value.encode()); - } else if (value is NavigationViewOptionsDto) { + } else if (value is MapOptionsDto) { buffer.putUint8(155); writeValue(buffer, value.encode()); - } else if (value is ViewCreationOptionsDto) { + } else if (value is NavigationViewOptionsDto) { buffer.putUint8(156); writeValue(buffer, value.encode()); - } else if (value is CameraPositionDto) { + } else if (value is ViewCreationOptionsDto) { buffer.putUint8(157); writeValue(buffer, value.encode()); - } else if (value is MarkerDto) { + } else if (value is CameraPositionDto) { buffer.putUint8(158); writeValue(buffer, value.encode()); - } else if (value is MarkerOptionsDto) { + } else if (value is MarkerDto) { buffer.putUint8(159); writeValue(buffer, value.encode()); - } else if (value is ImageDescriptorDto) { + } else if (value is MarkerOptionsDto) { buffer.putUint8(160); writeValue(buffer, value.encode()); - } else if (value is InfoWindowDto) { + } else if (value is ImageDescriptorDto) { buffer.putUint8(161); writeValue(buffer, value.encode()); - } else if (value is MarkerAnchorDto) { + } else if (value is InfoWindowDto) { buffer.putUint8(162); writeValue(buffer, value.encode()); - } else if (value is PointOfInterestDto) { + } else if (value is MarkerAnchorDto) { buffer.putUint8(163); writeValue(buffer, value.encode()); - } else if (value is PolygonDto) { + } else if (value is PointOfInterestDto) { buffer.putUint8(164); writeValue(buffer, value.encode()); - } else if (value is PolygonOptionsDto) { + } else if (value is PolygonDto) { buffer.putUint8(165); writeValue(buffer, value.encode()); - } else if (value is PolygonHoleDto) { + } else if (value is PolygonOptionsDto) { buffer.putUint8(166); writeValue(buffer, value.encode()); - } else if (value is StyleSpanStrokeStyleDto) { + } else if (value is PolygonHoleDto) { buffer.putUint8(167); writeValue(buffer, value.encode()); - } else if (value is StyleSpanDto) { + } else if (value is StyleSpanStrokeStyleDto) { buffer.putUint8(168); writeValue(buffer, value.encode()); - } else if (value is PolylineDto) { + } else if (value is StyleSpanDto) { buffer.putUint8(169); writeValue(buffer, value.encode()); - } else if (value is PatternItemDto) { + } else if (value is PolylineDto) { buffer.putUint8(170); writeValue(buffer, value.encode()); - } else if (value is PolylineOptionsDto) { + } else if (value is PatternItemDto) { buffer.putUint8(171); writeValue(buffer, value.encode()); - } else if (value is CircleDto) { + } else if (value is PolylineOptionsDto) { buffer.putUint8(172); writeValue(buffer, value.encode()); - } else if (value is CircleOptionsDto) { + } else if (value is CircleDto) { buffer.putUint8(173); writeValue(buffer, value.encode()); - } else if (value is MapPaddingDto) { + } else if (value is CircleOptionsDto) { buffer.putUint8(174); writeValue(buffer, value.encode()); - } else if (value is RouteTokenOptionsDto) { + } else if (value is MapPaddingDto) { buffer.putUint8(175); writeValue(buffer, value.encode()); - } else if (value is DestinationsDto) { + } else if (value is RouteTokenOptionsDto) { buffer.putUint8(176); writeValue(buffer, value.encode()); - } else if (value is RoutingOptionsDto) { + } else if (value is DestinationsDto) { buffer.putUint8(177); writeValue(buffer, value.encode()); - } else if (value is NavigationDisplayOptionsDto) { + } else if (value is RoutingOptionsDto) { buffer.putUint8(178); writeValue(buffer, value.encode()); - } else if (value is NavigationWaypointDto) { + } else if (value is NavigationDisplayOptionsDto) { buffer.putUint8(179); writeValue(buffer, value.encode()); - } else if (value is NavigationTimeAndDistanceDto) { + } else if (value is NavigationWaypointDto) { buffer.putUint8(180); writeValue(buffer, value.encode()); - } else if (value is NavigationAudioGuidanceSettingsDto) { + } else if (value is NavigationTimeAndDistanceDto) { buffer.putUint8(181); writeValue(buffer, value.encode()); - } else if (value is SimulationOptionsDto) { + } else if (value is NavigationAudioGuidanceSettingsDto) { buffer.putUint8(182); writeValue(buffer, value.encode()); - } else if (value is LatLngDto) { + } else if (value is SimulationOptionsDto) { buffer.putUint8(183); writeValue(buffer, value.encode()); - } else if (value is LatLngBoundsDto) { + } else if (value is LatLngDto) { buffer.putUint8(184); writeValue(buffer, value.encode()); - } else if (value is SpeedingUpdatedEventDto) { + } else if (value is LatLngBoundsDto) { buffer.putUint8(185); writeValue(buffer, value.encode()); - } else if (value is GpsAvailabilityChangeEventDto) { + } else if (value is SpeedingUpdatedEventDto) { buffer.putUint8(186); writeValue(buffer, value.encode()); - } else if (value is SpeedAlertOptionsThresholdPercentageDto) { + } else if (value is GpsAvailabilityChangeEventDto) { buffer.putUint8(187); writeValue(buffer, value.encode()); - } else if (value is SpeedAlertOptionsDto) { + } else if (value is SpeedAlertOptionsThresholdPercentageDto) { buffer.putUint8(188); writeValue(buffer, value.encode()); - } else if (value is RouteSegmentTrafficDataRoadStretchRenderingDataDto) { + } else if (value is SpeedAlertOptionsDto) { buffer.putUint8(189); writeValue(buffer, value.encode()); - } else if (value is RouteSegmentTrafficDataDto) { + } else if (value is RouteSegmentTrafficDataRoadStretchRenderingDataDto) { buffer.putUint8(190); writeValue(buffer, value.encode()); - } else if (value is RouteSegmentDto) { + } else if (value is RouteSegmentTrafficDataDto) { buffer.putUint8(191); writeValue(buffer, value.encode()); - } else if (value is LaneDirectionDto) { + } else if (value is RouteSegmentDto) { buffer.putUint8(192); writeValue(buffer, value.encode()); - } else if (value is LaneDto) { + } else if (value is LaneDirectionDto) { buffer.putUint8(193); writeValue(buffer, value.encode()); - } else if (value is StepInfoDto) { + } else if (value is LaneDto) { buffer.putUint8(194); writeValue(buffer, value.encode()); - } else if (value is NavInfoDto) { + } else if (value is StepInfoDto) { buffer.putUint8(195); writeValue(buffer, value.encode()); + } else if (value is NavInfoDto) { + buffer.putUint8(196); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -3043,92 +3113,94 @@ class _PigeonCodec extends StandardMessageCodec { final int? value = readValue(buffer) as int?; return value == null ? null : TaskRemovedBehaviorDto.values[value]; case 154: - return MapOptionsDto.decode(readValue(buffer)!); + return AutoMapOptionsDto.decode(readValue(buffer)!); case 155: - return NavigationViewOptionsDto.decode(readValue(buffer)!); + return MapOptionsDto.decode(readValue(buffer)!); case 156: - return ViewCreationOptionsDto.decode(readValue(buffer)!); + return NavigationViewOptionsDto.decode(readValue(buffer)!); case 157: - return CameraPositionDto.decode(readValue(buffer)!); + return ViewCreationOptionsDto.decode(readValue(buffer)!); case 158: - return MarkerDto.decode(readValue(buffer)!); + return CameraPositionDto.decode(readValue(buffer)!); case 159: - return MarkerOptionsDto.decode(readValue(buffer)!); + return MarkerDto.decode(readValue(buffer)!); case 160: - return ImageDescriptorDto.decode(readValue(buffer)!); + return MarkerOptionsDto.decode(readValue(buffer)!); case 161: - return InfoWindowDto.decode(readValue(buffer)!); + return ImageDescriptorDto.decode(readValue(buffer)!); case 162: - return MarkerAnchorDto.decode(readValue(buffer)!); + return InfoWindowDto.decode(readValue(buffer)!); case 163: - return PointOfInterestDto.decode(readValue(buffer)!); + return MarkerAnchorDto.decode(readValue(buffer)!); case 164: - return PolygonDto.decode(readValue(buffer)!); + return PointOfInterestDto.decode(readValue(buffer)!); case 165: - return PolygonOptionsDto.decode(readValue(buffer)!); + return PolygonDto.decode(readValue(buffer)!); case 166: - return PolygonHoleDto.decode(readValue(buffer)!); + return PolygonOptionsDto.decode(readValue(buffer)!); case 167: - return StyleSpanStrokeStyleDto.decode(readValue(buffer)!); + return PolygonHoleDto.decode(readValue(buffer)!); case 168: - return StyleSpanDto.decode(readValue(buffer)!); + return StyleSpanStrokeStyleDto.decode(readValue(buffer)!); case 169: - return PolylineDto.decode(readValue(buffer)!); + return StyleSpanDto.decode(readValue(buffer)!); case 170: - return PatternItemDto.decode(readValue(buffer)!); + return PolylineDto.decode(readValue(buffer)!); case 171: - return PolylineOptionsDto.decode(readValue(buffer)!); + return PatternItemDto.decode(readValue(buffer)!); case 172: - return CircleDto.decode(readValue(buffer)!); + return PolylineOptionsDto.decode(readValue(buffer)!); case 173: - return CircleOptionsDto.decode(readValue(buffer)!); + return CircleDto.decode(readValue(buffer)!); case 174: - return MapPaddingDto.decode(readValue(buffer)!); + return CircleOptionsDto.decode(readValue(buffer)!); case 175: - return RouteTokenOptionsDto.decode(readValue(buffer)!); + return MapPaddingDto.decode(readValue(buffer)!); case 176: - return DestinationsDto.decode(readValue(buffer)!); + return RouteTokenOptionsDto.decode(readValue(buffer)!); case 177: - return RoutingOptionsDto.decode(readValue(buffer)!); + return DestinationsDto.decode(readValue(buffer)!); case 178: - return NavigationDisplayOptionsDto.decode(readValue(buffer)!); + return RoutingOptionsDto.decode(readValue(buffer)!); case 179: - return NavigationWaypointDto.decode(readValue(buffer)!); + return NavigationDisplayOptionsDto.decode(readValue(buffer)!); case 180: - return NavigationTimeAndDistanceDto.decode(readValue(buffer)!); + return NavigationWaypointDto.decode(readValue(buffer)!); case 181: - return NavigationAudioGuidanceSettingsDto.decode(readValue(buffer)!); + return NavigationTimeAndDistanceDto.decode(readValue(buffer)!); case 182: - return SimulationOptionsDto.decode(readValue(buffer)!); + return NavigationAudioGuidanceSettingsDto.decode(readValue(buffer)!); case 183: - return LatLngDto.decode(readValue(buffer)!); + return SimulationOptionsDto.decode(readValue(buffer)!); case 184: - return LatLngBoundsDto.decode(readValue(buffer)!); + return LatLngDto.decode(readValue(buffer)!); case 185: - return SpeedingUpdatedEventDto.decode(readValue(buffer)!); + return LatLngBoundsDto.decode(readValue(buffer)!); case 186: - return GpsAvailabilityChangeEventDto.decode(readValue(buffer)!); + return SpeedingUpdatedEventDto.decode(readValue(buffer)!); case 187: + return GpsAvailabilityChangeEventDto.decode(readValue(buffer)!); + case 188: return SpeedAlertOptionsThresholdPercentageDto.decode( readValue(buffer)!, ); - case 188: - return SpeedAlertOptionsDto.decode(readValue(buffer)!); case 189: + return SpeedAlertOptionsDto.decode(readValue(buffer)!); + case 190: return RouteSegmentTrafficDataRoadStretchRenderingDataDto.decode( readValue(buffer)!, ); - case 190: - return RouteSegmentTrafficDataDto.decode(readValue(buffer)!); case 191: - return RouteSegmentDto.decode(readValue(buffer)!); + return RouteSegmentTrafficDataDto.decode(readValue(buffer)!); case 192: - return LaneDirectionDto.decode(readValue(buffer)!); + return RouteSegmentDto.decode(readValue(buffer)!); case 193: - return LaneDto.decode(readValue(buffer)!); + return LaneDirectionDto.decode(readValue(buffer)!); case 194: - return StepInfoDto.decode(readValue(buffer)!); + return LaneDto.decode(readValue(buffer)!); case 195: + return StepInfoDto.decode(readValue(buffer)!); + case 196: return NavInfoDto.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -8563,6 +8635,36 @@ class AutoMapViewApi { final String pigeonVar_messageChannelSuffix; + /// Sets the map options to be used for Android Auto and CarPlay views. + /// Should be called before the Auto/CarPlay screen is created. + /// This allows customization of mapId and basic map settings. + Future setAutoMapOptions(AutoMapOptionsDto mapOptions) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setAutoMapOptions$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [mapOptions], + ); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + Future isMyLocationEnabled() async { final String pigeonVar_channelName = 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isMyLocationEnabled$pigeonVar_messageChannelSuffix'; @@ -9699,16 +9801,18 @@ class AutoMapViewApi { } } - Future isMyLocationButtonEnabled() async { + Future setTrafficPromptsEnabled(bool enabled) async { final String pigeonVar_channelName = - 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isMyLocationButtonEnabled$pigeonVar_messageChannelSuffix'; + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setTrafficPromptsEnabled$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [enabled], + ); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -9719,26 +9823,23 @@ class AutoMapViewApi { message: pigeonVar_replyList[1] as String?, details: pigeonVar_replyList[2], ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); } else { - return (pigeonVar_replyList[0] as bool?)!; + return; } } - Future isConsumeMyLocationButtonClickEventsEnabled() async { + Future setTrafficIncidentCardsEnabled(bool enabled) async { final String pigeonVar_channelName = - 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isConsumeMyLocationButtonClickEventsEnabled$pigeonVar_messageChannelSuffix'; + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setTrafficIncidentCardsEnabled$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [enabled], + ); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -9749,8 +9850,90 @@ class AutoMapViewApi { message: pigeonVar_replyList[1] as String?, details: pigeonVar_replyList[2], ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( + } else { + return; + } + } + + Future setReportIncidentButtonEnabled(bool enabled) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setReportIncidentButtonEnabled$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [enabled], + ); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + + Future isMyLocationButtonEnabled() async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isMyLocationButtonEnabled$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + Future isConsumeMyLocationButtonClickEventsEnabled() async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isConsumeMyLocationButtonClickEventsEnabled$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( code: 'null-error', message: 'Host platform returned null value for non-null return value.', ); @@ -10029,6 +10212,96 @@ class AutoMapViewApi { } } + Future isTrafficPromptsEnabled() async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isTrafficPromptsEnabled$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + Future isTrafficIncidentCardsEnabled() async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isTrafficIncidentCardsEnabled$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + Future isReportIncidentButtonEnabled() async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isReportIncidentButtonEnabled$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + Future> getMarkers() async { final String pigeonVar_channelName = 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMarkers$pigeonVar_messageChannelSuffix'; @@ -10749,6 +11022,149 @@ class AutoMapViewApi { return (pigeonVar_replyList[0] as MapPaddingDto?)!; } } + + Future getMapColorScheme() async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMapColorScheme$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as MapColorSchemeDto?)!; + } + } + + Future setMapColorScheme(MapColorSchemeDto mapColorScheme) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMapColorScheme$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [mapColorScheme], + ); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + + Future getForceNightMode() async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getForceNightMode$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as NavigationForceNightModeDto?)!; + } + } + + Future setForceNightMode( + NavigationForceNightModeDto forceNightMode, + ) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setForceNightMode$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [forceNightMode], + ); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + + Future sendCustomNavigationAutoEvent(String event, Object data) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.sendCustomNavigationAutoEvent$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [event, data], + ); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } } abstract class AutoViewEventApi { @@ -10758,6 +11174,8 @@ abstract class AutoViewEventApi { void onAutoScreenAvailabilityChanged(bool isAvailable); + void onPromptVisibilityChanged(bool promptVisible); + static void setUp( AutoViewEventApi? api, { BinaryMessenger? binaryMessenger, @@ -10839,6 +11257,40 @@ abstract class AutoViewEventApi { }); } } + { + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.google_navigation_flutter.AutoViewEventApi.onPromptVisibilityChanged$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); + if (api == null) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + assert( + message != null, + 'Argument for dev.flutter.pigeon.google_navigation_flutter.AutoViewEventApi.onPromptVisibilityChanged was null.', + ); + final List args = (message as List?)!; + final bool? arg_promptVisible = (args[0] as bool?); + assert( + arg_promptVisible != null, + 'Argument for dev.flutter.pigeon.google_navigation_flutter.AutoViewEventApi.onPromptVisibilityChanged was null, expected non-null bool.', + ); + try { + api.onPromptVisibilityChanged(arg_promptVisible!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } + }); + } + } } } diff --git a/lib/src/types/auto_map_options.dart b/lib/src/types/auto_map_options.dart new file mode 100644 index 00000000..f0275b0f --- /dev/null +++ b/lib/src/types/auto_map_options.dart @@ -0,0 +1,68 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'types.dart'; + +/// Configuration options for Android Auto and CarPlay map views. +/// +/// This class contains only the settings relevant for Auto and CarPlay views, +/// excluding gesture controls and other UI elements that are handled by the system. +class AutoMapOptions { + /// Creates map options for Android Auto and CarPlay views. + /// + /// [cameraPosition] - The initial positioning of the camera in the map view. + /// [mapId] - Cloud-based map ID for custom styling. + /// [mapType] - The type of map to display (normal, satellite, terrain, hybrid). + /// [mapColorScheme] - The color scheme for the map (light, dark, or follow system). + /// [forceNightMode] - Forces night mode (dark theme) regardless of system settings. + const AutoMapOptions({ + this.cameraPosition, + this.mapId, + this.mapType, + this.mapColorScheme, + this.forceNightMode, + }); + + /// The initial positioning of the camera in the map view. + /// + /// Specifies the initial camera position (target location, zoom level, bearing, and tilt) + /// when the map view is created. + final CameraPosition? cameraPosition; + + /// Cloud-based map ID for custom styling. + /// + /// You can create map IDs in the Google Cloud Console to customize + /// the appearance of your map with custom styles. + final String? mapId; + + /// The type of map to display. + /// + /// Defaults to [MapType.normal] if not specified. + final MapType? mapType; + + /// The color scheme for the map. + /// + /// Defaults to [MapColorScheme.followSystem] if not specified, + /// which automatically switches between light and dark based on system settings. + final MapColorScheme? mapColorScheme; + + /// Forces night mode (dark theme) for the map. + /// + /// This is different from [mapColorScheme]: + /// - [mapColorScheme] affects the overall map appearance (roads, labels, etc.) + /// - [forceNightMode] forces the dark theme regardless of system or time settings + /// + /// Use [NavigationForceNightMode.auto] to automatically switch based on time of day. + final NavigationForceNightMode? forceNightMode; +} diff --git a/lib/src/types/navigation_view_types.dart b/lib/src/types/navigation_view_types.dart index 8d1c8d01..bd256989 100644 --- a/lib/src/types/navigation_view_types.dart +++ b/lib/src/types/navigation_view_types.dart @@ -200,12 +200,18 @@ class NavigationUIEnabledChangedEvent { /// Represents prompt visibility changed event in a view. /// {@category Navigation View} +/// {@category Android Auto} +/// {@category Carplay} class PromptVisibilityChangedEvent { /// Creates a [PromptVisibilityChangedEvent] object. const PromptVisibilityChangedEvent(this.promptVisible); /// Value representing whether prompts are visible or not. final bool promptVisible; + + @override + String toString() => + 'PromptVisibilityChangedEvent(promptVisible: $promptVisible)'; } /// Represents the long click position in a Google Maps view. diff --git a/lib/src/types/types.dart b/lib/src/types/types.dart index 49aa7d77..53fd7090 100644 --- a/lib/src/types/types.dart +++ b/lib/src/types/types.dart @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +export 'auto_map_options.dart'; export 'circles.dart'; export 'images.dart'; export 'lat_lng.dart'; diff --git a/pigeons/messages.dart b/pigeons/messages.dart index 05015a9f..067f860e 100644 --- a/pigeons/messages.dart +++ b/pigeons/messages.dart @@ -36,6 +36,32 @@ enum MapViewTypeDto { map, } +/// Object containing auto/carplay map options. +class AutoMapOptionsDto { + AutoMapOptionsDto({ + this.cameraPosition, + this.mapId, + this.mapType, + this.mapColorScheme, + this.forceNightMode, + }); + + /// The initial positioning of the camera in the map view. + final CameraPositionDto? cameraPosition; + + /// Cloud-based map ID for custom styling. + final String? mapId; + + /// The type of map to display (e.g., satellite, terrain, hybrid, etc.). + final MapTypeDto? mapType; + + /// The color scheme for the map (light, dark, or follow system). + final MapColorSchemeDto? mapColorScheme; + + /// Forces night mode (dark theme) regardless of system settings. + final NavigationForceNightModeDto? forceNightMode; +} + /// Object containing map options used to initialize Google Map view. class MapOptionsDto { MapOptionsDto({ @@ -1425,6 +1451,11 @@ abstract class NavigationSessionEventApi { @HostApi() abstract class AutoMapViewApi { + /// Sets the map options to be used for Android Auto and CarPlay views. + /// Should be called before the Auto/CarPlay screen is created. + /// This allows customization of mapId and basic map settings. + void setAutoMapOptions(AutoMapOptionsDto mapOptions); + bool isMyLocationEnabled(); void setMyLocationEnabled(bool enabled); LatLngDto? getMyLocation(); @@ -1492,6 +1523,9 @@ abstract class AutoMapViewApi { void setTiltGesturesEnabled(bool enabled); void setMapToolbarEnabled(bool enabled); void setTrafficEnabled(bool enabled); + void setTrafficPromptsEnabled(bool enabled); + void setTrafficIncidentCardsEnabled(bool enabled); + void setReportIncidentButtonEnabled(bool enabled); bool isMyLocationButtonEnabled(); bool isConsumeMyLocationButtonClickEventsEnabled(); @@ -1504,6 +1538,9 @@ abstract class AutoMapViewApi { bool isTiltGesturesEnabled(); bool isMapToolbarEnabled(); bool isTrafficEnabled(); + bool isTrafficPromptsEnabled(); + bool isTrafficIncidentCardsEnabled(); + bool isReportIncidentButtonEnabled(); List getMarkers(); List addMarkers(List markers); @@ -1534,12 +1571,20 @@ abstract class AutoMapViewApi { bool isAutoScreenAvailable(); void setPadding(MapPaddingDto padding); MapPaddingDto getPadding(); + + MapColorSchemeDto getMapColorScheme(); + void setMapColorScheme(MapColorSchemeDto mapColorScheme); + NavigationForceNightModeDto getForceNightMode(); + void setForceNightMode(NavigationForceNightModeDto forceNightMode); + + void sendCustomNavigationAutoEvent(String event, Object data); } @FlutterApi() abstract class AutoViewEventApi { void onCustomNavigationAutoEvent(String event, Object data); void onAutoScreenAvailabilityChanged(bool isAvailable); + void onPromptVisibilityChanged(bool promptVisible); } @HostApi() diff --git a/test/messages_test.g.dart b/test/messages_test.g.dart index b6c868b2..9054e1e7 100644 --- a/test/messages_test.g.dart +++ b/test/messages_test.g.dart @@ -107,132 +107,135 @@ class _PigeonCodec extends StandardMessageCodec { } else if (value is TaskRemovedBehaviorDto) { buffer.putUint8(153); writeValue(buffer, value.index); - } else if (value is MapOptionsDto) { + } else if (value is AutoMapOptionsDto) { buffer.putUint8(154); writeValue(buffer, value.encode()); - } else if (value is NavigationViewOptionsDto) { + } else if (value is MapOptionsDto) { buffer.putUint8(155); writeValue(buffer, value.encode()); - } else if (value is ViewCreationOptionsDto) { + } else if (value is NavigationViewOptionsDto) { buffer.putUint8(156); writeValue(buffer, value.encode()); - } else if (value is CameraPositionDto) { + } else if (value is ViewCreationOptionsDto) { buffer.putUint8(157); writeValue(buffer, value.encode()); - } else if (value is MarkerDto) { + } else if (value is CameraPositionDto) { buffer.putUint8(158); writeValue(buffer, value.encode()); - } else if (value is MarkerOptionsDto) { + } else if (value is MarkerDto) { buffer.putUint8(159); writeValue(buffer, value.encode()); - } else if (value is ImageDescriptorDto) { + } else if (value is MarkerOptionsDto) { buffer.putUint8(160); writeValue(buffer, value.encode()); - } else if (value is InfoWindowDto) { + } else if (value is ImageDescriptorDto) { buffer.putUint8(161); writeValue(buffer, value.encode()); - } else if (value is MarkerAnchorDto) { + } else if (value is InfoWindowDto) { buffer.putUint8(162); writeValue(buffer, value.encode()); - } else if (value is PointOfInterestDto) { + } else if (value is MarkerAnchorDto) { buffer.putUint8(163); writeValue(buffer, value.encode()); - } else if (value is PolygonDto) { + } else if (value is PointOfInterestDto) { buffer.putUint8(164); writeValue(buffer, value.encode()); - } else if (value is PolygonOptionsDto) { + } else if (value is PolygonDto) { buffer.putUint8(165); writeValue(buffer, value.encode()); - } else if (value is PolygonHoleDto) { + } else if (value is PolygonOptionsDto) { buffer.putUint8(166); writeValue(buffer, value.encode()); - } else if (value is StyleSpanStrokeStyleDto) { + } else if (value is PolygonHoleDto) { buffer.putUint8(167); writeValue(buffer, value.encode()); - } else if (value is StyleSpanDto) { + } else if (value is StyleSpanStrokeStyleDto) { buffer.putUint8(168); writeValue(buffer, value.encode()); - } else if (value is PolylineDto) { + } else if (value is StyleSpanDto) { buffer.putUint8(169); writeValue(buffer, value.encode()); - } else if (value is PatternItemDto) { + } else if (value is PolylineDto) { buffer.putUint8(170); writeValue(buffer, value.encode()); - } else if (value is PolylineOptionsDto) { + } else if (value is PatternItemDto) { buffer.putUint8(171); writeValue(buffer, value.encode()); - } else if (value is CircleDto) { + } else if (value is PolylineOptionsDto) { buffer.putUint8(172); writeValue(buffer, value.encode()); - } else if (value is CircleOptionsDto) { + } else if (value is CircleDto) { buffer.putUint8(173); writeValue(buffer, value.encode()); - } else if (value is MapPaddingDto) { + } else if (value is CircleOptionsDto) { buffer.putUint8(174); writeValue(buffer, value.encode()); - } else if (value is RouteTokenOptionsDto) { + } else if (value is MapPaddingDto) { buffer.putUint8(175); writeValue(buffer, value.encode()); - } else if (value is DestinationsDto) { + } else if (value is RouteTokenOptionsDto) { buffer.putUint8(176); writeValue(buffer, value.encode()); - } else if (value is RoutingOptionsDto) { + } else if (value is DestinationsDto) { buffer.putUint8(177); writeValue(buffer, value.encode()); - } else if (value is NavigationDisplayOptionsDto) { + } else if (value is RoutingOptionsDto) { buffer.putUint8(178); writeValue(buffer, value.encode()); - } else if (value is NavigationWaypointDto) { + } else if (value is NavigationDisplayOptionsDto) { buffer.putUint8(179); writeValue(buffer, value.encode()); - } else if (value is NavigationTimeAndDistanceDto) { + } else if (value is NavigationWaypointDto) { buffer.putUint8(180); writeValue(buffer, value.encode()); - } else if (value is NavigationAudioGuidanceSettingsDto) { + } else if (value is NavigationTimeAndDistanceDto) { buffer.putUint8(181); writeValue(buffer, value.encode()); - } else if (value is SimulationOptionsDto) { + } else if (value is NavigationAudioGuidanceSettingsDto) { buffer.putUint8(182); writeValue(buffer, value.encode()); - } else if (value is LatLngDto) { + } else if (value is SimulationOptionsDto) { buffer.putUint8(183); writeValue(buffer, value.encode()); - } else if (value is LatLngBoundsDto) { + } else if (value is LatLngDto) { buffer.putUint8(184); writeValue(buffer, value.encode()); - } else if (value is SpeedingUpdatedEventDto) { + } else if (value is LatLngBoundsDto) { buffer.putUint8(185); writeValue(buffer, value.encode()); - } else if (value is GpsAvailabilityChangeEventDto) { + } else if (value is SpeedingUpdatedEventDto) { buffer.putUint8(186); writeValue(buffer, value.encode()); - } else if (value is SpeedAlertOptionsThresholdPercentageDto) { + } else if (value is GpsAvailabilityChangeEventDto) { buffer.putUint8(187); writeValue(buffer, value.encode()); - } else if (value is SpeedAlertOptionsDto) { + } else if (value is SpeedAlertOptionsThresholdPercentageDto) { buffer.putUint8(188); writeValue(buffer, value.encode()); - } else if (value is RouteSegmentTrafficDataRoadStretchRenderingDataDto) { + } else if (value is SpeedAlertOptionsDto) { buffer.putUint8(189); writeValue(buffer, value.encode()); - } else if (value is RouteSegmentTrafficDataDto) { + } else if (value is RouteSegmentTrafficDataRoadStretchRenderingDataDto) { buffer.putUint8(190); writeValue(buffer, value.encode()); - } else if (value is RouteSegmentDto) { + } else if (value is RouteSegmentTrafficDataDto) { buffer.putUint8(191); writeValue(buffer, value.encode()); - } else if (value is LaneDirectionDto) { + } else if (value is RouteSegmentDto) { buffer.putUint8(192); writeValue(buffer, value.encode()); - } else if (value is LaneDto) { + } else if (value is LaneDirectionDto) { buffer.putUint8(193); writeValue(buffer, value.encode()); - } else if (value is StepInfoDto) { + } else if (value is LaneDto) { buffer.putUint8(194); writeValue(buffer, value.encode()); - } else if (value is NavInfoDto) { + } else if (value is StepInfoDto) { buffer.putUint8(195); writeValue(buffer, value.encode()); + } else if (value is NavInfoDto) { + buffer.putUint8(196); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -324,92 +327,94 @@ class _PigeonCodec extends StandardMessageCodec { final int? value = readValue(buffer) as int?; return value == null ? null : TaskRemovedBehaviorDto.values[value]; case 154: - return MapOptionsDto.decode(readValue(buffer)!); + return AutoMapOptionsDto.decode(readValue(buffer)!); case 155: - return NavigationViewOptionsDto.decode(readValue(buffer)!); + return MapOptionsDto.decode(readValue(buffer)!); case 156: - return ViewCreationOptionsDto.decode(readValue(buffer)!); + return NavigationViewOptionsDto.decode(readValue(buffer)!); case 157: - return CameraPositionDto.decode(readValue(buffer)!); + return ViewCreationOptionsDto.decode(readValue(buffer)!); case 158: - return MarkerDto.decode(readValue(buffer)!); + return CameraPositionDto.decode(readValue(buffer)!); case 159: - return MarkerOptionsDto.decode(readValue(buffer)!); + return MarkerDto.decode(readValue(buffer)!); case 160: - return ImageDescriptorDto.decode(readValue(buffer)!); + return MarkerOptionsDto.decode(readValue(buffer)!); case 161: - return InfoWindowDto.decode(readValue(buffer)!); + return ImageDescriptorDto.decode(readValue(buffer)!); case 162: - return MarkerAnchorDto.decode(readValue(buffer)!); + return InfoWindowDto.decode(readValue(buffer)!); case 163: - return PointOfInterestDto.decode(readValue(buffer)!); + return MarkerAnchorDto.decode(readValue(buffer)!); case 164: - return PolygonDto.decode(readValue(buffer)!); + return PointOfInterestDto.decode(readValue(buffer)!); case 165: - return PolygonOptionsDto.decode(readValue(buffer)!); + return PolygonDto.decode(readValue(buffer)!); case 166: - return PolygonHoleDto.decode(readValue(buffer)!); + return PolygonOptionsDto.decode(readValue(buffer)!); case 167: - return StyleSpanStrokeStyleDto.decode(readValue(buffer)!); + return PolygonHoleDto.decode(readValue(buffer)!); case 168: - return StyleSpanDto.decode(readValue(buffer)!); + return StyleSpanStrokeStyleDto.decode(readValue(buffer)!); case 169: - return PolylineDto.decode(readValue(buffer)!); + return StyleSpanDto.decode(readValue(buffer)!); case 170: - return PatternItemDto.decode(readValue(buffer)!); + return PolylineDto.decode(readValue(buffer)!); case 171: - return PolylineOptionsDto.decode(readValue(buffer)!); + return PatternItemDto.decode(readValue(buffer)!); case 172: - return CircleDto.decode(readValue(buffer)!); + return PolylineOptionsDto.decode(readValue(buffer)!); case 173: - return CircleOptionsDto.decode(readValue(buffer)!); + return CircleDto.decode(readValue(buffer)!); case 174: - return MapPaddingDto.decode(readValue(buffer)!); + return CircleOptionsDto.decode(readValue(buffer)!); case 175: - return RouteTokenOptionsDto.decode(readValue(buffer)!); + return MapPaddingDto.decode(readValue(buffer)!); case 176: - return DestinationsDto.decode(readValue(buffer)!); + return RouteTokenOptionsDto.decode(readValue(buffer)!); case 177: - return RoutingOptionsDto.decode(readValue(buffer)!); + return DestinationsDto.decode(readValue(buffer)!); case 178: - return NavigationDisplayOptionsDto.decode(readValue(buffer)!); + return RoutingOptionsDto.decode(readValue(buffer)!); case 179: - return NavigationWaypointDto.decode(readValue(buffer)!); + return NavigationDisplayOptionsDto.decode(readValue(buffer)!); case 180: - return NavigationTimeAndDistanceDto.decode(readValue(buffer)!); + return NavigationWaypointDto.decode(readValue(buffer)!); case 181: - return NavigationAudioGuidanceSettingsDto.decode(readValue(buffer)!); + return NavigationTimeAndDistanceDto.decode(readValue(buffer)!); case 182: - return SimulationOptionsDto.decode(readValue(buffer)!); + return NavigationAudioGuidanceSettingsDto.decode(readValue(buffer)!); case 183: - return LatLngDto.decode(readValue(buffer)!); + return SimulationOptionsDto.decode(readValue(buffer)!); case 184: - return LatLngBoundsDto.decode(readValue(buffer)!); + return LatLngDto.decode(readValue(buffer)!); case 185: - return SpeedingUpdatedEventDto.decode(readValue(buffer)!); + return LatLngBoundsDto.decode(readValue(buffer)!); case 186: - return GpsAvailabilityChangeEventDto.decode(readValue(buffer)!); + return SpeedingUpdatedEventDto.decode(readValue(buffer)!); case 187: + return GpsAvailabilityChangeEventDto.decode(readValue(buffer)!); + case 188: return SpeedAlertOptionsThresholdPercentageDto.decode( readValue(buffer)!, ); - case 188: - return SpeedAlertOptionsDto.decode(readValue(buffer)!); case 189: + return SpeedAlertOptionsDto.decode(readValue(buffer)!); + case 190: return RouteSegmentTrafficDataRoadStretchRenderingDataDto.decode( readValue(buffer)!, ); - case 190: - return RouteSegmentTrafficDataDto.decode(readValue(buffer)!); case 191: - return RouteSegmentDto.decode(readValue(buffer)!); + return RouteSegmentTrafficDataDto.decode(readValue(buffer)!); case 192: - return LaneDirectionDto.decode(readValue(buffer)!); + return RouteSegmentDto.decode(readValue(buffer)!); case 193: - return LaneDto.decode(readValue(buffer)!); + return LaneDirectionDto.decode(readValue(buffer)!); case 194: - return StepInfoDto.decode(readValue(buffer)!); + return LaneDto.decode(readValue(buffer)!); case 195: + return StepInfoDto.decode(readValue(buffer)!); + case 196: return NavInfoDto.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer);