diff --git a/ANDROIDAUTO.md b/ANDROIDAUTO.md new file mode 100644 index 00000000..3ba4424f --- /dev/null +++ b/ANDROIDAUTO.md @@ -0,0 +1,81 @@ +# Navigation for Android Auto + +This guide explains how to enable and integrate Android Auto with the Flutter Navigation SDK. + +## Requirements + +- Android device +- Android Auto test device or Android Automotive OS emulator + +## Setup + +Refer to the [Android for Cars developer documentation](https://developer.android.com/training/cars) to understand how the Android Auto works and to complete the initial setup. Key steps include: + +- Installing Android for Cars App Library. +- Configuring your app's manifest file to include Android Auto. +- Declaring a minimum car-app level in your manifest. +- Creating 'CarAppService' and session + +For all the steps above, you can refer to the Android example application for guidance. + +### Screen for Android Auto + +Once your project is configured accordingly, and you are ready to build the screen for Android Auto, you can leverage the `AndroidAutoBaseScreen` provided by the SDK. This base class simplifies the setup by handling initialization, teardown, and rendering the map on the Android Auto display. + +Please refer to the `SampleAndroidAutoScreen.kt` file in the Android example app for guidance. + +To customize the Android Auto experience, override the `onGetTemplate` method in your custom AndroidAutoScreen class, providing your own `Template`: + +```kotlin +override fun onGetTemplate(): Template { + /** ... */ + @SuppressLint("MissingPermission") + val navigationTemplateBuilder = + NavigationTemplate.Builder() + .setActionStrip( + ActionStrip.Builder() + .addAction( + Action.Builder() + .setTitle("Re-center") + .setOnClickListener { + if (mGoogleMap == null) return@setOnClickListener + mGoogleMap!!.followMyLocation(GoogleMap.CameraPerspective.TILTED) + } + .build()) + .addAction( + Action.Builder() + .setTitle("Custom event") + .setOnClickListener { + sendCustomNavigationAutoEvent("CustomAndroidAutoEvent", mapOf("sampleDataKey" to "sampleDataContent")) + } + .build()) + .build()) + .setMapActionStrip(ActionStrip.Builder().addAction(Action.PAN).build()) + /** ... */ +} +``` + +For advanced customization, you can bypass the base class and implement your own screen by inheriting `Screen`. You can use the provided `AndroidAutoBaseScreen` base class as a reference on how to do that. + +### Flutter Setup + +On the Flutter side, you can use the `GoogleMapsAutoViewController` to interface with the CarPlay instance. The `GoogleMapsAutoViewController` allows you to call map functions on the CarPlay map view, and you can manage listeners using the provided functions. + +```dart +final GoogleMapsAutoViewController _autoViewController = + GoogleMapsAutoViewController(); + +_autoViewController.listenForCustomNavigationAutoEvents((event) { + showMessage("Received event: ${event.event}"); +}); + +Future _setMapTypeForAutoToSatellite() async { + await _autoViewController.setMapType(mapType: MapType.satellite); +} +``` + +For a more detailed example, refer to the `lib/pages/navigation.dart` file in the Flutter example application. + +## Example Project + +For a fully functional Android Auto implementation, check out the [Android Studio example app](./example/android/). diff --git a/CARPLAY.MD b/CARPLAY.MD new file mode 100644 index 00000000..e9bc3160 --- /dev/null +++ b/CARPLAY.MD @@ -0,0 +1,63 @@ +# Navigation for Apple CarPlay + +This guide explains how to enable and integrate Apple CarPlay with the Flutter SDK. + +## Requirements + +- iOS device or iOS simulator +- CarPlay Simulator +- CarPlay entitlement for your application (provided by Apple) + +## Setup + +Refer to the [Apple CarPlay Developer Guide](https://developer.apple.com/carplay/) to understand how CarPlay works and to complete the initial setup. Key steps include: + +- Adding the CarPlay entitlement to your Xcode project. +- Creating a separate scene for the CarPlay map and enabling support for multiple scenes. + +### SceneDelegate for CarPlay + +Once your project is configured to support multiple scenes, and you are setting up a dedicated scene for CarPlay, you can leverage the `BaseCarSceneDelegate` provided by the SDK. This base class simplifies the setup by handling initialization, teardown, and rendering the map on the CarPlay display. + +Please refer to the `CarSceneDelegate.swift` file in the iOS example app for guidance. + +To customize the CarPlay experience, override the `getTemplate` method in your custom `CarSceneDelegate` class, providing your own `CPMapTemplate`: + +```swift +override func getTemplate() -> CPMapTemplate { + let template = CPMapTemplate() + template.showPanningInterface(animated: true) + + let button = CPBarButton(title: "Custom Event") { [weak self] _ in + let data = ["sampleDataKey": "sampleDataContent"] + self?.sendCustomNavigationAutoEvent(event: "CustomCarPlayEvent", data: data) + } + template.leadingNavigationBarButtons = [button] + return template + } +``` + +For advanced customization, you can bypass the base class and implement your own delegate inheriting `CPTemplateApplicationSceneDelegate`. You can use the provided `BaseCarSceneDelegate` base class as a reference on how to do that. + +### Flutter Setup + +On the Flutter side, you can use the `GoogleMapsAutoViewController` to interface with the CarPlay instance. The `GoogleMapsAutoViewController` allows you to call map functions on the CarPlay map view, and you can manage listeners using the provided functions. + +```dart +final GoogleMapsAutoViewController _autoViewController = + GoogleMapsAutoViewController(); + +_autoViewController.listenForCustomNavigationAutoEvents((event) { + showMessage("Received event: ${event.event}"); +}); + +Future _setMapTypeForAutoToSatellite() async { + await _autoViewController.setMapType(mapType: MapType.satellite); +} +``` + +For a more detailed example, refer to the `lib/pages/navigation.dart` file in the Flutter example application. + +## Example Project + +For a fully functional CarPlay implementation, check out the [Runner](./example/ios/) Xcode project, which includes the `RunnerCarPlay` build target. The sample already contains test entitlement so you don't need to request one from Apple to run it. diff --git a/README.md b/README.md index d2d113ef..201b0e3c 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,12 @@ Widget build(BuildContext context) { } ``` +## Support for Android Auto and Apple CarPlay +This plugin is compatible with both Android Auto and Apple CarPlay infotainment systems. For more details, please refer to the respective platform documentation: + +- [Android Auto documentation](./ANDROIDAUTO.md) +- [CarPlay documentation](./CARPLAY.md) + ## Known issues ### Compatibility with other libraries diff --git a/android/build.gradle b/android/build.gradle index e7faec17..9530184a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -55,7 +55,7 @@ android { namespace 'com.google.maps.flutter.navigation' } - compileSdk 33 + compileSdk 34 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -77,6 +77,8 @@ android { } dependencies { + implementation "androidx.car.app:app:1.4.0" + implementation "androidx.car.app:app-projected:1.4.0" implementation 'com.google.android.libraries.navigation:navigation:6.0.0' testImplementation 'org.jetbrains.kotlin:kotlin-test' testImplementation 'io.mockk:mockk:1.13.8' 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 new file mode 100644 index 00000000..c2fff070 --- /dev/null +++ b/android/src/main/kotlin/com/google/maps/flutter/navigation/AndroidAutoBaseScreen.kt @@ -0,0 +1,181 @@ +/* + * 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 + +import android.app.Presentation +import android.graphics.Point +import android.hardware.display.DisplayManager +import android.hardware.display.VirtualDisplay +import androidx.car.app.AppManager +import androidx.car.app.CarContext +import androidx.car.app.Screen +import androidx.car.app.SurfaceCallback +import androidx.car.app.SurfaceContainer +import androidx.car.app.model.Action +import androidx.car.app.model.ActionStrip +import androidx.car.app.model.Template +import androidx.car.app.navigation.model.NavigationTemplate +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleObserver +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 + +open class AndroidAutoBaseScreen(carContext: CarContext) : + Screen(carContext), SurfaceCallback, NavigationReadyListener { + private val VIRTUAL_DISPLAY_NAME = "AndroidAutoNavScreen" + private var mVirtualDisplay: VirtualDisplay? = null + private var mPresentation: Presentation? = null + private var mNavigationView: NavigationViewForAuto? = null + private var mAutoMapView: GoogleMapsAutoMapView? = null + private var mViewRegistry: GoogleMapsViewRegistry? = null + protected var mIsNavigationReady: Boolean = false + var mGoogleMap: GoogleMap? = null + + init { + initializeSurfaceCallback() + initializeNavigationListener() + } + + private fun initializeNavigationListener() { + GoogleMapsNavigationSessionManager.navigationReadyListener = this + try { + mIsNavigationReady = GoogleMapsNavigationSessionManager.getInstance().isInitialized() + } catch (exception: RuntimeException) { + // If GoogleMapsNavigationSessionManager is not initialized navigation is not ready. + mIsNavigationReady = false + } + } + + private fun initializeSurfaceCallback() { + carContext.getCarService(AppManager::class.java).setSurfaceCallback(this) + } + + private val mLifeCycleObserver: LifecycleObserver = + object : DefaultLifecycleObserver { + override fun onDestroy(owner: LifecycleOwner) { + GoogleMapsNavigationSessionManager.navigationReadyListener = null + mIsNavigationReady = false + } + } + + private fun isSurfaceReady(surfaceContainer: SurfaceContainer): Boolean { + return surfaceContainer.surface != null && + surfaceContainer.dpi != 0 && + surfaceContainer.height != 0 && + surfaceContainer.width != 0 + } + + override fun onSurfaceAvailable(surfaceContainer: SurfaceContainer) { + super.onSurfaceAvailable(surfaceContainer) + lifecycle.addObserver(mLifeCycleObserver) + if (!isSurfaceReady(surfaceContainer)) { + return + } + mVirtualDisplay = + carContext + .getSystemService(DisplayManager::class.java) + .createVirtualDisplay( + VIRTUAL_DISPLAY_NAME, + surfaceContainer.width, + surfaceContainer.height, + surfaceContainer.dpi, + surfaceContainer.surface, + DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY, + ) + val virtualDisplay = mVirtualDisplay ?: return + + mPresentation = Presentation(carContext, virtualDisplay.display) + val presentation = mPresentation ?: return + + mNavigationView = NavigationViewForAuto(carContext) + val navigationView = mNavigationView ?: return + navigationView.onCreate(null) + navigationView.onStart() + navigationView.onResume() + + presentation.setContentView(navigationView) + presentation.show() + + navigationView.getMapAsync { googleMap: GoogleMap -> + val viewRegistry = GoogleMapsNavigationPlugin.getInstance()?.viewRegistry + val imageRegistry = GoogleMapsNavigationPlugin.getInstance()?.imageRegistry + if (viewRegistry != null && imageRegistry != null) { + mGoogleMap = googleMap + mViewRegistry = viewRegistry + mAutoMapView = + GoogleMapsAutoMapView( + GoogleMapOptions(), + viewRegistry, + imageRegistry, + navigationView, + googleMap, + ) + sendAutoScreenAvailabilityChangedEvent(true) + invalidate() + } + } + } + + override fun onSurfaceDestroyed(surfaceContainer: SurfaceContainer) { + super.onSurfaceDestroyed(surfaceContainer) + sendAutoScreenAvailabilityChangedEvent(false) + mViewRegistry?.unregisterAndroidAutoView() + mNavigationView?.onPause() + mNavigationView?.onStop() + mNavigationView?.onDestroy() + mGoogleMap = null + + mPresentation?.dismiss() + mVirtualDisplay?.release() + } + + override fun onScroll(distanceX: Float, distanceY: Float) { + mGoogleMap?.moveCamera(CameraUpdateFactory.scrollBy(distanceX, distanceY)) + } + + override fun onScale(focusX: Float, focusY: Float, scaleFactor: Float) { + val update = + CameraUpdateFactory.zoomBy((scaleFactor - 1), Point(focusX.toInt(), focusY.toInt())) + mGoogleMap?.animateCamera(update) // map is set in onSurfaceAvailable. + } + + override fun onGetTemplate(): Template { + return NavigationTemplate.Builder() + .setMapActionStrip(ActionStrip.Builder().addAction(Action.PAN).build()) + .build() + } + + fun sendCustomNavigationAutoEvent(event: String, data: Any) { + GoogleMapsNavigationPlugin.getInstance()?.autoViewEventApi?.onCustomNavigationAutoEvent( + event, + data, + ) {} + } + + private fun sendAutoScreenAvailabilityChangedEvent(isAvailable: Boolean) { + GoogleMapsNavigationPlugin.getInstance()?.autoViewEventApi?.onAutoScreenAvailabilityChanged( + isAvailable + ) {} + } + + override fun onNavigationReady(ready: Boolean) { + mIsNavigationReady = ready + } +} diff --git a/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapView.kt b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapView.kt index 55bc84fc..6d6febcb 100644 --- a/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapView.kt +++ b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapView.kt @@ -62,7 +62,7 @@ internal constructor( _mapView.onStop() _mapView.onDestroy() - viewRegistry.unregisterMapView(viewId) + viewRegistry.unregisterMapView(getViewId()) } override fun onStart() { 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 new file mode 100644 index 00000000..7ca8e9c2 --- /dev/null +++ b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsAutoMapView.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2023 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 + +import android.view.View +import com.google.android.gms.maps.GoogleMap +import com.google.android.gms.maps.GoogleMapOptions +import com.google.android.libraries.navigation.NavigationViewForAuto + +class GoogleMapsAutoMapView +internal constructor( + mapOptions: GoogleMapOptions, + private val viewRegistry: GoogleMapsViewRegistry, + imageRegistry: ImageRegistry, + private val mapView: NavigationViewForAuto, + private val map: GoogleMap, +) : GoogleMapsBaseMapView(null, mapOptions, null, imageRegistry) { + override fun getView(): View { + return mapView + } + + init { + setMap(map) + initListeners() + imageRegistry.mapViewInitializationComplete() + mapReady() + invalidateViewAfterMapLoad() + + viewRegistry.registerAndroidAutoView(this) + } + + // Handled by AndroidAutoBaseScreen. + override fun onStart() {} + + // Handled by AndroidAutoBaseScreen. + override fun onResume() {} + + // Handled by AndroidAutoBaseScreen. + override fun onStop() {} + + // Handled by AndroidAutoBaseScreen. + override fun onPause() {} +} 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 new file mode 100644 index 00000000..351a4fea --- /dev/null +++ b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsAutoViewMessageHandler.kt @@ -0,0 +1,388 @@ +/* + * Copyright 2023 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 + +import android.content.res.Resources + +/** GoogleMapsAutoViewMessageHandler */ +class GoogleMapsAutoViewMessageHandler(private val viewRegistry: GoogleMapsViewRegistry) : + AutoMapViewApi { + + private fun getView(): GoogleMapsBaseMapView { + val view = viewRegistry.getAndroidAutoView() + if (view != null) { + return view + } else { + throw FlutterError("viewNotFound", "No valid android auto view found") + } + } + + override fun isMyLocationEnabled(): Boolean { + return getView().isMyLocationEnabled() + } + + override fun setMyLocationEnabled(enabled: Boolean) { + getView().setMyLocationEnabled(enabled) + } + + override fun getMapType(): MapTypeDto { + val googleMapType = getView().getMapType() + return Convert.convertMapTypeToDto(googleMapType) + } + + override fun setMapType(mapType: MapTypeDto) { + val view = getView() + val googleMapType = Convert.convertMapTypeFromDto(mapType) + view.setMapType(googleMapType) + } + + override fun setMapStyle(styleJson: String) { + val view = getView() + view.setMapStyle(styleJson) + } + + override fun setMyLocationButtonEnabled(enabled: Boolean) { + getView().setMyLocationButtonEnabled(enabled) + } + + override fun setConsumeMyLocationButtonClickEventsEnabled(enabled: Boolean) { + getView().setConsumeMyLocationButtonClickEventsEnabled(enabled) + } + + override fun setZoomGesturesEnabled(enabled: Boolean) { + getView().setZoomGesturesEnabled(enabled) + } + + override fun setZoomControlsEnabled(enabled: Boolean) { + getView().setZoomControlsEnabled(enabled) + } + + override fun setCompassEnabled(enabled: Boolean) { + getView().setCompassEnabled(enabled) + } + + override fun setRotateGesturesEnabled(enabled: Boolean) { + getView().setRotateGesturesEnabled(enabled) + } + + override fun setScrollGesturesEnabled(enabled: Boolean) { + getView().setScrollGesturesEnabled(enabled) + } + + override fun setScrollGesturesDuringRotateOrZoomEnabled(enabled: Boolean) { + getView().setScrollGesturesDuringRotateOrZoomEnabled(enabled) + } + + override fun setTiltGesturesEnabled(enabled: Boolean) { + getView().setTiltGesturesEnabled(enabled) + } + + override fun setMapToolbarEnabled(enabled: Boolean) { + getView().setMapToolbarEnabled(enabled) + } + + override fun setTrafficEnabled(enabled: Boolean) { + getView().setTrafficEnabled(enabled) + } + + override fun isMyLocationButtonEnabled(): Boolean { + return getView().isMyLocationButtonEnabled() + } + + override fun isConsumeMyLocationButtonClickEventsEnabled(): Boolean { + return getView().isConsumeMyLocationButtonClickEventsEnabled() + } + + override fun isZoomGesturesEnabled(): Boolean { + return getView().isZoomGesturesEnabled() + } + + override fun isZoomControlsEnabled(): Boolean { + return getView().isZoomControlsEnabled() + } + + override fun isCompassEnabled(): Boolean { + return getView().isCompassEnabled() + } + + override fun isRotateGesturesEnabled(): Boolean { + return getView().isRotateGesturesEnabled() + } + + override fun isScrollGesturesEnabled(): Boolean { + return getView().isScrollGesturesEnabled() + } + + override fun isScrollGesturesEnabledDuringRotateOrZoom(): Boolean { + return getView().isScrollGesturesEnabledDuringRotateOrZoom() + } + + override fun isTiltGesturesEnabled(): Boolean { + return getView().isTiltGesturesEnabled() + } + + override fun isMapToolbarEnabled(): Boolean { + return getView().isMapToolbarEnabled() + } + + override fun isTrafficEnabled(): Boolean { + return getView().isTrafficEnabled() + } + + override fun getMyLocation(): LatLngDto? { + val location = getView().getMyLocation() ?: return null + return LatLngDto(location.latitude, location.longitude) + } + + override fun getCameraPosition(): CameraPositionDto { + return Convert.convertCameraPositionToDto(getView().getCameraPosition()) + } + + override fun getVisibleRegion(): LatLngBoundsDto { + return Convert.convertLatLngBoundsToDto(getView().getVisibleRegion()) + } + + override fun animateCameraToCameraPosition( + cameraPosition: CameraPositionDto, + duration: Long?, + callback: (Result) -> Unit, + ) { + return getView() + .animateCameraToCameraPosition( + Convert.convertCameraPositionFromDto(cameraPosition), + duration, + callback, + ) + } + + override fun animateCameraToLatLng( + point: LatLngDto, + duration: Long?, + callback: (Result) -> Unit, + ) { + return getView().animateCameraToLatLng(Convert.convertLatLngFromDto(point), duration, callback) + } + + override fun animateCameraToLatLngBounds( + bounds: LatLngBoundsDto, + padding: Double, + duration: Long?, + callback: (Result) -> Unit, + ) { + val density = Resources.getSystem().displayMetrics.density + return getView() + .animateCameraToLatLngBounds( + Convert.convertLatLngBoundsFromDto(bounds), + Convert.convertLogicalToScreenPixel(padding, density), + duration, + callback, + ) + } + + override fun animateCameraToLatLngZoom( + point: LatLngDto, + zoom: Double, + duration: Long?, + callback: (Result) -> Unit, + ) { + return getView() + .animateCameraToLatLngZoom(Convert.convertLatLngFromDto(point), zoom, duration, callback) + } + + override fun animateCameraByScroll( + scrollByDx: Double, + scrollByDy: Double, + duration: Long?, + callback: (Result) -> Unit, + ) { + return getView().animateCameraByScroll(scrollByDx, scrollByDy, duration, callback) + } + + override fun animateCameraByZoom( + zoomBy: Double, + focusDx: Double?, + focusDy: Double?, + duration: Long?, + callback: (Result) -> Unit, + ) { + return getView() + .animateCameraByZoom( + zoomBy, + Convert.convertDeltaToPoint(focusDx, focusDy), + duration, + callback, + ) + } + + override fun animateCameraToZoom( + zoom: Double, + duration: Long?, + callback: (Result) -> Unit, + ) { + return getView().animateCameraToZoom(zoom, duration, callback) + } + + override fun moveCameraToCameraPosition(cameraPosition: CameraPositionDto) { + return getView() + .moveCameraToCameraPosition(Convert.convertCameraPositionFromDto(cameraPosition)) + } + + override fun moveCameraToLatLng(point: LatLngDto) { + return getView().moveCameraToLatLng(Convert.convertLatLngFromDto(point)) + } + + override fun moveCameraToLatLngBounds(bounds: LatLngBoundsDto, padding: Double) { + val density = Resources.getSystem().displayMetrics.density + return getView() + .moveCameraToLatLngBounds( + Convert.convertLatLngBoundsFromDto(bounds), + Convert.convertLogicalToScreenPixel(padding, density), + ) + } + + override fun moveCameraToLatLngZoom(point: LatLngDto, zoom: Double) { + return getView().moveCameraToLatLngZoom(Convert.convertLatLngFromDto(point), zoom) + } + + override fun moveCameraByScroll(scrollByDx: Double, scrollByDy: Double) { + return getView().moveCameraByScroll(scrollByDx, scrollByDy) + } + + override fun moveCameraByZoom(zoomBy: Double, focusDx: Double?, focusDy: Double?) { + return getView().moveCameraByZoom(zoomBy, Convert.convertDeltaToPoint(focusDx, focusDy)) + } + + override fun moveCameraToZoom(zoom: Double) { + return getView().moveCameraToZoom(zoom) + } + + override fun followMyLocation(perspective: CameraPerspectiveDto, zoomLevel: Double?) { + getView().followMyLocation(Convert.convertCameraPerspectiveFromDto(perspective), zoomLevel) + } + + override fun getMinZoomPreference(): Double { + return getView().getMinZoomPreference().toDouble() + } + + override fun getMaxZoomPreference(): Double { + return getView().getMaxZoomPreference().toDouble() + } + + override fun resetMinMaxZoomPreference() { + getView().resetMinMaxZoomPreference() + } + + override fun setMinZoomPreference(minZoomPreference: Double) { + getView().setMinZoomPreference(minZoomPreference.toFloat()) + } + + override fun setMaxZoomPreference(maxZoomPreference: Double) { + getView().setMaxZoomPreference(maxZoomPreference.toFloat()) + } + + override fun getMarkers(): List { + return getView().getMarkers() + } + + override fun addMarkers(markers: List): List { + return getView().addMarkers(markers) + } + + override fun updateMarkers(markers: List): List { + return getView().updateMarkers(markers) + } + + override fun removeMarkers(markers: List) { + getView().removeMarkers(markers) + } + + override fun clearMarkers() { + getView().clearMarkers() + } + + override fun clear() { + getView().clear() + } + + override fun getPolygons(): List { + return getView().getPolygons() + } + + override fun addPolygons(polygons: List): List { + return getView().addPolygons(polygons) + } + + override fun updatePolygons(polygons: List): List { + return getView().updatePolygons(polygons) + } + + override fun removePolygons(polygons: List) { + getView().removePolygons(polygons) + } + + override fun clearPolygons() { + getView().clearPolygons() + } + + override fun getPolylines(): List { + return getView().getPolylines() + } + + override fun addPolylines(polylines: List): List { + return getView().addPolylines(polylines) + } + + override fun updatePolylines(polylines: List): List { + return getView().updatePolylines(polylines) + } + + override fun removePolylines(polylines: List) { + getView().removePolylines(polylines) + } + + override fun clearPolylines() { + getView().clearPolylines() + } + + override fun getCircles(): List { + return getView().getCircles() + } + + override fun addCircles(circles: List): List { + return getView().addCircles(circles) + } + + override fun updateCircles(circles: List): List { + return getView().updateCircles(circles) + } + + override fun removeCircles(circles: List) { + getView().removeCircles(circles) + } + + override fun clearCircles() { + getView().clearCircles() + } + + override fun registerOnCameraChangedListener() { + getView().registerOnCameraChangedListener() + } + + override fun isAutoScreenAvailable(): Boolean { + return viewRegistry.getAndroidAutoView() != null + } +} 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 647e5d09..9223b988 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 @@ -38,9 +38,9 @@ import com.google.android.gms.maps.model.Polyline import com.google.android.libraries.navigation.NavigationView abstract class GoogleMapsBaseMapView( - protected val viewId: Int, + protected val viewId: Int?, mapOptions: GoogleMapOptions, - protected val viewEventApi: ViewEventApi, + protected val viewEventApi: ViewEventApi?, private val imageRegistry: ImageRegistry, ) { companion object { @@ -90,6 +90,15 @@ abstract class GoogleMapsBaseMapView( } } + @Throws(FlutterError::class) + protected fun getViewId(): Int { + if (viewId != null) { + return viewId + } else { + throw FlutterError("viewIdNotFound", "viewId is not available") + } + } + init { _minZoomLevelPreference = mapOptions.minZoomPreference _maxZoomLevelPreference = mapOptions.maxZoomPreference @@ -105,10 +114,13 @@ abstract class GoogleMapsBaseMapView( protected open fun initListeners() { getMap().setOnMapClickListener { - viewEventApi.onMapClickEvent(viewId.toLong(), LatLngDto(it.latitude, it.longitude)) {} + viewEventApi?.onMapClickEvent(getViewId().toLong(), LatLngDto(it.latitude, it.longitude)) {} } getMap().setOnMapLongClickListener { - viewEventApi.onMapLongClickEvent(viewId.toLong(), LatLngDto(it.latitude, it.longitude)) {} + viewEventApi?.onMapLongClickEvent( + getViewId().toLong(), + LatLngDto(it.latitude, it.longitude), + ) {} } getMap().setOnMarkerClickListener { marker -> val markerId = findMarkerId(marker) @@ -156,23 +168,25 @@ abstract class GoogleMapsBaseMapView( getMap().setOnPolygonClickListener { polygon -> val polygonId = findPolygonId(polygon) - viewEventApi.onPolygonClicked(viewId.toLong(), polygonId) {} + viewEventApi?.onPolygonClicked(getViewId().toLong(), polygonId) {} } getMap().setOnPolylineClickListener { polyline -> val polylineId = findPolylineId(polyline) - viewEventApi.onPolylineClicked(viewId.toLong(), polylineId) {} + viewEventApi?.onPolylineClicked(getViewId().toLong(), polylineId) {} } getMap().setOnCircleClickListener { circle -> val circleId = findCircleId(circle) - viewEventApi.onCircleClicked(viewId.toLong(), circleId) {} + viewEventApi?.onCircleClicked(getViewId().toLong(), circleId) {} } - getMap().setOnMyLocationClickListener { viewEventApi.onMyLocationClicked(viewId.toLong()) {} } + getMap().setOnMyLocationClickListener { + viewEventApi?.onMyLocationClicked(getViewId().toLong()) {} + } getMap().setOnMyLocationButtonClickListener { - viewEventApi.onMyLocationButtonClicked(viewId.toLong()) {} + viewEventApi?.onMyLocationButtonClicked(getViewId().toLong()) {} _consumeMyLocationButtonClickEventsEnabled } @@ -180,16 +194,16 @@ abstract class GoogleMapsBaseMapView( .setOnFollowMyLocationCallback( object : GoogleMap.OnCameraFollowLocationCallback { override fun onCameraStartedFollowingLocation() { - viewEventApi.onCameraChanged( - viewId.toLong(), + viewEventApi?.onCameraChanged( + getViewId().toLong(), CameraEventTypeDto.ONCAMERASTARTEDFOLLOWINGLOCATION, Convert.convertCameraPositionToDto(getMap().cameraPosition), ) {} } override fun onCameraStoppedFollowingLocation() { - viewEventApi.onCameraChanged( - viewId.toLong(), + viewEventApi?.onCameraChanged( + getViewId().toLong(), CameraEventTypeDto.ONCAMERASTOPPEDFOLLOWINGLOCATION, Convert.convertCameraPositionToDto(getMap().cameraPosition), ) {} @@ -268,14 +282,14 @@ abstract class GoogleMapsBaseMapView( @Throws(FlutterError::class) private fun sendMarkerEvent(marker: Marker, eventType: MarkerEventTypeDto) { val markerId = findMarkerId(marker) - viewEventApi.onMarkerEvent(viewId.toLong(), markerId, eventType) {} + viewEventApi?.onMarkerEvent(getViewId().toLong(), markerId, eventType) {} } @Throws(FlutterError::class) private fun sendMarkerDragEvent(marker: Marker, eventType: MarkerDragEventTypeDto) { val markerId = findMarkerId(marker) - viewEventApi.onMarkerDragEvent( - viewId.toLong(), + viewEventApi?.onMarkerDragEvent( + getViewId().toLong(), markerId, eventType, LatLngDto(marker.position.latitude, marker.position.longitude), @@ -909,15 +923,23 @@ abstract class GoogleMapsBaseMapView( } } val position = Convert.convertCameraPositionToDto(getMap().cameraPosition) - viewEventApi.onCameraChanged(viewId.toLong(), event, position) {} + viewEventApi?.onCameraChanged(getViewId().toLong(), event, position) {} } getMap().setOnCameraMoveListener { val position = Convert.convertCameraPositionToDto(getMap().cameraPosition) - viewEventApi.onCameraChanged(viewId.toLong(), CameraEventTypeDto.ONCAMERAMOVE, position) {} + viewEventApi?.onCameraChanged( + getViewId().toLong(), + CameraEventTypeDto.ONCAMERAMOVE, + position, + ) {} } getMap().setOnCameraIdleListener { val position = Convert.convertCameraPositionToDto(getMap().cameraPosition) - viewEventApi.onCameraChanged(viewId.toLong(), CameraEventTypeDto.ONCAMERAIDLE, position) {} + viewEventApi?.onCameraChanged( + getViewId().toLong(), + CameraEventTypeDto.ONCAMERAIDLE, + position, + ) {} } } } diff --git a/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsNavigationPlugin.kt b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsNavigationPlugin.kt index 07e86772..2083e5a7 100644 --- a/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsNavigationPlugin.kt +++ b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsNavigationPlugin.kt @@ -24,15 +24,26 @@ import io.flutter.embedding.engine.plugins.lifecycle.FlutterLifecycleAdapter /** GoogleMapsNavigationPlugin */ class GoogleMapsNavigationPlugin : FlutterPlugin, ActivityAware { - private lateinit var viewRegistry: GoogleMapsViewRegistry + companion object { + private var instance: GoogleMapsNavigationPlugin? = null + + fun getInstance(): GoogleMapsNavigationPlugin? { + return instance + } + } + + internal lateinit var viewRegistry: GoogleMapsViewRegistry private lateinit var viewMessageHandler: GoogleMapsViewMessageHandler private lateinit var imageRegistryMessageHandler: GoogleMapsImageRegistryMessageHandler - private lateinit var viewEventApi: ViewEventApi + internal lateinit var viewEventApi: ViewEventApi private lateinit var _binding: FlutterPlugin.FlutterPluginBinding private lateinit var lifecycle: Lifecycle - private lateinit var imageRegistry: ImageRegistry + internal lateinit var imageRegistry: ImageRegistry + private lateinit var autoViewMessageHandler: GoogleMapsAutoViewMessageHandler + internal lateinit var autoViewEventApi: AutoViewEventApi override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { + instance = this viewRegistry = GoogleMapsViewRegistry() imageRegistry = ImageRegistry() viewMessageHandler = GoogleMapsViewMessageHandler(viewRegistry) @@ -42,6 +53,9 @@ class GoogleMapsNavigationPlugin : FlutterPlugin, ActivityAware { viewEventApi = ViewEventApi(binding.binaryMessenger) _binding = binding binding.applicationContext.registerComponentCallbacks(viewRegistry) + autoViewMessageHandler = GoogleMapsAutoViewMessageHandler(viewRegistry) + AutoMapViewApi.setUp(binding.binaryMessenger, autoViewMessageHandler) + autoViewEventApi = AutoViewEventApi(binding.binaryMessenger) } override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { @@ -49,6 +63,7 @@ class GoogleMapsNavigationPlugin : FlutterPlugin, ActivityAware { ImageRegistryApi.setUp(binding.binaryMessenger, null) GoogleMapsNavigationSessionManager.destroyInstance() binding.applicationContext.unregisterComponentCallbacks(viewRegistry) + instance = null } override fun onAttachedToActivity(binding: ActivityPluginBinding) { diff --git a/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsNavigationSessionManager.kt b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsNavigationSessionManager.kt index b8a191f0..f4e950fb 100644 --- a/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsNavigationSessionManager.kt +++ b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsNavigationSessionManager.kt @@ -43,15 +43,21 @@ import com.google.android.libraries.navigation.TermsAndConditionsUIParams import com.google.android.libraries.navigation.TimeAndDistance import com.google.android.libraries.navigation.Waypoint import com.google.maps.flutter.navigation.Convert.convertTravelModeFromDto +import com.google.maps.flutter.navigation.GoogleMapsNavigationSessionManager.Companion.navigationReadyListener import io.flutter.plugin.common.BinaryMessenger import java.lang.ref.WeakReference +interface NavigationReadyListener { + fun onNavigationReady(ready: Boolean) +} + /** This class handles creation of navigation session and other navigation related tasks. */ class GoogleMapsNavigationSessionManager private constructor(private val navigationSessionEventApi: NavigationSessionEventApi) : DefaultLifecycleObserver { companion object { private var instance: GoogleMapsNavigationSessionManager? = null + var navigationReadyListener: NavigationReadyListener? = null /** * Create new GoogleMapsNavigationSessionManager instance. Does nothing if instance is already @@ -170,6 +176,7 @@ private constructor(private val navigationSessionEventApi: NavigationSessionEven // Navigator is already initialized, just re-register listeners. registerNavigationListeners() isNavigationSessionInitialized = true + navigationReadyListener?.onNavigationReady(true) callback(Result.success(Unit)) return } @@ -197,6 +204,7 @@ private constructor(private val navigationSessionEventApi: NavigationSessionEven navigator = newNavigator registerNavigationListeners() isNavigationSessionInitialized = true + navigationReadyListener?.onNavigationReady(true) callback(Result.success(Unit)) } @@ -279,6 +287,7 @@ private constructor(private val navigationSessionEventApi: NavigationSessionEven // As unregisterListeners() is removing all listeners, we need to re-register them when // navigator is re-initialized. This is done in createNavigationSession() method. isNavigationSessionInitialized = false + navigationReadyListener?.onNavigationReady(false) } private fun unregisterListeners() { 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 fb478e53..55a5d5ae 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 @@ -108,7 +108,7 @@ internal constructor( _navigationView.removeOnRecenterButtonClickedListener {} - viewRegistry.unregisterNavigationView(viewId) + viewRegistry.unregisterNavigationView(getViewId()) } override fun onStart() { @@ -137,10 +137,10 @@ internal constructor( override fun initListeners() { _navigationView.addOnRecenterButtonClickedListener { - viewEventApi.onRecenterButtonClicked(viewId.toLong()) {} + viewEventApi?.onRecenterButtonClicked(getViewId().toLong()) {} } _navigationView.addOnNavigationUiChangedListener { - viewEventApi.onNavigationUIEnabledChanged(viewId.toLong(), it) {} + viewEventApi?.onNavigationUIEnabledChanged(getViewId().toLong(), it) {} } super.initListeners() } diff --git a/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsViewRegistry.kt b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsViewRegistry.kt index bda737cd..eabde9ee 100644 --- a/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsViewRegistry.kt +++ b/android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsViewRegistry.kt @@ -33,6 +33,8 @@ class GoogleMapsViewRegistry : DefaultLifecycleObserver, ComponentCallbacks, Com // This list contains all map views, including navigation views. private val allMapViews: SparseArray = SparseArray() + private var androidAutoView: GoogleMapsAutoMapView? = null + fun registerNavigationView(viewId: Int, view: GoogleMapsNavigationView) { // Navigation views are added both lists. navigationViews.put(viewId, view) @@ -43,6 +45,10 @@ class GoogleMapsViewRegistry : DefaultLifecycleObserver, ComponentCallbacks, Com allMapViews.put(viewId, view) } + fun registerAndroidAutoView(view: GoogleMapsAutoMapView) { + androidAutoView = view + } + fun unregisterNavigationView(viewId: Int) { // Navigation views need to be removed from both lists. navigationViews.remove(viewId) @@ -53,6 +59,10 @@ class GoogleMapsViewRegistry : DefaultLifecycleObserver, ComponentCallbacks, Com allMapViews.remove(viewId) } + fun unregisterAndroidAutoView() { + androidAutoView = null + } + fun getNavigationView(viewId: Int): GoogleMapsNavigationView? { return navigationViews.get(viewId) } @@ -61,20 +71,28 @@ class GoogleMapsViewRegistry : DefaultLifecycleObserver, ComponentCallbacks, Com return allMapViews.get(viewId) } + fun getAndroidAutoView(): GoogleMapsAutoMapView? { + return androidAutoView + } + override fun onStart(owner: LifecycleOwner) { allMapViews.forEach { _, view -> view.onStart() } + androidAutoView?.onStart() } override fun onResume(owner: LifecycleOwner) { allMapViews.forEach { _, view -> view.onResume() } + androidAutoView?.onResume() } override fun onPause(owner: LifecycleOwner) { allMapViews.forEach { _, view -> view.onPause() } + androidAutoView?.onPause() } override fun onStop(owner: LifecycleOwner) { allMapViews.forEach { _, view -> view.onStop() } + androidAutoView?.onStop() } override fun onConfigurationChanged(configuration: Configuration) { 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 7b2d19d1..57ab1854 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 @@ -6090,6 +6090,2361 @@ class NavigationSessionEventApi(private val binaryMessenger: BinaryMessenger) { } } +@Suppress("UNCHECKED_CAST") +private object AutoMapViewApiCodec : StandardMessageCodec() { + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return when (type) { + 128.toByte() -> { + return (readValue(buffer) as? List)?.let { CameraPositionDto.fromList(it) } + } + 129.toByte() -> { + return (readValue(buffer) as? List)?.let { CircleDto.fromList(it) } + } + 130.toByte() -> { + return (readValue(buffer) as? List)?.let { CircleOptionsDto.fromList(it) } + } + 131.toByte() -> { + return (readValue(buffer) as? List)?.let { ImageDescriptorDto.fromList(it) } + } + 132.toByte() -> { + return (readValue(buffer) as? List)?.let { InfoWindowDto.fromList(it) } + } + 133.toByte() -> { + return (readValue(buffer) as? List)?.let { LatLngBoundsDto.fromList(it) } + } + 134.toByte() -> { + return (readValue(buffer) as? List)?.let { LatLngDto.fromList(it) } + } + 135.toByte() -> { + return (readValue(buffer) as? List)?.let { LatLngDto.fromList(it) } + } + 136.toByte() -> { + return (readValue(buffer) as? List)?.let { MarkerAnchorDto.fromList(it) } + } + 137.toByte() -> { + return (readValue(buffer) as? List)?.let { MarkerDto.fromList(it) } + } + 138.toByte() -> { + return (readValue(buffer) as? List)?.let { MarkerOptionsDto.fromList(it) } + } + 139.toByte() -> { + return (readValue(buffer) as? List)?.let { PatternItemDto.fromList(it) } + } + 140.toByte() -> { + return (readValue(buffer) as? List)?.let { PolygonDto.fromList(it) } + } + 141.toByte() -> { + return (readValue(buffer) as? List)?.let { PolygonHoleDto.fromList(it) } + } + 142.toByte() -> { + return (readValue(buffer) as? List)?.let { PolygonOptionsDto.fromList(it) } + } + 143.toByte() -> { + return (readValue(buffer) as? List)?.let { PolylineDto.fromList(it) } + } + 144.toByte() -> { + return (readValue(buffer) as? List)?.let { PolylineOptionsDto.fromList(it) } + } + 145.toByte() -> { + return (readValue(buffer) as? List)?.let { StyleSpanDto.fromList(it) } + } + 146.toByte() -> { + return (readValue(buffer) as? List)?.let { StyleSpanStrokeStyleDto.fromList(it) } + } + else -> super.readValueOfType(type, buffer) + } + } + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + when (value) { + is CameraPositionDto -> { + stream.write(128) + writeValue(stream, value.toList()) + } + is CircleDto -> { + stream.write(129) + writeValue(stream, value.toList()) + } + is CircleOptionsDto -> { + stream.write(130) + writeValue(stream, value.toList()) + } + is ImageDescriptorDto -> { + stream.write(131) + writeValue(stream, value.toList()) + } + is InfoWindowDto -> { + stream.write(132) + writeValue(stream, value.toList()) + } + is LatLngBoundsDto -> { + stream.write(133) + writeValue(stream, value.toList()) + } + is LatLngDto -> { + stream.write(134) + writeValue(stream, value.toList()) + } + is LatLngDto -> { + stream.write(135) + writeValue(stream, value.toList()) + } + is MarkerAnchorDto -> { + stream.write(136) + writeValue(stream, value.toList()) + } + is MarkerDto -> { + stream.write(137) + writeValue(stream, value.toList()) + } + is MarkerOptionsDto -> { + stream.write(138) + writeValue(stream, value.toList()) + } + is PatternItemDto -> { + stream.write(139) + writeValue(stream, value.toList()) + } + is PolygonDto -> { + stream.write(140) + writeValue(stream, value.toList()) + } + is PolygonHoleDto -> { + stream.write(141) + writeValue(stream, value.toList()) + } + is PolygonOptionsDto -> { + stream.write(142) + writeValue(stream, value.toList()) + } + is PolylineDto -> { + stream.write(143) + writeValue(stream, value.toList()) + } + is PolylineOptionsDto -> { + stream.write(144) + writeValue(stream, value.toList()) + } + is StyleSpanDto -> { + stream.write(145) + writeValue(stream, value.toList()) + } + is StyleSpanStrokeStyleDto -> { + stream.write(146) + writeValue(stream, value.toList()) + } + else -> super.writeValue(stream, value) + } + } +} + +/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ +interface AutoMapViewApi { + fun isMyLocationEnabled(): Boolean + + fun setMyLocationEnabled(enabled: Boolean) + + fun getMyLocation(): LatLngDto? + + fun getMapType(): MapTypeDto + + fun setMapType(mapType: MapTypeDto) + + fun setMapStyle(styleJson: String) + + fun getCameraPosition(): CameraPositionDto + + fun getVisibleRegion(): LatLngBoundsDto + + fun followMyLocation(perspective: CameraPerspectiveDto, zoomLevel: Double?) + + fun animateCameraToCameraPosition( + cameraPosition: CameraPositionDto, + duration: Long?, + callback: (Result) -> Unit, + ) + + fun animateCameraToLatLng(point: LatLngDto, duration: Long?, callback: (Result) -> Unit) + + fun animateCameraToLatLngBounds( + bounds: LatLngBoundsDto, + padding: Double, + duration: Long?, + callback: (Result) -> Unit, + ) + + fun animateCameraToLatLngZoom( + point: LatLngDto, + zoom: Double, + duration: Long?, + callback: (Result) -> Unit, + ) + + fun animateCameraByScroll( + scrollByDx: Double, + scrollByDy: Double, + duration: Long?, + callback: (Result) -> Unit, + ) + + fun animateCameraByZoom( + zoomBy: Double, + focusDx: Double?, + focusDy: Double?, + duration: Long?, + callback: (Result) -> Unit, + ) + + fun animateCameraToZoom(zoom: Double, duration: Long?, callback: (Result) -> Unit) + + fun moveCameraToCameraPosition(cameraPosition: CameraPositionDto) + + fun moveCameraToLatLng(point: LatLngDto) + + fun moveCameraToLatLngBounds(bounds: LatLngBoundsDto, padding: Double) + + fun moveCameraToLatLngZoom(point: LatLngDto, zoom: Double) + + fun moveCameraByScroll(scrollByDx: Double, scrollByDy: Double) + + fun moveCameraByZoom(zoomBy: Double, focusDx: Double?, focusDy: Double?) + + fun moveCameraToZoom(zoom: Double) + + fun getMinZoomPreference(): Double + + fun getMaxZoomPreference(): Double + + fun resetMinMaxZoomPreference() + + fun setMinZoomPreference(minZoomPreference: Double) + + fun setMaxZoomPreference(maxZoomPreference: Double) + + fun setMyLocationButtonEnabled(enabled: Boolean) + + fun setConsumeMyLocationButtonClickEventsEnabled(enabled: Boolean) + + fun setZoomGesturesEnabled(enabled: Boolean) + + fun setZoomControlsEnabled(enabled: Boolean) + + fun setCompassEnabled(enabled: Boolean) + + fun setRotateGesturesEnabled(enabled: Boolean) + + fun setScrollGesturesEnabled(enabled: Boolean) + + fun setScrollGesturesDuringRotateOrZoomEnabled(enabled: Boolean) + + fun setTiltGesturesEnabled(enabled: Boolean) + + fun setMapToolbarEnabled(enabled: Boolean) + + fun setTrafficEnabled(enabled: Boolean) + + fun isMyLocationButtonEnabled(): Boolean + + fun isConsumeMyLocationButtonClickEventsEnabled(): Boolean + + fun isZoomGesturesEnabled(): Boolean + + fun isZoomControlsEnabled(): Boolean + + fun isCompassEnabled(): Boolean + + fun isRotateGesturesEnabled(): Boolean + + fun isScrollGesturesEnabled(): Boolean + + fun isScrollGesturesEnabledDuringRotateOrZoom(): Boolean + + fun isTiltGesturesEnabled(): Boolean + + fun isMapToolbarEnabled(): Boolean + + fun isTrafficEnabled(): Boolean + + fun getMarkers(): List + + fun addMarkers(markers: List): List + + fun updateMarkers(markers: List): List + + fun removeMarkers(markers: List) + + fun clearMarkers() + + fun clear() + + fun getPolygons(): List + + fun addPolygons(polygons: List): List + + fun updatePolygons(polygons: List): List + + fun removePolygons(polygons: List) + + fun clearPolygons() + + fun getPolylines(): List + + fun addPolylines(polylines: List): List + + fun updatePolylines(polylines: List): List + + fun removePolylines(polylines: List) + + fun clearPolylines() + + fun getCircles(): List + + fun addCircles(circles: List): List + + fun updateCircles(circles: List): List + + fun removeCircles(circles: List) + + fun clearCircles() + + fun registerOnCameraChangedListener() + + fun isAutoScreenAvailable(): Boolean + + companion object { + /** The codec used by AutoMapViewApi. */ + val codec: MessageCodec by lazy { AutoMapViewApiCodec } + + /** Sets up an instance of `AutoMapViewApi` to handle messages through the `binaryMessenger`. */ + @Suppress("UNCHECKED_CAST") + fun setUp(binaryMessenger: BinaryMessenger, api: AutoMapViewApi?) { + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isMyLocationEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.isMyLocationEnabled()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMyLocationEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val enabledArg = args[0] as Boolean + var wrapped: List + try { + api.setMyLocationEnabled(enabledArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMyLocation", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.getMyLocation()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMapType", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.getMapType().raw) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMapType", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val mapTypeArg = MapTypeDto.ofRaw(args[0] as Int)!! + var wrapped: List + try { + api.setMapType(mapTypeArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMapStyle", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val styleJsonArg = args[0] as String + var wrapped: List + try { + api.setMapStyle(styleJsonArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getCameraPosition", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.getCameraPosition()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getVisibleRegion", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.getVisibleRegion()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.followMyLocation", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val perspectiveArg = CameraPerspectiveDto.ofRaw(args[0] as Int)!! + val zoomLevelArg = args[1] as Double? + var wrapped: List + try { + api.followMyLocation(perspectiveArg, zoomLevelArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraToCameraPosition", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val cameraPositionArg = args[0] as CameraPositionDto + val durationArg = args[1].let { if (it is Int) it.toLong() else it as Long? } + api.animateCameraToCameraPosition(cameraPositionArg, durationArg) { + result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraToLatLng", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pointArg = args[0] as LatLngDto + val durationArg = args[1].let { if (it is Int) it.toLong() else it as Long? } + api.animateCameraToLatLng(pointArg, durationArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraToLatLngBounds", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val boundsArg = args[0] as LatLngBoundsDto + val paddingArg = args[1] as Double + val durationArg = args[2].let { if (it is Int) it.toLong() else it as Long? } + api.animateCameraToLatLngBounds(boundsArg, paddingArg, durationArg) { + result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraToLatLngZoom", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pointArg = args[0] as LatLngDto + val zoomArg = args[1] as Double + val durationArg = args[2].let { if (it is Int) it.toLong() else it as Long? } + api.animateCameraToLatLngZoom(pointArg, zoomArg, durationArg) { result: Result + -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraByScroll", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val scrollByDxArg = args[0] as Double + val scrollByDyArg = args[1] as Double + val durationArg = args[2].let { if (it is Int) it.toLong() else it as Long? } + api.animateCameraByScroll(scrollByDxArg, scrollByDyArg, durationArg) { + result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraByZoom", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val zoomByArg = args[0] as Double + val focusDxArg = args[1] as Double? + val focusDyArg = args[2] as Double? + val durationArg = args[3].let { if (it is Int) it.toLong() else it as Long? } + api.animateCameraByZoom(zoomByArg, focusDxArg, focusDyArg, durationArg) { + result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraToZoom", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val zoomArg = args[0] as Double + val durationArg = args[1].let { if (it is Int) it.toLong() else it as Long? } + api.animateCameraToZoom(zoomArg, durationArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraToCameraPosition", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val cameraPositionArg = args[0] as CameraPositionDto + var wrapped: List + try { + api.moveCameraToCameraPosition(cameraPositionArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraToLatLng", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pointArg = args[0] as LatLngDto + var wrapped: List + try { + api.moveCameraToLatLng(pointArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraToLatLngBounds", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val boundsArg = args[0] as LatLngBoundsDto + val paddingArg = args[1] as Double + var wrapped: List + try { + api.moveCameraToLatLngBounds(boundsArg, paddingArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraToLatLngZoom", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pointArg = args[0] as LatLngDto + val zoomArg = args[1] as Double + var wrapped: List + try { + api.moveCameraToLatLngZoom(pointArg, zoomArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraByScroll", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val scrollByDxArg = args[0] as Double + val scrollByDyArg = args[1] as Double + var wrapped: List + try { + api.moveCameraByScroll(scrollByDxArg, scrollByDyArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraByZoom", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val zoomByArg = args[0] as Double + val focusDxArg = args[1] as Double? + val focusDyArg = args[2] as Double? + var wrapped: List + try { + api.moveCameraByZoom(zoomByArg, focusDxArg, focusDyArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraToZoom", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val zoomArg = args[0] as Double + var wrapped: List + try { + api.moveCameraToZoom(zoomArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMinZoomPreference", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.getMinZoomPreference()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMaxZoomPreference", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.getMaxZoomPreference()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.resetMinMaxZoomPreference", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + api.resetMinMaxZoomPreference() + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMinZoomPreference", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val minZoomPreferenceArg = args[0] as Double + var wrapped: List + try { + api.setMinZoomPreference(minZoomPreferenceArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMaxZoomPreference", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val maxZoomPreferenceArg = args[0] as Double + var wrapped: List + try { + api.setMaxZoomPreference(maxZoomPreferenceArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMyLocationButtonEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val enabledArg = args[0] as Boolean + var wrapped: List + try { + api.setMyLocationButtonEnabled(enabledArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setConsumeMyLocationButtonClickEventsEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val enabledArg = args[0] as Boolean + var wrapped: List + try { + api.setConsumeMyLocationButtonClickEventsEnabled(enabledArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setZoomGesturesEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val enabledArg = args[0] as Boolean + var wrapped: List + try { + api.setZoomGesturesEnabled(enabledArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setZoomControlsEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val enabledArg = args[0] as Boolean + var wrapped: List + try { + api.setZoomControlsEnabled(enabledArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setCompassEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val enabledArg = args[0] as Boolean + var wrapped: List + try { + api.setCompassEnabled(enabledArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setRotateGesturesEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val enabledArg = args[0] as Boolean + var wrapped: List + try { + api.setRotateGesturesEnabled(enabledArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setScrollGesturesEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val enabledArg = args[0] as Boolean + var wrapped: List + try { + api.setScrollGesturesEnabled(enabledArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setScrollGesturesDuringRotateOrZoomEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val enabledArg = args[0] as Boolean + var wrapped: List + try { + api.setScrollGesturesDuringRotateOrZoomEnabled(enabledArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setTiltGesturesEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val enabledArg = args[0] as Boolean + var wrapped: List + try { + api.setTiltGesturesEnabled(enabledArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMapToolbarEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val enabledArg = args[0] as Boolean + var wrapped: List + try { + api.setMapToolbarEnabled(enabledArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setTrafficEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val enabledArg = args[0] as Boolean + var wrapped: List + try { + api.setTrafficEnabled(enabledArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isMyLocationButtonEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.isMyLocationButtonEnabled()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isConsumeMyLocationButtonClickEventsEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.isConsumeMyLocationButtonClickEventsEnabled()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isZoomGesturesEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.isZoomGesturesEnabled()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isZoomControlsEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.isZoomControlsEnabled()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isCompassEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.isCompassEnabled()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isRotateGesturesEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.isRotateGesturesEnabled()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isScrollGesturesEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.isScrollGesturesEnabled()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isScrollGesturesEnabledDuringRotateOrZoom", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.isScrollGesturesEnabledDuringRotateOrZoom()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isTiltGesturesEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.isTiltGesturesEnabled()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isMapToolbarEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.isMapToolbarEnabled()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isTrafficEnabled", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.isTrafficEnabled()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMarkers", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.getMarkers()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.addMarkers", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val markersArg = args[0] as List + var wrapped: List + try { + wrapped = listOf(api.addMarkers(markersArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.updateMarkers", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val markersArg = args[0] as List + var wrapped: List + try { + wrapped = listOf(api.updateMarkers(markersArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.removeMarkers", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val markersArg = args[0] as List + var wrapped: List + try { + api.removeMarkers(markersArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.clearMarkers", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + api.clearMarkers() + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.clear", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + api.clear() + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getPolygons", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.getPolygons()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.addPolygons", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val polygonsArg = args[0] as List + var wrapped: List + try { + wrapped = listOf(api.addPolygons(polygonsArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.updatePolygons", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val polygonsArg = args[0] as List + var wrapped: List + try { + wrapped = listOf(api.updatePolygons(polygonsArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.removePolygons", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val polygonsArg = args[0] as List + var wrapped: List + try { + api.removePolygons(polygonsArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.clearPolygons", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + api.clearPolygons() + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getPolylines", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.getPolylines()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.addPolylines", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val polylinesArg = args[0] as List + var wrapped: List + try { + wrapped = listOf(api.addPolylines(polylinesArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.updatePolylines", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val polylinesArg = args[0] as List + var wrapped: List + try { + wrapped = listOf(api.updatePolylines(polylinesArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.removePolylines", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val polylinesArg = args[0] as List + var wrapped: List + try { + api.removePolylines(polylinesArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.clearPolylines", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + api.clearPolylines() + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getCircles", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.getCircles()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.addCircles", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val circlesArg = args[0] as List + var wrapped: List + try { + wrapped = listOf(api.addCircles(circlesArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.updateCircles", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val circlesArg = args[0] as List + var wrapped: List + try { + wrapped = listOf(api.updateCircles(circlesArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.removeCircles", + codec, + ) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val circlesArg = args[0] as List + var wrapped: List + try { + api.removeCircles(circlesArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.clearCircles", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + api.clearCircles() + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.registerOnCameraChangedListener", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + api.registerOnCameraChangedListener() + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isAutoScreenAvailable", + codec, + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.isAutoScreenAvailable()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } +} + +@Suppress("UNCHECKED_CAST") +private object AutoViewEventApiCodec : StandardMessageCodec() { + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return when (type) { + 128.toByte() -> { + return (readValue(buffer) as? List)?.let { CameraPositionDto.fromList(it) } + } + 129.toByte() -> { + return (readValue(buffer) as? List)?.let { CircleDto.fromList(it) } + } + 130.toByte() -> { + return (readValue(buffer) as? List)?.let { CircleOptionsDto.fromList(it) } + } + 131.toByte() -> { + return (readValue(buffer) as? List)?.let { DestinationsDto.fromList(it) } + } + 132.toByte() -> { + return (readValue(buffer) as? List)?.let { ImageDescriptorDto.fromList(it) } + } + 133.toByte() -> { + return (readValue(buffer) as? List)?.let { InfoWindowDto.fromList(it) } + } + 134.toByte() -> { + return (readValue(buffer) as? List)?.let { LaneDirectionDto.fromList(it) } + } + 135.toByte() -> { + return (readValue(buffer) as? List)?.let { LaneDto.fromList(it) } + } + 136.toByte() -> { + return (readValue(buffer) as? List)?.let { LatLngBoundsDto.fromList(it) } + } + 137.toByte() -> { + return (readValue(buffer) as? List)?.let { LatLngDto.fromList(it) } + } + 138.toByte() -> { + return (readValue(buffer) as? List)?.let { MapOptionsDto.fromList(it) } + } + 139.toByte() -> { + return (readValue(buffer) as? List)?.let { MarkerAnchorDto.fromList(it) } + } + 140.toByte() -> { + return (readValue(buffer) as? List)?.let { MarkerDto.fromList(it) } + } + 141.toByte() -> { + return (readValue(buffer) as? List)?.let { MarkerOptionsDto.fromList(it) } + } + 142.toByte() -> { + return (readValue(buffer) as? List)?.let { NavInfoDto.fromList(it) } + } + 143.toByte() -> { + return (readValue(buffer) as? List)?.let { + NavigationAudioGuidanceSettingsDto.fromList(it) + } + } + 144.toByte() -> { + return (readValue(buffer) as? List)?.let { NavigationDisplayOptionsDto.fromList(it) } + } + 145.toByte() -> { + return (readValue(buffer) as? List)?.let { NavigationTimeAndDistanceDto.fromList(it) } + } + 146.toByte() -> { + return (readValue(buffer) as? List)?.let { NavigationViewOptionsDto.fromList(it) } + } + 147.toByte() -> { + return (readValue(buffer) as? List)?.let { NavigationWaypointDto.fromList(it) } + } + 148.toByte() -> { + return (readValue(buffer) as? List)?.let { PatternItemDto.fromList(it) } + } + 149.toByte() -> { + return (readValue(buffer) as? List)?.let { PolygonDto.fromList(it) } + } + 150.toByte() -> { + return (readValue(buffer) as? List)?.let { PolygonHoleDto.fromList(it) } + } + 151.toByte() -> { + return (readValue(buffer) as? List)?.let { PolygonOptionsDto.fromList(it) } + } + 152.toByte() -> { + return (readValue(buffer) as? List)?.let { PolylineDto.fromList(it) } + } + 153.toByte() -> { + return (readValue(buffer) as? List)?.let { PolylineOptionsDto.fromList(it) } + } + 154.toByte() -> { + return (readValue(buffer) as? List)?.let { RouteSegmentDto.fromList(it) } + } + 155.toByte() -> { + return (readValue(buffer) as? List)?.let { RouteSegmentTrafficDataDto.fromList(it) } + } + 156.toByte() -> { + return (readValue(buffer) as? List)?.let { + RouteSegmentTrafficDataRoadStretchRenderingDataDto.fromList(it) + } + } + 157.toByte() -> { + return (readValue(buffer) as? List)?.let { RouteTokenOptionsDto.fromList(it) } + } + 158.toByte() -> { + return (readValue(buffer) as? List)?.let { RoutingOptionsDto.fromList(it) } + } + 159.toByte() -> { + return (readValue(buffer) as? List)?.let { SimulationOptionsDto.fromList(it) } + } + 160.toByte() -> { + return (readValue(buffer) as? List)?.let { SpeedAlertOptionsDto.fromList(it) } + } + 161.toByte() -> { + return (readValue(buffer) as? List)?.let { SpeedingUpdatedEventDto.fromList(it) } + } + 162.toByte() -> { + return (readValue(buffer) as? List)?.let { StepInfoDto.fromList(it) } + } + 163.toByte() -> { + return (readValue(buffer) as? List)?.let { StyleSpanDto.fromList(it) } + } + 164.toByte() -> { + return (readValue(buffer) as? List)?.let { StyleSpanStrokeStyleDto.fromList(it) } + } + 165.toByte() -> { + return (readValue(buffer) as? List)?.let { ViewCreationOptionsDto.fromList(it) } + } + else -> super.readValueOfType(type, buffer) + } + } + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + when (value) { + is CameraPositionDto -> { + stream.write(128) + writeValue(stream, value.toList()) + } + is CircleDto -> { + stream.write(129) + writeValue(stream, value.toList()) + } + is CircleOptionsDto -> { + stream.write(130) + writeValue(stream, value.toList()) + } + is DestinationsDto -> { + stream.write(131) + writeValue(stream, value.toList()) + } + is ImageDescriptorDto -> { + stream.write(132) + writeValue(stream, value.toList()) + } + is InfoWindowDto -> { + stream.write(133) + writeValue(stream, value.toList()) + } + is LaneDirectionDto -> { + stream.write(134) + writeValue(stream, value.toList()) + } + is LaneDto -> { + stream.write(135) + writeValue(stream, value.toList()) + } + is LatLngBoundsDto -> { + stream.write(136) + writeValue(stream, value.toList()) + } + is LatLngDto -> { + stream.write(137) + writeValue(stream, value.toList()) + } + is MapOptionsDto -> { + stream.write(138) + writeValue(stream, value.toList()) + } + is MarkerAnchorDto -> { + stream.write(139) + writeValue(stream, value.toList()) + } + is MarkerDto -> { + stream.write(140) + writeValue(stream, value.toList()) + } + is MarkerOptionsDto -> { + stream.write(141) + writeValue(stream, value.toList()) + } + is NavInfoDto -> { + stream.write(142) + writeValue(stream, value.toList()) + } + is NavigationAudioGuidanceSettingsDto -> { + stream.write(143) + writeValue(stream, value.toList()) + } + is NavigationDisplayOptionsDto -> { + stream.write(144) + writeValue(stream, value.toList()) + } + is NavigationTimeAndDistanceDto -> { + stream.write(145) + writeValue(stream, value.toList()) + } + is NavigationViewOptionsDto -> { + stream.write(146) + writeValue(stream, value.toList()) + } + is NavigationWaypointDto -> { + stream.write(147) + writeValue(stream, value.toList()) + } + is PatternItemDto -> { + stream.write(148) + writeValue(stream, value.toList()) + } + is PolygonDto -> { + stream.write(149) + writeValue(stream, value.toList()) + } + is PolygonHoleDto -> { + stream.write(150) + writeValue(stream, value.toList()) + } + is PolygonOptionsDto -> { + stream.write(151) + writeValue(stream, value.toList()) + } + is PolylineDto -> { + stream.write(152) + writeValue(stream, value.toList()) + } + is PolylineOptionsDto -> { + stream.write(153) + writeValue(stream, value.toList()) + } + is RouteSegmentDto -> { + stream.write(154) + writeValue(stream, value.toList()) + } + is RouteSegmentTrafficDataDto -> { + stream.write(155) + writeValue(stream, value.toList()) + } + is RouteSegmentTrafficDataRoadStretchRenderingDataDto -> { + stream.write(156) + writeValue(stream, value.toList()) + } + is RouteTokenOptionsDto -> { + stream.write(157) + writeValue(stream, value.toList()) + } + is RoutingOptionsDto -> { + stream.write(158) + writeValue(stream, value.toList()) + } + is SimulationOptionsDto -> { + stream.write(159) + writeValue(stream, value.toList()) + } + is SpeedAlertOptionsDto -> { + stream.write(160) + writeValue(stream, value.toList()) + } + is SpeedingUpdatedEventDto -> { + stream.write(161) + writeValue(stream, value.toList()) + } + is StepInfoDto -> { + stream.write(162) + writeValue(stream, value.toList()) + } + is StyleSpanDto -> { + stream.write(163) + writeValue(stream, value.toList()) + } + is StyleSpanStrokeStyleDto -> { + stream.write(164) + writeValue(stream, value.toList()) + } + is ViewCreationOptionsDto -> { + stream.write(165) + writeValue(stream, value.toList()) + } + else -> super.writeValue(stream, value) + } + } +} + +/** Generated class from Pigeon that represents Flutter messages that can be called from Kotlin. */ +@Suppress("UNCHECKED_CAST") +class AutoViewEventApi(private val binaryMessenger: BinaryMessenger) { + companion object { + /** The codec used by AutoViewEventApi. */ + val codec: MessageCodec by lazy { AutoViewEventApiCodec } + } + + fun onCustomNavigationAutoEvent( + eventArg: String, + dataArg: Any, + callback: (Result) -> Unit, + ) { + val channelName = + "dev.flutter.pigeon.google_navigation_flutter.AutoViewEventApi.onCustomNavigationAutoEvent" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(eventArg, dataArg)) { + 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(createConnectionError(channelName))) + } + } + } + + fun onAutoScreenAvailabilityChanged(isAvailableArg: Boolean, callback: (Result) -> Unit) { + val channelName = + "dev.flutter.pigeon.google_navigation_flutter.AutoViewEventApi.onAutoScreenAvailabilityChanged" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(isAvailableArg)) { + 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(createConnectionError(channelName))) + } + } + } +} + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface NavigationInspector { fun isViewAttachedToSession(viewId: Long): Boolean diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 214ab9e4..74955c6a 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -105,6 +105,9 @@ flutter { } dependencies { + implementation "androidx.car.app:app:1.4.0" + implementation "androidx.car.app:app-projected:1.4.0" + implementation 'com.google.android.libraries.navigation:navigation:6.0.0' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4' androidTestUtil "androidx.test:orchestrator:1.4.2" } diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 102490a5..9b200f77 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -19,6 +19,12 @@ + + + + + + @@ -46,10 +52,33 @@ + + + + + + + + + + + + + + + + diff --git a/example/android/app/src/main/kotlin/com/google/maps/flutter/navigation_example/ManeuverConverter.kt b/example/android/app/src/main/kotlin/com/google/maps/flutter/navigation_example/ManeuverConverter.kt new file mode 100644 index 00000000..b3d006e0 --- /dev/null +++ b/example/android/app/src/main/kotlin/com/google/maps/flutter/navigation_example/ManeuverConverter.kt @@ -0,0 +1,156 @@ +/* +* 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_example + +import com.google.android.libraries.mapsplatform.turnbyturn.model.Maneuver + +/** Converter that converts between turn-by-turn and Android Auto Maneuvers. */ +object ManeuverConverter { + // Map from turn-by-turn Maneuver to Android Auto Maneuver.Type. + + private val MANEUVER_TO_ANDROID_AUTO_MANEUVER_TYPE = + mapOf(Maneuver.DEPART to androidx.car.app.navigation.model.Maneuver.TYPE_DEPART, + Maneuver.DESTINATION to androidx.car.app.navigation.model.Maneuver.TYPE_DESTINATION, + Maneuver.DESTINATION_LEFT to androidx.car.app.navigation.model.Maneuver.TYPE_DESTINATION_LEFT, + Maneuver.DESTINATION_RIGHT to androidx.car.app.navigation.model.Maneuver.TYPE_DESTINATION_RIGHT, + Maneuver.STRAIGHT to androidx.car.app.navigation.model.Maneuver.TYPE_STRAIGHT, + Maneuver.TURN_LEFT to androidx.car.app.navigation.model.Maneuver.TYPE_TURN_NORMAL_LEFT, + Maneuver.TURN_RIGHT to androidx.car.app.navigation.model.Maneuver.TYPE_TURN_NORMAL_RIGHT, + Maneuver.TURN_KEEP_LEFT to androidx.car.app.navigation.model.Maneuver.TYPE_KEEP_LEFT, + Maneuver.TURN_KEEP_RIGHT to androidx.car.app.navigation.model.Maneuver.TYPE_KEEP_RIGHT, + Maneuver.TURN_SLIGHT_LEFT to androidx.car.app.navigation.model.Maneuver.TYPE_TURN_SLIGHT_LEFT, + Maneuver.TURN_SLIGHT_RIGHT to androidx.car.app.navigation.model.Maneuver.TYPE_TURN_SLIGHT_RIGHT, + Maneuver.TURN_SHARP_LEFT to androidx.car.app.navigation.model.Maneuver.TYPE_TURN_SHARP_LEFT, + Maneuver.TURN_SHARP_RIGHT to androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_SHARP_RIGHT, + Maneuver.TURN_U_TURN_CLOCKWISE to androidx.car.app.navigation.model.Maneuver.TYPE_U_TURN_RIGHT, + Maneuver.TURN_U_TURN_COUNTERCLOCKWISE to androidx.car.app.navigation.model.Maneuver.TYPE_U_TURN_LEFT, + Maneuver.MERGE_UNSPECIFIED to androidx.car.app.navigation.model.Maneuver.TYPE_MERGE_SIDE_UNSPECIFIED, + Maneuver.MERGE_LEFT to androidx.car.app.navigation.model.Maneuver.TYPE_MERGE_LEFT, + Maneuver.MERGE_RIGHT to androidx.car.app.navigation.model.Maneuver.TYPE_MERGE_RIGHT, + Maneuver.FORK_LEFT to androidx.car.app.navigation.model.Maneuver.TYPE_FORK_LEFT, + Maneuver.FORK_RIGHT to androidx.car.app.navigation.model.Maneuver.TYPE_FORK_RIGHT, + Maneuver.ON_RAMP_UNSPECIFIED to androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_NORMAL_RIGHT, + Maneuver.ON_RAMP_LEFT to androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_NORMAL_LEFT, + Maneuver.ON_RAMP_RIGHT to androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_NORMAL_RIGHT, + Maneuver.ON_RAMP_KEEP_LEFT to androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_NORMAL_LEFT, + Maneuver.ON_RAMP_KEEP_RIGHT to androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_NORMAL_RIGHT, + Maneuver.ON_RAMP_SLIGHT_LEFT to androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_SLIGHT_LEFT, + Maneuver.ON_RAMP_SLIGHT_RIGHT to androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_SLIGHT_RIGHT, + Maneuver.ON_RAMP_SHARP_LEFT to androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_SHARP_LEFT, + Maneuver.ON_RAMP_SHARP_RIGHT to androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_SHARP_RIGHT, + Maneuver.ON_RAMP_U_TURN_CLOCKWISE to androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_U_TURN_RIGHT, + Maneuver.ON_RAMP_U_TURN_COUNTERCLOCKWISE to androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_U_TURN_LEFT, + Maneuver.OFF_RAMP_LEFT to androidx.car.app.navigation.model.Maneuver.TYPE_OFF_RAMP_NORMAL_LEFT, + Maneuver.OFF_RAMP_RIGHT to androidx.car.app.navigation.model.Maneuver.TYPE_OFF_RAMP_NORMAL_RIGHT, + Maneuver.OFF_RAMP_KEEP_LEFT to androidx.car.app.navigation.model.Maneuver.TYPE_OFF_RAMP_SLIGHT_LEFT, + Maneuver.OFF_RAMP_KEEP_RIGHT to androidx.car.app.navigation.model.Maneuver.TYPE_OFF_RAMP_SLIGHT_RIGHT, + Maneuver.OFF_RAMP_SLIGHT_LEFT to androidx.car.app.navigation.model.Maneuver.TYPE_OFF_RAMP_SLIGHT_LEFT, + Maneuver.OFF_RAMP_SLIGHT_RIGHT to androidx.car.app.navigation.model.Maneuver.TYPE_OFF_RAMP_SLIGHT_RIGHT, + Maneuver.OFF_RAMP_SHARP_LEFT to androidx.car.app.navigation.model.Maneuver.TYPE_OFF_RAMP_NORMAL_LEFT, + Maneuver.OFF_RAMP_SHARP_RIGHT to androidx.car.app.navigation.model.Maneuver.TYPE_OFF_RAMP_NORMAL_RIGHT, + Maneuver.ROUNDABOUT_CLOCKWISE to androidx.car.app.navigation.model.Maneuver.TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW, + Maneuver.ROUNDABOUT_COUNTERCLOCKWISE to androidx.car.app.navigation.model.Maneuver.TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW, + Maneuver.ROUNDABOUT_STRAIGHT_CLOCKWISE to androidx.car.app.navigation.model.Maneuver.TYPE_ROUNDABOUT_ENTER_CW, + Maneuver.ROUNDABOUT_STRAIGHT_COUNTERCLOCKWISE to androidx.car.app.navigation.model.Maneuver.TYPE_ROUNDABOUT_ENTER_CCW, + Maneuver.ROUNDABOUT_LEFT_CLOCKWISE to androidx.car.app.navigation.model.Maneuver + .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE, + Maneuver.ROUNDABOUT_LEFT_COUNTERCLOCKWISE to androidx.car.app.navigation.model.Maneuver + .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE, + Maneuver.ROUNDABOUT_RIGHT_CLOCKWISE to + androidx.car.app.navigation.model.Maneuver + .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE, + Maneuver.ROUNDABOUT_RIGHT_COUNTERCLOCKWISE to androidx.car.app.navigation.model.Maneuver + .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE, + Maneuver.ROUNDABOUT_SLIGHT_LEFT_CLOCKWISE to androidx.car.app.navigation.model.Maneuver + .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE, + Maneuver.ROUNDABOUT_SLIGHT_LEFT_COUNTERCLOCKWISE to androidx.car.app.navigation.model.Maneuver + .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE, + Maneuver.ROUNDABOUT_SLIGHT_RIGHT_CLOCKWISE to androidx.car.app.navigation.model.Maneuver + .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE, + Maneuver.ROUNDABOUT_SLIGHT_RIGHT_COUNTERCLOCKWISE to androidx.car.app.navigation.model.Maneuver + .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE, + Maneuver.ROUNDABOUT_SHARP_LEFT_CLOCKWISE to androidx.car.app.navigation.model.Maneuver + .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE, + Maneuver.ROUNDABOUT_SHARP_LEFT_COUNTERCLOCKWISE to androidx.car.app.navigation.model.Maneuver + .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE, + Maneuver.ROUNDABOUT_SHARP_RIGHT_CLOCKWISE to androidx.car.app.navigation.model.Maneuver + .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE, + Maneuver.ROUNDABOUT_SHARP_RIGHT_COUNTERCLOCKWISE to androidx.car.app.navigation.model.Maneuver + .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE, + Maneuver.ROUNDABOUT_U_TURN_CLOCKWISE to androidx.car.app.navigation.model.Maneuver + .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE, + Maneuver.ROUNDABOUT_U_TURN_COUNTERCLOCKWISE to androidx.car.app.navigation.model.Maneuver + .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE, + Maneuver.ROUNDABOUT_EXIT_CLOCKWISE to androidx.car.app.navigation.model.Maneuver.TYPE_ROUNDABOUT_EXIT_CW, + Maneuver.ROUNDABOUT_EXIT_COUNTERCLOCKWISE to androidx.car.app.navigation.model.Maneuver.TYPE_ROUNDABOUT_EXIT_CCW, + Maneuver.FERRY_BOAT to androidx.car.app.navigation.model.Maneuver.TYPE_FERRY_BOAT, + Maneuver.FERRY_TRAIN to androidx.car.app.navigation.model.Maneuver.TYPE_FERRY_TRAIN, + Maneuver.NAME_CHANGE to androidx.car.app.navigation.model.Maneuver.TYPE_NAME_CHANGE) + + /** Represents the roundabout turn angle for a slight turn in either right or left directions. */ + private const val ROUNDABOUT_ANGLE_SLIGHT = 10 + + /** Represents the roundabout turn angle for a normal turn in either right or left directions. */ + private const val ROUNDABOUT_ANGLE_NORMAL = 45 + + /** Represents the roundabout turn angle for a sharp turn in either right or left directions. */ + private const val ROUNDABOUT_ANGLE_SHARP = 135 + + /** Represents the roundabout turn angle for a u-turn in either right or left directions. */ + private const val ROUNDABOUT_ANGLE_U_TURN = 180 + + /** + * Returns the corresponding [androidx.car.app.navigation.model.Maneuver.Type] for the given + * direction [Maneuver] + * + * @throws [IllegalArgumentException] if the given maneuver does not have a corresponding + * Android Auto Maneuver type. + */ + fun getAndroidAutoManeuverType(@Maneuver maneuver: Int): Int { + if (MANEUVER_TO_ANDROID_AUTO_MANEUVER_TYPE.containsKey(maneuver)) { + return MANEUVER_TO_ANDROID_AUTO_MANEUVER_TYPE[maneuver]!! + } + throw IllegalArgumentException( + String.format( + "Given turn-by-turn Maneuver %d cannot be converted to an Android Auto equivalent.", + maneuver + ) + ) + } + + /** + * Returns the corresponding Android Auto roundabout angle for the given turn [Maneuver]. + * Returns `null` if given maneuver does not involve a roundabout with a turn. + */ + fun getAndroidAutoRoundaboutAngle(@Maneuver maneuver: Int): Int? { + if (maneuver == Maneuver.ROUNDABOUT_LEFT_CLOCKWISE || maneuver == Maneuver.ROUNDABOUT_RIGHT_CLOCKWISE || maneuver == Maneuver.ROUNDABOUT_LEFT_COUNTERCLOCKWISE || maneuver == Maneuver.ROUNDABOUT_RIGHT_COUNTERCLOCKWISE) { + return ROUNDABOUT_ANGLE_NORMAL + } + if (maneuver == Maneuver.ROUNDABOUT_SHARP_LEFT_CLOCKWISE || maneuver == Maneuver.ROUNDABOUT_SHARP_RIGHT_CLOCKWISE || maneuver == Maneuver.ROUNDABOUT_SHARP_LEFT_COUNTERCLOCKWISE || maneuver == Maneuver.ROUNDABOUT_SHARP_RIGHT_COUNTERCLOCKWISE) { + return ROUNDABOUT_ANGLE_SHARP + } + if (maneuver == Maneuver.ROUNDABOUT_SLIGHT_LEFT_CLOCKWISE || maneuver == Maneuver.ROUNDABOUT_SLIGHT_RIGHT_CLOCKWISE || maneuver == Maneuver.ROUNDABOUT_SLIGHT_LEFT_COUNTERCLOCKWISE || maneuver == Maneuver.ROUNDABOUT_SLIGHT_RIGHT_COUNTERCLOCKWISE) { + return ROUNDABOUT_ANGLE_SLIGHT + } + if (maneuver == Maneuver.ROUNDABOUT_U_TURN_CLOCKWISE + || maneuver == Maneuver.ROUNDABOUT_U_TURN_COUNTERCLOCKWISE + ) { + return ROUNDABOUT_ANGLE_U_TURN + } + return null + } +} \ No newline at end of file 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 new file mode 100644 index 00000000..2be97a23 --- /dev/null +++ b/example/android/app/src/main/kotlin/com/google/maps/flutter/navigation_example/SampleAndroidAutoScreen.kt @@ -0,0 +1,151 @@ +/* + * 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_example + +import android.annotation.SuppressLint +import androidx.car.app.CarContext +import androidx.car.app.model.Action +import androidx.car.app.model.ActionStrip +import androidx.car.app.model.CarIcon +import androidx.car.app.model.Distance +import androidx.car.app.model.Pane +import androidx.car.app.model.PaneTemplate +import androidx.car.app.model.Row +import androidx.car.app.model.Template +import androidx.car.app.navigation.model.Maneuver +import androidx.car.app.navigation.model.NavigationTemplate +import androidx.car.app.navigation.model.RoutingInfo +import androidx.car.app.navigation.model.Step +import androidx.core.graphics.drawable.IconCompat +import com.google.android.gms.maps.GoogleMap +import com.google.android.libraries.mapsplatform.turnbyturn.model.NavInfo +import com.google.android.libraries.mapsplatform.turnbyturn.model.StepInfo +import com.google.maps.flutter.navigation.AndroidAutoBaseScreen +import com.google.maps.flutter.navigation.GoogleMapsNavigationNavUpdatesService + + +class SampleAndroidAutoScreen(carContext: CarContext): AndroidAutoBaseScreen(carContext) { + + private var mNavInfo: RoutingInfo? = null + init { + // Connect to the Turn-by-Turn Navigation service to receive navigation data. + GoogleMapsNavigationNavUpdatesService.navInfoLiveData.observe(this) { navInfo: NavInfo? -> + this.buildNavInfo( + navInfo + ) + } + } + + private fun buildNavInfo(navInfo: NavInfo?) { + if (navInfo == null || navInfo.currentStep == null) { + return + } + + /** + * Converts data received from the Navigation data feed into Android-Auto compatible data + * structures. + */ + val currentStep: Step = buildStepFromStepInfo(navInfo.currentStep) + val distanceToStep = + Distance.create( + java.lang.Double.max( + navInfo.distanceToCurrentStepMeters.toDouble(), + 0.0 + ), Distance.UNIT_METERS + ) + + mNavInfo = RoutingInfo.Builder().setCurrentStep(currentStep, distanceToStep).build() + + // Invalidate the current template which leads to another onGetTemplate call. + invalidate() + } + + private fun buildStepFromStepInfo(stepInfo: StepInfo): Step { + val maneuver: Int = ManeuverConverter.getAndroidAutoManeuverType(stepInfo.maneuver) + val maneuverBuilder = Maneuver.Builder(maneuver) + if (stepInfo.maneuverBitmap != null) { + val maneuverIcon = IconCompat.createWithBitmap(stepInfo.maneuverBitmap) + val maneuverCarIcon = CarIcon.Builder(maneuverIcon).build() + maneuverBuilder.setIcon(maneuverCarIcon) + } + val stepBuilder = + Step.Builder() + .setRoad(stepInfo.fullRoadName) + .setCue(stepInfo.fullInstructionText) + .setManeuver(maneuverBuilder.build()) + return stepBuilder.build() + } + + override fun onNavigationReady(ready: Boolean) { + super.onNavigationReady(ready) + // Invalidate template layout because of conditional rendering in the + // onGetTemplate method. + invalidate() + } + + override fun onGetTemplate(): Template { + if (!mIsNavigationReady) { + return PaneTemplate.Builder( + Pane.Builder() + .addRow( + Row.Builder() + .setTitle("Nav SampleApp") + .addText( + "Initialize navigation to see navigation view on the Android Auto" + + " screen" + ) + .build() + ) + .build() + ) + .build() + } + // Suppresses the missing permission check for the followMyLocation method, which requires + // "android.permission.ACCESS_COARSE_LOCATION" or "android.permission.ACCESS_FINE_LOCATION", as + // these permissions are already handled elsewhere. + @SuppressLint("MissingPermission") + val navigationTemplateBuilder = + NavigationTemplate.Builder() + .setActionStrip( + ActionStrip.Builder() + .addAction( + Action.Builder() + .setTitle("Re-center") + .setOnClickListener { + if (mGoogleMap == null) return@setOnClickListener + mGoogleMap!!.followMyLocation(GoogleMap.CameraPerspective.TILTED) + } + .build()) + .addAction( + Action.Builder() + .setTitle("Custom event") + .setOnClickListener { + sendCustomNavigationAutoEvent("CustomAndroidAutoEvent", mapOf("sampleDataKey" to "sampleDataContent")) + } + .build()) + .build()) + .setMapActionStrip(ActionStrip.Builder().addAction(Action.PAN).build()) + + + // Show turn-by-turn navigation information if available. + if (mNavInfo != null) { + navigationTemplateBuilder.setNavigationInfo(mNavInfo!!) + } + + return navigationTemplateBuilder.build() + } +} \ No newline at end of file diff --git a/example/android/app/src/main/kotlin/com/google/maps/flutter/navigation_example/SampleAndroidAutoService.kt b/example/android/app/src/main/kotlin/com/google/maps/flutter/navigation_example/SampleAndroidAutoService.kt new file mode 100644 index 00000000..0ea34df8 --- /dev/null +++ b/example/android/app/src/main/kotlin/com/google/maps/flutter/navigation_example/SampleAndroidAutoService.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2023 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_example + +import androidx.car.app.CarAppService; +import androidx.car.app.Session +import androidx.car.app.SessionInfo +import androidx.car.app.validation.HostValidator + +class SampleAndroidAutoService: CarAppService() { + override fun createHostValidator(): HostValidator { + // This sample allows all hosts to connect to the app. + return HostValidator.ALLOW_ALL_HOSTS_VALIDATOR + } + + override fun onCreateSession(sessionInfo: SessionInfo): Session { + return SampleAndroidAutoSession(sessionInfo) + } +} \ No newline at end of file diff --git a/example/android/app/src/main/kotlin/com/google/maps/flutter/navigation_example/SampleAndroidAutoSession.kt b/example/android/app/src/main/kotlin/com/google/maps/flutter/navigation_example/SampleAndroidAutoSession.kt new file mode 100644 index 00000000..bd64cdcb --- /dev/null +++ b/example/android/app/src/main/kotlin/com/google/maps/flutter/navigation_example/SampleAndroidAutoSession.kt @@ -0,0 +1,101 @@ +/* + * 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_example + +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.ServiceConnection +import android.os.IBinder +import android.util.Log +import androidx.car.app.CarContext +import androidx.car.app.CarToast +import androidx.car.app.Screen +import androidx.car.app.Session +import androidx.car.app.SessionInfo +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleOwner + +class SampleAndroidAutoSession(sessionInfo: SessionInfo): Session() { + + private val TAG: String = SampleAndroidAutoSession::class.java.simpleName + + init { + if (sessionInfo.displayType == SessionInfo.DISPLAY_TYPE_MAIN) { + lifecycle.addObserver(object: DefaultLifecycleObserver { + override fun onCreate(owner: LifecycleOwner) { + Log.i(TAG, "In onCreate()") + carContext + .bindService( + Intent(carContext, SampleAndroidAutoService::class.java), + mServiceConnection, + Context.BIND_AUTO_CREATE + ) + } + + override fun onStart(owner: LifecycleOwner) { + Log.i(TAG, "In onStart()") + } + + override fun onResume(owner: LifecycleOwner) { + Log.i(TAG, "In onResume()") + } + + override fun onPause(owner: LifecycleOwner) { + Log.i(TAG, "In onPause()") + } + + override fun onStop(owner: LifecycleOwner) { + Log.i(TAG, "In onStop()") + } + + override fun onDestroy(owner: LifecycleOwner) { + Log.i(TAG, "In onDestroy()") + carContext.unbindService(mServiceConnection) + } + }) + } + } + + // Monitors the state of the connection to the Navigation service. + val mServiceConnection: ServiceConnection = object : ServiceConnection { + override fun onServiceConnected(name: ComponentName, service: IBinder) { + Log.i(TAG, "In onServiceConnected() component:$name") + } + + override fun onServiceDisconnected(name: ComponentName) { + Log.i( + TAG, + "In onServiceDisconnected() component:$name" + ) + } + } + + override fun onCreateScreen(intent: Intent): Screen { + Log.i(TAG, "In onCreateScreen()") + + val action = intent.action + if (action != null && CarContext.ACTION_NAVIGATE == action) { + CarToast.makeText( + carContext, "Navigation intent: " + intent.dataString, CarToast.LENGTH_LONG + ) + .show() + } + + return SampleAndroidAutoScreen(carContext) + } +} \ No newline at end of file diff --git a/example/android/app/src/main/res/xml/automotive_app_desc.xml b/example/android/app/src/main/res/xml/automotive_app_desc.xml new file mode 100644 index 00000000..cc83882a --- /dev/null +++ b/example/android/app/src/main/res/xml/automotive_app_desc.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/example/ios/Podfile b/example/ios/Podfile index bd3f5c0d..0007995b 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -40,6 +40,13 @@ target 'Runner' do end end +target 'RunnerCarPlay' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 9bf810c9..3e5b82f9 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -9,6 +9,16 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 2A18B91A2AB17E8000172055 /* ConvertTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A18B9192AB17E8000172055 /* ConvertTests.swift */; }; + 2A8C4ABD2CC646F200168311 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 2A8C4AC12CC646F200168311 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + 2A8C4AC22CC646F200168311 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 2A8C4AC32CC646F200168311 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 2A8C4AC42CC646F200168311 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 2A8C4AD02CC64A8500168311 /* AppDelegateCarPlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A8C4ACF2CC64A8500168311 /* AppDelegateCarPlay.swift */; }; + 2A8C4AD22CC64AE500168311 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A8C4AD12CC64AE500168311 /* main.swift */; }; + 2A8C4AD32CC64AE500168311 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A8C4AD12CC64AE500168311 /* main.swift */; }; + 2A8C4ADD2CC656D700168311 /* PhoneSceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A8C4ADC2CC656D700168311 /* PhoneSceneDelegate.swift */; }; + 2A8C4ADF2CC656E800168311 /* CarSceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A8C4ADE2CC656E800168311 /* CarSceneDelegate.swift */; }; 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 */; }; @@ -18,6 +28,8 @@ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 9BAC8E60A263AA40A946AFCF /* Pods_Runner_RunnerUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 981DBDBFB0E241F931B1E394 /* Pods_Runner_RunnerUITests.framework */; }; 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 */; }; + DA52652595AF0077243F8014 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 64B801515FD75D36D58A86FE /* Pods_Runner.framework */; }; EDFE577D2F64CF5D3712A4E9 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 64B801515FD75D36D58A86FE /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ @@ -39,6 +51,16 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 2A8C4AC52CC646F200168311 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; 9705A1C41CF9048500538489 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -56,6 +78,13 @@ 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 = ""; }; 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 = ""; }; + 2A8C4AD12CC64AE500168311 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; + 2A8C4AD82CC6503E00168311 /* Info-CarPlay.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-CarPlay.plist"; sourceTree = ""; }; + 2A8C4ADB2CC653B800168311 /* RunnerCarPlay.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerCarPlay.entitlements; sourceTree = ""; }; + 2A8C4ADC2CC656D700168311 /* PhoneSceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhoneSceneDelegate.swift; sourceTree = ""; }; + 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; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; @@ -79,12 +108,24 @@ 981DBDBFB0E241F931B1E394 /* Pods_Runner_RunnerUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner_RunnerUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9B707C730235859544DEFD11 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; A6E86B897576AE6CE04EDE41 /* Pods-Runner-RunnerUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner-RunnerUITests.release.xcconfig"; path = "Target Support Files/Pods-Runner-RunnerUITests/Pods-Runner-RunnerUITests.release.xcconfig"; sourceTree = ""; }; + B269F01B5CD151328AA7F8EB /* Pods_RunnerCarPlay.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerCarPlay.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B35F8B4336F9E9672910B2A8 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 2A8C4ABE2CC646F200168311 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D3A3B5ED895816BDF2A70351 /* Pods_RunnerCarPlay.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 506F57472AD8012C004AC70F /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -99,6 +140,7 @@ buildActionMask = 2147483647; files = ( EDFE577D2F64CF5D3712A4E9 /* Pods_Runner.framework in Frameworks */, + DA52652595AF0077243F8014 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -159,6 +201,7 @@ 97C146EE1CF9000F007C117D /* Runner.app */, 331C8081294A63A400263BE5 /* RunnerTests.xctest */, 506F574A2AD8012C004AC70F /* RunnerUITests.xctest */, + 2A8C4ACD2CC646F200168311 /* RunnerCarPlay.app */, ); name = Products; sourceTree = ""; @@ -166,14 +209,20 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + 2A8C4ADB2CC653B800168311 /* RunnerCarPlay.entitlements */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 97C147021CF9000F007C117D /* Info.plist */, + 2A8C4AD82CC6503E00168311 /* Info-CarPlay.plist */, 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 2A8C4AD12CC64AE500168311 /* main.swift */, 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 2A8C4ACF2CC64A8500168311 /* AppDelegateCarPlay.swift */, 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + 2A8C4ADC2CC656D700168311 /* PhoneSceneDelegate.swift */, + 2A8C4ADE2CC656E800168311 /* CarSceneDelegate.swift */, ); path = Runner; sourceTree = ""; @@ -190,6 +239,9 @@ 2EAF2B705FB6C39F7F5344DA /* Pods-Runner-RunnerUITests.debug.xcconfig */, A6E86B897576AE6CE04EDE41 /* Pods-Runner-RunnerUITests.release.xcconfig */, FD0B54A81651AC7754FA8D08 /* Pods-Runner-RunnerUITests.profile.xcconfig */, + C8406E69EBE45F2EF856A867 /* Pods-RunnerCarPlay.debug.xcconfig */, + F66F7193CD255958326CC224 /* Pods-RunnerCarPlay.release.xcconfig */, + B7C92A3F95B466A95C6F8F82 /* Pods-RunnerCarPlay.profile.xcconfig */, ); path = Pods; sourceTree = ""; @@ -201,6 +253,7 @@ 64B801515FD75D36D58A86FE /* Pods_Runner.framework */, 981DBDBFB0E241F931B1E394 /* Pods_Runner_RunnerUITests.framework */, 054752A3C68A7FF5D59CC247 /* Pods_RunnerTests.framework */, + B269F01B5CD151328AA7F8EB /* Pods_RunnerCarPlay.framework */, ); name = Frameworks; sourceTree = ""; @@ -208,6 +261,29 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 2A8C4AB82CC646F200168311 /* RunnerCarPlay */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2A8C4AC92CC646F200168311 /* Build configuration list for PBXNativeTarget "RunnerCarPlay" */; + buildPhases = ( + DB054ED881210D00E963C46A /* [CP] Check Pods Manifest.lock */, + 2A8C4ABA2CC646F200168311 /* Run Script */, + 2A8C4ABB2CC646F200168311 /* Sources */, + 2A8C4ABE2CC646F200168311 /* Frameworks */, + 2A8C4AC02CC646F200168311 /* Resources */, + 2A8C4AC52CC646F200168311 /* Embed Frameworks */, + 2A8C4AC62CC646F200168311 /* Thin Binary */, + BAAF78ADF4EC76C6CC3D931D /* [CP] Embed Pods Frameworks */, + E1A54FD049B3FD079D5EAF0B /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RunnerCarPlay; + productName = Runner; + productReference = 2A8C4ACD2CC646F200168311 /* RunnerCarPlay.app */; + productType = "com.apple.product-type.application"; + }; 331C8080294A63A400263BE5 /* RunnerTests */ = { isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; @@ -311,6 +387,7 @@ projectRoot = ""; targets = ( 97C146ED1CF9000F007C117D /* Runner */, + 2A8C4AB82CC646F200168311 /* RunnerCarPlay */, 331C8080294A63A400263BE5 /* RunnerTests */, 506F57492AD8012C004AC70F /* RunnerUITests */, ); @@ -318,6 +395,17 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 2A8C4AC02CC646F200168311 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2A8C4AC12CC646F200168311 /* LaunchScreen.storyboard in Resources */, + 2A8C4AC22CC646F200168311 /* AppFrameworkInfo.plist in Resources */, + 2A8C4AC32CC646F200168311 /* Assets.xcassets in Resources */, + 2A8C4AC42CC646F200168311 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 331C807F294A63A400263BE5 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -385,6 +473,37 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + 2A8C4ABA2CC646F200168311 /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; + }; + 2A8C4AC62CC646F200168311 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n"; + }; 3AC0A81F7D36AA565D151485 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -469,6 +588,23 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; }; + BAAF78ADF4EC76C6CC3D931D /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RunnerCarPlay/Pods-RunnerCarPlay-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RunnerCarPlay/Pods-RunnerCarPlay-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RunnerCarPlay/Pods-RunnerCarPlay-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; D1AE5F46BE0FA1B15C1D9A70 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -508,6 +644,45 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + DB054ED881210D00E963C46A /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerCarPlay-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + E1A54FD049B3FD079D5EAF0B /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RunnerCarPlay/Pods-RunnerCarPlay-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RunnerCarPlay/Pods-RunnerCarPlay-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RunnerCarPlay/Pods-RunnerCarPlay-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; F18CEB3456BF1353653A4B93 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -550,6 +725,18 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 2A8C4ABB2CC646F200168311 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2A8C4ABD2CC646F200168311 /* GeneratedPluginRegistrant.m in Sources */, + 2A8C4AD02CC64A8500168311 /* AppDelegateCarPlay.swift in Sources */, + 2A8C4ADD2CC656D700168311 /* PhoneSceneDelegate.swift in Sources */, + 2A8C4ADF2CC656E800168311 /* CarSceneDelegate.swift in Sources */, + 2A8C4AD32CC64AE500168311 /* main.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 331C807D294A63A400263BE5 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -572,6 +759,7 @@ files = ( 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + 2A8C4AD22CC64AE500168311 /* main.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -683,6 +871,82 @@ }; name = Profile; }; + 2A8C4ACA2CC646F200168311 /* Debug */ = { + 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 = 15.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; + }; + 2A8C4ACB2CC646F200168311 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.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 = 15.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_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; + 2A8C4ACC2CC646F200168311 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.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 = 15.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_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = B35F8B4336F9E9672910B2A8 /* Pods-RunnerTests.debug.xcconfig */; @@ -979,6 +1243,16 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 2A8C4AC92CC646F200168311 /* Build configuration list for PBXNativeTarget "RunnerCarPlay" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2A8C4ACA2CC646F200168311 /* Debug */, + 2A8C4ACB2CC646F200168311 /* Release */, + 2A8C4ACC2CC646F200168311 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/RunnerCarPlay.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/RunnerCarPlay.xcscheme new file mode 100644 index 00000000..46eef0f5 --- /dev/null +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/RunnerCarPlay.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift index 7d61451a..a83a5691 100644 --- a/example/ios/Runner/AppDelegate.swift +++ b/example/ios/Runner/AppDelegate.swift @@ -17,7 +17,6 @@ import Flutter import GoogleMaps import GoogleNavigation -@main @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, @@ -28,28 +27,28 @@ import GoogleNavigation // 3. Use the default Maps API key "YOUR_API_KEY". var mapsApiKey = ProcessInfo.processInfo.environment["MAPS_API_KEY"] ?? findMapApiKeyFromDartDefines("MAPS_API_KEY") ?? "" if (mapsApiKey.isEmpty) { - mapsApiKey = "YOUR_API_KEY" + mapsApiKey = "YOUR_API_KEY" } GMSServices.provideAPIKey(mapsApiKey) GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } - + // Helper function to find the Maps API key from the Dart defines private func findMapApiKeyFromDartDefines(_ defineKey: String) -> String? { - if (Bundle.main.infoDictionary!["DART_DEFINES"] == nil) { - return nil - } + if (Bundle.main.infoDictionary!["DART_DEFINES"] == nil) { + return nil + } - let dartDefinesString = Bundle.main.infoDictionary!["DART_DEFINES"] as! String - let base64EncodedDartDefines = dartDefinesString.components(separatedBy: ",") - for base64EncodedDartDefine in base64EncodedDartDefines { - let decoded = String(data: Data(base64Encoded: base64EncodedDartDefine)!, encoding: .utf8)! - let values = decoded.components(separatedBy: "=") - if (values[0] == defineKey && values.count == 2) { - return values[1] - } + let dartDefinesString = Bundle.main.infoDictionary!["DART_DEFINES"] as! String + let base64EncodedDartDefines = dartDefinesString.components(separatedBy: ",") + for base64EncodedDartDefine in base64EncodedDartDefines { + let decoded = String(data: Data(base64Encoded: base64EncodedDartDefine)!, encoding: .utf8)! + let values = decoded.components(separatedBy: "=") + if (values[0] == defineKey && values.count == 2) { + return values[1] } - return nil + } + return nil } } diff --git a/example/ios/Runner/AppDelegateCarPlay.swift b/example/ios/Runner/AppDelegateCarPlay.swift new file mode 100644 index 00000000..9412e5d6 --- /dev/null +++ b/example/ios/Runner/AppDelegateCarPlay.swift @@ -0,0 +1,69 @@ +// Copyright 2023 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 CarPlay +import Flutter +import GoogleMaps +import GoogleNavigation +import UIKit + +@objc class AppDelegateCarPlay: FlutterAppDelegate { + override func application(_ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [ + UIApplication.LaunchOptionsKey: Any + ]?) -> Bool { + // 1. Try to find the Maps API key from the environment variables. + // 2. Try to find the Maps API key from the Dart defines. + // 3. Use the default Maps API key "YOUR_API_KEY". + var mapsApiKey = ProcessInfo.processInfo + .environment["MAPS_API_KEY"] ?? findMapApiKeyFromDartDefines("MAPS_API_KEY") ?? "" + if mapsApiKey.isEmpty { + mapsApiKey = "YOUR_API_KEY" + } + GMSServices.provideAPIKey(mapsApiKey) + return true + } + + override func application(_ application: UIApplication, + configurationForConnecting connectingSceneSession: UISceneSession, + options: UIScene.ConnectionOptions) -> UISceneConfiguration { + if connectingSceneSession.role == .carTemplateApplication { + let scene = UISceneConfiguration(name: "CarPlay", sessionRole: connectingSceneSession.role) + scene.delegateClass = CarSceneDelegate.self + return scene + } else { + let scene = UISceneConfiguration(name: "Phone", sessionRole: connectingSceneSession.role) + scene.delegateClass = PhoneSceneDelegate.self + return scene + } + } + + // Helper function to find the Maps API key from the Dart defines + private func findMapApiKeyFromDartDefines(_ defineKey: String) -> String? { + if Bundle.main.infoDictionary!["DART_DEFINES"] == nil { + return nil + } + + let dartDefinesString = Bundle.main.infoDictionary!["DART_DEFINES"] as! String + let base64EncodedDartDefines = dartDefinesString.components(separatedBy: ",") + for base64EncodedDartDefine in base64EncodedDartDefines { + let decoded = String(data: Data(base64Encoded: base64EncodedDartDefine)!, encoding: .utf8)! + let values = decoded.components(separatedBy: "=") + if values[0] == defineKey, values.count == 2 { + return values[1] + } + } + return nil + } +} diff --git a/example/ios/Runner/CarSceneDelegate.swift b/example/ios/Runner/CarSceneDelegate.swift new file mode 100644 index 00000000..f593cac2 --- /dev/null +++ b/example/ios/Runner/CarSceneDelegate.swift @@ -0,0 +1,38 @@ +// Copyright 2023 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 CarPlay +import google_navigation_flutter +import GoogleNavigation +import UIKit + +class CarSceneDelegate: BaseCarSceneDelegate { + override func getTemplate() -> CPMapTemplate { + let template = CPMapTemplate() + template.showPanningInterface(animated: true) + + 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 + ) + } + template.leadingNavigationBarButtons = [customEventButton, recenterButton] + return template + } +} diff --git a/example/ios/Runner/Info-CarPlay.plist b/example/ios/Runner/Info-CarPlay.plist new file mode 100644 index 00000000..85bcc54c --- /dev/null +++ b/example/ios/Runner/Info-CarPlay.plist @@ -0,0 +1,99 @@ + + + + + BGTaskSchedulerPermittedIdentifiers + + $(PRODUCT_BUNDLE_IDENTIFIER) + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Google Maps Navigation + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + google_navigation_flutter_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + DART_DEFINES + $(DART_DEFINES) + LSRequiresIPhoneOS + + NSLocationAlwaysAndWhenInUseUsageDescription + Location needed for functionalities + NSLocationUsageDescription + Location needed for functionalities + NSLocationWhenInUseUsageDescription + Location needed for functionalities + UIApplicationSupportsIndirectInputEvents + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + CPTemplateApplicationSceneSessionRoleApplication + + + UISceneClassName + CPTemplateApplicationScene + UISceneConfigurationName + CarPlay + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).CarSceneDelegate + + + UIWindowSceneSessionRoleApplication + + + UISceneClassName + UIWindowScene + UISceneConfigurationName + Phone + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).PhoneSceneDelegate + UISceneStoryboardFile + Main + + + + + UIBackgroundModes + + location + processing + remote-notification + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/example/ios/Runner/PhoneSceneDelegate.swift b/example/ios/Runner/PhoneSceneDelegate.swift new file mode 100644 index 00000000..b64ee1bb --- /dev/null +++ b/example/ios/Runner/PhoneSceneDelegate.swift @@ -0,0 +1,32 @@ +// Copyright 2023 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 UIKit + +class PhoneSceneDelegate: UIResponder, UIWindowSceneDelegate { + var window: UIWindow? + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, + options connectionOptions: UIScene.ConnectionOptions) { + if let windowScene = scene as? UIWindowScene { + window = UIWindow(windowScene: windowScene) + let flutterEngine = FlutterEngine(name: "PhoneSceneDelegateEngine") + flutterEngine.run() + GeneratedPluginRegistrant.register(with: flutterEngine) + let controller = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil) + window?.rootViewController = controller + window?.makeKeyAndVisible() + } + } +} diff --git a/example/ios/Runner/RunnerCarPlay.entitlements b/example/ios/Runner/RunnerCarPlay.entitlements new file mode 100644 index 00000000..8195a00e --- /dev/null +++ b/example/ios/Runner/RunnerCarPlay.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.developer.carplay-maps + + + diff --git a/example/ios/Runner/main.swift b/example/ios/Runner/main.swift new file mode 100644 index 00000000..50454f5e --- /dev/null +++ b/example/ios/Runner/main.swift @@ -0,0 +1,29 @@ +// Copyright 2023 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. + +#if CARPLAY + UIApplicationMain( + CommandLine.argc, + CommandLine.unsafeArgv, + nil, + NSStringFromClass(AppDelegateCarPlay.self) + ) +#else + UIApplicationMain( + CommandLine.argc, + CommandLine.unsafeArgv, + nil, + NSStringFromClass(AppDelegate.self) + ) +#endif diff --git a/example/ios/RunnerTests/ConvertTests.swift b/example/ios/RunnerTests/ConvertTests.swift index 7db99cde..ed6bfef0 100644 --- a/example/ios/RunnerTests/ConvertTests.swift +++ b/example/ios/RunnerTests/ConvertTests.swift @@ -551,17 +551,17 @@ class ConvertTests: XCTestCase { // Make sure these match because comparison between different enums is complicated. XCTAssert(mapOptions.mapType == .normal) XCTAssert(configuration.mapType == .normal) - XCTAssertEqual(mapOptions.cameraPosition.bearing, configuration.cameraPosition.bearing) + XCTAssertEqual(mapOptions.cameraPosition.bearing, configuration.cameraPosition!.bearing) XCTAssertEqual( mapOptions.cameraPosition.target.latitude, - configuration.cameraPosition.target.latitude + configuration.cameraPosition!.target.latitude ) XCTAssertEqual( mapOptions.cameraPosition.target.longitude, - configuration.cameraPosition.target.longitude + configuration.cameraPosition!.target.longitude ) - XCTAssertEqual(mapOptions.cameraPosition.tilt, configuration.cameraPosition.viewingAngle) - XCTAssertEqual(mapOptions.cameraPosition.zoom, Double(configuration.cameraPosition.zoom)) + XCTAssertEqual(mapOptions.cameraPosition.tilt, configuration.cameraPosition!.viewingAngle) + XCTAssertEqual(mapOptions.cameraPosition.zoom, Double(configuration.cameraPosition!.zoom)) XCTAssertEqual(mapOptions.compassEnabled, configuration.compassEnabled) XCTAssertEqual(mapOptions.rotateGesturesEnabled, configuration.rotateGesturesEnabled) XCTAssertEqual(mapOptions.scrollGesturesEnabled, configuration.scrollGesturesEnabled) diff --git a/example/lib/pages/navigation.dart b/example/lib/pages/navigation.dart index 7cdedd07..10580842 100644 --- a/example/lib/pages/navigation.dart +++ b/example/lib/pages/navigation.dart @@ -73,6 +73,9 @@ class _NavigationPageState extends ExamplePageState { /// Navigation view controller used to interact with the navigation view. GoogleNavigationViewController? _navigationViewController; + final GoogleMapsAutoViewController _autoViewController = + GoogleMapsAutoViewController(); + /// Latest user location received from the navigator. LatLng? _userLocation; @@ -101,6 +104,9 @@ class _NavigationPageState extends ExamplePageState { bool _termsAndConditionsAccepted = false; bool _locationPermissionsAccepted = false; + bool _turnByTurnNavigationEventEnabled = false; + + bool _isAutoScreenAvailable = false; bool _validRoute = false; bool _errorOnSetDestinations = false; @@ -162,6 +168,20 @@ class _NavigationPageState extends ExamplePageState { if (_termsAndConditionsAccepted && _locationPermissionsAccepted) { await _initializeNavigator(); } + + _autoViewController.listenForCustomNavigationAutoEvents((event) { + showMessage("Received event: ${event.event}"); + }); + + _isAutoScreenAvailable = await _autoViewController.isAutoScreenAvailable(); + _autoViewController.listenForAutoScreenAvailibilityChangedEvent((event) { + debugPrint(event.isAvailable + ? "Auto screen is available" + : "Auto screen is not available"); + setState(() { + _isAutoScreenAvailable = event.isAvailable; + }); + }); } Future _setRouteTokensEnabled(bool value) async { @@ -196,6 +216,29 @@ class _NavigationPageState extends ExamplePageState { setState(() {}); } + Future _setMapTypeForAutoToSatellite() async { + await _autoViewController.setMapType(mapType: MapType.satellite); + } + + Future _moveCameraForAuto() async { + final CameraUpdate positionUpdate = CameraUpdate.newLatLng(const LatLng( + latitude: 60.34856639667419, longitude: 25.03459821831162)); + await _autoViewController.moveCamera(positionUpdate); + } + + Future _addMarkerForAuto() async { + LatLng myLocation = (await _autoViewController.getCameraPosition()).target; + // markerOne options. + MarkerOptions markerOptions = MarkerOptions( + position: myLocation, + infoWindow: const InfoWindow( + title: 'Auto marker', + snippet: 'autoMarkerOne', + ), + ); + await _autoViewController.addMarkers([markerOptions]); + } + /// iOS emulator does not update location and does not fire roadsnapping /// events. Initialize user location to [cameraLocationMIT] if user /// location is not available after timeout. @@ -1290,6 +1333,22 @@ class _NavigationPageState extends ExamplePageState { ? null : (bool value) => _setRouteTokensEnabled(value), ), + ExampleSwitch( + title: 'Turn by turn events', + initialValue: _turnByTurnNavigationEventEnabled, + onChanged: (bool newValue) async { + if (newValue) { + await GoogleMapsNavigator + .enableTurnByTurnNavigationEvents( + double.maxFinite.toInt()); + } else { + await GoogleMapsNavigator + .disableTurnByTurnNavigationEvents(); + } + setState(() { + _turnByTurnNavigationEventEnabled = newValue; + }); + }), ], ), const SizedBox(height: 10) @@ -1419,6 +1478,29 @@ class _NavigationPageState extends ExamplePageState { }), ]), )), + Card( + child: ExpansionTile( + enabled: _isAutoScreenAvailable, + title: const Text('Auto view'), + collapsedTextColor: + getExpansionTileTextColor(!_isAutoScreenAvailable), + collapsedIconColor: + getExpansionTileTextColor(!_isAutoScreenAvailable), + children: [ + ElevatedButton( + onPressed: () => _setMapTypeForAutoToSatellite(), + child: const Text('Set map type to satellite'), + ), + ElevatedButton( + onPressed: () => _moveCameraForAuto(), + child: const Text('Move camera'), + ), + ElevatedButton( + onPressed: () => _addMarkerForAuto(), + child: const Text('Add marker'), + ), + ]), + ), IgnorePointer( ignoring: !_navigatorInitialized || _navigationViewController == null, child: Card( diff --git a/ios/Classes/BaseCarSceneDelegate.swift b/ios/Classes/BaseCarSceneDelegate.swift new file mode 100644 index 00000000..81cb1dd4 --- /dev/null +++ b/ios/Classes/BaseCarSceneDelegate.swift @@ -0,0 +1,152 @@ +// Copyright 2023 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 CarPlay +import Foundation +import GoogleMaps + +open class BaseCarSceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate, + CPMapTemplateDelegate { + private var interfaceController: CPInterfaceController? + private var carWindow: CPWindow? + private var mapTemplate: CPMapTemplate? + private var navView: GoogleMapsNavigationView? + private var navViewController: UIViewController? + private var templateApplicationScene: CPTemplateApplicationScene? + private var autoViewEventApi: AutoViewEventApi? + private var viewRegistry: GoogleMapsNavigationViewRegistry? + + public func getNavView() -> GoogleMapsNavigationView? { + navView + } + + public func templateApplicationScene(_ templateApplicationScene: CPTemplateApplicationScene, + didConnect interfaceController: CPInterfaceController, + to window: CPWindow) { + self.interfaceController = interfaceController + carWindow = window + mapTemplate = getTemplate() + self.templateApplicationScene = templateApplicationScene + mapTemplate?.mapDelegate = self + createVC() + } + + open func getTemplate() -> CPMapTemplate { + let template = CPMapTemplate() + template.showPanningInterface(animated: true) + return template + } + + open func templateApplicationScene(_ templateApplicationScene: CPTemplateApplicationScene, + didDisconnect interfaceController: CPInterfaceController, + from window: CPWindow) { + self.interfaceController = nil + carWindow?.rootViewController = nil + carWindow = nil + mapTemplate = nil + navView?.unregisterView() + navView = nil + navViewController = nil + self.templateApplicationScene = nil + } + + open func sceneDidBecomeActive(_ scene: UIScene) {} + + func createVC() { + guard + let templateApplicationScene, + navView == nil + else { return } + + GoogleMapsNavigationPlugin + .pluginInitializedCallback = { [weak self] viewRegistry, autoViewEventApi, imageRegistry in + guard let self else { return } + self.viewRegistry = viewRegistry + self.autoViewEventApi = autoViewEventApi + self.navView = GoogleMapsNavigationView( + frame: templateApplicationScene.carWindow.screen.bounds, + viewIdentifier: nil, + isNavigationView: true, + viewRegistry: viewRegistry, + viewEventApi: nil, + navigationUIEnabledPreference: NavigationUIEnabledPreference.automatic, + mapConfiguration: MapConfiguration( + cameraPosition: nil, + mapType: .normal, + compassEnabled: true, + rotateGesturesEnabled: false, + scrollGesturesEnabled: true, + tiltGesturesEnabled: false, + zoomGesturesEnabled: true, + scrollGesturesEnabledDuringRotateOrZoom: false + ), + imageRegistry: imageRegistry, + isCarPlayView: true + ) + self.navView?.setNavigationHeaderEnabled(false) + self.navView?.setRecenterButtonEnabled(false) + self.navView?.setNavigationFooterEnabled(false) + self.navView?.setSpeedometerEnabled(false) + self.navViewController = UIViewController() + self.navViewController?.view = self.navView?.view() + self.carWindow?.rootViewController = self.navViewController + self.interfaceController?.setRootTemplate(self.mapTemplate!, animated: true) { _, _ in } + + self.viewRegistry?.onHasCarPlayViewChanged = { isAvalable in + self.sendAutoScreenAvailabilityChangedEvent(isAvailable: isAvalable) + } + } + } + + // CPMapTemplateDelegate + open func mapTemplate(_ mapTemplate: CPMapTemplate, + panWith direction: CPMapTemplate.PanDirection) { + let scrollAmount = scrollAmount(for: direction) + navView?.animateCameraByScroll(dx: scrollAmount.x, dy: scrollAmount.y) + } + + func scrollAmount(for direction: CPMapTemplate.PanDirection) -> CGPoint { + let scrollDistance: CGFloat = 80.0 + var scrollAmount = CGPoint(x: 0.0, y: 0.0) + + if direction.contains(.left) { + scrollAmount.x = -scrollDistance + } + if direction.contains(.right) { + scrollAmount.x = scrollDistance + } + if direction.contains(.up) { + scrollAmount.y = -scrollDistance + } + if direction.contains(.down) { + scrollAmount.y = scrollDistance + } + + if scrollAmount.x != 0, scrollAmount.y != 0 { + let factor = CGFloat(Double(1.0 / sqrt(2.0))) + scrollAmount.x *= factor + scrollAmount.y *= factor + } + + return scrollAmount + } + + open func sendCustomNavigationAutoEvent(event: String, data: Any) { + autoViewEventApi?.onCustomNavigationAutoEvent(event: event, data: data) { _ in } + } + + func sendAutoScreenAvailabilityChangedEvent(isAvailable: Bool) { + autoViewEventApi?.onAutoScreenAvailabilityChanged(isAvailable: isAvailable) { _ in } + } +} diff --git a/ios/Classes/GoogleMapsAutoViewMessageHandler.swift b/ios/Classes/GoogleMapsAutoViewMessageHandler.swift new file mode 100644 index 00000000..6048a583 --- /dev/null +++ b/ios/Classes/GoogleMapsAutoViewMessageHandler.swift @@ -0,0 +1,444 @@ +// Copyright 2023 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 GoogleMaps + +enum GoogleMapsAutoViewHandlerError: Error { + case viewNotFound +} + +class GoogleMapsAutoViewMessageHandler: AutoMapViewApi { + private let viewRegistry: GoogleMapsNavigationViewRegistry + + init(viewRegistry: GoogleMapsNavigationViewRegistry) { + self.viewRegistry = viewRegistry + } + + private func getView() throws -> GoogleMapsNavigationView { + guard let view = viewRegistry.getCarPlayView() else { + throw GoogleMapsNavigationViewHandlerError.viewNotFound + } + return view + } + + func awaitMapReady(completion: @escaping (Result) -> Void) { + do { + let mapView = try getView() + mapView.awaitMapReady { result in + switch result { + case .success: + completion(.success(())) + case let .failure(error): + completion(.failure(error)) + } + } + } catch { + completion(.failure(error)) + } + } + + func setMyLocationEnabled(enabled: Bool) throws { + try getView().setMyLocationEnabled(enabled) + } + + func getMapType() throws -> MapTypeDto { + try Convert.convertMapType(gmsMapType: getView().getMapType()) + } + + func setMapType(mapType: MapTypeDto) throws { + let gmsMapType = Convert.convertMapType(mapType: mapType) + try getView().setMapType(mapType: gmsMapType) + } + + func setMapStyle(styleJson: String) throws { + try getView().setMapStyle(styleJson: styleJson) + } + + func setMyLocationButtonEnabled(enabled: Bool) throws { + try getView().setMyLocationButtonEnabled(enabled) + } + + func setZoomGesturesEnabled(enabled: Bool) throws { + try getView().setZoomGesturesEnabled(enabled) + } + + func setZoomControlsEnabled(enabled: Bool) throws { + try getView().setZoomControlsEnabled(enabled) + } + + func setCompassEnabled(enabled: Bool) throws { + try getView().setCompassEnabled(enabled) + } + + func setRotateGesturesEnabled(enabled: Bool) throws { + try getView().setRotateGesturesEnabled(enabled) + } + + func setScrollGesturesEnabled(enabled: Bool) throws { + try getView().setScrollGesturesEnabled(enabled) + } + + func setScrollGesturesDuringRotateOrZoomEnabled(enabled: Bool) throws { + try getView().setScrollGesturesDuringRotateOrZoomEnabled(enabled) + } + + func setTiltGesturesEnabled(enabled: Bool) throws { + try getView().setTiltGesturesEnabled(enabled) + } + + func setMapToolbarEnabled(enabled: Bool) throws { + try getView().setMapToolbarEnabled(enabled) + } + + func setTrafficEnabled(enabled: Bool) throws { + try getView().setTrafficEnabled(enabled) + } + + func isMyLocationEnabled() throws -> Bool { + try getView().isMyLocationEnabled() + } + + func isMyLocationButtonEnabled() throws -> Bool { + try getView().isMyLocationButtonEnabled() + } + + func isZoomGesturesEnabled() throws -> Bool { + try getView().isZoomGesturesEnabled() + } + + func isZoomControlsEnabled() throws -> Bool { + try getView().isZoomControlsEnabled() + } + + func isCompassEnabled() throws -> Bool { + try getView().isCompassEnabled() + } + + func isRotateGesturesEnabled() throws -> Bool { + try getView().isRotateGesturesEnabled() + } + + func isScrollGesturesEnabled() throws -> Bool { + try getView().isScrollGesturesEnabled() + } + + func isScrollGesturesEnabledDuringRotateOrZoom() throws -> Bool { + try getView().isScrollGesturesEnabledDuringRotateOrZoom() + } + + func isTiltGesturesEnabled() throws -> Bool { + try getView().isTiltGesturesEnabled() + } + + func isMapToolbarEnabled() throws -> Bool { + try getView().isMapToolbarEnabled() + } + + func isTrafficEnabled() throws -> Bool { + try getView().isTrafficEnabled() + } + + func getMyLocation() throws -> LatLngDto? { + do { + guard let myLocation = try getView().getMyLocation() else { + return nil + } + return LatLngDto( + latitude: myLocation.latitude, + longitude: myLocation.longitude + ) + } catch { + throw error + } + } + + func getCameraPosition() throws -> CameraPositionDto { + try Convert.convertCameraPosition(position: getView().getCameraPosition()) + } + + func getVisibleRegion() throws -> LatLngBoundsDto { + try Convert.convertLatLngBounds(bounds: getView().getVisibleRegion()) + } + + func animateCameraToCameraPosition(cameraPosition: CameraPositionDto, + duration: Int64?, + completion: @escaping (Result) -> Void) { + do { + try getView() + .animateCameraToCameraPosition(cameraPosition: Convert + .convertCameraPosition(position: cameraPosition)) + + // No callback supported, just return immediately + completion(.success(true)) + } catch { + completion(.failure(error)) + } + } + + func animateCameraToLatLng(point: LatLngDto, duration: Int64?, + completion: @escaping (Result) -> Void) { + do { + try getView().animateCameraToLatLng(point: Convert.convertLatLngFromDto(point: point)) + + // No callback supported, just return immediately + completion(.success(true)) + } catch { + completion(.failure(error)) + } + } + + func animateCameraToLatLngBounds(bounds: LatLngBoundsDto, + padding: Double, duration: Int64?, completion: @escaping (Result< + Bool, + Error + >) + -> Void) { + do { + try getView().animateCameraToLatLngBounds( + bounds: Convert.convertLatLngBounds(bounds: bounds), + padding: padding + ) + + // No callback supported, just return immediately + completion(.success(true)) + } catch { + completion(.failure(error)) + } + } + + func animateCameraToLatLngZoom(point: LatLngDto, zoom: Double, + duration: Int64?, + completion: @escaping (Result) -> Void) { + do { + try getView().animateCameraToLatLngZoom( + point: Convert.convertLatLngFromDto(point: point), + zoom: zoom + ) + + // No callback supported, just return immediately + completion(.success(true)) + } catch { + completion(.failure(error)) + } + } + + func animateCameraByScroll(scrollByDx: Double, scrollByDy: Double, + duration: Int64?, + completion: @escaping (Result) -> Void) { + do { + try getView().animateCameraByScroll(dx: scrollByDx, dy: scrollByDy) + + // No callback supported, just return immediately + completion(.success(true)) + } catch { + completion(.failure(error)) + } + } + + func animateCameraByZoom(zoomBy: Double, focusDx: Double?, + focusDy: Double?, duration: Int64?, completion: @escaping (Result< + Bool, + Error + >) -> Void) { + do { + let focus = Convert.convertDeltaToPoint(dx: focusDx, dy: focusDy) + try getView().animateCameraByZoom(zoomBy: zoomBy, focus: focus) + + // No callback supported, just return immediately + completion(.success(true)) + } catch { + completion(.failure(error)) + } + } + + func animateCameraToZoom(zoom: Double, duration: Int64?, + completion: @escaping (Result) -> Void) { + do { + try getView().animateCameraToZoom(zoom: zoom) + + // No callback supported, just return immediately + completion(.success(true)) + } catch { + completion(.failure(error)) + } + } + + func moveCameraToCameraPosition(cameraPosition: CameraPositionDto) throws { + try getView() + .moveCameraToCameraPosition(cameraPosition: Convert + .convertCameraPosition(position: cameraPosition)) + } + + func moveCameraToLatLng(point: LatLngDto) throws { + try getView().moveCameraToLatLng(point: Convert.convertLatLngFromDto(point: point)) + } + + func moveCameraToLatLngBounds(bounds: LatLngBoundsDto, + padding: Double) throws { + try getView().moveCameraToLatLngBounds( + bounds: Convert.convertLatLngBounds(bounds: bounds), + padding: padding + ) + } + + func moveCameraToLatLngZoom(point: LatLngDto, zoom: Double) throws { + try getView().moveCameraToLatLngZoom( + point: Convert.convertLatLngFromDto(point: point), + zoom: zoom + ) + } + + func moveCameraByScroll(scrollByDx: Double, scrollByDy: Double) throws { + try getView().moveCameraByScroll(dx: scrollByDx, dy: scrollByDy) + } + + func moveCameraByZoom(zoomBy: Double, focusDx: Double?, + focusDy: Double?) throws { + let focus = Convert.convertDeltaToPoint(dx: focusDx, dy: focusDy) + return try getView().moveCameraByZoom(zoomBy: zoomBy, focus: focus) + } + + func moveCameraToZoom(zoom: Double) throws { + try getView().moveCameraToZoom(zoom: zoom) + } + + func followMyLocation(perspective: CameraPerspectiveDto, + zoomLevel: Double?) throws { + try getView() + .followMyLocation( + perspective: Convert.convertCameraPerspective(perspective: perspective), + zoomLevel: zoomLevel + ) + } + + func getMarkers() throws -> [MarkerDto] { + try getView().getMarkers() + } + + func addMarkers(markers: [MarkerDto]) throws -> [MarkerDto] { + try getView().addMarkers(markers: markers) + } + + func updateMarkers(markers: [MarkerDto]) throws -> [MarkerDto] { + try getView().updateMarkers(markers: markers) + } + + func removeMarkers(markers: [MarkerDto]) throws { + try getView().removeMarkers(markers: markers) + } + + func clearMarkers() throws { + try getView().clearMarkers() + } + + func getPolygons() throws -> [PolygonDto] { + try getView().getPolygons() + } + + func addPolygons(polygons: [PolygonDto]) throws -> [PolygonDto] { + try getView().addPolygons(polygons: polygons) + } + + func updatePolygons(polygons: [PolygonDto]) throws -> [PolygonDto] { + try getView().updatePolygons(polygons: polygons) + } + + func removePolygons(polygons: [PolygonDto]) throws { + try getView().removePolygons(polygons: polygons) + } + + func clearPolygons() throws { + try getView().clearPolygons() + } + + func getPolylines() throws -> [PolylineDto] { + try getView().getPolylines() + } + + func addPolylines(polylines: [PolylineDto]) throws -> [PolylineDto] { + try getView().addPolylines(polylines: polylines) + } + + func updatePolylines(polylines: [PolylineDto]) throws -> [PolylineDto] { + try getView().updatePolylines(polylines: polylines) + } + + func removePolylines(polylines: [PolylineDto]) throws { + try getView().removePolylines(polylines: polylines) + } + + func clearPolylines() throws { + try getView().clearPolylines() + } + + func getCircles() throws -> [CircleDto] { + try getView().getCircles() + } + + func addCircles(circles: [CircleDto]) throws -> [CircleDto] { + try getView().addCircles(circles: circles) + } + + func updateCircles(circles: [CircleDto]) throws -> [CircleDto] { + try getView().updateCircles(circles: circles) + } + + func removeCircles(circles: [CircleDto]) throws { + try getView().removeCircles(circles: circles) + } + + func clearCircles() throws { + try getView().clearCircles() + } + + func clear() throws { + try getView().clear() + } + + func setConsumeMyLocationButtonClickEventsEnabled(enabled: Bool) throws { + try getView().setConsumeMyLocationButtonClickEventsEnabled(enabled: enabled) + } + + func isConsumeMyLocationButtonClickEventsEnabled() throws -> Bool { + try getView().isConsumeMyLocationButtonClickEventsEnabled() + } + + func getMinZoomPreference() throws -> Double { + try Double(getView().getMinZoomPreference()) + } + + func getMaxZoomPreference() throws -> Double { + try Double(getView().getMaxZoomPreference()) + } + + func resetMinMaxZoomPreference() throws { + try getView().resetMinMaxZoomPreference() + } + + func setMinZoomPreference(minZoomPreference: Double) throws { + try getView().setMinZoomPreference(minZoomPreference: Float(minZoomPreference)) + } + + func setMaxZoomPreference(maxZoomPreference: Double) throws { + try getView().setMaxZoomPreference(maxZoomPreference: Float(maxZoomPreference)) + } + + func registerOnCameraChangedListener() throws { + try getView().registerOnCameraChangedListener() + } + + func isAutoScreenAvailable() throws -> Bool { + viewRegistry.getCarPlayView() != nil + } +} diff --git a/ios/Classes/GoogleMapsNavigationPlugin.swift b/ios/Classes/GoogleMapsNavigationPlugin.swift index 4b05f481..35bd5dac 100644 --- a/ios/Classes/GoogleMapsNavigationPlugin.swift +++ b/ios/Classes/GoogleMapsNavigationPlugin.swift @@ -27,9 +27,27 @@ public class GoogleMapsNavigationPlugin: NSObject, FlutterPlugin { private static var navigationSessionEventApi: NavigationSessionEventApi? private static var navigationSessionManager: GoogleMapsNavigationSessionManager? private static var navigationInspectorHandler: GoogleMapsNavigationInspectorHandler? + private static var autoViewMessageHandler: GoogleMapsAutoViewMessageHandler? + private static var autoViewEventApi: AutoViewEventApi? private static var imageRegistryMessageHandler: GoogleMapsImageRegistryMessageHandler? - private static var imageRegistry: ImageRegistry? + static var imageRegistry: ImageRegistry? + private static var isPluginInitialized: Bool = false { + didSet { + if isPluginInitialized { + pluginInitializedCallback?(viewRegistry!, autoViewEventApi!, imageRegistry!) + } + } + } + + static var pluginInitializedCallback: ((GoogleMapsNavigationViewRegistry, AutoViewEventApi, + ImageRegistry) -> Void)? { + didSet { + if isPluginInitialized { + pluginInitializedCallback?(viewRegistry!, autoViewEventApi!, imageRegistry!) + } + } + } public static func register(with registrar: FlutterPluginRegistrar) { // Navigation View handling @@ -70,6 +88,14 @@ public class GoogleMapsNavigationPlugin: NSObject, FlutterPlugin { api: sessionMessageHandler ) + // CarPlay map view message handling + autoViewMessageHandler = GoogleMapsAutoViewMessageHandler(viewRegistry: viewRegistry!) + AutoMapViewApiSetup.setUp( + binaryMessenger: registrar.messenger(), + api: autoViewMessageHandler + ) + autoViewEventApi = AutoViewEventApi(binaryMessenger: registrar.messenger()) + navigationInspector = GoogleMapsNavigationInspectorHandler( viewRegistry: viewRegistry! ) @@ -84,5 +110,6 @@ public class GoogleMapsNavigationPlugin: NSObject, FlutterPlugin { binaryMessenger: registrar.messenger(), api: imageRegistryMessageHandler ) + isPluginInitialized = true } } diff --git a/ios/Classes/GoogleMapsNavigationSessionManager.swift b/ios/Classes/GoogleMapsNavigationSessionManager.swift index 5f85d750..bfeb42e4 100644 --- a/ios/Classes/GoogleMapsNavigationSessionManager.swift +++ b/ios/Classes/GoogleMapsNavigationSessionManager.swift @@ -139,6 +139,9 @@ class GoogleMapsNavigationSessionManager: NSObject { try _viewRegistry?.getAllRegisteredNavigationViewIds().forEach { id in try attachNavigationSessionToMapView(mapId: id) } + if let carPlayMapView = _viewRegistry?.getCarPlayView() { + attachNavigationSessionToMapView(mapView: carPlayMapView) + } } func isInitialized() -> Bool { diff --git a/ios/Classes/GoogleMapsNavigationView.swift b/ios/Classes/GoogleMapsNavigationView.swift index 47620770..fa2d7898 100644 --- a/ios/Classes/GoogleMapsNavigationView.swift +++ b/ios/Classes/GoogleMapsNavigationView.swift @@ -28,11 +28,11 @@ enum GoogleMapsNavigationViewError: Error { case maxZoomLessThanMinZoom } -class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettledDelegate { +public class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettledDelegate { private var _mapView: ViewStateAwareGMSMapView! private var _viewRegistry: GoogleMapsNavigationViewRegistry - private var _viewEventApi: ViewEventApi - private var _viewId: Int64 + private var _viewEventApi: ViewEventApi? + private var _viewId: Int64? private var _isNavigationView: Bool private var _myLocationButton: Bool = true private var _markerControllers: [MarkerController] = [] @@ -48,24 +48,40 @@ class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettledDelega private var _consumeMyLocationButtonClickEventsEnabled: Bool = false private var _listenCameraChanges = false var isAttachedToSession: Bool = false + private let _isCarPlayView: Bool - func view() -> UIView { + public func view() -> UIView { _mapView } + // Getter that wont return viewEventApi if viewId is missing. + private func getViewEventApi() -> ViewEventApi? { + if _viewId != nil { + return _viewEventApi + } + return nil + } + init(frame: CGRect, - viewIdentifier viewId: Int64, + viewIdentifier viewId: Int64?, isNavigationView: Bool, viewRegistry registry: GoogleMapsNavigationViewRegistry, - viewEventApi: ViewEventApi, + viewEventApi: ViewEventApi?, navigationUIEnabledPreference: NavigationUIEnabledPreference, - mapConfiguration: MapConfiguration, imageRegistry: ImageRegistry) { + mapConfiguration: MapConfiguration, + imageRegistry: ImageRegistry, + isCarPlayView: Bool) { + if !isCarPlayView, viewId == nil || viewEventApi == nil { + fatalError("For non-carplay map view viewId and viewEventApi is required") + } + _viewId = viewId _isNavigationView = isNavigationView _viewRegistry = registry _viewEventApi = viewEventApi _mapConfiguration = mapConfiguration _imageRegistry = imageRegistry + _isCarPlayView = isCarPlayView let mapViewOptions = GMSMapViewOptions() _mapConfiguration.apply(to: mapViewOptions, withFrame: frame) @@ -77,16 +93,36 @@ class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettledDelega _navigationUIEnabledPreference = navigationUIEnabledPreference applyNavigationUIEnabledPreference() - registry.registerView(viewId: viewId, view: self) + registerView() _mapView.delegate = self _mapView.viewSettledDelegate = self } deinit { - _viewRegistry.unregisterView(viewId: _viewId) + unregisterView() _mapView.delegate = nil } + func registerView() { + if _isCarPlayView { + _viewRegistry.registerCarPlayView(view: self) + } else { + if let _viewId { + _viewRegistry.registerView(viewId: _viewId, view: self) + } + } + } + + func unregisterView() { + if _isCarPlayView { + _viewRegistry.unregisterCarPlayView() + } else { + if let _viewId { + _viewRegistry.unregisterView(viewId: _viewId) + } + } + } + func isNavigationView() -> Bool { _isNavigationView } @@ -186,11 +222,11 @@ class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettledDelega try updateMyLocationButton() } - func getMapType() -> GMSMapViewType { + public func getMapType() -> GMSMapViewType { _mapView.mapType } - func setMapType(mapType: GMSMapViewType) throws { + public func setMapType(mapType: GMSMapViewType) throws { _mapView.mapType = mapType } @@ -294,7 +330,7 @@ class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettledDelega _mapView.cameraMode = .overview } - func getMyLocation() -> CLLocationCoordinate2D? { + public func getMyLocation() -> CLLocationCoordinate2D? { if let location = _mapView.myLocation { return location.coordinate } else { @@ -302,35 +338,35 @@ class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettledDelega } } - func getCameraPosition() -> GMSCameraPosition { + public func getCameraPosition() -> GMSCameraPosition { _mapView.camera } - func getVisibleRegion() -> GMSCoordinateBounds { + public func getVisibleRegion() -> GMSCoordinateBounds { GMSCoordinateBounds(region: _mapView.projection.visibleRegion()) } - func animateCameraToCameraPosition(cameraPosition: GMSCameraPosition) { + public func animateCameraToCameraPosition(cameraPosition: GMSCameraPosition) { _mapView.animate(with: GMSCameraUpdate.setCamera(cameraPosition)) } - func animateCameraToLatLng(point: CLLocationCoordinate2D) { + public func animateCameraToLatLng(point: CLLocationCoordinate2D) { _mapView.animate(with: GMSCameraUpdate.setTarget(point)) } - func animateCameraToLatLngBounds(bounds: GMSCoordinateBounds, padding: Double) { + public func animateCameraToLatLngBounds(bounds: GMSCoordinateBounds, padding: Double) { _mapView.animate(with: GMSCameraUpdate.fit(bounds, withPadding: padding)) } - func animateCameraToLatLngZoom(point: CLLocationCoordinate2D, zoom: Double) { + public func animateCameraToLatLngZoom(point: CLLocationCoordinate2D, zoom: Double) { _mapView.animate(with: GMSCameraUpdate.setTarget(point, zoom: Float(zoom))) } - func animateCameraByScroll(dx: Double, dy: Double) { + public func animateCameraByScroll(dx: Double, dy: Double) { _mapView.animate(with: GMSCameraUpdate.scrollBy(x: CGFloat(dx), y: CGFloat(dy))) } - func animateCameraByZoom(zoomBy: Double, focus: CGPoint?) { + public func animateCameraByZoom(zoomBy: Double, focus: CGPoint?) { if focus != nil { _mapView.animate(with: GMSCameraUpdate.zoom(by: Float(zoomBy), at: focus!)) } else { @@ -338,31 +374,31 @@ class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettledDelega } } - func animateCameraToZoom(zoom: Double) { + public func animateCameraToZoom(zoom: Double) { _mapView.animate(with: GMSCameraUpdate.zoom(to: Float(zoom))) } - func moveCameraToCameraPosition(cameraPosition: GMSCameraPosition) { + public func moveCameraToCameraPosition(cameraPosition: GMSCameraPosition) { _mapView.moveCamera(GMSCameraUpdate.setCamera(cameraPosition)) } - func moveCameraToLatLng(point: CLLocationCoordinate2D) { + public func moveCameraToLatLng(point: CLLocationCoordinate2D) { _mapView.moveCamera(GMSCameraUpdate.setTarget(point)) } - func moveCameraToLatLngBounds(bounds: GMSCoordinateBounds, padding: Double) { + public func moveCameraToLatLngBounds(bounds: GMSCoordinateBounds, padding: Double) { _mapView.moveCamera(GMSCameraUpdate.fit(bounds, withPadding: padding)) } - func moveCameraToLatLngZoom(point: CLLocationCoordinate2D, zoom: Double) { + public func moveCameraToLatLngZoom(point: CLLocationCoordinate2D, zoom: Double) { _mapView.moveCamera(GMSCameraUpdate.setTarget(point, zoom: Float(zoom))) } - func moveCameraByScroll(dx: Double, dy: Double) { + public func moveCameraByScroll(dx: Double, dy: Double) { _mapView.moveCamera(GMSCameraUpdate.scrollBy(x: CGFloat(dx), y: CGFloat(dy))) } - func moveCameraByZoom(zoomBy: Double, focus: CGPoint?) { + public func moveCameraByZoom(zoomBy: Double, focus: CGPoint?) { if focus != nil { _mapView.moveCamera(GMSCameraUpdate.zoom(by: Float(zoomBy), at: focus!)) } else { @@ -370,11 +406,11 @@ class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettledDelega } } - func moveCameraToZoom(zoom: Double) { + public func moveCameraToZoom(zoom: Double) { _mapView.moveCamera(GMSCameraUpdate.zoom(to: Float(zoom))) } - func followMyLocation(perspective: GMSNavigationCameraPerspective, zoomLevel: Double?) { + public func followMyLocation(perspective: GMSNavigationCameraPerspective, zoomLevel: Double?) { _mapView.followingPerspective = perspective _mapView.cameraMode = .following if zoomLevel != nil { @@ -398,9 +434,9 @@ class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettledDelega if navigationWasEnabled != _mapView.isNavigationEnabled { // Navigation UI got enabled, send enabled change event. - _viewEventApi + getViewEventApi()? .onNavigationUIEnabledChanged( - viewId: _viewId, + viewId: _viewId!, navigationUIEnabled: _mapView.isNavigationEnabled ) { _ in } } @@ -485,8 +521,8 @@ class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettledDelega func setNavigationUIEnabled(_ enabled: Bool) { if _mapView.isNavigationEnabled != enabled { _mapView.isNavigationEnabled = enabled - _viewEventApi - .onNavigationUIEnabledChanged(viewId: _viewId, navigationUIEnabled: enabled) { _ in } + getViewEventApi()? + .onNavigationUIEnabledChanged(viewId: _viewId!, navigationUIEnabled: enabled) { _ in } if !enabled { let camera = _mapView.camera @@ -500,19 +536,19 @@ class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettledDelega } } - func getMinZoomPreference() -> Float { + public func getMinZoomPreference() -> Float { _mapView.minZoom } - func getMaxZoomPreference() -> Float { + public func getMaxZoomPreference() -> Float { _mapView.maxZoom } - func resetMinMaxZoomPreference() { + public func resetMinMaxZoomPreference() { _mapView.setMinZoom(kGMSMinZoomLevel, maxZoom: kGMSMaxZoomLevel) } - func setMinZoomPreference(minZoomPreference: Float) throws { + public func setMinZoomPreference(minZoomPreference: Float) throws { if minZoomPreference > _mapView.maxZoom { throw GoogleMapsNavigationViewError.minZoomGreaterThanMaxZoom } @@ -520,7 +556,7 @@ class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettledDelega _mapView.setMinZoom(minZoomPreference, maxZoom: _mapView.maxZoom) } - func setMaxZoomPreference(maxZoomPreference: Float) throws { + public func setMaxZoomPreference(maxZoomPreference: Float) throws { if maxZoomPreference < _mapView.minZoom { throw GoogleMapsNavigationViewError.maxZoomLessThanMinZoom } @@ -745,8 +781,8 @@ class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettledDelega do { let markerController = try findMarkerController(gmsMarker: marker) - _viewEventApi.onMarkerEvent( - viewId: _viewId, + getViewEventApi()?.onMarkerEvent( + viewId: _viewId!, markerId: markerController.markerId, eventType: eventType, completion: { _ in } @@ -760,8 +796,8 @@ class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettledDelega eventType: MarkerDragEventTypeDto) { do { let markerController = try findMarkerController(gmsMarker: marker) - _viewEventApi.onMarkerDragEvent( - viewId: _viewId, + getViewEventApi()?.onMarkerDragEvent( + viewId: _viewId!, markerId: markerController.markerId, eventType: eventType, position: .init( @@ -792,15 +828,15 @@ class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettledDelega } extension GoogleMapsNavigationView: GMSMapViewNavigationUIDelegate { - func mapViewDidTapRecenterButton(_ mapView: GMSMapView) { - _viewEventApi.onRecenterButtonClicked(viewId: _viewId) { _ in } + public func mapViewDidTapRecenterButton(_ mapView: GMSMapView) { + getViewEventApi()?.onRecenterButtonClicked(viewId: _viewId!) { _ in } } } extension GoogleMapsNavigationView: GMSMapViewDelegate { - func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) { - _viewEventApi.onMapClickEvent( - viewId: _viewId, + public func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) { + getViewEventApi()?.onMapClickEvent( + viewId: _viewId!, latLng: .init( latitude: coordinate.latitude, longitude: coordinate.longitude @@ -809,9 +845,9 @@ extension GoogleMapsNavigationView: GMSMapViewDelegate { ) } - func mapView(_ mapView: GMSMapView, didLongPressAt coordinate: CLLocationCoordinate2D) { - _viewEventApi.onMapLongClickEvent( - viewId: _viewId, + public func mapView(_ mapView: GMSMapView, didLongPressAt coordinate: CLLocationCoordinate2D) { + getViewEventApi()?.onMapLongClickEvent( + viewId: _viewId!, latLng: .init( latitude: coordinate.latitude, longitude: coordinate.longitude @@ -820,7 +856,7 @@ extension GoogleMapsNavigationView: GMSMapViewDelegate { ) } - func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool { + public func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool { do { let markerController = try findMarkerController(gmsMarker: marker) sendMarkerEvent(marker: markerController.gmsMarker, eventType: .clicked) @@ -835,66 +871,66 @@ extension GoogleMapsNavigationView: GMSMapViewDelegate { } } - func mapView(_ mapView: GMSMapView, didBeginDragging marker: GMSMarker) { + public func mapView(_ mapView: GMSMapView, didBeginDragging marker: GMSMarker) { sendMarkerDragEvent(marker: marker, eventType: .dragStart) } - func mapView(_ mapView: GMSMapView, didEndDragging marker: GMSMarker) { + public func mapView(_ mapView: GMSMapView, didEndDragging marker: GMSMarker) { sendMarkerDragEvent(marker: marker, eventType: .dragEnd) } - func mapView(_ mapView: GMSMapView, didDrag marker: GMSMarker) { + public func mapView(_ mapView: GMSMapView, didDrag marker: GMSMarker) { sendMarkerDragEvent(marker: marker, eventType: .drag) } - func mapView(_ mapView: GMSMapView, didTapInfoWindowOf marker: GMSMarker) { + public func mapView(_ mapView: GMSMapView, didTapInfoWindowOf marker: GMSMarker) { sendMarkerEvent(marker: marker, eventType: .infoWindowClicked) } - func mapView(_ mapView: GMSMapView, didCloseInfoWindowOf marker: GMSMarker) { + public func mapView(_ mapView: GMSMapView, didCloseInfoWindowOf marker: GMSMarker) { sendMarkerEvent(marker: marker, eventType: .infoWindowClosed) } - func mapView(_ mapView: GMSMapView, didLongPressInfoWindowOf marker: GMSMarker) { + public func mapView(_ mapView: GMSMapView, didLongPressInfoWindowOf marker: GMSMarker) { sendMarkerEvent(marker: marker, eventType: .infoWindowLongClicked) } - func mapView(_ mapView: GMSMapView, didTap overlay: GMSOverlay) { + public func mapView(_ mapView: GMSMapView, didTap overlay: GMSOverlay) { if let polygon = overlay as? GMSPolygon { - _viewEventApi.onPolygonClicked( - viewId: _viewId, + getViewEventApi()?.onPolygonClicked( + viewId: _viewId!, polygonId: polygon.getPolygonId(), completion: { _ in } ) } else if let polyline = overlay as? GMSPolyline { - _viewEventApi.onPolylineClicked( - viewId: _viewId, + getViewEventApi()?.onPolylineClicked( + viewId: _viewId!, polylineId: polyline.getPolylineId(), completion: { _ in } ) } else if let circle = overlay as? GMSCircle { - _viewEventApi.onCircleClicked( - viewId: _viewId, + getViewEventApi()?.onCircleClicked( + viewId: _viewId!, circleId: circle.getCircleId(), completion: { _ in } ) } } - func mapView(_ mapView: GMSMapView, didTapMyLocation location: CLLocationCoordinate2D) { - _viewEventApi.onMyLocationClicked(viewId: _viewId, completion: { _ in }) + public func mapView(_ mapView: GMSMapView, didTapMyLocation location: CLLocationCoordinate2D) { + getViewEventApi()?.onMyLocationClicked(viewId: _viewId!, completion: { _ in }) } - func didTapMyLocationButton(for mapView: GMSMapView) -> Bool { - _viewEventApi.onMyLocationButtonClicked(viewId: _viewId, completion: { _ in }) + public func didTapMyLocationButton(for mapView: GMSMapView) -> Bool { + getViewEventApi()?.onMyLocationButtonClicked(viewId: _viewId!, completion: { _ in }) return _consumeMyLocationButtonClickEventsEnabled } - func mapView(_ mapView: GMSMapView, willMove gesture: Bool) { + public func mapView(_ mapView: GMSMapView, willMove gesture: Bool) { if _listenCameraChanges { let position = Convert.convertCameraPosition(position: mapView.camera) - _viewEventApi.onCameraChanged( - viewId: _viewId, + getViewEventApi()?.onCameraChanged( + viewId: _viewId!, eventType: gesture ? .moveStartedByGesture : .moveStartedByApi, position: position, completion: { _ in } @@ -902,10 +938,10 @@ extension GoogleMapsNavigationView: GMSMapViewDelegate { } } - func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) { + public func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) { if _listenCameraChanges { - _viewEventApi.onCameraChanged( - viewId: _viewId, + getViewEventApi()?.onCameraChanged( + viewId: _viewId!, eventType: .onCameraIdle, position: Convert.convertCameraPosition(position: position), completion: { _ in } @@ -913,10 +949,10 @@ extension GoogleMapsNavigationView: GMSMapViewDelegate { } } - func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) { + public func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) { if _listenCameraChanges { - _viewEventApi.onCameraChanged( - viewId: _viewId, + getViewEventApi()?.onCameraChanged( + viewId: _viewId!, eventType: .onCameraMove, position: Convert.convertCameraPosition(position: position), completion: { _ in } diff --git a/ios/Classes/GoogleMapsNavigationViewFactory.swift b/ios/Classes/GoogleMapsNavigationViewFactory.swift index 52cbc57c..708fe560 100644 --- a/ios/Classes/GoogleMapsNavigationViewFactory.swift +++ b/ios/Classes/GoogleMapsNavigationViewFactory.swift @@ -54,7 +54,8 @@ class GoogleMapsNavigationViewFactory: NSObject, FlutterPlatformViewFactory { .convertNavigationUIEnabledPreference(preference: params.navigationViewOptions? .navigationUIEnabledPreference), mapConfiguration: mapConfiguration, - imageRegistry: imageRegistry + imageRegistry: imageRegistry, + isCarPlayView: false ) } } diff --git a/ios/Classes/GoogleMapsNavigationViewRegistry.swift b/ios/Classes/GoogleMapsNavigationViewRegistry.swift index fbdbb71d..6e6d1699 100644 --- a/ios/Classes/GoogleMapsNavigationViewRegistry.swift +++ b/ios/Classes/GoogleMapsNavigationViewRegistry.swift @@ -14,6 +14,13 @@ class GoogleMapsNavigationViewRegistry { private var views: [Int64: GoogleMapsNavigationView] = [:] + private var carPlayView: GoogleMapsNavigationView? { + didSet { + onHasCarPlayViewChanged?(carPlayView != nil) + } + } + + var onHasCarPlayViewChanged: ((Bool) -> Void)? // Using a concurrent queue with a barrier ensures that write operations are serialized, // meaning each write completes before another write can access the shared resource. // Multiple read operations can still proceed concurrently as long as no write is in progress. @@ -60,4 +67,26 @@ class GoogleMapsNavigationViewRegistry { // Filter the views dictionary to include only those views that are navigation views views.filter { $0.value.isNavigationView() }.map(\.key) } + + func registerCarPlayView(view: GoogleMapsNavigationView) { + queue.async(flags: .barrier) { [weak self] in + DispatchQueue.main.async { + self?.carPlayView = view + } + } + } + + func unregisterCarPlayView() { + queue.async(flags: .barrier) { [weak self] in + DispatchQueue.main.async { + self?.carPlayView = nil + } + } + } + + func getCarPlayView() -> GoogleMapsNavigationView? { + queue.sync { + self.carPlayView + } + } } diff --git a/ios/Classes/MapConfiguration.swift b/ios/Classes/MapConfiguration.swift index dbf328cb..2e9fa2b2 100644 --- a/ios/Classes/MapConfiguration.swift +++ b/ios/Classes/MapConfiguration.swift @@ -26,7 +26,7 @@ enum NavigationUIEnabledPreference { struct MapConfiguration { // MapView related configurations - var cameraPosition: GMSCameraPosition + var cameraPosition: GMSCameraPosition? var mapType: GMSMapViewType var compassEnabled: Bool var rotateGesturesEnabled: Bool @@ -72,6 +72,7 @@ extension MapConfiguration { // // - Parameter to: The GMSMapView to configure. func applyCameraPosition(to mapView: GMSMapView) { + guard let cameraPosition else { return } mapView.camera = cameraPosition } } diff --git a/ios/Classes/messages.g.swift b/ios/Classes/messages.g.swift index 83efdb19..b6071ead 100644 --- a/ios/Classes/messages.g.swift +++ b/ios/Classes/messages.g.swift @@ -5609,6 +5609,1898 @@ class NavigationSessionEventApi: NavigationSessionEventApiProtocol { } } +private class AutoMapViewApiCodecReader: FlutterStandardReader { + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 128: + return CameraPositionDto.fromList(readValue() as! [Any?]) + case 129: + return CircleDto.fromList(readValue() as! [Any?]) + case 130: + return CircleOptionsDto.fromList(readValue() as! [Any?]) + case 131: + return ImageDescriptorDto.fromList(readValue() as! [Any?]) + case 132: + return InfoWindowDto.fromList(readValue() as! [Any?]) + case 133: + return LatLngBoundsDto.fromList(readValue() as! [Any?]) + case 134: + return LatLngDto.fromList(readValue() as! [Any?]) + case 135: + return LatLngDto.fromList(readValue() as! [Any?]) + case 136: + return MarkerAnchorDto.fromList(readValue() as! [Any?]) + case 137: + return MarkerDto.fromList(readValue() as! [Any?]) + case 138: + return MarkerOptionsDto.fromList(readValue() as! [Any?]) + case 139: + return PatternItemDto.fromList(readValue() as! [Any?]) + case 140: + return PolygonDto.fromList(readValue() as! [Any?]) + case 141: + return PolygonHoleDto.fromList(readValue() as! [Any?]) + case 142: + return PolygonOptionsDto.fromList(readValue() as! [Any?]) + case 143: + return PolylineDto.fromList(readValue() as! [Any?]) + case 144: + return PolylineOptionsDto.fromList(readValue() as! [Any?]) + case 145: + return StyleSpanDto.fromList(readValue() as! [Any?]) + case 146: + return StyleSpanStrokeStyleDto.fromList(readValue() as! [Any?]) + default: + return super.readValue(ofType: type) + } + } +} + +private class AutoMapViewApiCodecWriter: FlutterStandardWriter { + override func writeValue(_ value: Any) { + if let value = value as? CameraPositionDto { + super.writeByte(128) + super.writeValue(value.toList()) + } else if let value = value as? CircleDto { + super.writeByte(129) + super.writeValue(value.toList()) + } else if let value = value as? CircleOptionsDto { + super.writeByte(130) + super.writeValue(value.toList()) + } else if let value = value as? ImageDescriptorDto { + super.writeByte(131) + super.writeValue(value.toList()) + } else if let value = value as? InfoWindowDto { + super.writeByte(132) + super.writeValue(value.toList()) + } else if let value = value as? LatLngBoundsDto { + super.writeByte(133) + super.writeValue(value.toList()) + } else if let value = value as? LatLngDto { + super.writeByte(134) + super.writeValue(value.toList()) + } else if let value = value as? LatLngDto { + super.writeByte(135) + super.writeValue(value.toList()) + } else if let value = value as? MarkerAnchorDto { + super.writeByte(136) + super.writeValue(value.toList()) + } else if let value = value as? MarkerDto { + super.writeByte(137) + super.writeValue(value.toList()) + } else if let value = value as? MarkerOptionsDto { + super.writeByte(138) + super.writeValue(value.toList()) + } else if let value = value as? PatternItemDto { + super.writeByte(139) + super.writeValue(value.toList()) + } else if let value = value as? PolygonDto { + super.writeByte(140) + super.writeValue(value.toList()) + } else if let value = value as? PolygonHoleDto { + super.writeByte(141) + super.writeValue(value.toList()) + } else if let value = value as? PolygonOptionsDto { + super.writeByte(142) + super.writeValue(value.toList()) + } else if let value = value as? PolylineDto { + super.writeByte(143) + super.writeValue(value.toList()) + } else if let value = value as? PolylineOptionsDto { + super.writeByte(144) + super.writeValue(value.toList()) + } else if let value = value as? StyleSpanDto { + super.writeByte(145) + super.writeValue(value.toList()) + } else if let value = value as? StyleSpanStrokeStyleDto { + super.writeByte(146) + super.writeValue(value.toList()) + } else { + super.writeValue(value) + } + } +} + +private class AutoMapViewApiCodecReaderWriter: FlutterStandardReaderWriter { + override func reader(with data: Data) -> FlutterStandardReader { + AutoMapViewApiCodecReader(data: data) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + AutoMapViewApiCodecWriter(data: data) + } +} + +class AutoMapViewApiCodec: FlutterStandardMessageCodec { + static let shared = AutoMapViewApiCodec(readerWriter: AutoMapViewApiCodecReaderWriter()) +} + +/// Generated protocol from Pigeon that represents a handler of messages from Flutter. +protocol AutoMapViewApi { + func isMyLocationEnabled() throws -> Bool + func setMyLocationEnabled(enabled: Bool) throws + func getMyLocation() throws -> LatLngDto? + func getMapType() throws -> MapTypeDto + func setMapType(mapType: MapTypeDto) throws + func setMapStyle(styleJson: String) throws + func getCameraPosition() throws -> CameraPositionDto + func getVisibleRegion() throws -> LatLngBoundsDto + func followMyLocation(perspective: CameraPerspectiveDto, zoomLevel: Double?) throws + func animateCameraToCameraPosition(cameraPosition: CameraPositionDto, duration: Int64?, + completion: @escaping (Result) -> Void) + func animateCameraToLatLng(point: LatLngDto, duration: Int64?, + completion: @escaping (Result) -> Void) + func animateCameraToLatLngBounds(bounds: LatLngBoundsDto, padding: Double, duration: Int64?, + completion: @escaping (Result) -> Void) + func animateCameraToLatLngZoom(point: LatLngDto, zoom: Double, duration: Int64?, + completion: @escaping (Result) -> Void) + func animateCameraByScroll(scrollByDx: Double, scrollByDy: Double, duration: Int64?, + completion: @escaping (Result) -> Void) + func animateCameraByZoom(zoomBy: Double, focusDx: Double?, focusDy: Double?, duration: Int64?, + completion: @escaping (Result) -> Void) + func animateCameraToZoom(zoom: Double, duration: Int64?, + completion: @escaping (Result) -> Void) + func moveCameraToCameraPosition(cameraPosition: CameraPositionDto) throws + func moveCameraToLatLng(point: LatLngDto) throws + func moveCameraToLatLngBounds(bounds: LatLngBoundsDto, padding: Double) throws + func moveCameraToLatLngZoom(point: LatLngDto, zoom: Double) throws + func moveCameraByScroll(scrollByDx: Double, scrollByDy: Double) throws + func moveCameraByZoom(zoomBy: Double, focusDx: Double?, focusDy: Double?) throws + func moveCameraToZoom(zoom: Double) throws + func getMinZoomPreference() throws -> Double + func getMaxZoomPreference() throws -> Double + func resetMinMaxZoomPreference() throws + func setMinZoomPreference(minZoomPreference: Double) throws + func setMaxZoomPreference(maxZoomPreference: Double) throws + func setMyLocationButtonEnabled(enabled: Bool) throws + func setConsumeMyLocationButtonClickEventsEnabled(enabled: Bool) throws + func setZoomGesturesEnabled(enabled: Bool) throws + func setZoomControlsEnabled(enabled: Bool) throws + func setCompassEnabled(enabled: Bool) throws + func setRotateGesturesEnabled(enabled: Bool) throws + func setScrollGesturesEnabled(enabled: Bool) throws + func setScrollGesturesDuringRotateOrZoomEnabled(enabled: Bool) throws + func setTiltGesturesEnabled(enabled: Bool) throws + func setMapToolbarEnabled(enabled: Bool) throws + func setTrafficEnabled(enabled: Bool) throws + func isMyLocationButtonEnabled() throws -> Bool + func isConsumeMyLocationButtonClickEventsEnabled() throws -> Bool + func isZoomGesturesEnabled() throws -> Bool + func isZoomControlsEnabled() throws -> Bool + func isCompassEnabled() throws -> Bool + func isRotateGesturesEnabled() throws -> Bool + func isScrollGesturesEnabled() throws -> Bool + func isScrollGesturesEnabledDuringRotateOrZoom() throws -> Bool + func isTiltGesturesEnabled() throws -> Bool + func isMapToolbarEnabled() throws -> Bool + func isTrafficEnabled() throws -> Bool + func getMarkers() throws -> [MarkerDto] + func addMarkers(markers: [MarkerDto]) throws -> [MarkerDto] + func updateMarkers(markers: [MarkerDto]) throws -> [MarkerDto] + func removeMarkers(markers: [MarkerDto]) throws + func clearMarkers() throws + func clear() throws + func getPolygons() throws -> [PolygonDto] + func addPolygons(polygons: [PolygonDto]) throws -> [PolygonDto] + func updatePolygons(polygons: [PolygonDto]) throws -> [PolygonDto] + func removePolygons(polygons: [PolygonDto]) throws + func clearPolygons() throws + func getPolylines() throws -> [PolylineDto] + func addPolylines(polylines: [PolylineDto]) throws -> [PolylineDto] + func updatePolylines(polylines: [PolylineDto]) throws -> [PolylineDto] + func removePolylines(polylines: [PolylineDto]) throws + func clearPolylines() throws + func getCircles() throws -> [CircleDto] + func addCircles(circles: [CircleDto]) throws -> [CircleDto] + func updateCircles(circles: [CircleDto]) throws -> [CircleDto] + func removeCircles(circles: [CircleDto]) throws + func clearCircles() throws + func registerOnCameraChangedListener() throws + func isAutoScreenAvailable() throws -> Bool +} + +/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. +class AutoMapViewApiSetup { + /// The codec used by AutoMapViewApi. + static var codec: FlutterStandardMessageCodec { AutoMapViewApiCodec.shared } + /// Sets up an instance of `AutoMapViewApi` to handle messages through the `binaryMessenger`. + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: AutoMapViewApi?) { + let isMyLocationEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isMyLocationEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + isMyLocationEnabledChannel.setMessageHandler { _, reply in + do { + let result = try api.isMyLocationEnabled() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isMyLocationEnabledChannel.setMessageHandler(nil) + } + let setMyLocationEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMyLocationEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setMyLocationEnabledChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let enabledArg = args[0] as! Bool + do { + try api.setMyLocationEnabled(enabled: enabledArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setMyLocationEnabledChannel.setMessageHandler(nil) + } + let getMyLocationChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMyLocation", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + getMyLocationChannel.setMessageHandler { _, reply in + do { + let result = try api.getMyLocation() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + getMyLocationChannel.setMessageHandler(nil) + } + let getMapTypeChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMapType", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + getMapTypeChannel.setMessageHandler { _, reply in + do { + let result = try api.getMapType() + reply(wrapResult(result.rawValue)) + } catch { + reply(wrapError(error)) + } + } + } else { + getMapTypeChannel.setMessageHandler(nil) + } + let setMapTypeChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMapType", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setMapTypeChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let mapTypeArg = MapTypeDto(rawValue: args[0] as! Int)! + do { + try api.setMapType(mapType: mapTypeArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setMapTypeChannel.setMessageHandler(nil) + } + let setMapStyleChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMapStyle", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setMapStyleChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let styleJsonArg = args[0] as! String + do { + try api.setMapStyle(styleJson: styleJsonArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setMapStyleChannel.setMessageHandler(nil) + } + let getCameraPositionChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getCameraPosition", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + getCameraPositionChannel.setMessageHandler { _, reply in + do { + let result = try api.getCameraPosition() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + getCameraPositionChannel.setMessageHandler(nil) + } + let getVisibleRegionChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getVisibleRegion", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + getVisibleRegionChannel.setMessageHandler { _, reply in + do { + let result = try api.getVisibleRegion() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + getVisibleRegionChannel.setMessageHandler(nil) + } + let followMyLocationChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.followMyLocation", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + followMyLocationChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let perspectiveArg = CameraPerspectiveDto(rawValue: args[0] as! Int)! + let zoomLevelArg: Double? = nilOrValue(args[1]) + do { + try api.followMyLocation(perspective: perspectiveArg, zoomLevel: zoomLevelArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + followMyLocationChannel.setMessageHandler(nil) + } + let animateCameraToCameraPositionChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraToCameraPosition", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + animateCameraToCameraPositionChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let cameraPositionArg = args[0] as! CameraPositionDto + let durationArg: Int64? = isNullish(args[1]) ? nil : + (args[1] is Int64? ? args[1] as! Int64? : Int64(args[1] as! Int32)) + api + .animateCameraToCameraPosition(cameraPosition: cameraPositionArg, + duration: durationArg) { result in + switch result { + case let .success(res): + reply(wrapResult(res)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + animateCameraToCameraPositionChannel.setMessageHandler(nil) + } + let animateCameraToLatLngChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraToLatLng", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + animateCameraToLatLngChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pointArg = args[0] as! LatLngDto + let durationArg: Int64? = isNullish(args[1]) ? nil : + (args[1] is Int64? ? args[1] as! Int64? : Int64(args[1] as! Int32)) + api.animateCameraToLatLng(point: pointArg, duration: durationArg) { result in + switch result { + case let .success(res): + reply(wrapResult(res)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + animateCameraToLatLngChannel.setMessageHandler(nil) + } + let animateCameraToLatLngBoundsChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraToLatLngBounds", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + animateCameraToLatLngBoundsChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let boundsArg = args[0] as! LatLngBoundsDto + let paddingArg = args[1] as! Double + let durationArg: Int64? = isNullish(args[2]) ? nil : + (args[2] is Int64? ? args[2] as! Int64? : Int64(args[2] as! Int32)) + api.animateCameraToLatLngBounds( + bounds: boundsArg, + padding: paddingArg, + duration: durationArg + ) { result in + switch result { + case let .success(res): + reply(wrapResult(res)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + animateCameraToLatLngBoundsChannel.setMessageHandler(nil) + } + let animateCameraToLatLngZoomChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraToLatLngZoom", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + animateCameraToLatLngZoomChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pointArg = args[0] as! LatLngDto + let zoomArg = args[1] as! Double + let durationArg: Int64? = isNullish(args[2]) ? nil : + (args[2] is Int64? ? args[2] as! Int64? : Int64(args[2] as! Int32)) + api + .animateCameraToLatLngZoom(point: pointArg, zoom: zoomArg, + duration: durationArg) { result in + switch result { + case let .success(res): + reply(wrapResult(res)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + animateCameraToLatLngZoomChannel.setMessageHandler(nil) + } + let animateCameraByScrollChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraByScroll", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + animateCameraByScrollChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let scrollByDxArg = args[0] as! Double + let scrollByDyArg = args[1] as! Double + let durationArg: Int64? = isNullish(args[2]) ? nil : + (args[2] is Int64? ? args[2] as! Int64? : Int64(args[2] as! Int32)) + api.animateCameraByScroll( + scrollByDx: scrollByDxArg, + scrollByDy: scrollByDyArg, + duration: durationArg + ) { result in + switch result { + case let .success(res): + reply(wrapResult(res)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + animateCameraByScrollChannel.setMessageHandler(nil) + } + let animateCameraByZoomChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraByZoom", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + animateCameraByZoomChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let zoomByArg = args[0] as! Double + let focusDxArg: Double? = nilOrValue(args[1]) + let focusDyArg: Double? = nilOrValue(args[2]) + let durationArg: Int64? = isNullish(args[3]) ? nil : + (args[3] is Int64? ? args[3] as! Int64? : Int64(args[3] as! Int32)) + api.animateCameraByZoom( + zoomBy: zoomByArg, + focusDx: focusDxArg, + focusDy: focusDyArg, + duration: durationArg + ) { result in + switch result { + case let .success(res): + reply(wrapResult(res)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + animateCameraByZoomChannel.setMessageHandler(nil) + } + let animateCameraToZoomChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraToZoom", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + animateCameraToZoomChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let zoomArg = args[0] as! Double + let durationArg: Int64? = isNullish(args[1]) ? nil : + (args[1] is Int64? ? args[1] as! Int64? : Int64(args[1] as! Int32)) + api.animateCameraToZoom(zoom: zoomArg, duration: durationArg) { result in + switch result { + case let .success(res): + reply(wrapResult(res)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + animateCameraToZoomChannel.setMessageHandler(nil) + } + let moveCameraToCameraPositionChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraToCameraPosition", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + moveCameraToCameraPositionChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let cameraPositionArg = args[0] as! CameraPositionDto + do { + try api.moveCameraToCameraPosition(cameraPosition: cameraPositionArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + moveCameraToCameraPositionChannel.setMessageHandler(nil) + } + let moveCameraToLatLngChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraToLatLng", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + moveCameraToLatLngChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pointArg = args[0] as! LatLngDto + do { + try api.moveCameraToLatLng(point: pointArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + moveCameraToLatLngChannel.setMessageHandler(nil) + } + let moveCameraToLatLngBoundsChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraToLatLngBounds", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + moveCameraToLatLngBoundsChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let boundsArg = args[0] as! LatLngBoundsDto + let paddingArg = args[1] as! Double + do { + try api.moveCameraToLatLngBounds(bounds: boundsArg, padding: paddingArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + moveCameraToLatLngBoundsChannel.setMessageHandler(nil) + } + let moveCameraToLatLngZoomChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraToLatLngZoom", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + moveCameraToLatLngZoomChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pointArg = args[0] as! LatLngDto + let zoomArg = args[1] as! Double + do { + try api.moveCameraToLatLngZoom(point: pointArg, zoom: zoomArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + moveCameraToLatLngZoomChannel.setMessageHandler(nil) + } + let moveCameraByScrollChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraByScroll", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + moveCameraByScrollChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let scrollByDxArg = args[0] as! Double + let scrollByDyArg = args[1] as! Double + do { + try api.moveCameraByScroll(scrollByDx: scrollByDxArg, scrollByDy: scrollByDyArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + moveCameraByScrollChannel.setMessageHandler(nil) + } + let moveCameraByZoomChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraByZoom", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + moveCameraByZoomChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let zoomByArg = args[0] as! Double + let focusDxArg: Double? = nilOrValue(args[1]) + let focusDyArg: Double? = nilOrValue(args[2]) + do { + try api.moveCameraByZoom(zoomBy: zoomByArg, focusDx: focusDxArg, focusDy: focusDyArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + moveCameraByZoomChannel.setMessageHandler(nil) + } + let moveCameraToZoomChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraToZoom", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + moveCameraToZoomChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let zoomArg = args[0] as! Double + do { + try api.moveCameraToZoom(zoom: zoomArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + moveCameraToZoomChannel.setMessageHandler(nil) + } + let getMinZoomPreferenceChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMinZoomPreference", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + getMinZoomPreferenceChannel.setMessageHandler { _, reply in + do { + let result = try api.getMinZoomPreference() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + getMinZoomPreferenceChannel.setMessageHandler(nil) + } + let getMaxZoomPreferenceChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMaxZoomPreference", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + getMaxZoomPreferenceChannel.setMessageHandler { _, reply in + do { + let result = try api.getMaxZoomPreference() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + getMaxZoomPreferenceChannel.setMessageHandler(nil) + } + let resetMinMaxZoomPreferenceChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.resetMinMaxZoomPreference", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + resetMinMaxZoomPreferenceChannel.setMessageHandler { _, reply in + do { + try api.resetMinMaxZoomPreference() + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + resetMinMaxZoomPreferenceChannel.setMessageHandler(nil) + } + let setMinZoomPreferenceChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMinZoomPreference", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setMinZoomPreferenceChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let minZoomPreferenceArg = args[0] as! Double + do { + try api.setMinZoomPreference(minZoomPreference: minZoomPreferenceArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setMinZoomPreferenceChannel.setMessageHandler(nil) + } + let setMaxZoomPreferenceChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMaxZoomPreference", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setMaxZoomPreferenceChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let maxZoomPreferenceArg = args[0] as! Double + do { + try api.setMaxZoomPreference(maxZoomPreference: maxZoomPreferenceArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setMaxZoomPreferenceChannel.setMessageHandler(nil) + } + let setMyLocationButtonEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMyLocationButtonEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setMyLocationButtonEnabledChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let enabledArg = args[0] as! Bool + do { + try api.setMyLocationButtonEnabled(enabled: enabledArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setMyLocationButtonEnabledChannel.setMessageHandler(nil) + } + let setConsumeMyLocationButtonClickEventsEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setConsumeMyLocationButtonClickEventsEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setConsumeMyLocationButtonClickEventsEnabledChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let enabledArg = args[0] as! Bool + do { + try api.setConsumeMyLocationButtonClickEventsEnabled(enabled: enabledArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setConsumeMyLocationButtonClickEventsEnabledChannel.setMessageHandler(nil) + } + let setZoomGesturesEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setZoomGesturesEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setZoomGesturesEnabledChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let enabledArg = args[0] as! Bool + do { + try api.setZoomGesturesEnabled(enabled: enabledArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setZoomGesturesEnabledChannel.setMessageHandler(nil) + } + let setZoomControlsEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setZoomControlsEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setZoomControlsEnabledChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let enabledArg = args[0] as! Bool + do { + try api.setZoomControlsEnabled(enabled: enabledArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setZoomControlsEnabledChannel.setMessageHandler(nil) + } + let setCompassEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setCompassEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setCompassEnabledChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let enabledArg = args[0] as! Bool + do { + try api.setCompassEnabled(enabled: enabledArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setCompassEnabledChannel.setMessageHandler(nil) + } + let setRotateGesturesEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setRotateGesturesEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setRotateGesturesEnabledChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let enabledArg = args[0] as! Bool + do { + try api.setRotateGesturesEnabled(enabled: enabledArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setRotateGesturesEnabledChannel.setMessageHandler(nil) + } + let setScrollGesturesEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setScrollGesturesEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setScrollGesturesEnabledChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let enabledArg = args[0] as! Bool + do { + try api.setScrollGesturesEnabled(enabled: enabledArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setScrollGesturesEnabledChannel.setMessageHandler(nil) + } + let setScrollGesturesDuringRotateOrZoomEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setScrollGesturesDuringRotateOrZoomEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setScrollGesturesDuringRotateOrZoomEnabledChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let enabledArg = args[0] as! Bool + do { + try api.setScrollGesturesDuringRotateOrZoomEnabled(enabled: enabledArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setScrollGesturesDuringRotateOrZoomEnabledChannel.setMessageHandler(nil) + } + let setTiltGesturesEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setTiltGesturesEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setTiltGesturesEnabledChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let enabledArg = args[0] as! Bool + do { + try api.setTiltGesturesEnabled(enabled: enabledArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setTiltGesturesEnabledChannel.setMessageHandler(nil) + } + let setMapToolbarEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMapToolbarEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setMapToolbarEnabledChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let enabledArg = args[0] as! Bool + do { + try api.setMapToolbarEnabled(enabled: enabledArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setMapToolbarEnabledChannel.setMessageHandler(nil) + } + let setTrafficEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setTrafficEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setTrafficEnabledChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let enabledArg = args[0] as! Bool + do { + try api.setTrafficEnabled(enabled: enabledArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setTrafficEnabledChannel.setMessageHandler(nil) + } + let isMyLocationButtonEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isMyLocationButtonEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + isMyLocationButtonEnabledChannel.setMessageHandler { _, reply in + do { + let result = try api.isMyLocationButtonEnabled() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isMyLocationButtonEnabledChannel.setMessageHandler(nil) + } + let isConsumeMyLocationButtonClickEventsEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isConsumeMyLocationButtonClickEventsEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + isConsumeMyLocationButtonClickEventsEnabledChannel.setMessageHandler { _, reply in + do { + let result = try api.isConsumeMyLocationButtonClickEventsEnabled() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isConsumeMyLocationButtonClickEventsEnabledChannel.setMessageHandler(nil) + } + let isZoomGesturesEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isZoomGesturesEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + isZoomGesturesEnabledChannel.setMessageHandler { _, reply in + do { + let result = try api.isZoomGesturesEnabled() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isZoomGesturesEnabledChannel.setMessageHandler(nil) + } + let isZoomControlsEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isZoomControlsEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + isZoomControlsEnabledChannel.setMessageHandler { _, reply in + do { + let result = try api.isZoomControlsEnabled() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isZoomControlsEnabledChannel.setMessageHandler(nil) + } + let isCompassEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isCompassEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + isCompassEnabledChannel.setMessageHandler { _, reply in + do { + let result = try api.isCompassEnabled() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isCompassEnabledChannel.setMessageHandler(nil) + } + let isRotateGesturesEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isRotateGesturesEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + isRotateGesturesEnabledChannel.setMessageHandler { _, reply in + do { + let result = try api.isRotateGesturesEnabled() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isRotateGesturesEnabledChannel.setMessageHandler(nil) + } + let isScrollGesturesEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isScrollGesturesEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + isScrollGesturesEnabledChannel.setMessageHandler { _, reply in + do { + let result = try api.isScrollGesturesEnabled() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isScrollGesturesEnabledChannel.setMessageHandler(nil) + } + let isScrollGesturesEnabledDuringRotateOrZoomChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isScrollGesturesEnabledDuringRotateOrZoom", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + isScrollGesturesEnabledDuringRotateOrZoomChannel.setMessageHandler { _, reply in + do { + let result = try api.isScrollGesturesEnabledDuringRotateOrZoom() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isScrollGesturesEnabledDuringRotateOrZoomChannel.setMessageHandler(nil) + } + let isTiltGesturesEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isTiltGesturesEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + isTiltGesturesEnabledChannel.setMessageHandler { _, reply in + do { + let result = try api.isTiltGesturesEnabled() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isTiltGesturesEnabledChannel.setMessageHandler(nil) + } + let isMapToolbarEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isMapToolbarEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + isMapToolbarEnabledChannel.setMessageHandler { _, reply in + do { + let result = try api.isMapToolbarEnabled() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isMapToolbarEnabledChannel.setMessageHandler(nil) + } + let isTrafficEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isTrafficEnabled", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + isTrafficEnabledChannel.setMessageHandler { _, reply in + do { + let result = try api.isTrafficEnabled() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isTrafficEnabledChannel.setMessageHandler(nil) + } + let getMarkersChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMarkers", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + getMarkersChannel.setMessageHandler { _, reply in + do { + let result = try api.getMarkers() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + getMarkersChannel.setMessageHandler(nil) + } + let addMarkersChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.addMarkers", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + addMarkersChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let markersArg = args[0] as! [MarkerDto] + do { + let result = try api.addMarkers(markers: markersArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + addMarkersChannel.setMessageHandler(nil) + } + let updateMarkersChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.updateMarkers", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + updateMarkersChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let markersArg = args[0] as! [MarkerDto] + do { + let result = try api.updateMarkers(markers: markersArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + updateMarkersChannel.setMessageHandler(nil) + } + let removeMarkersChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.removeMarkers", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + removeMarkersChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let markersArg = args[0] as! [MarkerDto] + do { + try api.removeMarkers(markers: markersArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + removeMarkersChannel.setMessageHandler(nil) + } + let clearMarkersChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.clearMarkers", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + clearMarkersChannel.setMessageHandler { _, reply in + do { + try api.clearMarkers() + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + clearMarkersChannel.setMessageHandler(nil) + } + let clearChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.clear", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + clearChannel.setMessageHandler { _, reply in + do { + try api.clear() + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + clearChannel.setMessageHandler(nil) + } + let getPolygonsChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getPolygons", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + getPolygonsChannel.setMessageHandler { _, reply in + do { + let result = try api.getPolygons() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + getPolygonsChannel.setMessageHandler(nil) + } + let addPolygonsChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.addPolygons", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + addPolygonsChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let polygonsArg = args[0] as! [PolygonDto] + do { + let result = try api.addPolygons(polygons: polygonsArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + addPolygonsChannel.setMessageHandler(nil) + } + let updatePolygonsChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.updatePolygons", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + updatePolygonsChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let polygonsArg = args[0] as! [PolygonDto] + do { + let result = try api.updatePolygons(polygons: polygonsArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + updatePolygonsChannel.setMessageHandler(nil) + } + let removePolygonsChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.removePolygons", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + removePolygonsChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let polygonsArg = args[0] as! [PolygonDto] + do { + try api.removePolygons(polygons: polygonsArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + removePolygonsChannel.setMessageHandler(nil) + } + let clearPolygonsChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.clearPolygons", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + clearPolygonsChannel.setMessageHandler { _, reply in + do { + try api.clearPolygons() + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + clearPolygonsChannel.setMessageHandler(nil) + } + let getPolylinesChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getPolylines", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + getPolylinesChannel.setMessageHandler { _, reply in + do { + let result = try api.getPolylines() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + getPolylinesChannel.setMessageHandler(nil) + } + let addPolylinesChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.addPolylines", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + addPolylinesChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let polylinesArg = args[0] as! [PolylineDto] + do { + let result = try api.addPolylines(polylines: polylinesArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + addPolylinesChannel.setMessageHandler(nil) + } + let updatePolylinesChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.updatePolylines", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + updatePolylinesChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let polylinesArg = args[0] as! [PolylineDto] + do { + let result = try api.updatePolylines(polylines: polylinesArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + updatePolylinesChannel.setMessageHandler(nil) + } + let removePolylinesChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.removePolylines", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + removePolylinesChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let polylinesArg = args[0] as! [PolylineDto] + do { + try api.removePolylines(polylines: polylinesArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + removePolylinesChannel.setMessageHandler(nil) + } + let clearPolylinesChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.clearPolylines", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + clearPolylinesChannel.setMessageHandler { _, reply in + do { + try api.clearPolylines() + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + clearPolylinesChannel.setMessageHandler(nil) + } + let getCirclesChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getCircles", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + getCirclesChannel.setMessageHandler { _, reply in + do { + let result = try api.getCircles() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + getCirclesChannel.setMessageHandler(nil) + } + let addCirclesChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.addCircles", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + addCirclesChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let circlesArg = args[0] as! [CircleDto] + do { + let result = try api.addCircles(circles: circlesArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + addCirclesChannel.setMessageHandler(nil) + } + let updateCirclesChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.updateCircles", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + updateCirclesChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let circlesArg = args[0] as! [CircleDto] + do { + let result = try api.updateCircles(circles: circlesArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + updateCirclesChannel.setMessageHandler(nil) + } + let removeCirclesChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.removeCircles", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + removeCirclesChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let circlesArg = args[0] as! [CircleDto] + do { + try api.removeCircles(circles: circlesArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + removeCirclesChannel.setMessageHandler(nil) + } + let clearCirclesChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.clearCircles", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + clearCirclesChannel.setMessageHandler { _, reply in + do { + try api.clearCircles() + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + clearCirclesChannel.setMessageHandler(nil) + } + let registerOnCameraChangedListenerChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.registerOnCameraChangedListener", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + registerOnCameraChangedListenerChannel.setMessageHandler { _, reply in + do { + try api.registerOnCameraChangedListener() + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + registerOnCameraChangedListenerChannel.setMessageHandler(nil) + } + let isAutoScreenAvailableChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isAutoScreenAvailable", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + isAutoScreenAvailableChannel.setMessageHandler { _, reply in + do { + let result = try api.isAutoScreenAvailable() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isAutoScreenAvailableChannel.setMessageHandler(nil) + } + } +} + +private class AutoViewEventApiCodecReader: FlutterStandardReader { + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 128: + return CameraPositionDto.fromList(readValue() as! [Any?]) + case 129: + return CircleDto.fromList(readValue() as! [Any?]) + case 130: + return CircleOptionsDto.fromList(readValue() as! [Any?]) + case 131: + return DestinationsDto.fromList(readValue() as! [Any?]) + case 132: + return ImageDescriptorDto.fromList(readValue() as! [Any?]) + case 133: + return InfoWindowDto.fromList(readValue() as! [Any?]) + case 134: + return LaneDirectionDto.fromList(readValue() as! [Any?]) + case 135: + return LaneDto.fromList(readValue() as! [Any?]) + case 136: + return LatLngBoundsDto.fromList(readValue() as! [Any?]) + case 137: + return LatLngDto.fromList(readValue() as! [Any?]) + case 138: + return MapOptionsDto.fromList(readValue() as! [Any?]) + case 139: + return MarkerAnchorDto.fromList(readValue() as! [Any?]) + case 140: + return MarkerDto.fromList(readValue() as! [Any?]) + case 141: + return MarkerOptionsDto.fromList(readValue() as! [Any?]) + case 142: + return NavInfoDto.fromList(readValue() as! [Any?]) + case 143: + return NavigationAudioGuidanceSettingsDto.fromList(readValue() as! [Any?]) + case 144: + return NavigationDisplayOptionsDto.fromList(readValue() as! [Any?]) + case 145: + return NavigationTimeAndDistanceDto.fromList(readValue() as! [Any?]) + case 146: + return NavigationViewOptionsDto.fromList(readValue() as! [Any?]) + case 147: + return NavigationWaypointDto.fromList(readValue() as! [Any?]) + case 148: + return PatternItemDto.fromList(readValue() as! [Any?]) + case 149: + return PolygonDto.fromList(readValue() as! [Any?]) + case 150: + return PolygonHoleDto.fromList(readValue() as! [Any?]) + case 151: + return PolygonOptionsDto.fromList(readValue() as! [Any?]) + case 152: + return PolylineDto.fromList(readValue() as! [Any?]) + case 153: + return PolylineOptionsDto.fromList(readValue() as! [Any?]) + case 154: + return RouteSegmentDto.fromList(readValue() as! [Any?]) + case 155: + return RouteSegmentTrafficDataDto.fromList(readValue() as! [Any?]) + case 156: + return RouteSegmentTrafficDataRoadStretchRenderingDataDto.fromList(readValue() as! [Any?]) + case 157: + return RouteTokenOptionsDto.fromList(readValue() as! [Any?]) + case 158: + return RoutingOptionsDto.fromList(readValue() as! [Any?]) + case 159: + return SimulationOptionsDto.fromList(readValue() as! [Any?]) + case 160: + return SpeedAlertOptionsDto.fromList(readValue() as! [Any?]) + case 161: + return SpeedingUpdatedEventDto.fromList(readValue() as! [Any?]) + case 162: + return StepInfoDto.fromList(readValue() as! [Any?]) + case 163: + return StyleSpanDto.fromList(readValue() as! [Any?]) + case 164: + return StyleSpanStrokeStyleDto.fromList(readValue() as! [Any?]) + case 165: + return ViewCreationOptionsDto.fromList(readValue() as! [Any?]) + default: + return super.readValue(ofType: type) + } + } +} + +private class AutoViewEventApiCodecWriter: FlutterStandardWriter { + override func writeValue(_ value: Any) { + if let value = value as? CameraPositionDto { + super.writeByte(128) + super.writeValue(value.toList()) + } else if let value = value as? CircleDto { + super.writeByte(129) + super.writeValue(value.toList()) + } else if let value = value as? CircleOptionsDto { + super.writeByte(130) + super.writeValue(value.toList()) + } else if let value = value as? DestinationsDto { + super.writeByte(131) + super.writeValue(value.toList()) + } else if let value = value as? ImageDescriptorDto { + super.writeByte(132) + super.writeValue(value.toList()) + } else if let value = value as? InfoWindowDto { + super.writeByte(133) + super.writeValue(value.toList()) + } else if let value = value as? LaneDirectionDto { + super.writeByte(134) + super.writeValue(value.toList()) + } else if let value = value as? LaneDto { + super.writeByte(135) + super.writeValue(value.toList()) + } else if let value = value as? LatLngBoundsDto { + super.writeByte(136) + super.writeValue(value.toList()) + } else if let value = value as? LatLngDto { + super.writeByte(137) + super.writeValue(value.toList()) + } else if let value = value as? MapOptionsDto { + super.writeByte(138) + super.writeValue(value.toList()) + } else if let value = value as? MarkerAnchorDto { + super.writeByte(139) + super.writeValue(value.toList()) + } else if let value = value as? MarkerDto { + super.writeByte(140) + super.writeValue(value.toList()) + } else if let value = value as? MarkerOptionsDto { + super.writeByte(141) + super.writeValue(value.toList()) + } else if let value = value as? NavInfoDto { + super.writeByte(142) + super.writeValue(value.toList()) + } else if let value = value as? NavigationAudioGuidanceSettingsDto { + super.writeByte(143) + super.writeValue(value.toList()) + } else if let value = value as? NavigationDisplayOptionsDto { + super.writeByte(144) + super.writeValue(value.toList()) + } else if let value = value as? NavigationTimeAndDistanceDto { + super.writeByte(145) + super.writeValue(value.toList()) + } else if let value = value as? NavigationViewOptionsDto { + super.writeByte(146) + super.writeValue(value.toList()) + } else if let value = value as? NavigationWaypointDto { + super.writeByte(147) + super.writeValue(value.toList()) + } else if let value = value as? PatternItemDto { + super.writeByte(148) + super.writeValue(value.toList()) + } else if let value = value as? PolygonDto { + super.writeByte(149) + super.writeValue(value.toList()) + } else if let value = value as? PolygonHoleDto { + super.writeByte(150) + super.writeValue(value.toList()) + } else if let value = value as? PolygonOptionsDto { + super.writeByte(151) + super.writeValue(value.toList()) + } else if let value = value as? PolylineDto { + super.writeByte(152) + super.writeValue(value.toList()) + } else if let value = value as? PolylineOptionsDto { + super.writeByte(153) + super.writeValue(value.toList()) + } else if let value = value as? RouteSegmentDto { + super.writeByte(154) + super.writeValue(value.toList()) + } else if let value = value as? RouteSegmentTrafficDataDto { + super.writeByte(155) + super.writeValue(value.toList()) + } else if let value = value as? RouteSegmentTrafficDataRoadStretchRenderingDataDto { + super.writeByte(156) + super.writeValue(value.toList()) + } else if let value = value as? RouteTokenOptionsDto { + super.writeByte(157) + super.writeValue(value.toList()) + } else if let value = value as? RoutingOptionsDto { + super.writeByte(158) + super.writeValue(value.toList()) + } else if let value = value as? SimulationOptionsDto { + super.writeByte(159) + super.writeValue(value.toList()) + } else if let value = value as? SpeedAlertOptionsDto { + super.writeByte(160) + super.writeValue(value.toList()) + } else if let value = value as? SpeedingUpdatedEventDto { + super.writeByte(161) + super.writeValue(value.toList()) + } else if let value = value as? StepInfoDto { + super.writeByte(162) + super.writeValue(value.toList()) + } else if let value = value as? StyleSpanDto { + super.writeByte(163) + super.writeValue(value.toList()) + } else if let value = value as? StyleSpanStrokeStyleDto { + super.writeByte(164) + super.writeValue(value.toList()) + } else if let value = value as? ViewCreationOptionsDto { + super.writeByte(165) + super.writeValue(value.toList()) + } else { + super.writeValue(value) + } + } +} + +private class AutoViewEventApiCodecReaderWriter: FlutterStandardReaderWriter { + override func reader(with data: Data) -> FlutterStandardReader { + AutoViewEventApiCodecReader(data: data) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + AutoViewEventApiCodecWriter(data: data) + } +} + +class AutoViewEventApiCodec: FlutterStandardMessageCodec { + static let shared = AutoViewEventApiCodec(readerWriter: AutoViewEventApiCodecReaderWriter()) +} + +/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift. +protocol AutoViewEventApiProtocol { + func onCustomNavigationAutoEvent(event eventArg: String, data dataArg: Any, + completion: @escaping (Result) -> Void) + func onAutoScreenAvailabilityChanged(isAvailable isAvailableArg: Bool, + completion: @escaping (Result) -> Void) +} + +class AutoViewEventApi: AutoViewEventApiProtocol { + private let binaryMessenger: FlutterBinaryMessenger + init(binaryMessenger: FlutterBinaryMessenger) { + self.binaryMessenger = binaryMessenger + } + + var codec: FlutterStandardMessageCodec { + AutoViewEventApiCodec.shared + } + + func onCustomNavigationAutoEvent(event eventArg: String, data dataArg: Any, + completion: @escaping (Result) -> Void) { + let channelName = + "dev.flutter.pigeon.google_navigation_flutter.AutoViewEventApi.onCustomNavigationAutoEvent" + let channel = FlutterBasicMessageChannel( + name: channelName, + binaryMessenger: binaryMessenger, + codec: codec + ) + channel.sendMessage([eventArg, dataArg] 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(FlutterError(code: code, message: message, details: details))) + } else { + completion(.success(())) + } + } + } + + func onAutoScreenAvailabilityChanged(isAvailable isAvailableArg: Bool, + completion: @escaping (Result) -> Void) { + let channelName = + "dev.flutter.pigeon.google_navigation_flutter.AutoViewEventApi.onAutoScreenAvailabilityChanged" + let channel = FlutterBasicMessageChannel( + name: channelName, + binaryMessenger: binaryMessenger, + codec: codec + ) + channel.sendMessage([isAvailableArg] 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(FlutterError(code: code, message: message, details: details))) + } else { + completion(.success(())) + } + } + } +} + /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol NavigationInspector { func isViewAttachedToSession(viewId: Int64) throws -> Bool diff --git a/lib/google_navigation_flutter.dart b/lib/google_navigation_flutter.dart index 61433227..0c209b3a 100644 --- a/lib/google_navigation_flutter.dart +++ b/lib/google_navigation_flutter.dart @@ -22,3 +22,4 @@ export 'src/google_maps_navigation_view.dart'; export 'src/google_maps_map_view.dart'; export 'src/google_maps_map_view_controller.dart'; export 'src/google_maps_navigation_view_controller.dart'; +export 'src/google_maps_auto_view_controller.dart'; diff --git a/lib/src/google_maps_auto_view_controller.dart b/lib/src/google_maps_auto_view_controller.dart new file mode 100644 index 00000000..ae332e7f --- /dev/null +++ b/lib/src/google_maps_auto_view_controller.dart @@ -0,0 +1,349 @@ +// 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 '../google_navigation_flutter.dart'; +import 'google_navigation_flutter_platform_interface.dart'; + +class GoogleMapsAutoViewController { + GoogleMapsAutoViewController() { + GoogleMapsNavigationPlatform.instance.initializeAutoViewEventAPI(); + } + + /// Change status of my location enabled. + /// + Future setMyLocationEnabled(bool enabled) { + return GoogleMapsNavigationPlatform.instance + .setMyLocationEnabledForAuto(enabled: enabled); + } + + /// This method returns the current map type of the Google Maps view instance. + Future getMapType() { + return GoogleMapsNavigationPlatform.instance.getMapTypeForAuto(); + } + + /// Changes the type of the map being displayed on the Google Maps view. + /// + /// The [mapType] parameter specifies the new map type to be set. + /// It should be one of the values defined in the [MapType] enum, + /// such as [MapType.normal], [MapType.satellite], [MapType.terrain], + /// or [MapType.hybrid]. + /// + /// Example usage: + /// ```dart + /// _mapViewController.changeMapType(MapType.satellite); + /// ``` + Future setMapType({required MapType mapType}) async { + return GoogleMapsNavigationPlatform.instance + .setMapTypeForAuto(mapType: mapType); + } + + /// Sets the styling of the base map using a string containing JSON. + /// Null value will reset the base map to default style. + /// If [styleJson] is invalid throws [MapStyleException]. + /// + /// For more details see the official documentation: + /// https://developers.google.com/maps/documentation/ios-sdk/styling + /// https://developers.google.com/maps/documentation/android-sdk/styling + Future setMapStyle(String? styleJson) async { + return GoogleMapsNavigationPlatform.instance.setMapStyleForAuto(styleJson); + } + + /// Gets whether the my location is enabled or disabled. + /// + Future isMyLocationEnabled() async { + return GoogleMapsNavigationPlatform.instance.isMyLocationEnabledForAuto(); + } + + /// Ask the camera to follow the user's location. + /// + /// Use [perspective] to specify the orientation of the camera + /// and optional [zoomLevel] to control the map zoom. + Future followMyLocation(CameraPerspective perspective, + {double? zoomLevel}) async { + return GoogleMapsNavigationPlatform.instance.followMyLocationForAuto( + perspective: perspective, zoomLevel: zoomLevel); + } + + /// Gets user's current location. + Future getMyLocation() async { + return GoogleMapsNavigationPlatform.instance.getMyLocationForAuto(); + } + + /// Gets the current visible map region or camera bounds. + Future getVisibleRegion() async { + return GoogleMapsNavigationPlatform.instance.getVisibleRegionForAuto(); + } + + /// Gets the current position of the camera. + Future getCameraPosition() async { + return GoogleMapsNavigationPlatform.instance.getCameraPositionForAuto(); + } + + /// Animates the movement of the camera from the current position + /// to the position defined in the [cameraUpdate]. + /// + /// See [CameraUpdate] for more information on how to create different camera + /// animations. + /// + /// On Android you can override the default animation [duration] and + /// set [onFinished] callback that is called when the animation completes + /// (passes true) or is cancelled (passes false). + /// + /// Example usage: + /// ```dart + /// controller.animateCamera(CameraUpdate.zoomIn(), + /// duration: Duration(milliseconds: 600), + /// onFinished: (bool success) => {}); + /// ``` + /// On iOS [duration] and [onFinished] are not supported and defining them + /// does nothing. + /// + /// See also [moveCamera], [followMyLocation]. + Future animateCamera(CameraUpdate cameraUpdate, + {Duration? duration, AnimationFinishedCallback? onFinished}) { + return GoogleMapsNavigationPlatform.instance.animateCameraForAuto( + cameraUpdate: cameraUpdate, + duration: duration?.inMilliseconds, + onFinished: onFinished); + } + + /// Moves the camera from the current position to the position + /// defined in the [cameraUpdate]. + /// + /// See [CameraUpdate] for more information + /// on how to create different camera movements. + Future moveCamera(CameraUpdate cameraUpdate) { + return GoogleMapsNavigationPlatform.instance + .moveCameraForAuto(cameraUpdate: cameraUpdate); + } + + /// Returns the minimum zoom level preference from the map view. + /// If minimum zoom preference is not set previously, returns minimum possible + /// zoom level for the current map type. + Future getMinZoomPreference() { + return GoogleMapsNavigationPlatform.instance.getMinZoomPreferenceForAuto(); + } + + /// Returns the maximum zoom level preference from the map view. + /// If maximum zoom preference is not set previously, returns maximum possible + /// zoom level for the current map type. + Future getMaxZoomPreference() { + return GoogleMapsNavigationPlatform.instance.getMaxZoomPreferenceForAuto(); + } + + /// Removes any previously specified upper and lower zoom bounds. + Future resetMinMaxZoomPreference() { + return GoogleMapsNavigationPlatform.instance + .resetMinMaxZoomPreferenceForAuto(); + } + + /// Sets a preferred lower bound for the camera zoom. + /// + /// When the minimum zoom changes, the SDK adjusts all later camera updates + /// to respect that minimum if possible. Note that there are technical + /// considerations that may prevent the SDK from allowing users to zoom too low. + /// + /// Throws [MinZoomRangeException] if [minZoomPreference] is + /// greater than maximum zoom lavel. + Future setMinZoomPreference(double minZoomPreference) { + return GoogleMapsNavigationPlatform.instance + .setMinZoomPreferenceForAuto(minZoomPreference: minZoomPreference); + } + + /// Sets a preferred upper bound for the camera zoom. + /// + /// When the maximum zoom changes, the SDK adjusts all later camera updates + /// to respect that maximum if possible. Note that there are technical + /// considerations that may prevent the SDK from allowing users to zoom too + /// deep into the map. For example, satellite or terrain may have a lower + /// maximum zoom than the base map tiles. + /// + /// Throws [MaxZoomRangeException] if [maxZoomPreference] is + /// less than minimum zoom lavel. + Future setMaxZoomPreference(double maxZoomPreference) { + return GoogleMapsNavigationPlatform.instance + .setMaxZoomPreferenceForAuto(maxZoomPreference: maxZoomPreference); + } + + /// Retrieves all markers that have been added to the map view. + Future> getMarkers() { + return GoogleMapsNavigationPlatform.instance.getMarkersForAuto(); + } + + /// Add markers to the map view. + Future> addMarkers(List markerOptions) { + return GoogleMapsNavigationPlatform.instance + .addMarkersForAuto(markerOptions: markerOptions); + } + + /// Update markers to the map view. + /// + /// Throws [MarkerNotFoundException] if the [markers] list contains one or + /// more markers that have not been added to the map view via [addMarkers] or + /// contains markers that have already been removed from the map view. + Future> updateMarkers(List markers) async { + return GoogleMapsNavigationPlatform.instance + .updateMarkersForAuto(markers: markers); + } + + /// Remove markers from the map view. + /// + /// Throws [MarkerNotFoundException] if the [markers] list contains one or + /// more markers that have not been added to the map view via [addMarkers] or + /// contains markers that have already been removed from the map view. + Future removeMarkers(List markers) async { + return GoogleMapsNavigationPlatform.instance + .removeMarkersForAuto(markers: markers); + } + + /// Remove all markers from the map view. + Future clearMarkers() { + return GoogleMapsNavigationPlatform.instance.clearMarkersForAuto(); + } + + /// Retrieves all polygons that have been added to the map view. + Future> getPolygons() { + return GoogleMapsNavigationPlatform.instance.getPolygonsForAuto(); + } + + /// Add polygons to the map view. + Future> addPolygons(List polygonOptions) { + return GoogleMapsNavigationPlatform.instance + .addPolygonsForAuto(polygonOptions: polygonOptions); + } + + /// Update polygons to the map view. + /// + /// Throws [PolygonNotFoundException] if the [polygons] list contains + /// polygon that has not beed added to the map view via [addPolygons] or + /// contains polygon that has already been removed from the map view. + Future> updatePolygons(List polygons) async { + return GoogleMapsNavigationPlatform.instance + .updatePolygonsForAuto(polygons: polygons); + } + + /// Remove polygons from the map view. + /// + /// Throws [PolygonNotFoundException] if the [polygons] list contains + /// polygon that has not beed added to the map view via [addPolygons] or + /// contains polygon that has already been removed from the map view. + Future removePolygons(List polygons) async { + return GoogleMapsNavigationPlatform.instance + .removePolygonsForAuto(polygons: polygons); + } + + /// Remove all polygons from the map view. + Future clearPolygons() { + return GoogleMapsNavigationPlatform.instance.clearPolygonsForAuto(); + } + + /// Retrieves all polylines that have been added to the map view. + Future> getPolylines() { + return GoogleMapsNavigationPlatform.instance.getPolylinesForAuto(); + } + + /// Add polylines to the map view. + Future> addPolylines(List polylineOptions) { + return GoogleMapsNavigationPlatform.instance + .addPolylinesForAuto(polylineOptions: polylineOptions); + } + + /// Update polylines to the map view. + /// + /// Throws [PolylineNotFoundException] if the [polylines] list contains + /// polyline that has not beed added to the map view via [addPolylines] or + /// contains polyline that has already been removed from the map view. + Future> updatePolylines(List polylines) async { + return GoogleMapsNavigationPlatform.instance + .updatePolylinesForAuto(polylines: polylines); + } + + /// Remove polylines from the map view. + /// + /// Throws [PolylineNotFoundException] if the [polylines] list contains + /// polyline that has not beed added to the map view via [addPolylines] or + /// contains polyline that has already been removed from the map view. + Future removePolylines(List polylines) async { + return GoogleMapsNavigationPlatform.instance + .removePolylinesForAuto(polylines: polylines); + } + + /// Remove all polylines from the map view. + Future clearPolylines() { + return GoogleMapsNavigationPlatform.instance.clearPolylinesForAuto(); + } + + /// Gets all circles from the map view. + Future> getCircles() { + return GoogleMapsNavigationPlatform.instance.getCirclesForAuto(); + } + + /// Add circles to the map view. + Future> addCircles(List options) { + return GoogleMapsNavigationPlatform.instance + .addCirclesForAuto(options: options); + } + + /// Update circles to the map view. + /// + /// Throws [CircleNotFoundException] if the [circles] list contains one or + /// more circles that have not been added to the map view via [addCircles] or + /// contains circles that have already been removed from the map view. + Future> updateCircles(List circles) async { + return GoogleMapsNavigationPlatform.instance + .updateCirclesForAuto(circles: circles); + } + + /// Remove circles from the map view. + /// + /// Throws [CircleNotFoundException] if the [circles] list contains one or + /// more circles that have not been added to the map view via [addCircles] or + /// contains circles that have already been removed from the map view. + Future removeCircles(List circles) async { + return GoogleMapsNavigationPlatform.instance + .removeCirclesForAuto(circles: circles); + } + + /// Remove all circles from the map view. + Future clearCircles() { + return GoogleMapsNavigationPlatform.instance.clearCirclesForAuto(); + } + + /// Remove all markers, polylines, polygons, overlays, etc from the map view. + Future clear() { + return GoogleMapsNavigationPlatform.instance.clearForAuto(); + } + + Future isAutoScreenAvailable() { + return GoogleMapsNavigationPlatform.instance.isAutoScreenAvailable(); + } + + void listenForCustomNavigationAutoEvents( + void Function(CustomNavigationAutoEvent event) func) { + GoogleMapsNavigationPlatform.instance + .getCustomNavigationAutoEventStream() + .listen((CustomNavigationAutoEvent event) { + func(event); + }); + } + + void listenForAutoScreenAvailibilityChangedEvent( + void Function(AutoScreenAvailabilityChangedEvent event) func) { + GoogleMapsNavigationPlatform.instance + .getAutoScreenAvailabilityChangedEventStream() + .listen((AutoScreenAvailabilityChangedEvent event) { + func(event); + }); + } +} diff --git a/lib/src/google_navigation_flutter_android.dart b/lib/src/google_navigation_flutter_android.dart index 49c5b886..d2998b0b 100644 --- a/lib/src/google_navigation_flutter_android.dart +++ b/lib/src/google_navigation_flutter_android.dart @@ -15,6 +15,7 @@ import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; +import 'package:google_navigation_flutter/src/method_channel/common_auto_view_api.dart'; import '../google_navigation_flutter.dart'; import 'google_navigation_flutter_platform_interface.dart'; @@ -25,7 +26,11 @@ import 'method_channel/method_channel.dart'; /// Google Maps Navigation Platform Android specific functionalities. /// @nodoc class GoogleMapsNavigationAndroid extends GoogleMapsNavigationPlatform - with CommonNavigationSessionAPI, CommonMapViewAPI, CommonImageRegistryAPI { + with + CommonNavigationSessionAPI, + CommonMapViewAPI, + CommonAutoMapViewAPI, + CommonImageRegistryAPI { /// Registers the Android implementation of GoogleMapsNavigationPlatform. static void registerWith() { GoogleMapsNavigationPlatform.instance = GoogleMapsNavigationAndroid(); diff --git a/lib/src/google_navigation_flutter_ios.dart b/lib/src/google_navigation_flutter_ios.dart index 8e565134..7630d977 100644 --- a/lib/src/google_navigation_flutter_ios.dart +++ b/lib/src/google_navigation_flutter_ios.dart @@ -14,6 +14,7 @@ import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; +import 'package:google_navigation_flutter/src/method_channel/common_auto_view_api.dart'; import '../google_navigation_flutter.dart'; import 'google_navigation_flutter_platform_interface.dart'; @@ -24,7 +25,11 @@ import 'method_channel/method_channel.dart'; /// Google Maps Navigation Platform iOS specific functionalities. /// @nodoc class GoogleMapsNavigationIOS extends GoogleMapsNavigationPlatform - with CommonNavigationSessionAPI, CommonMapViewAPI, CommonImageRegistryAPI { + with + CommonNavigationSessionAPI, + CommonMapViewAPI, + CommonAutoMapViewAPI, + CommonImageRegistryAPI { /// Registers the iOS implementation of GoogleMapsNavigationPlatform. static void registerWith() { GoogleMapsNavigationPlatform.instance = GoogleMapsNavigationIOS(); diff --git a/lib/src/google_navigation_flutter_platform_interface.dart b/lib/src/google_navigation_flutter_platform_interface.dart index ec7e3da8..288f3f62 100644 --- a/lib/src/google_navigation_flutter_platform_interface.dart +++ b/lib/src/google_navigation_flutter_platform_interface.dart @@ -41,6 +41,7 @@ abstract class GoogleMapsNavigationPlatform extends PlatformInterface with NavigationSessionAPIInterface, MapViewAPIInterface, + AutoMapViewAPIInterface, ImageRegistryAPIInterface { /// Constructs a GoogleMapsNavigationPlatform. GoogleMapsNavigationPlatform() : super(token: _token); @@ -572,6 +573,212 @@ abstract mixin class MapViewAPIInterface { } } +abstract mixin class AutoMapViewAPIInterface { + /// Get the preference for whether the my location should be enabled or disabled. + Future isMyLocationEnabledForAuto(); + + /// Enabled location in the auto map view. + Future setMyLocationEnabledForAuto({required bool enabled}); + + /// Get the map type. + Future getMapTypeForAuto(); + + /// Modified visible map type. + Future setMapTypeForAuto({required MapType mapType}); + + /// Set map style by json string. + Future setMapStyleForAuto(String? styleJson); + + /// Enables or disables the my-location button. + Future setMyLocationButtonEnabledForAuto({required bool enabled}); + + /// Enables or disables if the my location button consumes click events. + Future setConsumeMyLocationButtonClickEventsEnabledForAuto( + {required bool enabled}); + + /// Enables or disables the zoom gestures. + Future setZoomGesturesEnabledForAuto({required bool enabled}); + + /// Enables or disables the zoom controls. + Future setZoomControlsEnabledForAuto({required bool enabled}); + + /// Enables or disables the compass. + Future setCompassEnabledForAuto({required bool enabled}); + + /// Sets the preference for whether rotate gestures should be enabled or disabled. + Future setRotateGesturesEnabledForAuto({required bool enabled}); + + /// Sets the preference for whether scroll gestures should be enabled or disabled. + Future setScrollGesturesEnabledForAuto({required bool enabled}); + + /// Sets the preference for whether scroll gestures can take place at the same time as a zoom or rotate gesture. + Future setScrollGesturesDuringRotateOrZoomEnabledForAuto( + {required bool enabled}); + + /// Sets the preference for whether tilt gestures should be enabled or disabled. + Future setTiltGesturesEnabledForAuto({required bool enabled}); + + /// Sets the preference for whether the Map Toolbar should be enabled or disabled. + Future setMapToolbarEnabledForAuto({required bool enabled}); + + /// Turns the traffic layer on or off. + Future setTrafficEnabledForAuto({required bool enabled}); + + /// Get the preference for whether the my location button should be enabled or disabled. + Future isMyLocationButtonEnabledForAuto(); + + /// Get the preference for whether the my location button consumes click events. + Future isConsumeMyLocationButtonClickEventsEnabledForAuto(); + + /// Gets the preference for whether zoom gestures should be enabled or disabled. + Future isZoomGesturesEnabledForAuto(); + + /// Gets the preference for whether zoom controls should be enabled or disabled. + Future isZoomControlsEnabledForAuto(); + + /// Gets the preference for whether compass should be enabled or disabled. + Future isCompassEnabledForAuto(); + + /// Gets the preference for whether rotate gestures should be enabled or disabled. + Future isRotateGesturesEnabledForAuto(); + + /// Gets the preference for whether scroll gestures should be enabled or disabled. + Future isScrollGesturesEnabledForAuto(); + + /// Gets the preference for whether scroll gestures can take place at the same time as a zoom or rotate gesture. + Future isScrollGesturesEnabledDuringRotateOrZoomForAuto(); + + /// Gets the preference for whether tilt gestures should be enabled or disabled. + Future isTiltGesturesEnabledForAuto(); + + /// Gets whether the Map Toolbar is enabled/disabled. + Future isMapToolbarEnabledForAuto(); + + /// Checks whether the map is drawing traffic data. + Future isTrafficEnabledForAuto(); + + /// Sets the Camera to follow the location of the user. + Future followMyLocationForAuto( + {required CameraPerspective perspective, required double? zoomLevel}); + + /// Gets users current location. + Future getMyLocationForAuto(); + + /// Gets the current position of the camera. + Future getCameraPositionForAuto(); + + /// Gets the current visible area / camera bounds. + Future getVisibleRegionForAuto(); + + /// Animates the movement of the camera. + Future animateCameraForAuto( + {required CameraUpdate cameraUpdate, + required int? duration, + AnimationFinishedCallback? onFinished}); + + /// Moves the camera. + Future moveCameraForAuto({required CameraUpdate cameraUpdate}); + + /// Returns the minimum zoom level. + Future getMinZoomPreferenceForAuto(); + + /// Returns the maximum zoom level for the current camera position. + Future getMaxZoomPreferenceForAuto(); + + /// Removes any previously specified upper and lower zoom bounds. + Future resetMinMaxZoomPreferenceForAuto(); + + /// Sets a preferred lower bound for the camera zoom. + Future setMinZoomPreferenceForAuto({required double minZoomPreference}); + + /// Sets a preferred upper bound for the camera zoom. + Future setMaxZoomPreferenceForAuto({required double maxZoomPreference}); + + /// Get all markers from auto map view. + Future> getMarkersForAuto(); + + /// Add markers to auto map view. + Future> addMarkersForAuto( + {required List markerOptions}); + + /// Update markers on the auto map view. + Future> updateMarkersForAuto({required List markers}); + + /// Remove markers from auto map view. + Future removeMarkersForAuto({required List markers}); + + /// Remove all markers from auto map view. + Future clearMarkersForAuto(); + + /// Removes all markers, polylines, polygons, overlays, etc from the map. + Future clearForAuto(); + + /// Get all polygons from map auto view. + Future> getPolygonsForAuto(); + + /// Add polygons to auto map view. + Future> addPolygonsForAuto( + {required List polygonOptions}); + + /// Update polygons on the auto map view. + Future> updatePolygonsForAuto( + {required List polygons}); + + /// Remove polygons from auto map view. + Future removePolygonsForAuto({required List polygons}); + + /// Remove all polygons from auto map view. + Future clearPolygonsForAuto(); + + /// Get all polylines from auto map view. + Future> getPolylinesForAuto(); + + /// Add polylines to auto map view. + Future> addPolylinesForAuto( + {required List polylineOptions}); + + /// Update polylines on the auto map view. + Future> updatePolylinesForAuto( + {required List polylines}); + + /// Remove polylines from auto map view. + Future removePolylinesForAuto({required List polylines}); + + /// Remove all polylines from auto map view. + Future clearPolylinesForAuto(); + + /// Get all circles from auto map view. + Future> getCirclesForAuto(); + + /// Add circles to auto map view. + Future> addCirclesForAuto( + {required List options}); + + /// Update circles on the auto map view. + Future> updateCirclesForAuto({required List circles}); + + /// Remove circles from auto map view. + Future removeCirclesForAuto({required List circles}); + + /// Remove all circles from auto map view. + Future clearCirclesForAuto(); + + /// Register camera changed listeners. + Future registerOnCameraChangedListenerForAuto(); + + // Check whether auto screen is available; + Future isAutoScreenAvailable(); + + /// Get custom navigation auto event stream from the auto view. + Stream getCustomNavigationAutoEventStream(); + + /// Get auto screen availibility changed event stream from the auto view. + Stream + getAutoScreenAvailabilityChangedEventStream(); + + void initializeAutoViewEventAPI(); +} + /// API interface for actions of the image registry. /// @nodoc abstract mixin class ImageRegistryAPIInterface { diff --git a/lib/src/method_channel/common_auto_view_api.dart b/lib/src/method_channel/common_auto_view_api.dart new file mode 100644 index 00000000..88d70b1c --- /dev/null +++ b/lib/src/method_channel/common_auto_view_api.dart @@ -0,0 +1,788 @@ +// Copyright 2023 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 'dart:async'; +import 'dart:io'; + +import 'package:flutter/services.dart'; + +import '../../google_navigation_flutter.dart'; +import '../google_navigation_flutter_platform_interface.dart'; +import 'method_channel.dart'; + +/// @nodoc +/// Class that handles map view and navigation view communications. +mixin CommonAutoMapViewAPI on AutoMapViewAPIInterface { + final AutoMapViewApi _viewApi = AutoMapViewApi(); + bool _viewApiHasBeenSetUp = false; + final StreamController<_AutoEventWrapper> _autoEventStreamController = + StreamController<_AutoEventWrapper>.broadcast(); + + /// Keep track of marker count, used to generate marker ID's. + int _markerCounter = 0; + String _createMarkerId() { + final String markerId = 'Marker_$_markerCounter'; + _markerCounter += 1; + return markerId; + } + + /// Keep track of polygon count, used to generate polygon ID's. + int _polygonCounter = 0; + String _createPolygonId() { + final String polygonId = 'Polygon_$_polygonCounter'; + _polygonCounter += 1; + return polygonId; + } + + /// Keep track of polyline count, used to generate polyline ID's. + int _polylineCounter = 0; + String _createPolylineId() { + final String polylineId = 'Polyline_$_polylineCounter'; + _polylineCounter += 1; + return polylineId; + } + + /// Keep track of circle count, used to generate circle ID's. + int _circleCounter = 0; + String _createCircleId() { + final String circleId = 'Circle_$_circleCounter'; + _circleCounter += 1; + return circleId; + } + + /// This function ensures that the event API has been setup. This should be + /// called when initializing auto view controller. + @override + void initializeAutoViewEventAPI() { + if (!_viewApiHasBeenSetUp) { + AutoViewEventApi.setup( + AutoViewEventApiImpl( + viewEventStreamController: _autoEventStreamController), + ); + _viewApiHasBeenSetUp = true; + } + } + + @override + Future isMyLocationEnabledForAuto() { + return _viewApi.isMyLocationEnabled(); + } + + @override + Future setMyLocationEnabledForAuto({required bool enabled}) { + return _viewApi.setMyLocationEnabled(enabled); + } + + @override + Future getMapTypeForAuto() async { + final MapTypeDto mapType = await _viewApi.getMapType(); + return mapType.toMapType(); + } + + @override + Future setMapTypeForAuto({required MapType mapType}) async { + return _viewApi.setMapType(mapType.toDto()); + } + + @override + Future setMapStyleForAuto(String? styleJson) async { + try { + // Set the given json to the viewApi or reset the map style if + // the styleJson is null. + return await _viewApi.setMapStyle(styleJson ?? '[]'); + } on PlatformException catch (error) { + if (error.code == 'mapStyleError') { + throw const MapStyleException(); + } else { + rethrow; + } + } + } + + @override + Future setMyLocationButtonEnabledForAuto({required bool enabled}) { + return _viewApi.setMyLocationButtonEnabled(enabled); + } + + @override + Future setConsumeMyLocationButtonClickEventsEnabledForAuto( + {required bool enabled}) async { + return _viewApi.setConsumeMyLocationButtonClickEventsEnabled(enabled); + } + + @override + Future setZoomGesturesEnabledForAuto({required bool enabled}) { + return _viewApi.setZoomGesturesEnabled(enabled); + } + + @override + Future setZoomControlsEnabledForAuto({required bool enabled}) async { + try { + return await _viewApi.setZoomControlsEnabled(enabled); + } on PlatformException catch (error) { + if (error.code == 'notSupported') { + throw UnsupportedError('Zoom controls are not supported on iOS.'); + } else { + rethrow; + } + } + } + + @override + Future setCompassEnabledForAuto({required bool enabled}) { + return _viewApi.setCompassEnabled(enabled); + } + + @override + Future setRotateGesturesEnabledForAuto({required bool enabled}) { + return _viewApi.setRotateGesturesEnabled(enabled); + } + + @override + Future setScrollGesturesEnabledForAuto({required bool enabled}) { + return _viewApi.setScrollGesturesEnabled(enabled); + } + + @override + Future setScrollGesturesDuringRotateOrZoomEnabledForAuto( + {required bool enabled}) { + return _viewApi.setScrollGesturesDuringRotateOrZoomEnabled(enabled); + } + + @override + Future setTiltGesturesEnabledForAuto({required bool enabled}) { + return _viewApi.setTiltGesturesEnabled(enabled); + } + + @override + Future setMapToolbarEnabledForAuto({required bool enabled}) async { + try { + return await _viewApi.setMapToolbarEnabled(enabled); + } on PlatformException catch (error) { + if (error.code == 'notSupported') { + throw UnsupportedError('Map toolbar is not supported on iOS.'); + } else { + rethrow; + } + } + } + + @override + Future setTrafficEnabledForAuto({required bool enabled}) { + return _viewApi.setTrafficEnabled(enabled); + } + + @override + Future isMyLocationButtonEnabledForAuto() { + return _viewApi.isMyLocationButtonEnabled(); + } + + @override + Future isConsumeMyLocationButtonClickEventsEnabledForAuto() { + return _viewApi.isConsumeMyLocationButtonClickEventsEnabled(); + } + + @override + Future isZoomGesturesEnabledForAuto() { + return _viewApi.isZoomGesturesEnabled(); + } + + @override + Future isZoomControlsEnabledForAuto() async { + try { + return await _viewApi.isZoomControlsEnabled(); + } on PlatformException catch (error) { + if (error.code == 'notSupported') { + throw UnsupportedError('Zoom controls are not supported on iOS.'); + } else { + rethrow; + } + } + } + + @override + Future isCompassEnabledForAuto() { + return _viewApi.isCompassEnabled(); + } + + @override + Future isRotateGesturesEnabledForAuto() { + return _viewApi.isRotateGesturesEnabled(); + } + + @override + Future isScrollGesturesEnabledForAuto() { + return _viewApi.isScrollGesturesEnabled(); + } + + @override + Future isScrollGesturesEnabledDuringRotateOrZoomForAuto() { + return _viewApi.isScrollGesturesEnabledDuringRotateOrZoom(); + } + + @override + Future isTiltGesturesEnabledForAuto() { + return _viewApi.isTiltGesturesEnabled(); + } + + @override + Future isMapToolbarEnabledForAuto() async { + try { + return await _viewApi.isMapToolbarEnabled(); + } on PlatformException catch (error) { + if (error.code == 'notSupported') { + throw UnsupportedError('Map toolbar is not supported on iOS.'); + } else { + rethrow; + } + } + } + + @override + Future isTrafficEnabledForAuto() { + return _viewApi.isTrafficEnabled(); + } + + @override + Future followMyLocationForAuto( + {required CameraPerspective perspective, required double? zoomLevel}) { + return _viewApi.followMyLocation(perspective.toDto(), zoomLevel); + } + + @override + Future getMyLocationForAuto() async { + final LatLngDto? myLocation = await _viewApi.getMyLocation(); + if (myLocation == null) { + return null; + } + return myLocation.toLatLng(); + } + + @override + Future getCameraPositionForAuto() async { + final CameraPositionDto position = await _viewApi.getCameraPosition(); + return position.toCameraPosition(); + } + + @override + Future getVisibleRegionForAuto() async { + final LatLngBoundsDto bounds = await _viewApi.getVisibleRegion(); + return LatLngBounds( + southwest: bounds.southwest.toLatLng(), + northeast: bounds.northeast.toLatLng(), + ); + } + + @override + Future animateCameraForAuto( + {required CameraUpdate cameraUpdate, + required int? duration, + AnimationFinishedCallback? onFinished}) async { + switch (cameraUpdate.type) { + case CameraUpdateType.cameraPosition: + unawaited(_viewApi + .animateCameraToCameraPosition( + cameraUpdate.cameraPosition!.toCameraPosition(), duration) + .then((bool success) => onFinished != null && Platform.isAndroid + ? onFinished(success) + : null)); + case CameraUpdateType.latLng: + unawaited(_viewApi + .animateCameraToLatLng(cameraUpdate.latLng!.toDto(), duration) + .then((bool success) => onFinished != null && Platform.isAndroid + ? onFinished(success) + : null)); + case CameraUpdateType.latLngBounds: + unawaited(_viewApi + .animateCameraToLatLngBounds( + cameraUpdate.bounds!.toDto(), cameraUpdate.padding!, duration) + .then((bool success) => onFinished != null && Platform.isAndroid + ? onFinished(success) + : null)); + case CameraUpdateType.latLngZoom: + unawaited(_viewApi + .animateCameraToLatLngZoom( + cameraUpdate.latLng!.toDto(), cameraUpdate.zoom!, duration) + .then((bool success) => onFinished != null && Platform.isAndroid + ? onFinished(success) + : null)); + case CameraUpdateType.scrollBy: + unawaited(_viewApi + .animateCameraByScroll( + cameraUpdate.scrollByDx!, cameraUpdate.scrollByDy!, duration) + .then((bool success) => onFinished != null && Platform.isAndroid + ? onFinished(success) + : null)); + case CameraUpdateType.zoomBy: + unawaited(_viewApi + .animateCameraByZoom(cameraUpdate.zoomByAmount!, + cameraUpdate.focus?.dx, cameraUpdate.focus?.dy, duration) + .then((bool success) => onFinished != null && Platform.isAndroid + ? onFinished(success) + : null)); + case CameraUpdateType.zoomTo: + unawaited(_viewApi + .animateCameraToZoom(cameraUpdate.zoom!, duration) + .then((bool success) => onFinished != null && Platform.isAndroid + ? onFinished(success) + : null)); + } + } + + @override + Future moveCameraForAuto({required CameraUpdate cameraUpdate}) async { + switch (cameraUpdate.type) { + case CameraUpdateType.cameraPosition: + assert(cameraUpdate.cameraPosition != null, 'Camera position is null'); + return _viewApi.moveCameraToCameraPosition( + cameraUpdate.cameraPosition!.toCameraPosition()); + case CameraUpdateType.latLng: + return _viewApi.moveCameraToLatLng(cameraUpdate.latLng!.toDto()); + case CameraUpdateType.latLngBounds: + assert(cameraUpdate.padding != null, 'Camera position is null'); + return _viewApi.moveCameraToLatLngBounds( + cameraUpdate.bounds!.toDto(), cameraUpdate.padding!); + case CameraUpdateType.latLngZoom: + return _viewApi.moveCameraToLatLngZoom( + cameraUpdate.latLng!.toDto(), cameraUpdate.zoom!); + case CameraUpdateType.scrollBy: + return _viewApi.moveCameraByScroll( + cameraUpdate.scrollByDx!, cameraUpdate.scrollByDy!); + case CameraUpdateType.zoomBy: + return _viewApi.moveCameraByZoom(cameraUpdate.zoomByAmount!, + cameraUpdate.focus?.dx, cameraUpdate.focus?.dy); + case CameraUpdateType.zoomTo: + return _viewApi.moveCameraToZoom(cameraUpdate.zoom!); + } + } + + @override + Future getMinZoomPreferenceForAuto() { + return _viewApi.getMinZoomPreference(); + } + + @override + Future getMaxZoomPreferenceForAuto() { + return _viewApi.getMaxZoomPreference(); + } + + @override + Future resetMinMaxZoomPreferenceForAuto() { + return _viewApi.resetMinMaxZoomPreference(); + } + + @override + Future setMinZoomPreferenceForAuto( + {required double minZoomPreference}) async { + try { + return await _viewApi.setMinZoomPreference(minZoomPreference); + } on PlatformException catch (error) { + if (error.code == 'minZoomGreaterThanMaxZoom') { + throw const MinZoomRangeException(); + } else { + rethrow; + } + } + } + + @override + Future setMaxZoomPreferenceForAuto( + {required double maxZoomPreference}) async { + try { + return await _viewApi.setMaxZoomPreference(maxZoomPreference); + } on PlatformException catch (error) { + if (error.code == 'maxZoomLessThanMinZoom') { + throw const MaxZoomRangeException(); + } else { + rethrow; + } + } + } + + @override + Future> getMarkersForAuto() async { + final List markers = await _viewApi.getMarkers(); + return markers + .whereType() + .map((MarkerDto e) => e.toMarker()) + .toList(); + } + + @override + Future> addMarkersForAuto( + {required List markerOptions}) async { + // Convert options to pigeon format + final List options = + markerOptions.map((MarkerOptions opt) => opt.toDto()).toList(); + + // Create marker objects with new ID's + final List markersToAdd = options + .map((MarkerOptionsDto options) => + MarkerDto(markerId: _createMarkerId(), options: options)) + .toList(); + + // Add markers to map + final List markersAdded = + await _viewApi.addMarkers(markersToAdd); + + if (markersToAdd.length != markersAdded.length) { + throw Exception('Could not add all markers to map view'); + } + + return markersAdded + .whereType() + .map((MarkerDto markerDto) => markerDto.toMarker()) + .toList(); + } + + @override + Future> updateMarkersForAuto( + {required List markers}) async { + try { + final List markerDtos = + markers.map((Marker marker) => marker.toDto()).toList(); + final List updatedMarkers = + await _viewApi.updateMarkers(markerDtos); + return updatedMarkers + .whereType() + .map((MarkerDto markerDto) => markerDto.toMarker()) + .toList(); + } on PlatformException catch (error) { + if (error.code == 'markerNotFound') { + throw const MarkerNotFoundException(); + } else { + rethrow; + } + } + } + + @override + Future removeMarkersForAuto({required List markers}) async { + try { + final List markerDtos = + markers.map((Marker marker) => marker.toDto()).toList(); + return await _viewApi.removeMarkers(markerDtos); + } on PlatformException catch (error) { + if (error.code == 'markerNotFound') { + throw const MarkerNotFoundException(); + } else { + rethrow; + } + } + } + + @override + Future clearMarkersForAuto() { + return _viewApi.clearMarkers(); + } + + @override + Future clearForAuto() { + return _viewApi.clear(); + } + + @override + Future> getPolygonsForAuto() async { + final List polygons = await _viewApi.getPolygons(); + + return polygons + .whereType() + .map((PolygonDto polygon) => polygon.toPolygon()) + .toList(); + } + + @override + Future> addPolygonsForAuto( + {required List polygonOptions}) async { + // Convert options to pigeon format + final List options = + polygonOptions.map((PolygonOptions opt) => opt.toDto()).toList(); + + // Create polygon objects with new ID's + final List polygonsToAdd = options + .map((PolygonOptionsDto options) => + PolygonDto(polygonId: _createPolygonId(), options: options)) + .toList(); + + // Add polygons to map + final List polygonsAdded = + await _viewApi.addPolygons(polygonsToAdd); + + if (polygonsToAdd.length != polygonsAdded.length) { + throw Exception('Could not add all polygons to map view'); + } + + return polygonsAdded + .whereType() + .map((PolygonDto polygon) => polygon.toPolygon()) + .toList(); + } + + @override + Future> updatePolygonsForAuto( + {required List polygons}) async { + try { + final List navigationViewPolygons = + polygons.map((Polygon polygon) => polygon.toDto()).toList(); + final List updatedPolygons = + await _viewApi.updatePolygons(navigationViewPolygons); + return updatedPolygons + .whereType() + .map((PolygonDto polygon) => polygon.toPolygon()) + .toList(); + } on PlatformException catch (error) { + if (error.code == 'polygonNotFound') { + throw const PolygonNotFoundException(); + } else { + rethrow; + } + } + } + + @override + Future removePolygonsForAuto({required List polygons}) async { + try { + final List navigationViewPolygons = + polygons.map((Polygon polygon) => polygon.toDto()).toList(); + return await _viewApi.removePolygons(navigationViewPolygons); + } on PlatformException catch (error) { + if (error.code == 'polygonNotFound') { + throw const PolygonNotFoundException(); + } else { + rethrow; + } + } + } + + @override + Future clearPolygonsForAuto() { + return _viewApi.clearPolygons(); + } + + @override + Future> getPolylinesForAuto() async { + final List polylines = await _viewApi.getPolylines(); + + return polylines + .whereType() + .map((PolylineDto polyline) => polyline.toPolyline()) + .toList(); + } + + @override + Future> addPolylinesForAuto( + {required List polylineOptions}) async { + // Convert options to pigeon format + final List options = + polylineOptions.map((PolylineOptions opt) => opt.toDto()).toList(); + + // Create polyline objects with new ID's + final List polylinesToAdd = options + .map((PolylineOptionsDto options) => + PolylineDto(polylineId: _createPolylineId(), options: options)) + .toList(); + + // Add polylines to map + final List polylinesAdded = + await _viewApi.addPolylines(polylinesToAdd); + + if (polylinesToAdd.length != polylinesAdded.length) { + throw Exception('Could not add all polylines to map view'); + } + + return polylinesAdded + .whereType() + .map((PolylineDto polyline) => polyline.toPolyline()) + .toList(); + } + + @override + Future> updatePolylinesForAuto( + {required List polylines}) async { + try { + final List navigationViewPolylines = polylines + .map((Polyline polyline) => polyline.toNavigationViewPolyline()) + .toList(); + final List updatedPolylines = + await _viewApi.updatePolylines(navigationViewPolylines); + return updatedPolylines + .whereType() + .map((PolylineDto polyline) => polyline.toPolyline()) + .toList(); + } on PlatformException catch (error) { + if (error.code == 'polylineNotFound') { + throw const PolylineNotFoundException(); + } else { + rethrow; + } + } + } + + @override + Future removePolylinesForAuto( + {required List polylines}) async { + try { + final List navigationViewPolylines = polylines + .map((Polyline polyline) => polyline.toNavigationViewPolyline()) + .toList(); + return await _viewApi.removePolylines(navigationViewPolylines); + } on PlatformException catch (error) { + if (error.code == 'polylineNotFound') { + throw const PolylineNotFoundException(); + } else { + rethrow; + } + } + } + + @override + Future clearPolylinesForAuto() { + return _viewApi.clearPolylines(); + } + + @override + Future> getCirclesForAuto() async { + final List circles = await _viewApi.getCircles(); + + return circles + .whereType() + .map((CircleDto circle) => circle.toCircle()) + .toList(); + } + + @override + Future> addCirclesForAuto( + {required List options}) async { + // Convert options to pigeon format + final List optionsDto = + options.map((CircleOptions opt) => opt.toDto()).toList(); + + // Create circle objects with new ID's + final List circlesToAdd = optionsDto + .map((CircleOptionsDto options) => + CircleDto(circleId: _createCircleId(), options: options)) + .toList(); + + // Add circles to map + final List circlesAdded = + await _viewApi.addCircles(circlesToAdd); + + if (circlesToAdd.length != circlesAdded.length) { + throw Exception('Could not add all circles to map view'); + } + + return circlesAdded + .whereType() + .map((CircleDto circle) => circle.toCircle()) + .toList(); + } + + @override + Future> updateCirclesForAuto( + {required List circles}) async { + try { + final List navigationViewCircles = + circles.map((Circle circle) => circle.toDto()).toList(); + final List updatedCircles = + await _viewApi.updateCircles(navigationViewCircles); + + return updatedCircles + .whereType() + .map((CircleDto circle) => circle.toCircle()) + .toList(); + } on PlatformException catch (error) { + if (error.code == 'circleNotFound') { + throw const CircleNotFoundException(); + } else { + rethrow; + } + } + } + + @override + Future removeCirclesForAuto({required List circles}) async { + try { + final List navigationViewCircles = + circles.map((Circle circle) => circle.toDto()).toList(); + return await _viewApi.removeCircles(navigationViewCircles); + } on PlatformException catch (error) { + if (error.code == 'circleNotFound') { + throw const CircleNotFoundException(); + } else { + rethrow; + } + } + } + + @override + Future clearCirclesForAuto() { + return _viewApi.clearCircles(); + } + + @override + Future registerOnCameraChangedListenerForAuto() { + return _viewApi.registerOnCameraChangedListener(); + } + + @override + Future isAutoScreenAvailable() { + return _viewApi.isAutoScreenAvailable(); + } + + Stream _unwrapEventStream() { + // If event that does not + return _autoEventStreamController.stream + .where((_AutoEventWrapper wrapper) => (wrapper.event is T)) + .map((_AutoEventWrapper wrapper) => wrapper.event as T); + } + + @override + Stream getCustomNavigationAutoEventStream() { + return _unwrapEventStream(); + } + + @override + Stream + getAutoScreenAvailabilityChangedEventStream() { + return _unwrapEventStream(); + } +} + +class AutoViewEventApiImpl implements AutoViewEventApi { + /// Initialize implementation for NavigationViewEventApi. + const AutoViewEventApiImpl({ + required StreamController viewEventStreamController, + }) : _viewEventStreamController = viewEventStreamController; + + final StreamController _viewEventStreamController; + + @override + void onCustomNavigationAutoEvent(String event, Object data) { + _viewEventStreamController.add( + _AutoEventWrapper(CustomNavigationAutoEvent(event: event, data: data))); + } + + @override + void onAutoScreenAvailabilityChanged(bool isAvailable) { + _viewEventStreamController.add(_AutoEventWrapper( + AutoScreenAvailabilityChangedEvent(isAvailable: isAvailable), + )); + } +} + +class _AutoEventWrapper { + _AutoEventWrapper(this.event); + + final Object event; +} diff --git a/lib/src/method_channel/messages.g.dart b/lib/src/method_channel/messages.g.dart index 8dc9cb0f..6c19dba2 100644 --- a/lib/src/method_channel/messages.g.dart +++ b/lib/src/method_channel/messages.g.dart @@ -6504,6 +6504,2359 @@ abstract class NavigationSessionEventApi { } } +class _AutoMapViewApiCodec extends StandardMessageCodec { + const _AutoMapViewApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is CameraPositionDto) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else if (value is CircleDto) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else if (value is CircleOptionsDto) { + buffer.putUint8(130); + writeValue(buffer, value.encode()); + } else if (value is ImageDescriptorDto) { + buffer.putUint8(131); + writeValue(buffer, value.encode()); + } else if (value is InfoWindowDto) { + buffer.putUint8(132); + writeValue(buffer, value.encode()); + } else if (value is LatLngBoundsDto) { + buffer.putUint8(133); + writeValue(buffer, value.encode()); + } else if (value is LatLngDto) { + buffer.putUint8(134); + writeValue(buffer, value.encode()); + } else if (value is LatLngDto) { + buffer.putUint8(135); + writeValue(buffer, value.encode()); + } else if (value is MarkerAnchorDto) { + buffer.putUint8(136); + writeValue(buffer, value.encode()); + } else if (value is MarkerDto) { + buffer.putUint8(137); + writeValue(buffer, value.encode()); + } else if (value is MarkerOptionsDto) { + buffer.putUint8(138); + writeValue(buffer, value.encode()); + } else if (value is PatternItemDto) { + buffer.putUint8(139); + writeValue(buffer, value.encode()); + } else if (value is PolygonDto) { + buffer.putUint8(140); + writeValue(buffer, value.encode()); + } else if (value is PolygonHoleDto) { + buffer.putUint8(141); + writeValue(buffer, value.encode()); + } else if (value is PolygonOptionsDto) { + buffer.putUint8(142); + writeValue(buffer, value.encode()); + } else if (value is PolylineDto) { + buffer.putUint8(143); + writeValue(buffer, value.encode()); + } else if (value is PolylineOptionsDto) { + buffer.putUint8(144); + writeValue(buffer, value.encode()); + } else if (value is StyleSpanDto) { + buffer.putUint8(145); + writeValue(buffer, value.encode()); + } else if (value is StyleSpanStrokeStyleDto) { + buffer.putUint8(146); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return CameraPositionDto.decode(readValue(buffer)!); + case 129: + return CircleDto.decode(readValue(buffer)!); + case 130: + return CircleOptionsDto.decode(readValue(buffer)!); + case 131: + return ImageDescriptorDto.decode(readValue(buffer)!); + case 132: + return InfoWindowDto.decode(readValue(buffer)!); + case 133: + return LatLngBoundsDto.decode(readValue(buffer)!); + case 134: + return LatLngDto.decode(readValue(buffer)!); + case 135: + return LatLngDto.decode(readValue(buffer)!); + case 136: + return MarkerAnchorDto.decode(readValue(buffer)!); + case 137: + return MarkerDto.decode(readValue(buffer)!); + case 138: + return MarkerOptionsDto.decode(readValue(buffer)!); + case 139: + return PatternItemDto.decode(readValue(buffer)!); + case 140: + return PolygonDto.decode(readValue(buffer)!); + case 141: + return PolygonHoleDto.decode(readValue(buffer)!); + case 142: + return PolygonOptionsDto.decode(readValue(buffer)!); + case 143: + return PolylineDto.decode(readValue(buffer)!); + case 144: + return PolylineOptionsDto.decode(readValue(buffer)!); + case 145: + return StyleSpanDto.decode(readValue(buffer)!); + case 146: + return StyleSpanStrokeStyleDto.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +class AutoMapViewApi { + /// Constructor for [AutoMapViewApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + AutoMapViewApi({BinaryMessenger? binaryMessenger}) + : __pigeon_binaryMessenger = binaryMessenger; + final BinaryMessenger? __pigeon_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = + _AutoMapViewApiCodec(); + + Future isMyLocationEnabled() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isMyLocationEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future setMyLocationEnabled(bool enabled) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMyLocationEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([enabled]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future getMyLocation() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMyLocation'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return (__pigeon_replyList[0] as LatLngDto?); + } + } + + Future getMapType() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMapType'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return MapTypeDto.values[__pigeon_replyList[0]! as int]; + } + } + + Future setMapType(MapTypeDto mapType) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMapType'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([mapType.index]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future setMapStyle(String styleJson) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMapStyle'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([styleJson]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future getCameraPosition() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getCameraPosition'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as CameraPositionDto?)!; + } + } + + Future getVisibleRegion() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getVisibleRegion'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as LatLngBoundsDto?)!; + } + } + + Future followMyLocation( + CameraPerspectiveDto perspective, double? zoomLevel) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.followMyLocation'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([perspective.index, zoomLevel]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future animateCameraToCameraPosition( + CameraPositionDto cameraPosition, int? duration) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraToCameraPosition'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([cameraPosition, duration]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future animateCameraToLatLng(LatLngDto point, int? duration) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraToLatLng'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([point, duration]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future animateCameraToLatLngBounds( + LatLngBoundsDto bounds, double padding, int? duration) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraToLatLngBounds'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([bounds, padding, duration]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future animateCameraToLatLngZoom( + LatLngDto point, double zoom, int? duration) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraToLatLngZoom'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([point, zoom, duration]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future animateCameraByScroll( + double scrollByDx, double scrollByDy, int? duration) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraByScroll'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([scrollByDx, scrollByDy, duration]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future animateCameraByZoom( + double zoomBy, double? focusDx, double? focusDy, int? duration) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraByZoom'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([zoomBy, focusDx, focusDy, duration]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future animateCameraToZoom(double zoom, int? duration) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.animateCameraToZoom'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([zoom, duration]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future moveCameraToCameraPosition( + CameraPositionDto cameraPosition) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraToCameraPosition'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([cameraPosition]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future moveCameraToLatLng(LatLngDto point) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraToLatLng'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([point]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future moveCameraToLatLngBounds( + LatLngBoundsDto bounds, double padding) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraToLatLngBounds'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([bounds, padding]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future moveCameraToLatLngZoom(LatLngDto point, double zoom) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraToLatLngZoom'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([point, zoom]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future moveCameraByScroll(double scrollByDx, double scrollByDy) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraByScroll'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([scrollByDx, scrollByDy]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future moveCameraByZoom( + double zoomBy, double? focusDx, double? focusDy) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraByZoom'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([zoomBy, focusDx, focusDy]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future moveCameraToZoom(double zoom) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.moveCameraToZoom'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([zoom]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future getMinZoomPreference() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMinZoomPreference'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as double?)!; + } + } + + Future getMaxZoomPreference() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMaxZoomPreference'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as double?)!; + } + } + + Future resetMinMaxZoomPreference() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.resetMinMaxZoomPreference'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future setMinZoomPreference(double minZoomPreference) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMinZoomPreference'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([minZoomPreference]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future setMaxZoomPreference(double maxZoomPreference) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMaxZoomPreference'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([maxZoomPreference]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future setMyLocationButtonEnabled(bool enabled) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMyLocationButtonEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([enabled]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future setConsumeMyLocationButtonClickEventsEnabled( + bool enabled) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setConsumeMyLocationButtonClickEventsEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([enabled]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future setZoomGesturesEnabled(bool enabled) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setZoomGesturesEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([enabled]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future setZoomControlsEnabled(bool enabled) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setZoomControlsEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([enabled]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future setCompassEnabled(bool enabled) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setCompassEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([enabled]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future setRotateGesturesEnabled(bool enabled) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setRotateGesturesEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([enabled]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future setScrollGesturesEnabled(bool enabled) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setScrollGesturesEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([enabled]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future setScrollGesturesDuringRotateOrZoomEnabled(bool enabled) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setScrollGesturesDuringRotateOrZoomEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([enabled]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future setTiltGesturesEnabled(bool enabled) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setTiltGesturesEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([enabled]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future setMapToolbarEnabled(bool enabled) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setMapToolbarEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([enabled]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future setTrafficEnabled(bool enabled) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.setTrafficEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([enabled]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future isMyLocationButtonEnabled() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isMyLocationButtonEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future isConsumeMyLocationButtonClickEventsEnabled() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isConsumeMyLocationButtonClickEventsEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future isZoomGesturesEnabled() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isZoomGesturesEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future isZoomControlsEnabled() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isZoomControlsEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future isCompassEnabled() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isCompassEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future isRotateGesturesEnabled() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isRotateGesturesEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future isScrollGesturesEnabled() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isScrollGesturesEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future isScrollGesturesEnabledDuringRotateOrZoom() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isScrollGesturesEnabledDuringRotateOrZoom'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future isTiltGesturesEnabled() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isTiltGesturesEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future isMapToolbarEnabled() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isMapToolbarEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future isTrafficEnabled() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isTrafficEnabled'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future> getMarkers() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getMarkers'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as List?)!.cast(); + } + } + + Future> addMarkers(List markers) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.addMarkers'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([markers]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as List?)!.cast(); + } + } + + Future> updateMarkers(List markers) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.updateMarkers'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([markers]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as List?)!.cast(); + } + } + + Future removeMarkers(List markers) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.removeMarkers'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([markers]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future clearMarkers() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.clearMarkers'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future clear() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.clear'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future> getPolygons() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getPolygons'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as List?)!.cast(); + } + } + + Future> addPolygons(List polygons) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.addPolygons'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([polygons]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as List?)!.cast(); + } + } + + Future> updatePolygons(List polygons) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.updatePolygons'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([polygons]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as List?)!.cast(); + } + } + + Future removePolygons(List polygons) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.removePolygons'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([polygons]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future clearPolygons() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.clearPolygons'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future> getPolylines() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getPolylines'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as List?)!.cast(); + } + } + + Future> addPolylines(List polylines) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.addPolylines'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([polylines]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as List?)!.cast(); + } + } + + Future> updatePolylines( + List polylines) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.updatePolylines'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([polylines]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as List?)!.cast(); + } + } + + Future removePolylines(List polylines) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.removePolylines'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([polylines]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future clearPolylines() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.clearPolylines'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future> getCircles() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.getCircles'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as List?)!.cast(); + } + } + + Future> addCircles(List circles) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.addCircles'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([circles]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as List?)!.cast(); + } + } + + Future> updateCircles(List circles) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.updateCircles'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([circles]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as List?)!.cast(); + } + } + + Future removeCircles(List circles) async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.removeCircles'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([circles]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future clearCircles() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.clearCircles'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future registerOnCameraChangedListener() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.registerOnCameraChangedListener'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future isAutoScreenAvailable() async { + const String __pigeon_channelName = + 'dev.flutter.pigeon.google_navigation_flutter.AutoMapViewApi.isAutoScreenAvailable'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } +} + +class _AutoViewEventApiCodec extends StandardMessageCodec { + const _AutoViewEventApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is CameraPositionDto) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else if (value is CircleDto) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else if (value is CircleOptionsDto) { + buffer.putUint8(130); + writeValue(buffer, value.encode()); + } else if (value is DestinationsDto) { + buffer.putUint8(131); + writeValue(buffer, value.encode()); + } else if (value is ImageDescriptorDto) { + buffer.putUint8(132); + writeValue(buffer, value.encode()); + } else if (value is InfoWindowDto) { + buffer.putUint8(133); + writeValue(buffer, value.encode()); + } else if (value is LaneDirectionDto) { + buffer.putUint8(134); + writeValue(buffer, value.encode()); + } else if (value is LaneDto) { + buffer.putUint8(135); + writeValue(buffer, value.encode()); + } else if (value is LatLngBoundsDto) { + buffer.putUint8(136); + writeValue(buffer, value.encode()); + } else if (value is LatLngDto) { + buffer.putUint8(137); + writeValue(buffer, value.encode()); + } else if (value is MapOptionsDto) { + buffer.putUint8(138); + writeValue(buffer, value.encode()); + } else if (value is MarkerAnchorDto) { + buffer.putUint8(139); + writeValue(buffer, value.encode()); + } else if (value is MarkerDto) { + buffer.putUint8(140); + writeValue(buffer, value.encode()); + } else if (value is MarkerOptionsDto) { + buffer.putUint8(141); + writeValue(buffer, value.encode()); + } else if (value is NavInfoDto) { + buffer.putUint8(142); + writeValue(buffer, value.encode()); + } else if (value is NavigationAudioGuidanceSettingsDto) { + buffer.putUint8(143); + writeValue(buffer, value.encode()); + } else if (value is NavigationDisplayOptionsDto) { + buffer.putUint8(144); + writeValue(buffer, value.encode()); + } else if (value is NavigationTimeAndDistanceDto) { + buffer.putUint8(145); + writeValue(buffer, value.encode()); + } else if (value is NavigationViewOptionsDto) { + buffer.putUint8(146); + writeValue(buffer, value.encode()); + } else if (value is NavigationWaypointDto) { + buffer.putUint8(147); + writeValue(buffer, value.encode()); + } else if (value is PatternItemDto) { + buffer.putUint8(148); + writeValue(buffer, value.encode()); + } else if (value is PolygonDto) { + buffer.putUint8(149); + writeValue(buffer, value.encode()); + } else if (value is PolygonHoleDto) { + buffer.putUint8(150); + writeValue(buffer, value.encode()); + } else if (value is PolygonOptionsDto) { + buffer.putUint8(151); + writeValue(buffer, value.encode()); + } else if (value is PolylineDto) { + buffer.putUint8(152); + writeValue(buffer, value.encode()); + } else if (value is PolylineOptionsDto) { + buffer.putUint8(153); + writeValue(buffer, value.encode()); + } else if (value is RouteSegmentDto) { + buffer.putUint8(154); + writeValue(buffer, value.encode()); + } else if (value is RouteSegmentTrafficDataDto) { + buffer.putUint8(155); + writeValue(buffer, value.encode()); + } else if (value is RouteSegmentTrafficDataRoadStretchRenderingDataDto) { + buffer.putUint8(156); + writeValue(buffer, value.encode()); + } else if (value is RouteTokenOptionsDto) { + buffer.putUint8(157); + writeValue(buffer, value.encode()); + } else if (value is RoutingOptionsDto) { + buffer.putUint8(158); + writeValue(buffer, value.encode()); + } else if (value is SimulationOptionsDto) { + buffer.putUint8(159); + writeValue(buffer, value.encode()); + } else if (value is SpeedAlertOptionsDto) { + buffer.putUint8(160); + writeValue(buffer, value.encode()); + } else if (value is SpeedingUpdatedEventDto) { + buffer.putUint8(161); + writeValue(buffer, value.encode()); + } else if (value is StepInfoDto) { + buffer.putUint8(162); + writeValue(buffer, value.encode()); + } else if (value is StyleSpanDto) { + buffer.putUint8(163); + writeValue(buffer, value.encode()); + } else if (value is StyleSpanStrokeStyleDto) { + buffer.putUint8(164); + writeValue(buffer, value.encode()); + } else if (value is ViewCreationOptionsDto) { + buffer.putUint8(165); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return CameraPositionDto.decode(readValue(buffer)!); + case 129: + return CircleDto.decode(readValue(buffer)!); + case 130: + return CircleOptionsDto.decode(readValue(buffer)!); + case 131: + return DestinationsDto.decode(readValue(buffer)!); + case 132: + return ImageDescriptorDto.decode(readValue(buffer)!); + case 133: + return InfoWindowDto.decode(readValue(buffer)!); + case 134: + return LaneDirectionDto.decode(readValue(buffer)!); + case 135: + return LaneDto.decode(readValue(buffer)!); + case 136: + return LatLngBoundsDto.decode(readValue(buffer)!); + case 137: + return LatLngDto.decode(readValue(buffer)!); + case 138: + return MapOptionsDto.decode(readValue(buffer)!); + case 139: + return MarkerAnchorDto.decode(readValue(buffer)!); + case 140: + return MarkerDto.decode(readValue(buffer)!); + case 141: + return MarkerOptionsDto.decode(readValue(buffer)!); + case 142: + return NavInfoDto.decode(readValue(buffer)!); + case 143: + return NavigationAudioGuidanceSettingsDto.decode(readValue(buffer)!); + case 144: + return NavigationDisplayOptionsDto.decode(readValue(buffer)!); + case 145: + return NavigationTimeAndDistanceDto.decode(readValue(buffer)!); + case 146: + return NavigationViewOptionsDto.decode(readValue(buffer)!); + case 147: + return NavigationWaypointDto.decode(readValue(buffer)!); + case 148: + return PatternItemDto.decode(readValue(buffer)!); + case 149: + return PolygonDto.decode(readValue(buffer)!); + case 150: + return PolygonHoleDto.decode(readValue(buffer)!); + case 151: + return PolygonOptionsDto.decode(readValue(buffer)!); + case 152: + return PolylineDto.decode(readValue(buffer)!); + case 153: + return PolylineOptionsDto.decode(readValue(buffer)!); + case 154: + return RouteSegmentDto.decode(readValue(buffer)!); + case 155: + return RouteSegmentTrafficDataDto.decode(readValue(buffer)!); + case 156: + return RouteSegmentTrafficDataRoadStretchRenderingDataDto.decode( + readValue(buffer)!); + case 157: + return RouteTokenOptionsDto.decode(readValue(buffer)!); + case 158: + return RoutingOptionsDto.decode(readValue(buffer)!); + case 159: + return SimulationOptionsDto.decode(readValue(buffer)!); + case 160: + return SpeedAlertOptionsDto.decode(readValue(buffer)!); + case 161: + return SpeedingUpdatedEventDto.decode(readValue(buffer)!); + case 162: + return StepInfoDto.decode(readValue(buffer)!); + case 163: + return StyleSpanDto.decode(readValue(buffer)!); + case 164: + return StyleSpanStrokeStyleDto.decode(readValue(buffer)!); + case 165: + return ViewCreationOptionsDto.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +abstract class AutoViewEventApi { + static const MessageCodec pigeonChannelCodec = + _AutoViewEventApiCodec(); + + void onCustomNavigationAutoEvent(String event, Object data); + + void onAutoScreenAvailabilityChanged(bool isAvailable); + + static void setup(AutoViewEventApi? api, {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.google_navigation_flutter.AutoViewEventApi.onCustomNavigationAutoEvent', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (api == null) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.google_navigation_flutter.AutoViewEventApi.onCustomNavigationAutoEvent was null.'); + final List args = (message as List?)!; + final String? arg_event = (args[0] as String?); + assert(arg_event != null, + 'Argument for dev.flutter.pigeon.google_navigation_flutter.AutoViewEventApi.onCustomNavigationAutoEvent was null, expected non-null String.'); + final Object? arg_data = (args[1] as Object?); + assert(arg_data != null, + 'Argument for dev.flutter.pigeon.google_navigation_flutter.AutoViewEventApi.onCustomNavigationAutoEvent was null, expected non-null Object.'); + try { + api.onCustomNavigationAutoEvent(arg_event!, arg_data!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.google_navigation_flutter.AutoViewEventApi.onAutoScreenAvailabilityChanged', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (api == null) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.google_navigation_flutter.AutoViewEventApi.onAutoScreenAvailabilityChanged was null.'); + final List args = (message as List?)!; + final bool? arg_isAvailable = (args[0] as bool?); + assert(arg_isAvailable != null, + 'Argument for dev.flutter.pigeon.google_navigation_flutter.AutoViewEventApi.onAutoScreenAvailabilityChanged was null, expected non-null bool.'); + try { + api.onAutoScreenAvailabilityChanged(arg_isAvailable!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } +} + class NavigationInspector { /// Constructor for [NavigationInspector]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default diff --git a/lib/src/navigator/google_navigation_flutter_navigator.dart b/lib/src/navigator/google_navigation_flutter_navigator.dart index 013fd743..518e8c60 100644 --- a/lib/src/navigator/google_navigation_flutter_navigator.dart +++ b/lib/src/navigator/google_navigation_flutter_navigator.dart @@ -534,6 +534,17 @@ class GoogleMapsNavigator { static Future getCurrentRouteSegment() { return GoogleMapsNavigationPlatform.instance.getCurrentRouteSegment(); } + + static Future enableTurnByTurnNavigationEvents( + int? numNextStepsToPreview) { + return GoogleMapsNavigationPlatform.instance + .enableTurnByTurnNavigationEvents(numNextStepsToPreview); + } + + static Future disableTurnByTurnNavigationEvents() { + return GoogleMapsNavigationPlatform.instance + .disableTurnByTurnNavigationEvents(); + } } /// Possible errors that [GoogleMapsNavigator.initializeNavigationSession] can throw. diff --git a/lib/src/types/navigation_view_types.dart b/lib/src/types/navigation_view_types.dart index b4244767..e54e0986 100644 --- a/lib/src/types/navigation_view_types.dart +++ b/lib/src/types/navigation_view_types.dart @@ -88,6 +88,19 @@ enum CameraPerspective { topDownNorthUp } +class CustomNavigationAutoEvent { + final String? event; + final Object? data; + + CustomNavigationAutoEvent({required this.event, required this.data}); +} + +class AutoScreenAvailabilityChangedEvent { + final bool isAvailable; + + AutoScreenAvailabilityChangedEvent({required this.isAvailable}); +} + /// Represents the click position in a Google Maps view. /// {@category Navigation View} /// {@category Map View} diff --git a/pigeons/messages.dart b/pigeons/messages.dart index 78fe5cf3..4e469378 100644 --- a/pigeons/messages.dart +++ b/pigeons/messages.dart @@ -1254,6 +1254,111 @@ abstract class NavigationSessionEventApi { void onNavInfo(NavInfoDto navInfo); } +@HostApi() +abstract class AutoMapViewApi { + bool isMyLocationEnabled(); + void setMyLocationEnabled(bool enabled); + LatLngDto? getMyLocation(); + + MapTypeDto getMapType(); + void setMapType(MapTypeDto mapType); + void setMapStyle(String styleJson); + + CameraPositionDto getCameraPosition(); + LatLngBoundsDto getVisibleRegion(); + + void followMyLocation(CameraPerspectiveDto perspective, double? zoomLevel); + @async + bool animateCameraToCameraPosition( + CameraPositionDto cameraPosition, int? duration); + @async + bool animateCameraToLatLng(LatLngDto point, int? duration); + @async + bool animateCameraToLatLngBounds( + LatLngBoundsDto bounds, double padding, int? duration); + @async + bool animateCameraToLatLngZoom(LatLngDto point, double zoom, int? duration); + @async + bool animateCameraByScroll( + double scrollByDx, double scrollByDy, int? duration); + @async + bool animateCameraByZoom( + double zoomBy, double? focusDx, double? focusDy, int? duration); + @async + bool animateCameraToZoom(double zoom, int? duration); + + void moveCameraToCameraPosition(CameraPositionDto cameraPosition); + void moveCameraToLatLng(LatLngDto point); + void moveCameraToLatLngBounds(LatLngBoundsDto bounds, double padding); + void moveCameraToLatLngZoom(LatLngDto point, double zoom); + void moveCameraByScroll(double scrollByDx, double scrollByDy); + void moveCameraByZoom(double zoomBy, double? focusDx, double? focusDy); + void moveCameraToZoom(double zoom); + double getMinZoomPreference(); + double getMaxZoomPreference(); + void resetMinMaxZoomPreference(); + void setMinZoomPreference(double minZoomPreference); + void setMaxZoomPreference(double maxZoomPreference); + + void setMyLocationButtonEnabled(bool enabled); + void setConsumeMyLocationButtonClickEventsEnabled(bool enabled); + void setZoomGesturesEnabled(bool enabled); + void setZoomControlsEnabled(bool enabled); + void setCompassEnabled(bool enabled); + void setRotateGesturesEnabled(bool enabled); + void setScrollGesturesEnabled(bool enabled); + void setScrollGesturesDuringRotateOrZoomEnabled(bool enabled); + void setTiltGesturesEnabled(bool enabled); + void setMapToolbarEnabled(bool enabled); + void setTrafficEnabled(bool enabled); + + bool isMyLocationButtonEnabled(); + bool isConsumeMyLocationButtonClickEventsEnabled(); + bool isZoomGesturesEnabled(); + bool isZoomControlsEnabled(); + bool isCompassEnabled(); + bool isRotateGesturesEnabled(); + bool isScrollGesturesEnabled(); + bool isScrollGesturesEnabledDuringRotateOrZoom(); + bool isTiltGesturesEnabled(); + bool isMapToolbarEnabled(); + bool isTrafficEnabled(); + + List getMarkers(); + List addMarkers(List markers); + List updateMarkers(List markers); + void removeMarkers(List markers); + void clearMarkers(); + void clear(); + + List getPolygons(); + List addPolygons(List polygons); + List updatePolygons(List polygons); + void removePolygons(List polygons); + void clearPolygons(); + + List getPolylines(); + List addPolylines(List polylines); + List updatePolylines(List polylines); + void removePolylines(List polylines); + void clearPolylines(); + + List getCircles(); + List addCircles(List circles); + List updateCircles(List circles); + void removeCircles(List circles); + void clearCircles(); + + void registerOnCameraChangedListener(); + bool isAutoScreenAvailable(); +} + +@FlutterApi() +abstract class AutoViewEventApi { + void onCustomNavigationAutoEvent(String event, Object data); + void onAutoScreenAvailabilityChanged(bool isAvailable); +} + @HostApi() abstract class NavigationInspector { bool isViewAttachedToSession(int viewId);