From 853c6773177a32be019c55c2ff45c9908196dadd Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Thu, 20 Jun 2024 15:38:10 -0400 Subject: [PATCH] [google_maps_flutter] Move Android inspector to Pigeon (#6958) Converts the inspector API (only intended for use in integration tests) of the Android implementation to Pigeon. This is a small, simple API surface to start the migration with, allowing setting up the basic Pigeon plumbing without major changes. Part of https://github.com/flutter/flutter/issues/117907 --- .../google_maps_flutter_android/CHANGELOG.md | 4 + .../googlemaps/ClusterManagersController.java | 12 +- .../flutter/plugins/googlemaps/Convert.java | 41 +- .../googlemaps/GoogleMapController.java | 211 ++-- .../flutter/plugins/googlemaps/Messages.java | 1015 +++++++++++++++++ .../googlemaps/TileOverlayController.java | 12 +- .../googlemaps/TileOverlaysController.java | 6 +- .../ClusterManagersControllerTest.java | 52 +- .../plugins/googlemaps/ConvertTest.java | 18 +- .../googlemaps/GoogleMapControllerTest.java | 1 + .../lib/src/google_map_inspector_android.dart | 90 +- .../lib/src/google_maps_flutter_android.dart | 29 +- .../lib/src/messages.g.dart | 631 ++++++++++ .../pigeons/copyright.txt | 3 + .../pigeons/messages.dart | 91 ++ .../google_maps_flutter_android/pubspec.yaml | 3 +- 16 files changed, 1994 insertions(+), 225 deletions(-) create mode 100644 packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/Messages.java create mode 100644 packages/google_maps_flutter/google_maps_flutter_android/lib/src/messages.g.dart create mode 100644 packages/google_maps_flutter/google_maps_flutter_android/pigeons/copyright.txt create mode 100644 packages/google_maps_flutter/google_maps_flutter_android/pigeons/messages.dart diff --git a/packages/google_maps_flutter/google_maps_flutter_android/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_android/CHANGELOG.md index f2fcc3cc80e4..24847dd1531c 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.9.1 + +* Converts inspector interface platform calls to Pigeon. + ## 2.9.0 * Adds support for BitmapDescriptor classes `AssetMapBitmap` and `BytesMapBitmap`. diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/ClusterManagersController.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/ClusterManagersController.java index 1c46161df4cb..09ee5d2416f8 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/ClusterManagersController.java +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/ClusterManagersController.java @@ -169,20 +169,16 @@ private static String getClusterManagerId(Object clusterManagerData) { * Requests all current clusters from the algorithm of the requested ClusterManager and converts * them to result response. */ - public void getClustersWithClusterManagerId( - String clusterManagerId, MethodChannel.Result result) { + public @NonNull Set> getClustersWithClusterManagerId( + String clusterManagerId) { ClusterManager clusterManager = clusterManagerIdToManager.get(clusterManagerId); if (clusterManager == null) { - result.error( + throw new Messages.FlutterError( "Invalid clusterManagerId", "getClusters called with invalid clusterManagerId:" + clusterManagerId, null); - return; } - - final Set> clusters = - clusterManager.getAlgorithm().getClusters(googleMap.getCameraPosition().zoom); - result.success(Convert.clustersToJson(clusterManagerId, clusters)); + return clusterManager.getAlgorithm().getClusters(googleMap.getCameraPosition().zoom); } @Override diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/Convert.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/Convert.java index 8b0796207d3c..dee95907724a 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/Convert.java +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/Convert.java @@ -36,7 +36,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; /** Conversions between JSON-like values and GoogleMaps data types. */ class Convert { @@ -377,6 +376,13 @@ static Object latLngBoundsToJson(LatLngBounds latLngBounds) { return arguments; } + static Messages.PlatformLatLngBounds latLngBoundsToPigeon(LatLngBounds latLngBounds) { + return new Messages.PlatformLatLngBounds.Builder() + .setNortheast(latLngToPigeon(latLngBounds.northeast)) + .setSouthwest(latLngToPigeon(latLngBounds.southwest)) + .build(); + } + static Object markerIdToJson(String markerId) { if (markerId == null) { return null; @@ -431,13 +437,11 @@ static Object latLngToJson(LatLng latLng) { return Arrays.asList(latLng.latitude, latLng.longitude); } - static Object clustersToJson( - String clusterManagerId, Set> clusters) { - List data = new ArrayList<>(clusters.size()); - for (Cluster cluster : clusters) { - data.add(clusterToJson(clusterManagerId, cluster)); - } - return data; + static Messages.PlatformLatLng latLngToPigeon(LatLng latLng) { + return new Messages.PlatformLatLng.Builder() + .setLat(latLng.latitude) + .setLng(latLng.longitude) + .build(); } static Object clusterToJson(String clusterManagerId, Cluster cluster) { @@ -470,6 +474,27 @@ static Object clusterToJson(String clusterManagerId, Cluster clus return data; } + static Messages.PlatformCluster clusterToPigeon( + String clusterManagerId, Cluster cluster) { + int clusterSize = cluster.getSize(); + String[] markerIds = new String[clusterSize]; + MarkerBuilder[] markerBuilders = cluster.getItems().toArray(new MarkerBuilder[clusterSize]); + + LatLngBounds.Builder latLngBoundsBuilder = LatLngBounds.builder(); + for (int i = 0; i < clusterSize; i++) { + MarkerBuilder markerBuilder = markerBuilders[i]; + latLngBoundsBuilder.include(markerBuilder.getPosition()); + markerIds[i] = markerBuilder.markerId(); + } + + return new Messages.PlatformCluster.Builder() + .setClusterManagerId(clusterManagerId) + .setPosition(latLngToPigeon(cluster.getPosition())) + .setBounds(latLngBoundsToPigeon(latLngBoundsBuilder.build())) + .setMarkerIds(Arrays.asList(markerIds)) + .build(); + } + static LatLng toLatLng(Object o) { final List data = toList(o); return new LatLng(toDouble(data.get(0)), toDouble(data.get(1))); diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java index 24d66fed24c5..3aab82c6f2f3 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java @@ -4,6 +4,8 @@ package io.flutter.plugins.googlemaps; +import static io.flutter.plugins.googlemaps.Convert.clusterToPigeon; + import android.Manifest; import android.annotation.SuppressLint; import android.content.Context; @@ -38,6 +40,8 @@ import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.Polygon; import com.google.android.gms.maps.model.Polyline; +import com.google.android.gms.maps.model.TileOverlay; +import com.google.maps.android.clustering.Cluster; import com.google.maps.android.clustering.ClusterManager; import com.google.maps.android.collections.MarkerManager; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; @@ -45,6 +49,7 @@ import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.platform.PlatformView; +import io.flutter.plugins.googlemaps.Messages.MapsInspectorApi; import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.Collections; @@ -52,22 +57,25 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; /** Controller of a single GoogleMaps MapView instance. */ class GoogleMapController - implements DefaultLifecycleObserver, - ActivityPluginBinding.OnSaveInstanceStateListener, + implements ActivityPluginBinding.OnSaveInstanceStateListener, + ClusterManager.OnClusterItemClickListener, + ClusterManagersController.OnClusterItemRendered, + DefaultLifecycleObserver, + GoogleMapListener, GoogleMapOptionsSink, + MapsInspectorApi, MethodChannel.MethodCallHandler, OnMapReadyCallback, - GoogleMapListener, - ClusterManager.OnClusterItemClickListener, - ClusterManagersController.OnClusterItemRendered, PlatformView { private static final String TAG = "GoogleMapController"; private final int id; private final MethodChannel methodChannel; + private final BinaryMessenger binaryMessenger; private final GoogleMapOptions options; @Nullable private MapView mapView; @Nullable private GoogleMap googleMap; @@ -113,9 +121,11 @@ class GoogleMapController this.options = options; this.mapView = new MapView(context, options); this.density = context.getResources().getDisplayMetrics().density; + this.binaryMessenger = binaryMessenger; methodChannel = new MethodChannel(binaryMessenger, "plugins.flutter.dev/google_maps_android_" + id); methodChannel.setMethodCallHandler(this); + MapsInspectorApi.setUp(binaryMessenger, Integer.toString(id), this); AssetManager assetManager = context.getAssets(); this.lifecycleProvider = lifecycleProvider; this.clusterManagersController = new ClusterManagersController(methodChannel, context); @@ -132,6 +142,7 @@ class GoogleMapController GoogleMapController( int id, Context context, + BinaryMessenger binaryMessenger, MethodChannel methodChannel, LifecycleProvider lifecycleProvider, GoogleMapOptions options, @@ -143,6 +154,7 @@ class GoogleMapController TileOverlaysController tileOverlaysController) { this.id = id; this.context = context; + this.binaryMessenger = binaryMessenger; this.methodChannel = methodChannel; this.options = options; this.mapView = new MapView(context, options); @@ -184,7 +196,7 @@ private CameraPosition getCameraPosition() { } @Override - public void onMapReady(GoogleMap googleMap) { + public void onMapReady(@NonNull GoogleMap googleMap) { this.googleMap = googleMap; this.googleMap.setIndoorEnabled(this.indoorEnabled); this.googleMap.setTrafficEnabled(this.trafficEnabled); @@ -263,26 +275,28 @@ private void installInvalidator() { final MapView mapView = this.mapView; textureView.setSurfaceTextureListener( new TextureView.SurfaceTextureListener() { - public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { + public void onSurfaceTextureAvailable( + @NonNull SurfaceTexture surface, int width, int height) { if (internalListener != null) { internalListener.onSurfaceTextureAvailable(surface, width, height); } } - public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { + public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) { if (internalListener != null) { return internalListener.onSurfaceTextureDestroyed(surface); } return true; } - public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { + public void onSurfaceTextureSizeChanged( + @NonNull SurfaceTexture surface, int width, int height) { if (internalListener != null) { internalListener.onSurfaceTextureSizeChanged(surface, width, height); } } - public void onSurfaceTextureUpdated(SurfaceTexture surface) { + public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) { if (internalListener != null) { internalListener.onSurfaceTextureUpdated(surface); } @@ -292,7 +306,7 @@ public void onSurfaceTextureUpdated(SurfaceTexture surface) { } @Override - public void onMethodCall(MethodCall call, MethodChannel.Result result) { + public void onMethodCall(MethodCall call, @NonNull MethodChannel.Result result) { switch (call.method) { case "map#waitForMap": if (googleMap != null) { @@ -424,15 +438,6 @@ public void onSnapshotReady(Bitmap bitmap) { result.success(null); break; } - case "clusterManager#getClusters": - { - // The "clusterManagerId" is set in getClusters method at: - // packages/google_maps_flutter/google_maps_flutter_android/lib/src/google_map_inspector_android.dart - Object clusterManagerId = call.argument("clusterManagerId"); - clusterManagersController.getClustersWithClusterManagerId( - (String) clusterManagerId, result); - break; - } case "polygons#update": { List polygonsToAdd = call.argument("polygonsToAdd"); @@ -466,69 +471,6 @@ public void onSnapshotReady(Bitmap bitmap) { result.success(null); break; } - case "map#isCompassEnabled": - { - result.success(googleMap.getUiSettings().isCompassEnabled()); - break; - } - case "map#isMapToolbarEnabled": - { - result.success(googleMap.getUiSettings().isMapToolbarEnabled()); - break; - } - case "map#getMinMaxZoomLevels": - { - List zoomLevels = new ArrayList<>(2); - zoomLevels.add(googleMap.getMinZoomLevel()); - zoomLevels.add(googleMap.getMaxZoomLevel()); - result.success(zoomLevels); - break; - } - case "map#isZoomGesturesEnabled": - { - result.success(googleMap.getUiSettings().isZoomGesturesEnabled()); - break; - } - case "map#isLiteModeEnabled": - { - result.success(options.getLiteMode()); - break; - } - case "map#isZoomControlsEnabled": - { - result.success(googleMap.getUiSettings().isZoomControlsEnabled()); - break; - } - case "map#isScrollGesturesEnabled": - { - result.success(googleMap.getUiSettings().isScrollGesturesEnabled()); - break; - } - case "map#isTiltGesturesEnabled": - { - result.success(googleMap.getUiSettings().isTiltGesturesEnabled()); - break; - } - case "map#isRotateGesturesEnabled": - { - result.success(googleMap.getUiSettings().isRotateGesturesEnabled()); - break; - } - case "map#isMyLocationButtonEnabled": - { - result.success(googleMap.getUiSettings().isMyLocationButtonEnabled()); - break; - } - case "map#isTrafficEnabled": - { - result.success(googleMap.isTrafficEnabled()); - break; - } - case "map#isBuildingsEnabled": - { - result.success(googleMap.isBuildingsEnabled()); - break; - } case "map#getZoomLevel": { result.success(googleMap.getCameraPosition().zoom); @@ -570,26 +512,20 @@ public void onSnapshotReady(Bitmap bitmap) { result.success(null); break; } - case "map#getTileOverlayInfo": - { - String tileOverlayId = call.argument("tileOverlayId"); - result.success(tileOverlaysController.getTileOverlayInfo(tileOverlayId)); - break; - } default: result.notImplemented(); } } @Override - public void onMapClick(LatLng latLng) { + public void onMapClick(@NonNull LatLng latLng) { final Map arguments = new HashMap<>(2); arguments.put("position", Convert.latLngToJson(latLng)); methodChannel.invokeMethod("map#onTap", arguments); } @Override - public void onMapLongClick(LatLng latLng) { + public void onMapLongClick(@NonNull LatLng latLng) { final Map arguments = new HashMap<>(2); arguments.put("position", Convert.latLngToJson(latLng)); methodChannel.invokeMethod("map#onLongPress", arguments); @@ -666,6 +602,7 @@ public void dispose() { } disposed = true; methodChannel.setMethodCallHandler(null); + MapsInspectorApi.setUp(binaryMessenger, Integer.toString(id), null); setGoogleMapListener(null); setMarkerCollectionListener(null); setClusterItemClickListener(null); @@ -786,7 +723,7 @@ public void onRestoreInstanceState(Bundle bundle) { } @Override - public void onSaveInstanceState(Bundle bundle) { + public void onSaveInstanceState(@NonNull Bundle bundle) { if (disposed) { return; } @@ -1052,7 +989,7 @@ public void setBuildingsEnabled(boolean buildingsEnabled) { } @Override - public void onClusterItemRendered(MarkerBuilder markerBuilder, Marker marker) { + public void onClusterItemRendered(@NonNull MarkerBuilder markerBuilder, @NonNull Marker marker) { markersController.onClusterItemRendered(markerBuilder, marker); } @@ -1078,4 +1015,92 @@ private boolean updateMapStyle(String style) { set ? null : "Unable to set the map style. Please check console logs for errors."; return set; } + + @Override + public @NonNull Boolean areBuildingsEnabled() { + return googleMap.isBuildingsEnabled(); + } + + @Override + public @NonNull Boolean areRotateGesturesEnabled() { + return googleMap.getUiSettings().isRotateGesturesEnabled(); + } + + @Override + public @NonNull Boolean areZoomControlsEnabled() { + return googleMap.getUiSettings().isZoomControlsEnabled(); + } + + @Override + public @NonNull Boolean areScrollGesturesEnabled() { + return googleMap.getUiSettings().isScrollGesturesEnabled(); + } + + @Override + public @NonNull Boolean areTiltGesturesEnabled() { + return googleMap.getUiSettings().isTiltGesturesEnabled(); + } + + @Override + public @NonNull Boolean areZoomGesturesEnabled() { + return googleMap.getUiSettings().isZoomGesturesEnabled(); + } + + @Override + public @NonNull Boolean isCompassEnabled() { + return googleMap.getUiSettings().isCompassEnabled(); + } + + @Override + public Boolean isLiteModeEnabled() { + return options.getLiteMode(); + } + + @Override + public @NonNull Boolean isMapToolbarEnabled() { + return googleMap.getUiSettings().isMapToolbarEnabled(); + } + + @Override + public @NonNull Boolean isMyLocationButtonEnabled() { + return googleMap.getUiSettings().isMyLocationButtonEnabled(); + } + + @Override + public @NonNull Boolean isTrafficEnabled() { + return googleMap.isTrafficEnabled(); + } + + @Override + public @Nullable Messages.PlatformTileLayer getTileOverlayInfo(@NonNull String tileOverlayId) { + TileOverlay tileOverlay = tileOverlaysController.getTileOverlay(tileOverlayId); + if (tileOverlay == null) { + return null; + } + return new Messages.PlatformTileLayer.Builder() + .setFadeIn(tileOverlay.getFadeIn()) + .setTransparency((double) tileOverlay.getTransparency()) + .setZIndex((double) tileOverlay.getZIndex()) + .setVisible(tileOverlay.isVisible()) + .build(); + } + + @Override + public @NonNull Messages.PlatformZoomRange getZoomRange() { + return new Messages.PlatformZoomRange.Builder() + .setMin((double) googleMap.getMinZoomLevel()) + .setMax((double) googleMap.getMaxZoomLevel()) + .build(); + } + + @Override + public @NonNull List getClusters(@NonNull String clusterManagerId) { + Set> clusters = + clusterManagersController.getClustersWithClusterManagerId(clusterManagerId); + List data = new ArrayList<>(clusters.size()); + for (Cluster cluster : clusters) { + data.add(clusterToPigeon(clusterManagerId, cluster)); + } + return data; + } } diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/Messages.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/Messages.java new file mode 100644 index 000000000000..4b5b8ad948d1 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/Messages.java @@ -0,0 +1,1015 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v20.0.1), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +package io.flutter.plugins.googlemaps; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.CLASS; + +import android.util.Log; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import io.flutter.plugin.common.BasicMessageChannel; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.MessageCodec; +import io.flutter.plugin.common.StandardMessageCodec; +import java.io.ByteArrayOutputStream; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +/** Generated class from Pigeon. */ +@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"}) +public class Messages { + + /** Error class for passing custom error details to Flutter via a thrown PlatformException. */ + public static class FlutterError extends RuntimeException { + + /** The error code. */ + public final String code; + + /** The error details. Must be a datatype supported by the api codec. */ + public final Object details; + + public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details) { + super(message); + this.code = code; + this.details = details; + } + } + + @NonNull + protected static ArrayList wrapError(@NonNull Throwable exception) { + ArrayList errorList = new ArrayList(3); + if (exception instanceof FlutterError) { + FlutterError error = (FlutterError) exception; + errorList.add(error.code); + errorList.add(error.getMessage()); + errorList.add(error.details); + } else { + errorList.add(exception.toString()); + errorList.add(exception.getClass().getSimpleName()); + errorList.add( + "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception)); + } + return errorList; + } + + @Target(METHOD) + @Retention(CLASS) + @interface CanIgnoreReturnValue {} + + /** + * Pigeon equivalent of LatLng. + * + *

Generated class from Pigeon that represents data sent in messages. + */ + public static final class PlatformLatLng { + private @NonNull Double lat; + + public @NonNull Double getLat() { + return lat; + } + + public void setLat(@NonNull Double setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"lat\" is null."); + } + this.lat = setterArg; + } + + private @NonNull Double lng; + + public @NonNull Double getLng() { + return lng; + } + + public void setLng(@NonNull Double setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"lng\" is null."); + } + this.lng = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PlatformLatLng() {} + + public static final class Builder { + + private @Nullable Double lat; + + @CanIgnoreReturnValue + public @NonNull Builder setLat(@NonNull Double setterArg) { + this.lat = setterArg; + return this; + } + + private @Nullable Double lng; + + @CanIgnoreReturnValue + public @NonNull Builder setLng(@NonNull Double setterArg) { + this.lng = setterArg; + return this; + } + + public @NonNull PlatformLatLng build() { + PlatformLatLng pigeonReturn = new PlatformLatLng(); + pigeonReturn.setLat(lat); + pigeonReturn.setLng(lng); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(2); + toListResult.add(lat); + toListResult.add(lng); + return toListResult; + } + + static @NonNull PlatformLatLng fromList(@NonNull ArrayList __pigeon_list) { + PlatformLatLng pigeonResult = new PlatformLatLng(); + Object lat = __pigeon_list.get(0); + pigeonResult.setLat((Double) lat); + Object lng = __pigeon_list.get(1); + pigeonResult.setLng((Double) lng); + return pigeonResult; + } + } + + /** + * Pigeon equivalent of LatLngBounds. + * + *

Generated class from Pigeon that represents data sent in messages. + */ + public static final class PlatformLatLngBounds { + private @NonNull PlatformLatLng northeast; + + public @NonNull PlatformLatLng getNortheast() { + return northeast; + } + + public void setNortheast(@NonNull PlatformLatLng setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"northeast\" is null."); + } + this.northeast = setterArg; + } + + private @NonNull PlatformLatLng southwest; + + public @NonNull PlatformLatLng getSouthwest() { + return southwest; + } + + public void setSouthwest(@NonNull PlatformLatLng setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"southwest\" is null."); + } + this.southwest = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PlatformLatLngBounds() {} + + public static final class Builder { + + private @Nullable PlatformLatLng northeast; + + @CanIgnoreReturnValue + public @NonNull Builder setNortheast(@NonNull PlatformLatLng setterArg) { + this.northeast = setterArg; + return this; + } + + private @Nullable PlatformLatLng southwest; + + @CanIgnoreReturnValue + public @NonNull Builder setSouthwest(@NonNull PlatformLatLng setterArg) { + this.southwest = setterArg; + return this; + } + + public @NonNull PlatformLatLngBounds build() { + PlatformLatLngBounds pigeonReturn = new PlatformLatLngBounds(); + pigeonReturn.setNortheast(northeast); + pigeonReturn.setSouthwest(southwest); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(2); + toListResult.add(northeast); + toListResult.add(southwest); + return toListResult; + } + + static @NonNull PlatformLatLngBounds fromList(@NonNull ArrayList __pigeon_list) { + PlatformLatLngBounds pigeonResult = new PlatformLatLngBounds(); + Object northeast = __pigeon_list.get(0); + pigeonResult.setNortheast((PlatformLatLng) northeast); + Object southwest = __pigeon_list.get(1); + pigeonResult.setSouthwest((PlatformLatLng) southwest); + return pigeonResult; + } + } + + /** + * Pigeon equivalent of Cluster. + * + *

Generated class from Pigeon that represents data sent in messages. + */ + public static final class PlatformCluster { + private @NonNull String clusterManagerId; + + public @NonNull String getClusterManagerId() { + return clusterManagerId; + } + + public void setClusterManagerId(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"clusterManagerId\" is null."); + } + this.clusterManagerId = setterArg; + } + + private @NonNull PlatformLatLng position; + + public @NonNull PlatformLatLng getPosition() { + return position; + } + + public void setPosition(@NonNull PlatformLatLng setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"position\" is null."); + } + this.position = setterArg; + } + + private @NonNull PlatformLatLngBounds bounds; + + public @NonNull PlatformLatLngBounds getBounds() { + return bounds; + } + + public void setBounds(@NonNull PlatformLatLngBounds setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"bounds\" is null."); + } + this.bounds = setterArg; + } + + private @NonNull List markerIds; + + public @NonNull List getMarkerIds() { + return markerIds; + } + + public void setMarkerIds(@NonNull List setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"markerIds\" is null."); + } + this.markerIds = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PlatformCluster() {} + + public static final class Builder { + + private @Nullable String clusterManagerId; + + @CanIgnoreReturnValue + public @NonNull Builder setClusterManagerId(@NonNull String setterArg) { + this.clusterManagerId = setterArg; + return this; + } + + private @Nullable PlatformLatLng position; + + @CanIgnoreReturnValue + public @NonNull Builder setPosition(@NonNull PlatformLatLng setterArg) { + this.position = setterArg; + return this; + } + + private @Nullable PlatformLatLngBounds bounds; + + @CanIgnoreReturnValue + public @NonNull Builder setBounds(@NonNull PlatformLatLngBounds setterArg) { + this.bounds = setterArg; + return this; + } + + private @Nullable List markerIds; + + @CanIgnoreReturnValue + public @NonNull Builder setMarkerIds(@NonNull List setterArg) { + this.markerIds = setterArg; + return this; + } + + public @NonNull PlatformCluster build() { + PlatformCluster pigeonReturn = new PlatformCluster(); + pigeonReturn.setClusterManagerId(clusterManagerId); + pigeonReturn.setPosition(position); + pigeonReturn.setBounds(bounds); + pigeonReturn.setMarkerIds(markerIds); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(4); + toListResult.add(clusterManagerId); + toListResult.add(position); + toListResult.add(bounds); + toListResult.add(markerIds); + return toListResult; + } + + static @NonNull PlatformCluster fromList(@NonNull ArrayList __pigeon_list) { + PlatformCluster pigeonResult = new PlatformCluster(); + Object clusterManagerId = __pigeon_list.get(0); + pigeonResult.setClusterManagerId((String) clusterManagerId); + Object position = __pigeon_list.get(1); + pigeonResult.setPosition((PlatformLatLng) position); + Object bounds = __pigeon_list.get(2); + pigeonResult.setBounds((PlatformLatLngBounds) bounds); + Object markerIds = __pigeon_list.get(3); + pigeonResult.setMarkerIds((List) markerIds); + return pigeonResult; + } + } + + /** + * Pigeon equivalent of native TileOverlay properties. + * + *

Generated class from Pigeon that represents data sent in messages. + */ + public static final class PlatformTileLayer { + private @NonNull Boolean visible; + + public @NonNull Boolean getVisible() { + return visible; + } + + public void setVisible(@NonNull Boolean setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"visible\" is null."); + } + this.visible = setterArg; + } + + private @NonNull Boolean fadeIn; + + public @NonNull Boolean getFadeIn() { + return fadeIn; + } + + public void setFadeIn(@NonNull Boolean setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"fadeIn\" is null."); + } + this.fadeIn = setterArg; + } + + private @NonNull Double transparency; + + public @NonNull Double getTransparency() { + return transparency; + } + + public void setTransparency(@NonNull Double setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"transparency\" is null."); + } + this.transparency = setterArg; + } + + private @NonNull Double zIndex; + + public @NonNull Double getZIndex() { + return zIndex; + } + + public void setZIndex(@NonNull Double setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"zIndex\" is null."); + } + this.zIndex = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PlatformTileLayer() {} + + public static final class Builder { + + private @Nullable Boolean visible; + + @CanIgnoreReturnValue + public @NonNull Builder setVisible(@NonNull Boolean setterArg) { + this.visible = setterArg; + return this; + } + + private @Nullable Boolean fadeIn; + + @CanIgnoreReturnValue + public @NonNull Builder setFadeIn(@NonNull Boolean setterArg) { + this.fadeIn = setterArg; + return this; + } + + private @Nullable Double transparency; + + @CanIgnoreReturnValue + public @NonNull Builder setTransparency(@NonNull Double setterArg) { + this.transparency = setterArg; + return this; + } + + private @Nullable Double zIndex; + + @CanIgnoreReturnValue + public @NonNull Builder setZIndex(@NonNull Double setterArg) { + this.zIndex = setterArg; + return this; + } + + public @NonNull PlatformTileLayer build() { + PlatformTileLayer pigeonReturn = new PlatformTileLayer(); + pigeonReturn.setVisible(visible); + pigeonReturn.setFadeIn(fadeIn); + pigeonReturn.setTransparency(transparency); + pigeonReturn.setZIndex(zIndex); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(4); + toListResult.add(visible); + toListResult.add(fadeIn); + toListResult.add(transparency); + toListResult.add(zIndex); + return toListResult; + } + + static @NonNull PlatformTileLayer fromList(@NonNull ArrayList __pigeon_list) { + PlatformTileLayer pigeonResult = new PlatformTileLayer(); + Object visible = __pigeon_list.get(0); + pigeonResult.setVisible((Boolean) visible); + Object fadeIn = __pigeon_list.get(1); + pigeonResult.setFadeIn((Boolean) fadeIn); + Object transparency = __pigeon_list.get(2); + pigeonResult.setTransparency((Double) transparency); + Object zIndex = __pigeon_list.get(3); + pigeonResult.setZIndex((Double) zIndex); + return pigeonResult; + } + } + + /** + * Possible outcomes of launching a URL. + * + *

Generated class from Pigeon that represents data sent in messages. + */ + public static final class PlatformZoomRange { + private @NonNull Double min; + + public @NonNull Double getMin() { + return min; + } + + public void setMin(@NonNull Double setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"min\" is null."); + } + this.min = setterArg; + } + + private @NonNull Double max; + + public @NonNull Double getMax() { + return max; + } + + public void setMax(@NonNull Double setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"max\" is null."); + } + this.max = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PlatformZoomRange() {} + + public static final class Builder { + + private @Nullable Double min; + + @CanIgnoreReturnValue + public @NonNull Builder setMin(@NonNull Double setterArg) { + this.min = setterArg; + return this; + } + + private @Nullable Double max; + + @CanIgnoreReturnValue + public @NonNull Builder setMax(@NonNull Double setterArg) { + this.max = setterArg; + return this; + } + + public @NonNull PlatformZoomRange build() { + PlatformZoomRange pigeonReturn = new PlatformZoomRange(); + pigeonReturn.setMin(min); + pigeonReturn.setMax(max); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(2); + toListResult.add(min); + toListResult.add(max); + return toListResult; + } + + static @NonNull PlatformZoomRange fromList(@NonNull ArrayList __pigeon_list) { + PlatformZoomRange pigeonResult = new PlatformZoomRange(); + Object min = __pigeon_list.get(0); + pigeonResult.setMin((Double) min); + Object max = __pigeon_list.get(1); + pigeonResult.setMax((Double) max); + return pigeonResult; + } + } + + private static class PigeonCodec extends StandardMessageCodec { + public static final PigeonCodec INSTANCE = new PigeonCodec(); + + private PigeonCodec() {} + + @Override + protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { + switch (type) { + case (byte) 129: + return PlatformLatLng.fromList((ArrayList) readValue(buffer)); + case (byte) 130: + return PlatformLatLngBounds.fromList((ArrayList) readValue(buffer)); + case (byte) 131: + return PlatformCluster.fromList((ArrayList) readValue(buffer)); + case (byte) 132: + return PlatformTileLayer.fromList((ArrayList) readValue(buffer)); + case (byte) 133: + return PlatformZoomRange.fromList((ArrayList) readValue(buffer)); + default: + return super.readValueOfType(type, buffer); + } + } + + @Override + protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { + if (value instanceof PlatformLatLng) { + stream.write(129); + writeValue(stream, ((PlatformLatLng) value).toList()); + } else if (value instanceof PlatformLatLngBounds) { + stream.write(130); + writeValue(stream, ((PlatformLatLngBounds) value).toList()); + } else if (value instanceof PlatformCluster) { + stream.write(131); + writeValue(stream, ((PlatformCluster) value).toList()); + } else if (value instanceof PlatformTileLayer) { + stream.write(132); + writeValue(stream, ((PlatformTileLayer) value).toList()); + } else if (value instanceof PlatformZoomRange) { + stream.write(133); + writeValue(stream, ((PlatformZoomRange) value).toList()); + } else { + super.writeValue(stream, value); + } + } + } + + /** + * Inspector API only intended for use in integration tests. + * + *

Generated interface from Pigeon that represents a handler of messages from Flutter. + */ + public interface MapsInspectorApi { + + @NonNull + Boolean areBuildingsEnabled(); + + @NonNull + Boolean areRotateGesturesEnabled(); + + @NonNull + Boolean areZoomControlsEnabled(); + + @NonNull + Boolean areScrollGesturesEnabled(); + + @NonNull + Boolean areTiltGesturesEnabled(); + + @NonNull + Boolean areZoomGesturesEnabled(); + + @NonNull + Boolean isCompassEnabled(); + + @Nullable + Boolean isLiteModeEnabled(); + + @NonNull + Boolean isMapToolbarEnabled(); + + @NonNull + Boolean isMyLocationButtonEnabled(); + + @NonNull + Boolean isTrafficEnabled(); + + @Nullable + PlatformTileLayer getTileOverlayInfo(@NonNull String tileOverlayId); + + @NonNull + PlatformZoomRange getZoomRange(); + + @NonNull + List getClusters(@NonNull String clusterManagerId); + + /** The codec used by MapsInspectorApi. */ + static @NonNull MessageCodec getCodec() { + return PigeonCodec.INSTANCE; + } + /** + * Sets up an instance of `MapsInspectorApi` to handle messages through the `binaryMessenger`. + */ + static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable MapsInspectorApi api) { + setUp(binaryMessenger, "", api); + } + + static void setUp( + @NonNull BinaryMessenger binaryMessenger, + @NonNull String messageChannelSuffix, + @Nullable MapsInspectorApi api) { + messageChannelSuffix = messageChannelSuffix.isEmpty() ? "" : "." + messageChannelSuffix; + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.areBuildingsEnabled" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Boolean output = api.areBuildingsEnabled(); + wrapped.add(0, output); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.areRotateGesturesEnabled" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Boolean output = api.areRotateGesturesEnabled(); + wrapped.add(0, output); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.areZoomControlsEnabled" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Boolean output = api.areZoomControlsEnabled(); + wrapped.add(0, output); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.areScrollGesturesEnabled" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Boolean output = api.areScrollGesturesEnabled(); + wrapped.add(0, output); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.areTiltGesturesEnabled" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Boolean output = api.areTiltGesturesEnabled(); + wrapped.add(0, output); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.areZoomGesturesEnabled" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Boolean output = api.areZoomGesturesEnabled(); + wrapped.add(0, output); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.isCompassEnabled" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Boolean output = api.isCompassEnabled(); + wrapped.add(0, output); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.isLiteModeEnabled" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Boolean output = api.isLiteModeEnabled(); + wrapped.add(0, output); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.isMapToolbarEnabled" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Boolean output = api.isMapToolbarEnabled(); + wrapped.add(0, output); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.isMyLocationButtonEnabled" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Boolean output = api.isMyLocationButtonEnabled(); + wrapped.add(0, output); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.isTrafficEnabled" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Boolean output = api.isTrafficEnabled(); + wrapped.add(0, output); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.getTileOverlayInfo" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + String tileOverlayIdArg = (String) args.get(0); + try { + PlatformTileLayer output = api.getTileOverlayInfo(tileOverlayIdArg); + wrapped.add(0, output); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.getZoomRange" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + PlatformZoomRange output = api.getZoomRange(); + wrapped.add(0, output); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.getClusters" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + String clusterManagerIdArg = (String) args.get(0); + try { + List output = api.getClusters(clusterManagerIdArg); + wrapped.add(0, output); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } +} diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/TileOverlayController.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/TileOverlayController.java index 7405b5fcc496..009dff78b3f8 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/TileOverlayController.java +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/TileOverlayController.java @@ -6,8 +6,6 @@ import com.google.android.gms.maps.model.TileOverlay; import com.google.android.gms.maps.model.TileProvider; -import java.util.HashMap; -import java.util.Map; class TileOverlayController implements TileOverlaySink { @@ -25,14 +23,8 @@ void clearTileCache() { tileOverlay.clearTileCache(); } - Map getTileOverlayInfo() { - Map tileOverlayInfo = new HashMap<>(); - tileOverlayInfo.put("fadeIn", tileOverlay.getFadeIn()); - tileOverlayInfo.put("transparency", tileOverlay.getTransparency()); - tileOverlayInfo.put("id", tileOverlay.getId()); - tileOverlayInfo.put("zIndex", tileOverlay.getZIndex()); - tileOverlayInfo.put("visible", tileOverlay.isVisible()); - return tileOverlayInfo; + TileOverlay getTileOverlay() { + return tileOverlay; } @Override diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/TileOverlaysController.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/TileOverlaysController.java index 82a3edcb32c0..52b9d1e6bc99 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/TileOverlaysController.java +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/TileOverlaysController.java @@ -4,6 +4,7 @@ package io.flutter.plugins.googlemaps; +import androidx.annotation.Nullable; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.model.TileOverlay; import com.google.android.gms.maps.model.TileOverlayOptions; @@ -67,7 +68,8 @@ void clearTileCache(String tileOverlayId) { } } - Map getTileOverlayInfo(String tileOverlayId) { + @Nullable + TileOverlay getTileOverlay(String tileOverlayId) { if (tileOverlayId == null) { return null; } @@ -75,7 +77,7 @@ Map getTileOverlayInfo(String tileOverlayId) { if (tileOverlayController == null) { return null; } - return tileOverlayController.getTileOverlayInfo(); + return tileOverlayController.getTileOverlay(); } private void addTileOverlay(Map tileOverlayOptions) { diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/test/java/io/flutter/plugins/googlemaps/ClusterManagersControllerTest.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/test/java/io/flutter/plugins/googlemaps/ClusterManagersControllerTest.java index b218c29ad7c8..bc80627c35f7 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/android/src/test/java/io/flutter/plugins/googlemaps/ClusterManagersControllerTest.java +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/test/java/io/flutter/plugins/googlemaps/ClusterManagersControllerTest.java @@ -6,11 +6,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; import android.content.Context; @@ -20,20 +19,22 @@ import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.model.CameraPosition; import com.google.android.gms.maps.model.LatLng; +import com.google.maps.android.clustering.Cluster; import com.google.maps.android.clustering.algo.StaticCluster; import com.google.maps.android.collections.MarkerManager; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodCodec; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; @@ -105,29 +106,19 @@ public void AddClusterManagersAndMarkers() throws InterruptedException { controller.addItem(markerBuilder1); controller.addItem(markerBuilder2); - final MethodChannel.Result clusterResult1 = mock(MethodChannel.Result.class); + Set> clusters = + controller.getClustersWithClusterManagerId(clusterManagerId); + assertEquals("Amount of clusters should be 1", 1, clusters.size()); - controller.getClustersWithClusterManagerId(clusterManagerId, clusterResult1); - - ArgumentCaptor resultCaptor1 = ArgumentCaptor.forClass(Object.class); - Mockito.verify(clusterResult1, times(1)).success(resultCaptor1.capture()); - Object capturedResult1 = resultCaptor1.getValue(); - - assertTrue( - "The captured result should be an instance of List", capturedResult1 instanceof List); - - List resultList1 = (List) capturedResult1; - assertEquals("Amount of clusters should be 1", 1, resultList1.size()); - - Map clusterData = (Map) resultList1.get(0); - assertEquals( - "Incorrect cluster manager ID", clusterManagerId, clusterData.get("clusterManagerId")); - assertNotNull("Cluster bounds should not be null", clusterData.get("bounds")); - assertNotNull("Cluster position should not be null", clusterData.get("position")); - List markerIds = (List) clusterData.get("markerIds"); + Cluster cluster = clusters.iterator().next(); + assertNotNull("Cluster position should not be null", cluster.getPosition()); + Set markerIds = new HashSet<>(); + for (MarkerBuilder marker : cluster.getItems()) { + markerIds.add(marker.markerId()); + } assertTrue("Marker IDs should contain markerId1", markerIds.contains(markerId1)); assertTrue("Marker IDs should contain markerId2", markerIds.contains(markerId2)); - assertEquals("Cluster should contain exactly 2 markers", 2, markerIds.size()); + assertEquals("Cluster should contain exactly 2 markers", 2, cluster.getSize()); } @Test @@ -165,17 +156,14 @@ public void RemoveClusterManagers() { clusterManagersToAdd.add(initialClusterManager); controller.addClusterManagers(clusterManagersToAdd); - final MethodChannel.Result clusterResult1 = mock(MethodChannel.Result.class); - controller.getClustersWithClusterManagerId(clusterManagerId, clusterResult1); // Verify that fetching the cluster data success and therefore ClusterManager is added. - Mockito.verify(clusterResult1, times(1)).success(any()); - - controller.removeClusterManagers(Arrays.asList(clusterManagerId)); - final MethodChannel.Result clusterResult2 = mock(MethodChannel.Result.class); - controller.getClustersWithClusterManagerId(clusterManagerId, clusterResult2); + controller.getClustersWithClusterManagerId(clusterManagerId); + controller.removeClusterManagers(Collections.singletonList(clusterManagerId)); // Verify that fetching the cluster data fails and therefore ClusterManager is removed. - Mockito.verify(clusterResult2, times(1)).error(any(), any(), any()); + assertThrows( + Messages.FlutterError.class, + () -> controller.getClustersWithClusterManagerId(clusterManagerId)); } private Map createMarkerData( diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/test/java/io/flutter/plugins/googlemaps/ConvertTest.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/test/java/io/flutter/plugins/googlemaps/ConvertTest.java index abb7681e436b..3680d918e2f1 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/android/src/test/java/io/flutter/plugins/googlemaps/ConvertTest.java +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/test/java/io/flutter/plugins/googlemaps/ConvertTest.java @@ -19,7 +19,6 @@ import android.util.Base64; import com.google.android.gms.maps.model.BitmapDescriptor; import com.google.android.gms.maps.model.LatLng; -import com.google.maps.android.clustering.Cluster; import com.google.maps.android.clustering.algo.StaticCluster; import io.flutter.plugins.googlemaps.Convert.BitmapDescriptorFactoryWrapper; import io.flutter.plugins.googlemaps.Convert.FlutterInjectorWrapper; @@ -28,10 +27,8 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -84,7 +81,7 @@ public void ConvertToPointsConvertsThePointsWithFullPrecision() { } @Test - public void ConvertClustersToJsonReturnsCorrectData() { + public void ConvertClusterToJsonReturnsCorrectData() { String clusterManagerId = "cm_1"; LatLng clusterPosition = new LatLng(43.00, -87.90); LatLng markerPosition1 = new LatLng(43.05, -87.95); @@ -100,17 +97,8 @@ public void ConvertClustersToJsonReturnsCorrectData() { marker2.setPosition(markerPosition2); cluster.add(marker2); - Set> clusters = new HashSet<>(); - clusters.add(cluster); - - Object result = Convert.clustersToJson(clusterManagerId, clusters); - - Assert.assertTrue(result instanceof List); - - List data = (List) result; - Assert.assertEquals(1, data.size()); - - Map clusterData = (Map) data.get(0); + Object result = Convert.clusterToJson(clusterManagerId, cluster); + Map clusterData = (Map) result; Assert.assertEquals(clusterManagerId, clusterData.get("clusterManagerId")); List position = (List) clusterData.get("position"); diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/test/java/io/flutter/plugins/googlemaps/GoogleMapControllerTest.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/test/java/io/flutter/plugins/googlemaps/GoogleMapControllerTest.java index 0c7e1946e295..3459b9b3139f 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/android/src/test/java/io/flutter/plugins/googlemaps/GoogleMapControllerTest.java +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/test/java/io/flutter/plugins/googlemaps/GoogleMapControllerTest.java @@ -77,6 +77,7 @@ public GoogleMapController getGoogleMapControllerWithMockedDependencies() { new GoogleMapController( 0, context, + mockMessenger, mockMethodChannel, activity::getLifecycle, null, diff --git a/packages/google_maps_flutter/google_maps_flutter_android/lib/src/google_map_inspector_android.dart b/packages/google_maps_flutter/google_maps_flutter_android/lib/src/google_map_inspector_android.dart index bb90ffc79670..abe361566b67 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/lib/src/google_map_inspector_android.dart +++ b/packages/google_maps_flutter/google_maps_flutter_android/lib/src/google_map_inspector_android.dart @@ -3,114 +3,102 @@ // found in the LICENSE file. import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; import 'google_maps_flutter_android.dart'; +import 'messages.g.dart'; /// An Android of implementation of [GoogleMapsInspectorPlatform]. @visibleForTesting class GoogleMapsInspectorAndroid extends GoogleMapsInspectorPlatform { - /// Creates a method-channel-based inspector instance that gets the channel - /// for a given map ID from [channelProvider]. - GoogleMapsInspectorAndroid(MethodChannel? Function(int mapId) channelProvider) - : _channelProvider = channelProvider; + /// Creates an inspector API instance for a given map ID from + /// [inspectorProvider]. + GoogleMapsInspectorAndroid( + MapsInspectorApi? Function(int mapId) inspectorProvider) + : _inspectorProvider = inspectorProvider; - final MethodChannel? Function(int mapId) _channelProvider; + final MapsInspectorApi? Function(int mapId) _inspectorProvider; @override Future areBuildingsEnabled({required int mapId}) async { - return (await _channelProvider(mapId)! - .invokeMethod('map#isBuildingsEnabled'))!; + return _inspectorProvider(mapId)!.areBuildingsEnabled(); } @override Future areRotateGesturesEnabled({required int mapId}) async { - return (await _channelProvider(mapId)! - .invokeMethod('map#isRotateGesturesEnabled'))!; + return _inspectorProvider(mapId)!.areRotateGesturesEnabled(); } @override Future areScrollGesturesEnabled({required int mapId}) async { - return (await _channelProvider(mapId)! - .invokeMethod('map#isScrollGesturesEnabled'))!; + return _inspectorProvider(mapId)!.areScrollGesturesEnabled(); } @override Future areTiltGesturesEnabled({required int mapId}) async { - return (await _channelProvider(mapId)! - .invokeMethod('map#isTiltGesturesEnabled'))!; + return _inspectorProvider(mapId)!.areTiltGesturesEnabled(); } @override Future areZoomControlsEnabled({required int mapId}) async { - return (await _channelProvider(mapId)! - .invokeMethod('map#isZoomControlsEnabled'))!; + return _inspectorProvider(mapId)!.areZoomControlsEnabled(); } @override Future areZoomGesturesEnabled({required int mapId}) async { - return (await _channelProvider(mapId)! - .invokeMethod('map#isZoomGesturesEnabled'))!; + return _inspectorProvider(mapId)!.areZoomGesturesEnabled(); } @override Future getMinMaxZoomLevels({required int mapId}) async { - final List zoomLevels = (await _channelProvider(mapId)! - .invokeMethod>('map#getMinMaxZoomLevels'))! - .cast(); - return MinMaxZoomPreference(zoomLevels[0], zoomLevels[1]); + final PlatformZoomRange zoomLevels = + await _inspectorProvider(mapId)!.getZoomRange(); + return MinMaxZoomPreference(zoomLevels.min, zoomLevels.max); } @override Future getTileOverlayInfo(TileOverlayId tileOverlayId, {required int mapId}) async { - final Map? tileInfo = await _channelProvider(mapId)! - .invokeMapMethod( - 'map#getTileOverlayInfo', { - 'tileOverlayId': tileOverlayId.value, - }); + final PlatformTileLayer? tileInfo = await _inspectorProvider(mapId)! + .getTileOverlayInfo(tileOverlayId.value); if (tileInfo == null) { return null; } return TileOverlay( tileOverlayId: tileOverlayId, - fadeIn: tileInfo['fadeIn']! as bool, - transparency: tileInfo['transparency']! as double, - visible: tileInfo['visible']! as bool, - // Android and iOS return different types. - zIndex: (tileInfo['zIndex']! as num).toInt(), + fadeIn: tileInfo.fadeIn, + transparency: tileInfo.transparency, + visible: tileInfo.visible, + // The plugin's API only allows setting integer z-index values, so this + // should never actually lose information. + zIndex: tileInfo.zIndex.round(), ); } @override Future isCompassEnabled({required int mapId}) async { - return (await _channelProvider(mapId)! - .invokeMethod('map#isCompassEnabled'))!; + return _inspectorProvider(mapId)!.isCompassEnabled(); } @override Future isLiteModeEnabled({required int mapId}) async { - return (await _channelProvider(mapId)! - .invokeMethod('map#isLiteModeEnabled'))!; + // Null indicates "unspecified"; interpret that as not enabled. + return (await _inspectorProvider(mapId)!.isLiteModeEnabled()) ?? false; } @override Future isMapToolbarEnabled({required int mapId}) async { - return (await _channelProvider(mapId)! - .invokeMethod('map#isMapToolbarEnabled'))!; + return _inspectorProvider(mapId)!.isMapToolbarEnabled(); } @override Future isMyLocationButtonEnabled({required int mapId}) async { - return (await _channelProvider(mapId)! - .invokeMethod('map#isMyLocationButtonEnabled'))!; + return _inspectorProvider(mapId)!.isMyLocationButtonEnabled(); } @override Future isTrafficEnabled({required int mapId}) async { - return (await _channelProvider(mapId)! - .invokeMethod('map#isTrafficEnabled'))!; + return _inspectorProvider(mapId)!.isTrafficEnabled(); } @override @@ -118,17 +106,11 @@ class GoogleMapsInspectorAndroid extends GoogleMapsInspectorPlatform { required int mapId, required ClusterManagerId clusterManagerId, }) async { - final List data = (await _channelProvider(mapId)! - .invokeMethod>('clusterManager#getClusters', - {'clusterManagerId': clusterManagerId.value}))!; - return data.map((dynamic clusterData) { - final Map clusterDataMap = - Map.from(clusterData as Map); - return GoogleMapsFlutterAndroid.parseCluster( - clusterDataMap['clusterManagerId']! as String, - clusterDataMap['position']! as Object, - clusterDataMap['bounds']! as Map, - clusterDataMap['markerIds']! as List); - }).toList(); + return (await _inspectorProvider(mapId)! + .getClusters(clusterManagerId.value)) + // See comment in messages.dart for why the force unwrap is okay. + .map((PlatformCluster? cluster) => + GoogleMapsFlutterAndroid.clusterFromPlatformCluster(cluster!)) + .toList(); } } diff --git a/packages/google_maps_flutter/google_maps_flutter_android/lib/src/google_maps_flutter_android.dart b/packages/google_maps_flutter/google_maps_flutter_android/lib/src/google_maps_flutter_android.dart index 76b258d651c1..59993bc88d1e 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/lib/src/google_maps_flutter_android.dart +++ b/packages/google_maps_flutter/google_maps_flutter_android/lib/src/google_maps_flutter_android.dart @@ -13,6 +13,7 @@ import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platf import 'package:stream_transform/stream_transform.dart'; import 'google_map_inspector_android.dart'; +import 'messages.g.dart'; import 'utils/cluster_manager_utils.dart'; // TODO(stuartmorgan): Remove the dependency on platform interface toJson @@ -719,8 +720,9 @@ class GoogleMapsFlutterAndroid extends GoogleMapsFlutterPlatform { @override @visibleForTesting void enableDebugInspection() { - GoogleMapsInspectorPlatform.instance = - GoogleMapsInspectorAndroid((int mapId) => _channel(mapId)); + GoogleMapsInspectorPlatform.instance = GoogleMapsInspectorAndroid( + (int mapId) => + MapsInspectorApi(messageChannelSuffix: mapId.toString())); } /// Parses cluster data from dynamic json objects and returns [Cluster] object. @@ -754,6 +756,29 @@ class GoogleMapsFlutterAndroid extends GoogleMapsFlutterPlatform { bounds: bounds, ); } + + /// Converts a Pigeon [PlatformCluster] to the corresponding [Cluster]. + static Cluster clusterFromPlatformCluster(PlatformCluster cluster) { + return Cluster( + ClusterManagerId(cluster.clusterManagerId), + cluster.markerIds + // See comment in messages.dart for why the force unwrap is okay. + .map((String? markerId) => MarkerId(markerId!)) + .toList(), + position: _latLngFromPlatformLatLng(cluster.position), + bounds: _latLngBoundsFromPlatformLatLngBounds(cluster.bounds)); + } + + static LatLng _latLngFromPlatformLatLng(PlatformLatLng latLng) { + return LatLng(latLng.lat, latLng.lng); + } + + static LatLngBounds _latLngBoundsFromPlatformLatLngBounds( + PlatformLatLngBounds bounds) { + return LatLngBounds( + southwest: _latLngFromPlatformLatLng(bounds.southwest), + northeast: _latLngFromPlatformLatLng(bounds.northeast)); + } } Map _jsonForMapConfiguration(MapConfiguration config) { diff --git a/packages/google_maps_flutter/google_maps_flutter_android/lib/src/messages.g.dart b/packages/google_maps_flutter/google_maps_flutter_android/lib/src/messages.g.dart new file mode 100644 index 000000000000..b7d501e2889f --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_android/lib/src/messages.g.dart @@ -0,0 +1,631 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v20.0.1), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers + +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +PlatformException _createConnectionError(String channelName) { + return PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); +} + +/// Pigeon equivalent of LatLng. +class PlatformLatLng { + PlatformLatLng({ + required this.lat, + required this.lng, + }); + + double lat; + + double lng; + + Object encode() { + return [ + lat, + lng, + ]; + } + + static PlatformLatLng decode(Object result) { + result as List; + return PlatformLatLng( + lat: result[0]! as double, + lng: result[1]! as double, + ); + } +} + +/// Pigeon equivalent of LatLngBounds. +class PlatformLatLngBounds { + PlatformLatLngBounds({ + required this.northeast, + required this.southwest, + }); + + PlatformLatLng northeast; + + PlatformLatLng southwest; + + Object encode() { + return [ + northeast, + southwest, + ]; + } + + static PlatformLatLngBounds decode(Object result) { + result as List; + return PlatformLatLngBounds( + northeast: result[0]! as PlatformLatLng, + southwest: result[1]! as PlatformLatLng, + ); + } +} + +/// Pigeon equivalent of Cluster. +class PlatformCluster { + PlatformCluster({ + required this.clusterManagerId, + required this.position, + required this.bounds, + required this.markerIds, + }); + + String clusterManagerId; + + PlatformLatLng position; + + PlatformLatLngBounds bounds; + + List markerIds; + + Object encode() { + return [ + clusterManagerId, + position, + bounds, + markerIds, + ]; + } + + static PlatformCluster decode(Object result) { + result as List; + return PlatformCluster( + clusterManagerId: result[0]! as String, + position: result[1]! as PlatformLatLng, + bounds: result[2]! as PlatformLatLngBounds, + markerIds: (result[3] as List?)!.cast(), + ); + } +} + +/// Pigeon equivalent of native TileOverlay properties. +class PlatformTileLayer { + PlatformTileLayer({ + required this.visible, + required this.fadeIn, + required this.transparency, + required this.zIndex, + }); + + bool visible; + + bool fadeIn; + + double transparency; + + double zIndex; + + Object encode() { + return [ + visible, + fadeIn, + transparency, + zIndex, + ]; + } + + static PlatformTileLayer decode(Object result) { + result as List; + return PlatformTileLayer( + visible: result[0]! as bool, + fadeIn: result[1]! as bool, + transparency: result[2]! as double, + zIndex: result[3]! as double, + ); + } +} + +/// Possible outcomes of launching a URL. +class PlatformZoomRange { + PlatformZoomRange({ + required this.min, + required this.max, + }); + + double min; + + double max; + + Object encode() { + return [ + min, + max, + ]; + } + + static PlatformZoomRange decode(Object result) { + result as List; + return PlatformZoomRange( + min: result[0]! as double, + max: result[1]! as double, + ); + } +} + +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PlatformLatLng) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else if (value is PlatformLatLngBounds) { + buffer.putUint8(130); + writeValue(buffer, value.encode()); + } else if (value is PlatformCluster) { + buffer.putUint8(131); + writeValue(buffer, value.encode()); + } else if (value is PlatformTileLayer) { + buffer.putUint8(132); + writeValue(buffer, value.encode()); + } else if (value is PlatformZoomRange) { + buffer.putUint8(133); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 129: + return PlatformLatLng.decode(readValue(buffer)!); + case 130: + return PlatformLatLngBounds.decode(readValue(buffer)!); + case 131: + return PlatformCluster.decode(readValue(buffer)!); + case 132: + return PlatformTileLayer.decode(readValue(buffer)!); + case 133: + return PlatformZoomRange.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +/// Inspector API only intended for use in integration tests. +class MapsInspectorApi { + /// Constructor for [MapsInspectorApi]. 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. + MapsInspectorApi( + {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : __pigeon_binaryMessenger = binaryMessenger, + __pigeon_messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + final BinaryMessenger? __pigeon_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + final String __pigeon_messageChannelSuffix; + + Future areBuildingsEnabled() async { + final String __pigeon_channelName = + 'dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.areBuildingsEnabled$__pigeon_messageChannelSuffix'; + 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 areRotateGesturesEnabled() async { + final String __pigeon_channelName = + 'dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.areRotateGesturesEnabled$__pigeon_messageChannelSuffix'; + 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 areZoomControlsEnabled() async { + final String __pigeon_channelName = + 'dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.areZoomControlsEnabled$__pigeon_messageChannelSuffix'; + 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 areScrollGesturesEnabled() async { + final String __pigeon_channelName = + 'dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.areScrollGesturesEnabled$__pigeon_messageChannelSuffix'; + 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 areTiltGesturesEnabled() async { + final String __pigeon_channelName = + 'dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.areTiltGesturesEnabled$__pigeon_messageChannelSuffix'; + 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 areZoomGesturesEnabled() async { + final String __pigeon_channelName = + 'dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.areZoomGesturesEnabled$__pigeon_messageChannelSuffix'; + 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 { + final String __pigeon_channelName = + 'dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.isCompassEnabled$__pigeon_messageChannelSuffix'; + 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 isLiteModeEnabled() async { + final String __pigeon_channelName = + 'dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.isLiteModeEnabled$__pigeon_messageChannelSuffix'; + 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 bool?); + } + } + + Future isMapToolbarEnabled() async { + final String __pigeon_channelName = + 'dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.isMapToolbarEnabled$__pigeon_messageChannelSuffix'; + 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 isMyLocationButtonEnabled() async { + final String __pigeon_channelName = + 'dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.isMyLocationButtonEnabled$__pigeon_messageChannelSuffix'; + 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 { + final String __pigeon_channelName = + 'dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.isTrafficEnabled$__pigeon_messageChannelSuffix'; + 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 getTileOverlayInfo(String tileOverlayId) async { + final String __pigeon_channelName = + 'dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.getTileOverlayInfo$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([tileOverlayId]) 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 PlatformTileLayer?); + } + } + + Future getZoomRange() async { + final String __pigeon_channelName = + 'dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.getZoomRange$__pigeon_messageChannelSuffix'; + 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 PlatformZoomRange?)!; + } + } + + Future> getClusters(String clusterManagerId) async { + final String __pigeon_channelName = + 'dev.flutter.pigeon.google_maps_flutter_android.MapsInspectorApi.getClusters$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([clusterManagerId]) 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(); + } + } +} diff --git a/packages/google_maps_flutter/google_maps_flutter_android/pigeons/copyright.txt b/packages/google_maps_flutter/google_maps_flutter_android/pigeons/copyright.txt new file mode 100644 index 000000000000..1236b63caf3a --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_android/pigeons/copyright.txt @@ -0,0 +1,3 @@ +Copyright 2013 The Flutter Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. diff --git a/packages/google_maps_flutter/google_maps_flutter_android/pigeons/messages.dart b/packages/google_maps_flutter/google_maps_flutter_android/pigeons/messages.dart new file mode 100644 index 000000000000..7cea60730e39 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_android/pigeons/messages.dart @@ -0,0 +1,91 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon(PigeonOptions( + dartOut: 'lib/src/messages.g.dart', + javaOptions: JavaOptions(package: 'io.flutter.plugins.googlemaps'), + javaOut: 'android/src/main/java/io/flutter/plugins/googlemaps/Messages.java', + copyrightHeader: 'pigeons/copyright.txt', +)) + +/// Pigeon equivalent of LatLng. +class PlatformLatLng { + PlatformLatLng({required this.lat, required this.lng}); + + final double lat; + final double lng; +} + +/// Pigeon equivalent of LatLngBounds. +class PlatformLatLngBounds { + PlatformLatLngBounds({required this.northeast, required this.southwest}); + + final PlatformLatLng northeast; + final PlatformLatLng southwest; +} + +/// Pigeon equivalent of Cluster. +class PlatformCluster { + PlatformCluster({ + required this.clusterManagerId, + required this.position, + required this.bounds, + required this.markerIds, + }); + + final String clusterManagerId; + final PlatformLatLng position; + final PlatformLatLngBounds bounds; + // TODO(stuartmorgan): Make the generic type non-nullable once supported. + // https://github.com/flutter/flutter/issues/97848 + // The consuming code treats the entries as non-nullable. + final List markerIds; +} + +/// Pigeon equivalent of native TileOverlay properties. +class PlatformTileLayer { + PlatformTileLayer({ + required this.visible, + required this.fadeIn, + required this.transparency, + required this.zIndex, + }); + + final bool visible; + final bool fadeIn; + final double transparency; + final double zIndex; +} + +/// Possible outcomes of launching a URL. +class PlatformZoomRange { + PlatformZoomRange({required this.min, required this.max}); + + final double min; + final double max; +} + +/// Inspector API only intended for use in integration tests. +@HostApi() +abstract class MapsInspectorApi { + bool areBuildingsEnabled(); + bool areRotateGesturesEnabled(); + bool areZoomControlsEnabled(); + bool areScrollGesturesEnabled(); + bool areTiltGesturesEnabled(); + bool areZoomGesturesEnabled(); + bool isCompassEnabled(); + bool? isLiteModeEnabled(); + bool isMapToolbarEnabled(); + bool isMyLocationButtonEnabled(); + bool isTrafficEnabled(); + PlatformTileLayer? getTileOverlayInfo(String tileOverlayId); + PlatformZoomRange getZoomRange(); + // TODO(stuartmorgan): Make the generic type non-nullable once supported. + // https://github.com/flutter/flutter/issues/97848 + // The consuming code treats the entries as non-nullable. + List getClusters(String clusterManagerId); +} diff --git a/packages/google_maps_flutter/google_maps_flutter_android/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_android/pubspec.yaml index f14b973f0d51..6705a98896d2 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_android/pubspec.yaml @@ -2,7 +2,7 @@ name: google_maps_flutter_android description: Android implementation of the google_maps_flutter plugin. repository: https://github.com/flutter/packages/tree/main/packages/google_maps_flutter/google_maps_flutter_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22 -version: 2.9.0 +version: 2.9.1 environment: sdk: ^3.4.0 @@ -28,6 +28,7 @@ dev_dependencies: async: ^2.5.0 flutter_test: sdk: flutter + pigeon: ^20.0.1 plugin_platform_interface: ^2.1.7 topics: