From 64c78ec9d91fd5553fac9942ea2d2a85edd6d0fb Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 16 Jul 2024 12:24:57 -0400 Subject: [PATCH 01/14] iOS Dart --- .../lib/example_google_map.dart | 10 - .../maps_example_dart/lib/lite_mode.dart | 1 - .../shared/maps_example_dart/lib/map_ui.dart | 14 -- .../ios/Classes/messages.g.h | 86 ++++++- .../ios/Classes/messages.g.m | 201 +++++++++++++++-- .../lib/src/google_maps_flutter_ios.dart | 198 ++++++++++++++-- .../lib/src/messages.g.dart | 212 ++++++++++++++++-- .../pigeons/messages.dart | 81 ++++++- .../test/google_maps_flutter_ios_test.dart | 52 +++-- 9 files changed, 731 insertions(+), 124 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/lib/example_google_map.dart b/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/lib/example_google_map.dart index 0734731af7c..c0d989b600f 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/lib/example_google_map.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/lib/example_google_map.dart @@ -214,7 +214,6 @@ class ExampleGoogleMap extends StatefulWidget { this.onMapCreated, this.gestureRecognizers = const >{}, this.compassEnabled = true, - this.mapToolbarEnabled = true, this.cameraTargetBounds = CameraTargetBounds.unbounded, this.mapType = MapType.normal, this.minMaxZoomPreference = MinMaxZoomPreference.unbounded, @@ -222,7 +221,6 @@ class ExampleGoogleMap extends StatefulWidget { this.scrollGesturesEnabled = true, this.zoomControlsEnabled = true, this.zoomGesturesEnabled = true, - this.liteModeEnabled = false, this.tiltGesturesEnabled = true, this.myLocationEnabled = false, this.myLocationButtonEnabled = true, @@ -258,9 +256,6 @@ class ExampleGoogleMap extends StatefulWidget { /// True if the map should show a compass when rotated. final bool compassEnabled; - /// True if the map should show a toolbar when you interact with the map. Android only. - final bool mapToolbarEnabled; - /// Geographical bounding box for the camera target. final CameraTargetBounds cameraTargetBounds; @@ -288,9 +283,6 @@ class ExampleGoogleMap extends StatefulWidget { /// True if the map view should respond to zoom gestures. final bool zoomGesturesEnabled; - /// True if the map view should be in lite mode. Android only. - final bool liteModeEnabled; - /// True if the map view should respond to tilt gestures. final bool tiltGesturesEnabled; @@ -524,7 +516,6 @@ class _ExampleGoogleMapState extends State { MapConfiguration _configurationFromMapWidget(ExampleGoogleMap map) { return MapConfiguration( compassEnabled: map.compassEnabled, - mapToolbarEnabled: map.mapToolbarEnabled, cameraTargetBounds: map.cameraTargetBounds, mapType: map.mapType, minMaxZoomPreference: map.minMaxZoomPreference, @@ -534,7 +525,6 @@ MapConfiguration _configurationFromMapWidget(ExampleGoogleMap map) { trackCameraPosition: map.onCameraMove != null, zoomControlsEnabled: map.zoomControlsEnabled, zoomGesturesEnabled: map.zoomGesturesEnabled, - liteModeEnabled: map.liteModeEnabled, myLocationEnabled: map.myLocationEnabled, myLocationButtonEnabled: map.myLocationButtonEnabled, padding: map.padding, diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/lib/lite_mode.dart b/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/lib/lite_mode.dart index f7bead951f5..a70ff98a4e7 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/lib/lite_mode.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/lib/lite_mode.dart @@ -37,7 +37,6 @@ class _LiteModeBody extends StatelessWidget { height: 300.0, child: ExampleGoogleMap( initialCameraPosition: _kInitialPosition, - liteModeEnabled: true, ), ), ), diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/lib/map_ui.dart b/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/lib/map_ui.dart index 105676da9ed..0038ec6f339 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/lib/map_ui.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/lib/map_ui.dart @@ -45,7 +45,6 @@ class MapUiBodyState extends State { bool _isMapCreated = false; final bool _isMoving = false; bool _compassEnabled = true; - bool _mapToolbarEnabled = true; CameraTargetBounds _cameraTargetBounds = CameraTargetBounds.unbounded; MinMaxZoomPreference _minMaxZoomPreference = MinMaxZoomPreference.unbounded; MapType _mapType = MapType.normal; @@ -83,17 +82,6 @@ class MapUiBodyState extends State { ); } - Widget _mapToolbarToggler() { - return TextButton( - child: Text('${_mapToolbarEnabled ? 'disable' : 'enable'} map toolbar'), - onPressed: () { - setState(() { - _mapToolbarEnabled = !_mapToolbarEnabled; - }); - }, - ); - } - Widget _latLngBoundsToggler() { return TextButton( child: Text( @@ -265,7 +253,6 @@ class MapUiBodyState extends State { onMapCreated: onMapCreated, initialCameraPosition: _kInitialPosition, compassEnabled: _compassEnabled, - mapToolbarEnabled: _mapToolbarEnabled, cameraTargetBounds: _cameraTargetBounds, minMaxZoomPreference: _minMaxZoomPreference, mapType: _mapType, @@ -308,7 +295,6 @@ class MapUiBodyState extends State { Text('camera tilt: ${_position.tilt}'), Text(_isMoving ? '(Camera moving)' : '(Camera idle)'), _compassToggler(), - _mapToolbarToggler(), _latLngBoundsToggler(), _mapTypeCycler(), _zoomBoundsToggler(), diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/messages.g.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/messages.g.h index 6dd112c6baa..c01282df525 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/messages.g.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/messages.g.h @@ -13,6 +13,21 @@ NS_ASSUME_NONNULL_BEGIN +/// Pigeon equivalent of MapType +typedef NS_ENUM(NSUInteger, FGMPlatformMapType) { + FGMPlatformMapTypeNone = 0, + FGMPlatformMapTypeNormal = 1, + FGMPlatformMapTypeSatellite = 2, + FGMPlatformMapTypeTerrain = 3, + FGMPlatformMapTypeHybrid = 4, +}; + +/// Wrapper for FGMPlatformMapType to allow for nullability. +@interface FGMPlatformMapTypeBox : NSObject +@property(nonatomic, assign) FGMPlatformMapType value; +- (instancetype)initWithValue:(FGMPlatformMapType)value; +@end + @class FGMPlatformCameraPosition; @class FGMPlatformCameraUpdate; @class FGMPlatformCircle; @@ -21,8 +36,10 @@ NS_ASSUME_NONNULL_BEGIN @class FGMPlatformPolyline; @class FGMPlatformTile; @class FGMPlatformTileOverlay; +@class FGMPlatformEdgeInsets; @class FGMPlatformLatLng; @class FGMPlatformLatLngBounds; +@class FGMPlatformCameraTargetBounds; @class FGMPlatformMapConfiguration; @class FGMPlatformPoint; @class FGMPlatformTileLayer; @@ -120,6 +137,17 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, strong) id json; @end +/// Pigeon equivalent of Flutter's EdgeInsets. +@interface FGMPlatformEdgeInsets : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithTop:(double)top bottom:(double)bottom left:(double)left right:(double)right; +@property(nonatomic, assign) double top; +@property(nonatomic, assign) double bottom; +@property(nonatomic, assign) double left; +@property(nonatomic, assign) double right; +@end + /// Pigeon equivalent of LatLng. @interface FGMPlatformLatLng : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. @@ -139,15 +167,51 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, strong) FGMPlatformLatLng *southwest; @end +/// Pigeon equivalent of CameraTargetBounds. +/// +/// As with the Dart version, it exists to distinguish between not setting a +/// a target, and having an explicitly unbounded target (null [bounds]). +@interface FGMPlatformCameraTargetBounds : NSObject ++ (instancetype)makeWithBounds:(nullable FGMPlatformLatLngBounds *)bounds; +@property(nonatomic, strong, nullable) FGMPlatformLatLngBounds *bounds; +@end + /// Pigeon equivalent of MapConfiguration. @interface FGMPlatformMapConfiguration : NSObject -/// `init` unavailable to enforce nonnull fields, see the `make` class method. -- (instancetype)init NS_UNAVAILABLE; -+ (instancetype)makeWithJson:(id)json; -/// The configuration options, as JSON. This should only be set from -/// _jsonForMapConfiguration, and the native code must intepret it according -/// to the internal implementation details of that method. -@property(nonatomic, strong) id json; ++ (instancetype)makeWithCompassEnabled:(nullable NSNumber *)compassEnabled + cameraTargetBounds:(nullable FGMPlatformCameraTargetBounds *)cameraTargetBounds + mapType:(nullable FGMPlatformMapTypeBox *)mapType + minMaxZoomPreference:(nullable FGMPlatformZoomRange *)minMaxZoomPreference + rotateGesturesEnabled:(nullable NSNumber *)rotateGesturesEnabled + scrollGesturesEnabled:(nullable NSNumber *)scrollGesturesEnabled + tiltGesturesEnabled:(nullable NSNumber *)tiltGesturesEnabled + trackCameraPosition:(nullable NSNumber *)trackCameraPosition + zoomGesturesEnabled:(nullable NSNumber *)zoomGesturesEnabled + myLocationEnabled:(nullable NSNumber *)myLocationEnabled + myLocationButtonEnabled:(nullable NSNumber *)myLocationButtonEnabled + padding:(nullable FGMPlatformEdgeInsets *)padding + indoorViewEnabled:(nullable NSNumber *)indoorViewEnabled + trafficEnabled:(nullable NSNumber *)trafficEnabled + buildingsEnabled:(nullable NSNumber *)buildingsEnabled + cloudMapId:(nullable NSString *)cloudMapId + style:(nullable NSString *)style; +@property(nonatomic, strong, nullable) NSNumber *compassEnabled; +@property(nonatomic, strong, nullable) FGMPlatformCameraTargetBounds *cameraTargetBounds; +@property(nonatomic, strong, nullable) FGMPlatformMapTypeBox *mapType; +@property(nonatomic, strong, nullable) FGMPlatformZoomRange *minMaxZoomPreference; +@property(nonatomic, strong, nullable) NSNumber *rotateGesturesEnabled; +@property(nonatomic, strong, nullable) NSNumber *scrollGesturesEnabled; +@property(nonatomic, strong, nullable) NSNumber *tiltGesturesEnabled; +@property(nonatomic, strong, nullable) NSNumber *trackCameraPosition; +@property(nonatomic, strong, nullable) NSNumber *zoomGesturesEnabled; +@property(nonatomic, strong, nullable) NSNumber *myLocationEnabled; +@property(nonatomic, strong, nullable) NSNumber *myLocationButtonEnabled; +@property(nonatomic, strong, nullable) FGMPlatformEdgeInsets *padding; +@property(nonatomic, strong, nullable) NSNumber *indoorViewEnabled; +@property(nonatomic, strong, nullable) NSNumber *trafficEnabled; +@property(nonatomic, strong, nullable) NSNumber *buildingsEnabled; +@property(nonatomic, copy, nullable) NSString *cloudMapId; +@property(nonatomic, copy, nullable) NSString *style; @end /// Pigeon representation of an x,y coordinate. @@ -175,11 +239,9 @@ NS_ASSUME_NONNULL_BEGIN /// Pigeon equivalent of MinMaxZoomPreference. @interface FGMPlatformZoomRange : NSObject -/// `init` unavailable to enforce nonnull fields, see the `make` class method. -- (instancetype)init NS_UNAVAILABLE; -+ (instancetype)makeWithMin:(double)min max:(double)max; -@property(nonatomic, assign) double min; -@property(nonatomic, assign) double max; ++ (instancetype)makeWithMin:(nullable NSNumber *)min max:(nullable NSNumber *)max; +@property(nonatomic, strong, nullable) NSNumber *min; +@property(nonatomic, strong, nullable) NSNumber *max; @end /// The codec used by all APIs. diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/messages.g.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/messages.g.m index 4836d517b89..f26d8f1bb85 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/messages.g.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/messages.g.m @@ -39,6 +39,17 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { return (result == [NSNull null]) ? nil : result; } +/// Pigeon equivalent of MapType +@implementation FGMPlatformMapTypeBox +- (instancetype)initWithValue:(FGMPlatformMapType)value { + self = [super init]; + if (self) { + _value = value; + } + return self; +} +@end + @interface FGMPlatformCameraPosition () + (FGMPlatformCameraPosition *)fromList:(NSArray *)list; + (nullable FGMPlatformCameraPosition *)nullableFromList:(NSArray *)list; @@ -87,6 +98,12 @@ + (nullable FGMPlatformTileOverlay *)nullableFromList:(NSArray *)list; - (NSArray *)toList; @end +@interface FGMPlatformEdgeInsets () ++ (FGMPlatformEdgeInsets *)fromList:(NSArray *)list; ++ (nullable FGMPlatformEdgeInsets *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + @interface FGMPlatformLatLng () + (FGMPlatformLatLng *)fromList:(NSArray *)list; + (nullable FGMPlatformLatLng *)nullableFromList:(NSArray *)list; @@ -99,6 +116,12 @@ + (nullable FGMPlatformLatLngBounds *)nullableFromList:(NSArray *)list; - (NSArray *)toList; @end +@interface FGMPlatformCameraTargetBounds () ++ (FGMPlatformCameraTargetBounds *)fromList:(NSArray *)list; ++ (nullable FGMPlatformCameraTargetBounds *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + @interface FGMPlatformMapConfiguration () + (FGMPlatformMapConfiguration *)fromList:(NSArray *)list; + (nullable FGMPlatformMapConfiguration *)nullableFromList:(NSArray *)list; @@ -311,6 +334,39 @@ + (nullable FGMPlatformTileOverlay *)nullableFromList:(NSArray *)list { } @end +@implementation FGMPlatformEdgeInsets ++ (instancetype)makeWithTop:(double)top + bottom:(double)bottom + left:(double)left + right:(double)right { + FGMPlatformEdgeInsets *pigeonResult = [[FGMPlatformEdgeInsets alloc] init]; + pigeonResult.top = top; + pigeonResult.bottom = bottom; + pigeonResult.left = left; + pigeonResult.right = right; + return pigeonResult; +} ++ (FGMPlatformEdgeInsets *)fromList:(NSArray *)list { + FGMPlatformEdgeInsets *pigeonResult = [[FGMPlatformEdgeInsets alloc] init]; + pigeonResult.top = [GetNullableObjectAtIndex(list, 0) doubleValue]; + pigeonResult.bottom = [GetNullableObjectAtIndex(list, 1) doubleValue]; + pigeonResult.left = [GetNullableObjectAtIndex(list, 2) doubleValue]; + pigeonResult.right = [GetNullableObjectAtIndex(list, 3) doubleValue]; + return pigeonResult; +} ++ (nullable FGMPlatformEdgeInsets *)nullableFromList:(NSArray *)list { + return (list) ? [FGMPlatformEdgeInsets fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + @(self.top), + @(self.bottom), + @(self.left), + @(self.right), + ]; +} +@end + @implementation FGMPlatformLatLng + (instancetype)makeWithLatitude:(double)latitude longitude:(double)longitude { FGMPlatformLatLng *pigeonResult = [[FGMPlatformLatLng alloc] init]; @@ -360,15 +416,84 @@ + (nullable FGMPlatformLatLngBounds *)nullableFromList:(NSArray *)list { } @end +@implementation FGMPlatformCameraTargetBounds ++ (instancetype)makeWithBounds:(nullable FGMPlatformLatLngBounds *)bounds { + FGMPlatformCameraTargetBounds *pigeonResult = [[FGMPlatformCameraTargetBounds alloc] init]; + pigeonResult.bounds = bounds; + return pigeonResult; +} ++ (FGMPlatformCameraTargetBounds *)fromList:(NSArray *)list { + FGMPlatformCameraTargetBounds *pigeonResult = [[FGMPlatformCameraTargetBounds alloc] init]; + pigeonResult.bounds = GetNullableObjectAtIndex(list, 0); + return pigeonResult; +} ++ (nullable FGMPlatformCameraTargetBounds *)nullableFromList:(NSArray *)list { + return (list) ? [FGMPlatformCameraTargetBounds fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + self.bounds ?: [NSNull null], + ]; +} +@end + @implementation FGMPlatformMapConfiguration -+ (instancetype)makeWithJson:(id)json { ++ (instancetype)makeWithCompassEnabled:(nullable NSNumber *)compassEnabled + cameraTargetBounds:(nullable FGMPlatformCameraTargetBounds *)cameraTargetBounds + mapType:(nullable FGMPlatformMapTypeBox *)mapType + minMaxZoomPreference:(nullable FGMPlatformZoomRange *)minMaxZoomPreference + rotateGesturesEnabled:(nullable NSNumber *)rotateGesturesEnabled + scrollGesturesEnabled:(nullable NSNumber *)scrollGesturesEnabled + tiltGesturesEnabled:(nullable NSNumber *)tiltGesturesEnabled + trackCameraPosition:(nullable NSNumber *)trackCameraPosition + zoomGesturesEnabled:(nullable NSNumber *)zoomGesturesEnabled + myLocationEnabled:(nullable NSNumber *)myLocationEnabled + myLocationButtonEnabled:(nullable NSNumber *)myLocationButtonEnabled + padding:(nullable FGMPlatformEdgeInsets *)padding + indoorViewEnabled:(nullable NSNumber *)indoorViewEnabled + trafficEnabled:(nullable NSNumber *)trafficEnabled + buildingsEnabled:(nullable NSNumber *)buildingsEnabled + cloudMapId:(nullable NSString *)cloudMapId + style:(nullable NSString *)style { FGMPlatformMapConfiguration *pigeonResult = [[FGMPlatformMapConfiguration alloc] init]; - pigeonResult.json = json; + pigeonResult.compassEnabled = compassEnabled; + pigeonResult.cameraTargetBounds = cameraTargetBounds; + pigeonResult.mapType = mapType; + pigeonResult.minMaxZoomPreference = minMaxZoomPreference; + pigeonResult.rotateGesturesEnabled = rotateGesturesEnabled; + pigeonResult.scrollGesturesEnabled = scrollGesturesEnabled; + pigeonResult.tiltGesturesEnabled = tiltGesturesEnabled; + pigeonResult.trackCameraPosition = trackCameraPosition; + pigeonResult.zoomGesturesEnabled = zoomGesturesEnabled; + pigeonResult.myLocationEnabled = myLocationEnabled; + pigeonResult.myLocationButtonEnabled = myLocationButtonEnabled; + pigeonResult.padding = padding; + pigeonResult.indoorViewEnabled = indoorViewEnabled; + pigeonResult.trafficEnabled = trafficEnabled; + pigeonResult.buildingsEnabled = buildingsEnabled; + pigeonResult.cloudMapId = cloudMapId; + pigeonResult.style = style; return pigeonResult; } + (FGMPlatformMapConfiguration *)fromList:(NSArray *)list { FGMPlatformMapConfiguration *pigeonResult = [[FGMPlatformMapConfiguration alloc] init]; - pigeonResult.json = GetNullableObjectAtIndex(list, 0); + pigeonResult.compassEnabled = GetNullableObjectAtIndex(list, 0); + pigeonResult.cameraTargetBounds = GetNullableObjectAtIndex(list, 1); + pigeonResult.mapType = GetNullableObjectAtIndex(list, 2); + pigeonResult.minMaxZoomPreference = GetNullableObjectAtIndex(list, 3); + pigeonResult.rotateGesturesEnabled = GetNullableObjectAtIndex(list, 4); + pigeonResult.scrollGesturesEnabled = GetNullableObjectAtIndex(list, 5); + pigeonResult.tiltGesturesEnabled = GetNullableObjectAtIndex(list, 6); + pigeonResult.trackCameraPosition = GetNullableObjectAtIndex(list, 7); + pigeonResult.zoomGesturesEnabled = GetNullableObjectAtIndex(list, 8); + pigeonResult.myLocationEnabled = GetNullableObjectAtIndex(list, 9); + pigeonResult.myLocationButtonEnabled = GetNullableObjectAtIndex(list, 10); + pigeonResult.padding = GetNullableObjectAtIndex(list, 11); + pigeonResult.indoorViewEnabled = GetNullableObjectAtIndex(list, 12); + pigeonResult.trafficEnabled = GetNullableObjectAtIndex(list, 13); + pigeonResult.buildingsEnabled = GetNullableObjectAtIndex(list, 14); + pigeonResult.cloudMapId = GetNullableObjectAtIndex(list, 15); + pigeonResult.style = GetNullableObjectAtIndex(list, 16); return pigeonResult; } + (nullable FGMPlatformMapConfiguration *)nullableFromList:(NSArray *)list { @@ -376,7 +501,23 @@ + (nullable FGMPlatformMapConfiguration *)nullableFromList:(NSArray *)list { } - (NSArray *)toList { return @[ - self.json ?: [NSNull null], + self.compassEnabled ?: [NSNull null], + self.cameraTargetBounds ?: [NSNull null], + self.mapType ?: [NSNull null], + self.minMaxZoomPreference ?: [NSNull null], + self.rotateGesturesEnabled ?: [NSNull null], + self.scrollGesturesEnabled ?: [NSNull null], + self.tiltGesturesEnabled ?: [NSNull null], + self.trackCameraPosition ?: [NSNull null], + self.zoomGesturesEnabled ?: [NSNull null], + self.myLocationEnabled ?: [NSNull null], + self.myLocationButtonEnabled ?: [NSNull null], + self.padding ?: [NSNull null], + self.indoorViewEnabled ?: [NSNull null], + self.trafficEnabled ?: [NSNull null], + self.buildingsEnabled ?: [NSNull null], + self.cloudMapId ?: [NSNull null], + self.style ?: [NSNull null], ]; } @end @@ -439,7 +580,7 @@ + (nullable FGMPlatformTileLayer *)nullableFromList:(NSArray *)list { @end @implementation FGMPlatformZoomRange -+ (instancetype)makeWithMin:(double)min max:(double)max { ++ (instancetype)makeWithMin:(nullable NSNumber *)min max:(nullable NSNumber *)max { FGMPlatformZoomRange *pigeonResult = [[FGMPlatformZoomRange alloc] init]; pigeonResult.min = min; pigeonResult.max = max; @@ -447,8 +588,8 @@ + (instancetype)makeWithMin:(double)min max:(double)max { } + (FGMPlatformZoomRange *)fromList:(NSArray *)list { FGMPlatformZoomRange *pigeonResult = [[FGMPlatformZoomRange alloc] init]; - pigeonResult.min = [GetNullableObjectAtIndex(list, 0) doubleValue]; - pigeonResult.max = [GetNullableObjectAtIndex(list, 1) doubleValue]; + pigeonResult.min = GetNullableObjectAtIndex(list, 0); + pigeonResult.max = GetNullableObjectAtIndex(list, 1); return pigeonResult; } + (nullable FGMPlatformZoomRange *)nullableFromList:(NSArray *)list { @@ -456,8 +597,8 @@ + (nullable FGMPlatformZoomRange *)nullableFromList:(NSArray *)list { } - (NSArray *)toList { return @[ - @(self.min), - @(self.max), + self.min ?: [NSNull null], + self.max ?: [NSNull null], ]; } @end @@ -484,17 +625,27 @@ - (nullable id)readValueOfType:(UInt8)type { case 136: return [FGMPlatformTileOverlay fromList:[self readValue]]; case 137: - return [FGMPlatformLatLng fromList:[self readValue]]; + return [FGMPlatformEdgeInsets fromList:[self readValue]]; case 138: - return [FGMPlatformLatLngBounds fromList:[self readValue]]; + return [FGMPlatformLatLng fromList:[self readValue]]; case 139: - return [FGMPlatformMapConfiguration fromList:[self readValue]]; + return [FGMPlatformLatLngBounds fromList:[self readValue]]; case 140: - return [FGMPlatformPoint fromList:[self readValue]]; + return [FGMPlatformCameraTargetBounds fromList:[self readValue]]; case 141: - return [FGMPlatformTileLayer fromList:[self readValue]]; + return [FGMPlatformMapConfiguration fromList:[self readValue]]; case 142: + return [FGMPlatformPoint fromList:[self readValue]]; + case 143: + return [FGMPlatformTileLayer fromList:[self readValue]]; + case 144: return [FGMPlatformZoomRange fromList:[self readValue]]; + case 145: { + NSNumber *enumAsNumber = [self readValue]; + return enumAsNumber == nil + ? nil + : [[FGMPlatformMapTypeBox alloc] initWithValue:[enumAsNumber integerValue]]; + } default: return [super readValueOfType:type]; } @@ -529,24 +680,34 @@ - (void)writeValue:(id)value { } else if ([value isKindOfClass:[FGMPlatformTileOverlay class]]) { [self writeByte:136]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[FGMPlatformLatLng class]]) { + } else if ([value isKindOfClass:[FGMPlatformEdgeInsets class]]) { [self writeByte:137]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[FGMPlatformLatLngBounds class]]) { + } else if ([value isKindOfClass:[FGMPlatformLatLng class]]) { [self writeByte:138]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[FGMPlatformMapConfiguration class]]) { + } else if ([value isKindOfClass:[FGMPlatformLatLngBounds class]]) { [self writeByte:139]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[FGMPlatformPoint class]]) { + } else if ([value isKindOfClass:[FGMPlatformCameraTargetBounds class]]) { [self writeByte:140]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[FGMPlatformTileLayer class]]) { + } else if ([value isKindOfClass:[FGMPlatformMapConfiguration class]]) { [self writeByte:141]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[FGMPlatformZoomRange class]]) { + } else if ([value isKindOfClass:[FGMPlatformPoint class]]) { [self writeByte:142]; [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[FGMPlatformTileLayer class]]) { + [self writeByte:143]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[FGMPlatformZoomRange class]]) { + [self writeByte:144]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[FGMPlatformMapTypeBox class]]) { + FGMPlatformMapTypeBox *box = (FGMPlatformMapTypeBox *)value; + [self writeByte:145]; + [self writeValue:(value == nil ? [NSNull null] : [NSNumber numberWithInteger:box.value])]; } else { [super writeValue:value]; } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/lib/src/google_maps_flutter_ios.dart b/packages/google_maps_flutter/google_maps_flutter_ios/lib/src/google_maps_flutter_ios.dart index 8e9a96d094b..72ef27687c3 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/lib/src/google_maps_flutter_ios.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios/lib/src/google_maps_flutter_ios.dart @@ -204,8 +204,8 @@ class GoogleMapsFlutterIOS extends GoogleMapsFlutterPlatform { MapConfiguration configuration, { required int mapId, }) { - return updateMapOptions(_jsonForMapConfiguration(configuration), - mapId: mapId); + return _hostApi(mapId).updateMapConfiguration( + _platformMapConfigurationFromMapConfiguration(configuration)); } @override @@ -213,8 +213,8 @@ class GoogleMapsFlutterIOS extends GoogleMapsFlutterPlatform { Map optionsUpdate, { required int mapId, }) { - return _hostApi(mapId) - .updateMapConfiguration(PlatformMapConfiguration(json: optionsUpdate)); + return _hostApi(mapId).updateMapConfiguration( + _platformMapConfigurationFromOptionsJson(optionsUpdate)); } @override @@ -515,11 +515,6 @@ class GoogleMapsFlutterIOS extends GoogleMapsFlutterPlatform { MapsInspectorApi(messageChannelSuffix: mapId.toString())); } - static PlatformLatLng _platformLatLngFromLatLng(LatLng latLng) { - return PlatformLatLng( - latitude: latLng.latitude, longitude: latLng.longitude); - } - static ScreenCoordinate _screenCoordinateFromPlatformPoint( PlatformPoint point) { return ScreenCoordinate(x: point.x.round(), y: point.y.round()); @@ -687,16 +682,102 @@ LatLngBounds _latLngBoundsFromPlatformLatLngBounds( northeast: _latLngFromPlatformLatLng(bounds.northeast)); } +PlatformLatLng _platformLatLngFromLatLng(LatLng latLng) { + return PlatformLatLng(latitude: latLng.latitude, longitude: latLng.longitude); +} + +PlatformLatLngBounds? _platformLatLngBoundsFromLatLngBounds( + LatLngBounds? bounds) { + if (bounds == null) { + return null; + } + return PlatformLatLngBounds( + northeast: _platformLatLngFromLatLng(bounds.northeast), + southwest: _platformLatLngFromLatLng(bounds.southwest)); +} + +PlatformCameraTargetBounds? _platformCameraTargetBoundsFromCameraTargetBounds( + CameraTargetBounds? bounds) { + return bounds == null + ? null + : PlatformCameraTargetBounds( + bounds: _platformLatLngBoundsFromLatLngBounds(bounds.bounds)); +} + PlatformTile _platformTileFromTile(Tile tile) { return PlatformTile(width: tile.width, height: tile.height, data: tile.data); } +PlatformMapType? _platformMapTypeFromMapType(MapType? type) { + switch (type) { + case null: + return null; + case MapType.none: + return PlatformMapType.none; + case MapType.normal: + return PlatformMapType.normal; + case MapType.satellite: + return PlatformMapType.satellite; + case MapType.terrain: + return PlatformMapType.terrain; + case MapType.hybrid: + return PlatformMapType.hybrid; + } + // The enum comes from a different package, which could get a new value at + // any time, so provide a fallback that ensures this won't break when used + // with a version that contains new values. This is deliberately outside + // the switch rather than a `default` so that the linter will flag the + // switch as needing an update. + // ignore: dead_code + return PlatformMapType.normal; +} + +PlatformZoomRange? _platformZoomRangeFromMinMaxZoomPreference( + MinMaxZoomPreference? zoomPref) { + return zoomPref == null + ? null + : PlatformZoomRange(min: zoomPref.minZoom, max: zoomPref.maxZoom); +} + +PlatformEdgeInsets? _platformEdgeInsetsFromEdgeInsets(EdgeInsets? insets) { + return insets == null + ? null + : PlatformEdgeInsets( + top: insets.top, + bottom: insets.bottom, + left: insets.left, + right: insets.right); +} + +PlatformMapConfiguration _platformMapConfigurationFromMapConfiguration( + MapConfiguration config) { + return PlatformMapConfiguration( + compassEnabled: config.compassEnabled, + cameraTargetBounds: _platformCameraTargetBoundsFromCameraTargetBounds( + config.cameraTargetBounds), + mapType: _platformMapTypeFromMapType(config.mapType), + minMaxZoomPreference: + _platformZoomRangeFromMinMaxZoomPreference(config.minMaxZoomPreference), + rotateGesturesEnabled: config.rotateGesturesEnabled, + scrollGesturesEnabled: config.scrollGesturesEnabled, + tiltGesturesEnabled: config.tiltGesturesEnabled, + trackCameraPosition: config.trackCameraPosition, + zoomGesturesEnabled: config.zoomGesturesEnabled, + myLocationEnabled: config.myLocationEnabled, + myLocationButtonEnabled: config.myLocationButtonEnabled, + padding: _platformEdgeInsetsFromEdgeInsets(config.padding), + indoorViewEnabled: config.indoorViewEnabled, + trafficEnabled: config.trafficEnabled, + buildingsEnabled: config.buildingsEnabled, + cloudMapId: config.cloudMapId, + style: config.style, + ); +} + Map _jsonForMapConfiguration(MapConfiguration config) { final EdgeInsets? padding = config.padding; return { if (config.compassEnabled != null) 'compassEnabled': config.compassEnabled!, - if (config.mapToolbarEnabled != null) - 'mapToolbarEnabled': config.mapToolbarEnabled!, if (config.cameraTargetBounds != null) 'cameraTargetBounds': config.cameraTargetBounds!.toJson(), if (config.mapType != null) 'mapType': config.mapType!.index, @@ -708,12 +789,8 @@ Map _jsonForMapConfiguration(MapConfiguration config) { 'scrollGesturesEnabled': config.scrollGesturesEnabled!, if (config.tiltGesturesEnabled != null) 'tiltGesturesEnabled': config.tiltGesturesEnabled!, - if (config.zoomControlsEnabled != null) - 'zoomControlsEnabled': config.zoomControlsEnabled!, if (config.zoomGesturesEnabled != null) 'zoomGesturesEnabled': config.zoomGesturesEnabled!, - if (config.liteModeEnabled != null) - 'liteModeEnabled': config.liteModeEnabled!, if (config.trackCameraPosition != null) 'trackCameraPosition': config.trackCameraPosition!, if (config.myLocationEnabled != null) @@ -737,6 +814,97 @@ Map _jsonForMapConfiguration(MapConfiguration config) { }; } +// For supporting the deprecated updateMapOptions API. +PlatformMapConfiguration _platformMapConfigurationFromOptionsJson( + Map options) { + // All of these hard-coded values and structures come from + // google_maps_flutter_platform_interface/lib/src/types/utils/map_configuration_serialization.dart + // to support this legacy API that relied on cross-package magic strings. + final List? padding = + (options['padding'] as List?)?.cast(); + final int? mapType = options['mapType'] as int?; + return PlatformMapConfiguration( + compassEnabled: options['compassEnabled'] as bool?, + cameraTargetBounds: _platformCameraTargetBoundsFromCameraTargetBoundsJson( + options['cameraTargetBounds']), + mapType: mapType == null ? null : _platformMapTypeFromMapTypeIndex(mapType), + minMaxZoomPreference: _platformZoomRangeFromMinMaxZoomPreferenceJson( + options['minMaxZoomPreference']), + rotateGesturesEnabled: options['rotateGesturesEnabled'] as bool?, + scrollGesturesEnabled: options['scrollGesturesEnabled'] as bool?, + tiltGesturesEnabled: options['tiltGesturesEnabled'] as bool?, + trackCameraPosition: options['trackCameraPosition'] as bool?, + zoomGesturesEnabled: options['zoomGesturesEnabled'] as bool?, + myLocationEnabled: options['myLocationEnabled'] as bool?, + myLocationButtonEnabled: options['myLocationButtonEnabled'] as bool?, + padding: padding == null + ? null + : PlatformEdgeInsets( + top: padding[0], + left: padding[1], + bottom: padding[2], + right: padding[3]), + indoorViewEnabled: options['indoorEnabled'] as bool?, + trafficEnabled: options['trafficEnabled'] as bool?, + buildingsEnabled: options['buildingsEnabled'] as bool?, + cloudMapId: options['cloudMapId'] as String?, + style: options['style'] as String?, + ); +} + +PlatformMapType _platformMapTypeFromMapTypeIndex(int index) { + // This is inherently fragile, but see comment in updateMapOptions. + return switch (index) { + 0 => PlatformMapType.none, + 1 => PlatformMapType.normal, + 2 => PlatformMapType.satellite, + 3 => PlatformMapType.terrain, + 4 => PlatformMapType.hybrid, + // For a new, unsupported type, just use normal. + _ => PlatformMapType.normal, + }; +} + +PlatformLatLng _platformLatLngFromLatLngJson(Object latLngJson) { + // See `LatLng.toJson`. + final List list = (latLngJson as List).cast(); + return PlatformLatLng(latitude: list[0], longitude: list[1]); +} + +PlatformLatLngBounds? _platformLatLngBoundsFromLatLngBoundsJson( + Object? boundsJson) { + if (boundsJson == null) { + return null; + } + // See `LatLngBounds.toJson`. + final List boundsList = (boundsJson as List).cast(); + return PlatformLatLngBounds( + southwest: _platformLatLngFromLatLngJson(boundsList[0]), + northeast: _platformLatLngFromLatLngJson(boundsList[1])); +} + +PlatformCameraTargetBounds? + _platformCameraTargetBoundsFromCameraTargetBoundsJson(Object? targetJson) { + if (targetJson == null) { + return null; + } + // See `CameraTargetBounds.toJson`. + return PlatformCameraTargetBounds( + bounds: _platformLatLngBoundsFromLatLngBoundsJson( + (targetJson as List)[0])); +} + +PlatformZoomRange? _platformZoomRangeFromMinMaxZoomPreferenceJson( + Object? zoomPrefsJson) { + if (zoomPrefsJson == null) { + return null; + } + // See `MinMaxZoomPreference.toJson`. + final List minMaxZoom = + (zoomPrefsJson as List).cast(); + return PlatformZoomRange(min: minMaxZoom[0], max: minMaxZoom[1]); +} + /// Update specification for a set of [TileOverlay]s. // TODO(stuartmorgan): Fix the missing export of this class in the platform // interface, and remove this copy. diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/lib/src/messages.g.dart b/packages/google_maps_flutter/google_maps_flutter_ios/lib/src/messages.g.dart index be309537588..991b057f432 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/lib/src/messages.g.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios/lib/src/messages.g.dart @@ -29,6 +29,15 @@ List wrapResponse( return [error.code, error.message, error.details]; } +/// Pigeon equivalent of MapType +enum PlatformMapType { + none, + normal, + satellite, + terrain, + hybrid, +} + /// Pigeon representatation of a CameraPosition. class PlatformCameraPosition { PlatformCameraPosition({ @@ -248,6 +257,43 @@ class PlatformTileOverlay { } } +/// Pigeon equivalent of Flutter's EdgeInsets. +class PlatformEdgeInsets { + PlatformEdgeInsets({ + required this.top, + required this.bottom, + required this.left, + required this.right, + }); + + double top; + + double bottom; + + double left; + + double right; + + Object encode() { + return [ + top, + bottom, + left, + right, + ]; + } + + static PlatformEdgeInsets decode(Object result) { + result as List; + return PlatformEdgeInsets( + top: result[0]! as double, + bottom: result[1]! as double, + left: result[2]! as double, + right: result[3]! as double, + ); + } +} + /// Pigeon equivalent of LatLng. class PlatformLatLng { PlatformLatLng({ @@ -302,27 +348,129 @@ class PlatformLatLngBounds { } } +/// Pigeon equivalent of CameraTargetBounds. +/// +/// As with the Dart version, it exists to distinguish between not setting a +/// a target, and having an explicitly unbounded target (null [bounds]). +class PlatformCameraTargetBounds { + PlatformCameraTargetBounds({ + this.bounds, + }); + + PlatformLatLngBounds? bounds; + + Object encode() { + return [ + bounds, + ]; + } + + static PlatformCameraTargetBounds decode(Object result) { + result as List; + return PlatformCameraTargetBounds( + bounds: result[0] as PlatformLatLngBounds?, + ); + } +} + /// Pigeon equivalent of MapConfiguration. class PlatformMapConfiguration { PlatformMapConfiguration({ - required this.json, + this.compassEnabled, + this.cameraTargetBounds, + this.mapType, + this.minMaxZoomPreference, + this.rotateGesturesEnabled, + this.scrollGesturesEnabled, + this.tiltGesturesEnabled, + this.trackCameraPosition, + this.zoomGesturesEnabled, + this.myLocationEnabled, + this.myLocationButtonEnabled, + this.padding, + this.indoorViewEnabled, + this.trafficEnabled, + this.buildingsEnabled, + this.cloudMapId, + this.style, }); - /// The configuration options, as JSON. This should only be set from - /// _jsonForMapConfiguration, and the native code must intepret it according - /// to the internal implementation details of that method. - Object json; + bool? compassEnabled; + + PlatformCameraTargetBounds? cameraTargetBounds; + + PlatformMapType? mapType; + + PlatformZoomRange? minMaxZoomPreference; + + bool? rotateGesturesEnabled; + + bool? scrollGesturesEnabled; + + bool? tiltGesturesEnabled; + + bool? trackCameraPosition; + + bool? zoomGesturesEnabled; + + bool? myLocationEnabled; + + bool? myLocationButtonEnabled; + + PlatformEdgeInsets? padding; + + bool? indoorViewEnabled; + + bool? trafficEnabled; + + bool? buildingsEnabled; + + String? cloudMapId; + + String? style; Object encode() { return [ - json, + compassEnabled, + cameraTargetBounds, + mapType, + minMaxZoomPreference, + rotateGesturesEnabled, + scrollGesturesEnabled, + tiltGesturesEnabled, + trackCameraPosition, + zoomGesturesEnabled, + myLocationEnabled, + myLocationButtonEnabled, + padding, + indoorViewEnabled, + trafficEnabled, + buildingsEnabled, + cloudMapId, + style, ]; } static PlatformMapConfiguration decode(Object result) { result as List; return PlatformMapConfiguration( - json: result[0]!, + compassEnabled: result[0] as bool?, + cameraTargetBounds: result[1] as PlatformCameraTargetBounds?, + mapType: result[2] as PlatformMapType?, + minMaxZoomPreference: result[3] as PlatformZoomRange?, + rotateGesturesEnabled: result[4] as bool?, + scrollGesturesEnabled: result[5] as bool?, + tiltGesturesEnabled: result[6] as bool?, + trackCameraPosition: result[7] as bool?, + zoomGesturesEnabled: result[8] as bool?, + myLocationEnabled: result[9] as bool?, + myLocationButtonEnabled: result[10] as bool?, + padding: result[11] as PlatformEdgeInsets?, + indoorViewEnabled: result[12] as bool?, + trafficEnabled: result[13] as bool?, + buildingsEnabled: result[14] as bool?, + cloudMapId: result[15] as String?, + style: result[16] as String?, ); } } @@ -394,13 +542,13 @@ class PlatformTileLayer { /// Pigeon equivalent of MinMaxZoomPreference. class PlatformZoomRange { PlatformZoomRange({ - required this.min, - required this.max, + this.min, + this.max, }); - double min; + double? min; - double max; + double? max; Object encode() { return [ @@ -412,8 +560,8 @@ class PlatformZoomRange { static PlatformZoomRange decode(Object result) { result as List; return PlatformZoomRange( - min: result[0]! as double, - max: result[1]! as double, + min: result[0] as double?, + max: result[1] as double?, ); } } @@ -446,24 +594,33 @@ class _PigeonCodec extends StandardMessageCodec { } else if (value is PlatformTileOverlay) { buffer.putUint8(136); writeValue(buffer, value.encode()); - } else if (value is PlatformLatLng) { + } else if (value is PlatformEdgeInsets) { buffer.putUint8(137); writeValue(buffer, value.encode()); - } else if (value is PlatformLatLngBounds) { + } else if (value is PlatformLatLng) { buffer.putUint8(138); writeValue(buffer, value.encode()); - } else if (value is PlatformMapConfiguration) { + } else if (value is PlatformLatLngBounds) { buffer.putUint8(139); writeValue(buffer, value.encode()); - } else if (value is PlatformPoint) { + } else if (value is PlatformCameraTargetBounds) { buffer.putUint8(140); writeValue(buffer, value.encode()); - } else if (value is PlatformTileLayer) { + } else if (value is PlatformMapConfiguration) { buffer.putUint8(141); writeValue(buffer, value.encode()); - } else if (value is PlatformZoomRange) { + } else if (value is PlatformPoint) { buffer.putUint8(142); writeValue(buffer, value.encode()); + } else if (value is PlatformTileLayer) { + buffer.putUint8(143); + writeValue(buffer, value.encode()); + } else if (value is PlatformZoomRange) { + buffer.putUint8(144); + writeValue(buffer, value.encode()); + } else if (value is PlatformMapType) { + buffer.putUint8(145); + writeValue(buffer, value.index); } else { super.writeValue(buffer, value); } @@ -489,17 +646,24 @@ class _PigeonCodec extends StandardMessageCodec { case 136: return PlatformTileOverlay.decode(readValue(buffer)!); case 137: - return PlatformLatLng.decode(readValue(buffer)!); + return PlatformEdgeInsets.decode(readValue(buffer)!); case 138: - return PlatformLatLngBounds.decode(readValue(buffer)!); + return PlatformLatLng.decode(readValue(buffer)!); case 139: - return PlatformMapConfiguration.decode(readValue(buffer)!); + return PlatformLatLngBounds.decode(readValue(buffer)!); case 140: - return PlatformPoint.decode(readValue(buffer)!); + return PlatformCameraTargetBounds.decode(readValue(buffer)!); case 141: - return PlatformTileLayer.decode(readValue(buffer)!); + return PlatformMapConfiguration.decode(readValue(buffer)!); case 142: + return PlatformPoint.decode(readValue(buffer)!); + case 143: + return PlatformTileLayer.decode(readValue(buffer)!); + case 144: return PlatformZoomRange.decode(readValue(buffer)!); + case 145: + final int? value = readValue(buffer) as int?; + return value == null ? null : PlatformMapType.values[value]; default: return super.readValueOfType(type, buffer); } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/pigeons/messages.dart b/packages/google_maps_flutter/google_maps_flutter_ios/pigeons/messages.dart index 19db3aa8502..9b34082a7a2 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/pigeons/messages.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios/pigeons/messages.dart @@ -12,6 +12,15 @@ import 'package:pigeon/pigeon.dart'; copyrightHeader: 'pigeons/copyright.txt', )) +/// Pigeon equivalent of MapType +enum PlatformMapType { + none, + normal, + satellite, + terrain, + hybrid, +} + /// Pigeon representatation of a CameraPosition. class PlatformCameraPosition { PlatformCameraPosition({ @@ -111,6 +120,21 @@ class PlatformTileOverlay { final Object json; } +/// Pigeon equivalent of Flutter's EdgeInsets. +class PlatformEdgeInsets { + PlatformEdgeInsets({ + required this.top, + required this.bottom, + required this.left, + required this.right, + }); + + final double top; + final double bottom; + final double left; + final double right; +} + /// Pigeon equivalent of LatLng. class PlatformLatLng { PlatformLatLng({required this.latitude, required this.longitude}); @@ -127,16 +151,55 @@ class PlatformLatLngBounds { final PlatformLatLng southwest; } +/// Pigeon equivalent of CameraTargetBounds. +/// +/// As with the Dart version, it exists to distinguish between not setting a +/// a target, and having an explicitly unbounded target (null [bounds]). +class PlatformCameraTargetBounds { + PlatformCameraTargetBounds({required this.bounds}); + + final PlatformLatLngBounds? bounds; +} + /// Pigeon equivalent of MapConfiguration. class PlatformMapConfiguration { - PlatformMapConfiguration({required this.json}); + PlatformMapConfiguration({ + required this.compassEnabled, + required this.cameraTargetBounds, + required this.mapType, + required this.minMaxZoomPreference, + required this.rotateGesturesEnabled, + required this.scrollGesturesEnabled, + required this.tiltGesturesEnabled, + required this.trackCameraPosition, + required this.zoomGesturesEnabled, + required this.myLocationEnabled, + required this.myLocationButtonEnabled, + required this.padding, + required this.indoorViewEnabled, + required this.trafficEnabled, + required this.buildingsEnabled, + required this.cloudMapId, + required this.style, + }); - /// The configuration options, as JSON. This should only be set from - /// _jsonForMapConfiguration, and the native code must intepret it according - /// to the internal implementation details of that method. - // TODO(stuartmorgan): Replace this with structured data. This exists only to - // allow incremental migration to Pigeon. - final Object json; + final bool? compassEnabled; + final PlatformCameraTargetBounds? cameraTargetBounds; + final PlatformMapType? mapType; + final PlatformZoomRange? minMaxZoomPreference; + final bool? rotateGesturesEnabled; + final bool? scrollGesturesEnabled; + final bool? tiltGesturesEnabled; + final bool? trackCameraPosition; + final bool? zoomGesturesEnabled; + final bool? myLocationEnabled; + final bool? myLocationButtonEnabled; + final PlatformEdgeInsets? padding; + final bool? indoorViewEnabled; + final bool? trafficEnabled; + final bool? buildingsEnabled; + final String? cloudMapId; + final String? style; } /// Pigeon representation of an x,y coordinate. @@ -166,8 +229,8 @@ class PlatformTileLayer { class PlatformZoomRange { PlatformZoomRange({required this.min, required this.max}); - final double min; - final double max; + final double? min; + final double? max; } /// Interface for non-test interactions with the native SDK. diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/test/google_maps_flutter_ios_test.dart b/packages/google_maps_flutter/google_maps_flutter_ios/test/google_maps_flutter_ios_test.dart index a033db4f509..e13f11e4944 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/test/google_maps_flutter_ios_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios/test/google_maps_flutter_ios_test.dart @@ -209,10 +209,12 @@ void main() { setUpMockMap(mapId: mapId); // Set some arbitrary options. - const MapConfiguration config = MapConfiguration( + final CameraTargetBounds cameraBounds = CameraTargetBounds(LatLngBounds( + southwest: const LatLng(10, 20), northeast: const LatLng(30, 40))); + final MapConfiguration config = MapConfiguration( compassEnabled: true, - liteModeEnabled: false, mapType: MapType.terrain, + cameraTargetBounds: cameraBounds, ); await maps.updateMapConfiguration(config, mapId: mapId); @@ -220,16 +222,21 @@ void main() { verify(api.updateMapConfiguration(captureAny)); final PlatformMapConfiguration passedConfig = verification.captured[0] as PlatformMapConfiguration; - final Map passedConfigJson = - passedConfig.json as Map; // Each set option should be present. - expect(passedConfigJson['compassEnabled'], true); - expect(passedConfigJson['liteModeEnabled'], false); - expect(passedConfigJson['mapType'], MapType.terrain.index); + expect(passedConfig.compassEnabled, true); + expect(passedConfig.mapType, PlatformMapType.terrain); + expect(passedConfig.cameraTargetBounds?.bounds?.northeast.latitude, + cameraBounds.bounds?.northeast.latitude); + expect(passedConfig.cameraTargetBounds?.bounds?.northeast.longitude, + cameraBounds.bounds?.northeast.longitude); + expect(passedConfig.cameraTargetBounds?.bounds?.southwest.latitude, + cameraBounds.bounds?.southwest.latitude); + expect(passedConfig.cameraTargetBounds?.bounds?.southwest.longitude, + cameraBounds.bounds?.southwest.longitude); // Spot-check that unset options are not be present. - expect(passedConfigJson['myLocationEnabled'], isNull); - expect(passedConfigJson['cameraTargetBounds'], isNull); - expect(passedConfigJson['padding'], isNull); + expect(passedConfig.myLocationEnabled, isNull); + expect(passedConfig.minMaxZoomPreference, isNull); + expect(passedConfig.padding, isNull); }); test('updateMapOptions passes expected arguments', () async { @@ -238,10 +245,12 @@ void main() { setUpMockMap(mapId: mapId); // Set some arbitrary options. + final CameraTargetBounds cameraBounds = CameraTargetBounds(LatLngBounds( + southwest: const LatLng(10, 20), northeast: const LatLng(30, 40))); final Map config = { 'compassEnabled': true, - 'liteModeEnabled': false, 'mapType': MapType.terrain.index, + 'cameraTargetBounds': cameraBounds.toJson(), }; await maps.updateMapOptions(config, mapId: mapId); @@ -249,16 +258,21 @@ void main() { verify(api.updateMapConfiguration(captureAny)); final PlatformMapConfiguration passedConfig = verification.captured[0] as PlatformMapConfiguration; - final Map passedConfigJson = - passedConfig.json as Map; // Each set option should be present. - expect(passedConfigJson['compassEnabled'], true); - expect(passedConfigJson['liteModeEnabled'], false); - expect(passedConfigJson['mapType'], MapType.terrain.index); + expect(passedConfig.compassEnabled, true); + expect(passedConfig.mapType, PlatformMapType.terrain); + expect(passedConfig.cameraTargetBounds?.bounds?.northeast.latitude, + cameraBounds.bounds?.northeast.latitude); + expect(passedConfig.cameraTargetBounds?.bounds?.northeast.longitude, + cameraBounds.bounds?.northeast.longitude); + expect(passedConfig.cameraTargetBounds?.bounds?.southwest.latitude, + cameraBounds.bounds?.southwest.latitude); + expect(passedConfig.cameraTargetBounds?.bounds?.southwest.longitude, + cameraBounds.bounds?.southwest.longitude); // Spot-check that unset options are not be present. - expect(passedConfigJson['myLocationEnabled'], isNull); - expect(passedConfigJson['cameraTargetBounds'], isNull); - expect(passedConfigJson['padding'], isNull); + expect(passedConfig.myLocationEnabled, isNull); + expect(passedConfig.minMaxZoomPreference, isNull); + expect(passedConfig.padding, isNull); }); test('updateCircles passes expected arguments', () async { From f88eb975e475886fe5cc39fdd3afa4a3fb680441 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 16 Jul 2024 13:05:04 -0400 Subject: [PATCH 02/14] Convert iOS native --- ...TGoogleMapJSONConversionsConversionTests.m | 8 ++ .../ios/Classes/FLTGoogleMapJSONConversions.h | 7 ++ .../ios/Classes/FLTGoogleMapJSONConversions.m | 21 +++++ .../ios/Classes/GoogleMapController.m | 83 +++++++++++++++++-- 4 files changed, 114 insertions(+), 5 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/FLTGoogleMapJSONConversionsConversionTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/FLTGoogleMapJSONConversionsConversionTests.m index 79da52d8198..d6594387330 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/FLTGoogleMapJSONConversionsConversionTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/FLTGoogleMapJSONConversionsConversionTests.m @@ -183,6 +183,14 @@ - (void)testMapViewTypeFromTypeValue { XCTAssertEqual(kGMSTypeNone, [FLTGoogleMapJSONConversions mapViewTypeFromTypeValue:@5]); } +- (void)testMapViewTypeFromPigeonType { + XCTAssertEqual(kGMSTypeNormal, FGMGetMapViewTypeForPigeonMapType(FGMPlatformMapTypeNormal)); + XCTAssertEqual(kGMSTypeSatellite, FGMGetMapViewTypeForPigeonMapType(FGMPlatformMapTypeSatellite)); + XCTAssertEqual(kGMSTypeTerrain, FGMGetMapViewTypeForPigeonMapType(FGMPlatformMapTypeTerrain)); + XCTAssertEqual(kGMSTypeHybrid, FGMGetMapViewTypeForPigeonMapType(FGMPlatformMapTypeHybrid)); + XCTAssertEqual(kGMSTypeNone, FGMGetMapViewTypeForPigeonMapType(FGMPlatformMapTypeNone)); +} + - (void)testCameraUpdateFromArrayNewCameraPosition { NSArray *channelValue = @[ @"newCameraPosition", @{@"target" : @[ @1, @2 ], @"zoom" : @3, @"bearing" : @4, @"tilt" : @5} diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.h index 5d45ddd7be7..5c9db91363b 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.h @@ -24,6 +24,10 @@ extern CLLocationCoordinate2D FGMGetCoordinateForPigeonLatLng(FGMPlatformLatLng /// Converts a CLLocationCoordinate2D to its Pigeon representation. extern FGMPlatformLatLng *FGMGetPigeonLatLngForCoordinate(CLLocationCoordinate2D coord); +/// Creates a GMSCoordinateBounds from its Pigeon representation. +extern GMSCoordinateBounds *FGMGetCoordinateBoundsForPigeonLatLngBounds( + FGMPlatformLatLngBounds *bounds); + /// Converts a GMSCoordinateBounds to its Pigeon representation. extern FGMPlatformLatLngBounds *FGMGetPigeonLatLngBoundsForCoordinateBounds( GMSCoordinateBounds *bounds); @@ -32,6 +36,9 @@ extern FGMPlatformLatLngBounds *FGMGetPigeonLatLngBoundsForCoordinateBounds( extern FGMPlatformCameraPosition *FGMGetPigeonCameraPositionForPosition( GMSCameraPosition *position); +/// Creates a GMSMapViewType from its Pigeon representation. +extern GMSMapViewType FGMGetMapViewTypeForPigeonMapType(FGMPlatformMapType type); + @interface FLTGoogleMapJSONConversions : NSObject + (CLLocationCoordinate2D)locationFromLatLong:(NSArray *)latlong; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.m index 56db3fbee0c..e6b4c853806 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.m @@ -26,6 +26,12 @@ CLLocationCoordinate2D FGMGetCoordinateForPigeonLatLng(FGMPlatformLatLng *latLng return [FGMPlatformLatLng makeWithLatitude:coord.latitude longitude:coord.longitude]; } +GMSCoordinateBounds *FGMGetCoordinateBoundsForPigeonLatLngBounds(FGMPlatformLatLngBounds *bounds) { + return [[GMSCoordinateBounds alloc] + initWithCoordinate:FGMGetCoordinateForPigeonLatLng(bounds.northeast) + coordinate:FGMGetCoordinateForPigeonLatLng(bounds.southwest)]; +} + FGMPlatformLatLngBounds *FGMGetPigeonLatLngBoundsForCoordinateBounds(GMSCoordinateBounds *bounds) { return [FGMPlatformLatLngBounds makeWithNortheast:FGMGetPigeonLatLngForCoordinate(bounds.northEast) @@ -39,6 +45,21 @@ CLLocationCoordinate2D FGMGetCoordinateForPigeonLatLng(FGMPlatformLatLng *latLng zoom:position.zoom]; } +extern GMSMapViewType FGMGetMapViewTypeForPigeonMapType(FGMPlatformMapType type) { + switch (type) { + case FGMPlatformMapTypeNone: + return kGMSTypeNone; + case FGMPlatformMapTypeNormal: + return kGMSTypeNormal; + case FGMPlatformMapTypeSatellite: + return kGMSTypeSatellite; + case FGMPlatformMapTypeTerrain: + return kGMSTypeTerrain; + case FGMPlatformMapTypeHybrid: + return kGMSTypeHybrid; + } +} + @implementation FLTGoogleMapJSONConversions + (CLLocationCoordinate2D)locationFromLatLong:(NSArray *)latlong { diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController.m index 8a69f712ba3..02e668cc21b 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController.m @@ -164,7 +164,7 @@ - (instancetype)initWithMapView:(GMSMapView *_Nonnull)mapView _mapView.accessibilityElementsHidden = NO; // TODO(cyanglaz): avoid sending message to self in the middle of the init method. // https://github.com/flutter/flutter/issues/104121 - [self interpretMapOptions:args[@"options"]]; + [self interpretMapOptionsJSON:args[@"options"]]; NSString *pigeonSuffix = [NSString stringWithFormat:@"%lld", viewId]; _dartCallbackHandler = [[FGMMapsCallbackApi alloc] initWithBinaryMessenger:registrar.messenger messageChannelSuffix:pigeonSuffix]; @@ -423,7 +423,80 @@ - (void)mapView:(GMSMapView *)mapView didLongPressAtCoordinate:(CLLocationCoordi }]; } -- (void)interpretMapOptions:(NSDictionary *)data { +- (void)interpretMapConfiguration:(FGMPlatformMapConfiguration *)config { + FGMPlatformCameraTargetBounds *cameraTargetBounds = config.cameraTargetBounds; + if (cameraTargetBounds) { + [self setCameraTargetBounds:cameraTargetBounds.bounds + ? FGMGetCoordinateBoundsForPigeonLatLngBounds( + cameraTargetBounds.bounds) + : nil]; + } + NSNumber *compassEnabled = config.compassEnabled; + if (compassEnabled) { + [self setCompassEnabled:compassEnabled.boolValue]; + } + NSNumber *indoorEnabled = config.indoorViewEnabled; + if (indoorEnabled) { + [self setIndoorEnabled:indoorEnabled.boolValue]; + } + NSNumber *trafficEnabled = config.trafficEnabled; + if (trafficEnabled) { + [self setTrafficEnabled:trafficEnabled.boolValue]; + } + NSNumber *buildingsEnabled = config.buildingsEnabled; + if (buildingsEnabled) { + [self setBuildingsEnabled:buildingsEnabled.boolValue]; + } + FGMPlatformMapTypeBox *mapType = config.mapType; + if (mapType) { + [self setMapType:FGMGetMapViewTypeForPigeonMapType(mapType.value)]; + } + FGMPlatformZoomRange *zoomData = config.minMaxZoomPreference; + if (zoomData) { + float minZoom = zoomData.min ? zoomData.min.floatValue : kGMSMinZoomLevel; + float maxZoom = zoomData.max ? zoomData.max.floatValue : kGMSMaxZoomLevel; + [self setMinZoom:minZoom maxZoom:maxZoom]; + } + FGMPlatformEdgeInsets *padding = config.padding; + if (padding) { + [self setPaddingTop:padding.top left:padding.left bottom:padding.bottom right:padding.right]; + } + + NSNumber *rotateGesturesEnabled = config.rotateGesturesEnabled; + if (rotateGesturesEnabled) { + [self setRotateGesturesEnabled:rotateGesturesEnabled.boolValue]; + } + NSNumber *scrollGesturesEnabled = config.scrollGesturesEnabled; + if (scrollGesturesEnabled) { + [self setScrollGesturesEnabled:scrollGesturesEnabled.boolValue]; + } + NSNumber *tiltGesturesEnabled = config.tiltGesturesEnabled; + if (tiltGesturesEnabled) { + [self setTiltGesturesEnabled:tiltGesturesEnabled.boolValue]; + } + NSNumber *trackCameraPosition = config.trackCameraPosition; + if (trackCameraPosition) { + [self setTrackCameraPosition:trackCameraPosition.boolValue]; + } + NSNumber *zoomGesturesEnabled = config.zoomGesturesEnabled; + if (zoomGesturesEnabled) { + [self setZoomGesturesEnabled:zoomGesturesEnabled.boolValue]; + } + NSNumber *myLocationEnabled = config.myLocationEnabled; + if (myLocationEnabled) { + [self setMyLocationEnabled:myLocationEnabled.boolValue]; + } + NSNumber *myLocationButtonEnabled = config.myLocationButtonEnabled; + if (myLocationButtonEnabled) { + [self setMyLocationButtonEnabled:myLocationButtonEnabled.boolValue]; + } + NSString *style = config.style; + if (style) { + [self setMapStyle:style]; + } +} + +- (void)interpretMapOptionsJSON:(NSDictionary *)data { NSArray *cameraTargetBounds = FGMGetValueOrNilFromDict(data, @"cameraTargetBounds"); if (cameraTargetBounds) { [self @@ -534,7 +607,7 @@ - (void)updateCirclesByAdding:(nonnull NSArray *)toAdd - (void)updateWithMapConfiguration:(nonnull FGMPlatformMapConfiguration *)configuration error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller interpretMapOptions:configuration.json]; + [self.controller interpretMapConfiguration:configuration]; } - (void)updateMarkersByAdding:(nonnull NSArray *)toAdd @@ -771,8 +844,8 @@ - (nullable NSNumber *)isTrafficEnabledWithError: - (nullable FGMPlatformZoomRange *)zoomRange: (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return [FGMPlatformZoomRange makeWithMin:self.controller.mapView.minZoom - max:self.controller.mapView.maxZoom]; + return [FGMPlatformZoomRange makeWithMin:@(self.controller.mapView.minZoom) + max:@(self.controller.mapView.maxZoom)]; } @end From 46e08056f9b62495ab259efcc21df74949fa4151 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Mon, 22 Jul 2024 14:51:49 -0400 Subject: [PATCH 03/14] Add Android native unit tests --- .../flutter/plugins/googlemaps/Convert.java | 150 +++- .../googlemaps/GoogleMapController.java | 2 +- .../flutter/plugins/googlemaps/Messages.java | 814 ++++++++++++++++-- .../plugins/googlemaps/ConvertTest.java | 201 +++++ .../lib/src/google_maps_flutter_android.dart | 193 ++++- .../lib/src/messages.g.dart | 235 ++++- .../pigeons/messages.dart | 87 +- .../google_maps_flutter_android_test.dart | 52 +- 8 files changed, 1577 insertions(+), 157 deletions(-) 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 d9caf66d688..529100a0c68 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 @@ -4,6 +4,12 @@ package io.flutter.plugins.googlemaps; +import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_HYBRID; +import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_NONE; +import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_NORMAL; +import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_SATELLITE; +import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_TERRAIN; + import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -359,6 +365,22 @@ private static int toInt(Object o) { return ((Number) o).intValue(); } + static int toMapType(@NonNull Messages.PlatformMapType type) { + switch (type) { + case NONE: + return MAP_TYPE_NONE; + case NORMAL: + return MAP_TYPE_NORMAL; + case SATELLITE: + return MAP_TYPE_SATELLITE; + case TERRAIN: + return MAP_TYPE_TERRAIN; + case HYBRID: + return MAP_TYPE_HYBRID; + } + return MAP_TYPE_NORMAL; + } + static @Nullable MapsInitializer.Renderer toMapRendererType( @Nullable Messages.PlatformRendererType type) { if (type == null) { @@ -383,13 +405,6 @@ private static int toInt(Object o) { .build(); } - static Object latLngBoundsToJson(LatLngBounds latLngBounds) { - final Map arguments = new HashMap<>(2); - arguments.put("southwest", latLngToJson(latLngBounds.southwest)); - arguments.put("northeast", latLngToJson(latLngBounds.northeast)); - return arguments; - } - static Messages.PlatformLatLngBounds latLngBoundsToPigeon(LatLngBounds latLngBounds) { return new Messages.PlatformLatLngBounds.Builder() .setNortheast(latLngToPigeon(latLngBounds.northeast)) @@ -397,35 +412,10 @@ static Messages.PlatformLatLngBounds latLngBoundsToPigeon(LatLngBounds latLngBou .build(); } - static Object markerIdToJson(String markerId) { - if (markerId == null) { - return null; - } - final Map data = new HashMap<>(1); - data.put("markerId", markerId); - return data; - } - - static Object polygonIdToJson(String polygonId) { - if (polygonId == null) { - return null; - } - final Map data = new HashMap<>(1); - data.put("polygonId", polygonId); - return data; - } - - static Object polylineIdToJson(String polylineId) { - if (polylineId == null) { - return null; - } - final Map data = new HashMap<>(1); - data.put("polylineId", polylineId); - return data; - } - - static Object latLngToJson(LatLng latLng) { - return Arrays.asList(latLng.latitude, latLng.longitude); + static @NonNull LatLngBounds latLngBoundsFromPigeon( + @NonNull Messages.PlatformLatLngBounds bounds) { + return new LatLngBounds( + latLngFromPigeon(bounds.getSouthwest()), latLngFromPigeon(bounds.getNortheast())); } static Messages.PlatformLatLng latLngToPigeon(LatLng latLng) { @@ -636,6 +626,94 @@ static void interpretGoogleMapOptions(Object o, GoogleMapOptionsSink sink) { } } + static void interpretMapConfiguration( + @NonNull Messages.PlatformMapConfiguration config, @NonNull GoogleMapOptionsSink sink) { + final Messages.PlatformCameraTargetBounds cameraTargetBounds = config.getCameraTargetBounds(); + if (cameraTargetBounds != null) { + final @Nullable Messages.PlatformLatLngBounds bounds = cameraTargetBounds.getBounds(); + sink.setCameraTargetBounds(bounds == null ? null : latLngBoundsFromPigeon(bounds)); + } + final Boolean compassEnabled = config.getCompassEnabled(); + if (compassEnabled != null) { + sink.setCompassEnabled(compassEnabled); + } + final Boolean mapToolbarEnabled = config.getMapToolbarEnabled(); + if (mapToolbarEnabled != null) { + sink.setMapToolbarEnabled(mapToolbarEnabled); + } + final Messages.PlatformMapType mapType = config.getMapType(); + if (mapType != null) { + sink.setMapType(toMapType(mapType)); + } + final Messages.PlatformZoomRange minMaxZoomPreference = config.getMinMaxZoomPreference(); + if (minMaxZoomPreference != null) { + final List zoomPreferenceData = toList(minMaxZoomPreference); + sink.setMinMaxZoomPreference( // + toFloatWrapper(zoomPreferenceData.get(0)), // + toFloatWrapper(zoomPreferenceData.get(1))); + } + final Messages.PlatformEdgeInsets padding = config.getPadding(); + if (padding != null) { + sink.setPadding( + padding.getTop().floatValue(), + padding.getLeft().floatValue(), + padding.getBottom().floatValue(), + padding.getRight().floatValue()); + } + final Boolean rotateGesturesEnabled = config.getRotateGesturesEnabled(); + if (rotateGesturesEnabled != null) { + sink.setRotateGesturesEnabled(rotateGesturesEnabled); + } + final Boolean scrollGesturesEnabled = config.getScrollGesturesEnabled(); + if (scrollGesturesEnabled != null) { + sink.setScrollGesturesEnabled(scrollGesturesEnabled); + } + final Boolean tiltGesturesEnabled = config.getTiltGesturesEnabled(); + if (tiltGesturesEnabled != null) { + sink.setTiltGesturesEnabled(tiltGesturesEnabled); + } + final Boolean trackCameraPosition = config.getTrackCameraPosition(); + if (trackCameraPosition != null) { + sink.setTrackCameraPosition(trackCameraPosition); + } + final Boolean zoomGesturesEnabled = config.getZoomGesturesEnabled(); + if (zoomGesturesEnabled != null) { + sink.setZoomGesturesEnabled(zoomGesturesEnabled); + } + final Boolean liteModeEnabled = config.getLiteModeEnabled(); + if (liteModeEnabled != null) { + sink.setLiteModeEnabled(liteModeEnabled); + } + final Boolean myLocationEnabled = config.getMyLocationEnabled(); + if (myLocationEnabled != null) { + sink.setMyLocationEnabled(myLocationEnabled); + } + final Boolean zoomControlsEnabled = config.getZoomControlsEnabled(); + if (zoomControlsEnabled != null) { + sink.setZoomControlsEnabled(zoomControlsEnabled); + } + final Boolean myLocationButtonEnabled = config.getMyLocationButtonEnabled(); + if (myLocationButtonEnabled != null) { + sink.setMyLocationButtonEnabled(myLocationButtonEnabled); + } + final Boolean indoorEnabled = config.getIndoorViewEnabled(); + if (indoorEnabled != null) { + sink.setIndoorEnabled(indoorEnabled); + } + final Boolean trafficEnabled = config.getTrafficEnabled(); + if (trafficEnabled != null) { + sink.setTrafficEnabled(trafficEnabled); + } + final Boolean buildingsEnabled = config.getBuildingsEnabled(); + if (buildingsEnabled != null) { + sink.setBuildingsEnabled(buildingsEnabled); + } + final String style = config.getStyle(); + if (style != null) { + sink.setMapStyle(style); + } + } + /** Set the options in the given object to marker options sink. */ static void interpretMarkerOptions( Map data, MarkerOptionsSink sink, AssetManager assetManager, float density) { 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 3e8aaffe97c..fceb45e0db2 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 @@ -789,7 +789,7 @@ public void waitForMap(@NonNull Messages.VoidResult result) { @Override public void updateMapConfiguration(@NonNull Messages.PlatformMapConfiguration configuration) { - Convert.interpretGoogleMapOptions(configuration.getJson(), this); + Convert.interpretMapConfiguration(configuration, this); } @Override 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 index 2e5a61cb075..2e11402ac0d 100644 --- 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 @@ -74,6 +74,21 @@ protected static FlutterError createConnectionError(@NonNull String channelName) @Retention(CLASS) @interface CanIgnoreReturnValue {} + /** Pigeon equivalent of MapType */ + public enum PlatformMapType { + NONE(0), + NORMAL(1), + SATELLITE(2), + TERRAIN(3), + HYBRID(4); + + final int index; + + private PlatformMapType(final int index) { + this.index = index; + } + } + public enum PlatformRendererType { LEGACY(0), LATEST(1); @@ -882,6 +897,155 @@ ArrayList toList() { } } + /** + * Pigeon equivalent of Flutter's EdgeInsets. + * + *

Generated class from Pigeon that represents data sent in messages. + */ + public static final class PlatformEdgeInsets { + private @NonNull Double top; + + public @NonNull Double getTop() { + return top; + } + + public void setTop(@NonNull Double setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"top\" is null."); + } + this.top = setterArg; + } + + private @NonNull Double bottom; + + public @NonNull Double getBottom() { + return bottom; + } + + public void setBottom(@NonNull Double setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"bottom\" is null."); + } + this.bottom = setterArg; + } + + private @NonNull Double left; + + public @NonNull Double getLeft() { + return left; + } + + public void setLeft(@NonNull Double setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"left\" is null."); + } + this.left = setterArg; + } + + private @NonNull Double right; + + public @NonNull Double getRight() { + return right; + } + + public void setRight(@NonNull Double setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"right\" is null."); + } + this.right = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PlatformEdgeInsets() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PlatformEdgeInsets that = (PlatformEdgeInsets) o; + return top.equals(that.top) + && bottom.equals(that.bottom) + && left.equals(that.left) + && right.equals(that.right); + } + + @Override + public int hashCode() { + return Objects.hash(top, bottom, left, right); + } + + public static final class Builder { + + private @Nullable Double top; + + @CanIgnoreReturnValue + public @NonNull Builder setTop(@NonNull Double setterArg) { + this.top = setterArg; + return this; + } + + private @Nullable Double bottom; + + @CanIgnoreReturnValue + public @NonNull Builder setBottom(@NonNull Double setterArg) { + this.bottom = setterArg; + return this; + } + + private @Nullable Double left; + + @CanIgnoreReturnValue + public @NonNull Builder setLeft(@NonNull Double setterArg) { + this.left = setterArg; + return this; + } + + private @Nullable Double right; + + @CanIgnoreReturnValue + public @NonNull Builder setRight(@NonNull Double setterArg) { + this.right = setterArg; + return this; + } + + public @NonNull PlatformEdgeInsets build() { + PlatformEdgeInsets pigeonReturn = new PlatformEdgeInsets(); + pigeonReturn.setTop(top); + pigeonReturn.setBottom(bottom); + pigeonReturn.setLeft(left); + pigeonReturn.setRight(right); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(4); + toListResult.add(top); + toListResult.add(bottom); + toListResult.add(left); + toListResult.add(right); + return toListResult; + } + + static @NonNull PlatformEdgeInsets fromList(@NonNull ArrayList __pigeon_list) { + PlatformEdgeInsets pigeonResult = new PlatformEdgeInsets(); + Object top = __pigeon_list.get(0); + pigeonResult.setTop((Double) top); + Object bottom = __pigeon_list.get(1); + pigeonResult.setBottom((Double) bottom); + Object left = __pigeon_list.get(2); + pigeonResult.setLeft((Double) left); + Object right = __pigeon_list.get(3); + pigeonResult.setRight((Double) right); + return pigeonResult; + } + } + /** * Pigeon equivalent of LatLng. * @@ -1223,32 +1387,279 @@ ArrayList toList() { } } + /** + * Pigeon equivalent of CameraTargetBounds. + * + *

As with the Dart version, it exists to distinguish between not setting a a target, and + * having an explicitly unbounded target (null [bounds]). + * + *

Generated class from Pigeon that represents data sent in messages. + */ + public static final class PlatformCameraTargetBounds { + private @Nullable PlatformLatLngBounds bounds; + + public @Nullable PlatformLatLngBounds getBounds() { + return bounds; + } + + public void setBounds(@Nullable PlatformLatLngBounds setterArg) { + this.bounds = setterArg; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PlatformCameraTargetBounds that = (PlatformCameraTargetBounds) o; + return Objects.equals(bounds, that.bounds); + } + + @Override + public int hashCode() { + return Objects.hash(bounds); + } + + public static final class Builder { + + private @Nullable PlatformLatLngBounds bounds; + + @CanIgnoreReturnValue + public @NonNull Builder setBounds(@Nullable PlatformLatLngBounds setterArg) { + this.bounds = setterArg; + return this; + } + + public @NonNull PlatformCameraTargetBounds build() { + PlatformCameraTargetBounds pigeonReturn = new PlatformCameraTargetBounds(); + pigeonReturn.setBounds(bounds); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(1); + toListResult.add(bounds); + return toListResult; + } + + static @NonNull PlatformCameraTargetBounds fromList(@NonNull ArrayList __pigeon_list) { + PlatformCameraTargetBounds pigeonResult = new PlatformCameraTargetBounds(); + Object bounds = __pigeon_list.get(0); + pigeonResult.setBounds((PlatformLatLngBounds) bounds); + return pigeonResult; + } + } + /** * Pigeon equivalent of MapConfiguration. * *

Generated class from Pigeon that represents data sent in messages. */ public static final class PlatformMapConfiguration { - /** - * The configuration options, as JSON. This should only be set from _jsonForMapConfiguration, - * and the native code must intepret it according to the internal implementation details of that - * method. - */ - private @NonNull Map json; + private @Nullable Boolean compassEnabled; - public @NonNull Map getJson() { - return json; + public @Nullable Boolean getCompassEnabled() { + return compassEnabled; } - public void setJson(@NonNull Map setterArg) { - if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"json\" is null."); - } - this.json = setterArg; + public void setCompassEnabled(@Nullable Boolean setterArg) { + this.compassEnabled = setterArg; } - /** Constructor is non-public to enforce null safety; use Builder. */ - PlatformMapConfiguration() {} + private @Nullable PlatformCameraTargetBounds cameraTargetBounds; + + public @Nullable PlatformCameraTargetBounds getCameraTargetBounds() { + return cameraTargetBounds; + } + + public void setCameraTargetBounds(@Nullable PlatformCameraTargetBounds setterArg) { + this.cameraTargetBounds = setterArg; + } + + private @Nullable PlatformMapType mapType; + + public @Nullable PlatformMapType getMapType() { + return mapType; + } + + public void setMapType(@Nullable PlatformMapType setterArg) { + this.mapType = setterArg; + } + + private @Nullable PlatformZoomRange minMaxZoomPreference; + + public @Nullable PlatformZoomRange getMinMaxZoomPreference() { + return minMaxZoomPreference; + } + + public void setMinMaxZoomPreference(@Nullable PlatformZoomRange setterArg) { + this.minMaxZoomPreference = setterArg; + } + + private @Nullable Boolean mapToolbarEnabled; + + public @Nullable Boolean getMapToolbarEnabled() { + return mapToolbarEnabled; + } + + public void setMapToolbarEnabled(@Nullable Boolean setterArg) { + this.mapToolbarEnabled = setterArg; + } + + private @Nullable Boolean rotateGesturesEnabled; + + public @Nullable Boolean getRotateGesturesEnabled() { + return rotateGesturesEnabled; + } + + public void setRotateGesturesEnabled(@Nullable Boolean setterArg) { + this.rotateGesturesEnabled = setterArg; + } + + private @Nullable Boolean scrollGesturesEnabled; + + public @Nullable Boolean getScrollGesturesEnabled() { + return scrollGesturesEnabled; + } + + public void setScrollGesturesEnabled(@Nullable Boolean setterArg) { + this.scrollGesturesEnabled = setterArg; + } + + private @Nullable Boolean tiltGesturesEnabled; + + public @Nullable Boolean getTiltGesturesEnabled() { + return tiltGesturesEnabled; + } + + public void setTiltGesturesEnabled(@Nullable Boolean setterArg) { + this.tiltGesturesEnabled = setterArg; + } + + private @Nullable Boolean trackCameraPosition; + + public @Nullable Boolean getTrackCameraPosition() { + return trackCameraPosition; + } + + public void setTrackCameraPosition(@Nullable Boolean setterArg) { + this.trackCameraPosition = setterArg; + } + + private @Nullable Boolean zoomControlsEnabled; + + public @Nullable Boolean getZoomControlsEnabled() { + return zoomControlsEnabled; + } + + public void setZoomControlsEnabled(@Nullable Boolean setterArg) { + this.zoomControlsEnabled = setterArg; + } + + private @Nullable Boolean zoomGesturesEnabled; + + public @Nullable Boolean getZoomGesturesEnabled() { + return zoomGesturesEnabled; + } + + public void setZoomGesturesEnabled(@Nullable Boolean setterArg) { + this.zoomGesturesEnabled = setterArg; + } + + private @Nullable Boolean myLocationEnabled; + + public @Nullable Boolean getMyLocationEnabled() { + return myLocationEnabled; + } + + public void setMyLocationEnabled(@Nullable Boolean setterArg) { + this.myLocationEnabled = setterArg; + } + + private @Nullable Boolean myLocationButtonEnabled; + + public @Nullable Boolean getMyLocationButtonEnabled() { + return myLocationButtonEnabled; + } + + public void setMyLocationButtonEnabled(@Nullable Boolean setterArg) { + this.myLocationButtonEnabled = setterArg; + } + + private @Nullable PlatformEdgeInsets padding; + + public @Nullable PlatformEdgeInsets getPadding() { + return padding; + } + + public void setPadding(@Nullable PlatformEdgeInsets setterArg) { + this.padding = setterArg; + } + + private @Nullable Boolean indoorViewEnabled; + + public @Nullable Boolean getIndoorViewEnabled() { + return indoorViewEnabled; + } + + public void setIndoorViewEnabled(@Nullable Boolean setterArg) { + this.indoorViewEnabled = setterArg; + } + + private @Nullable Boolean trafficEnabled; + + public @Nullable Boolean getTrafficEnabled() { + return trafficEnabled; + } + + public void setTrafficEnabled(@Nullable Boolean setterArg) { + this.trafficEnabled = setterArg; + } + + private @Nullable Boolean buildingsEnabled; + + public @Nullable Boolean getBuildingsEnabled() { + return buildingsEnabled; + } + + public void setBuildingsEnabled(@Nullable Boolean setterArg) { + this.buildingsEnabled = setterArg; + } + + private @Nullable Boolean liteModeEnabled; + + public @Nullable Boolean getLiteModeEnabled() { + return liteModeEnabled; + } + + public void setLiteModeEnabled(@Nullable Boolean setterArg) { + this.liteModeEnabled = setterArg; + } + + private @Nullable String cloudMapId; + + public @Nullable String getCloudMapId() { + return cloudMapId; + } + + public void setCloudMapId(@Nullable String setterArg) { + this.cloudMapId = setterArg; + } + + private @Nullable String style; + + public @Nullable String getStyle() { + return style; + } + + public void setStyle(@Nullable String setterArg) { + this.style = setterArg; + } @Override public boolean equals(Object o) { @@ -1259,42 +1670,310 @@ public boolean equals(Object o) { return false; } PlatformMapConfiguration that = (PlatformMapConfiguration) o; - return json.equals(that.json); + return Objects.equals(compassEnabled, that.compassEnabled) + && Objects.equals(cameraTargetBounds, that.cameraTargetBounds) + && Objects.equals(mapType, that.mapType) + && Objects.equals(minMaxZoomPreference, that.minMaxZoomPreference) + && Objects.equals(mapToolbarEnabled, that.mapToolbarEnabled) + && Objects.equals(rotateGesturesEnabled, that.rotateGesturesEnabled) + && Objects.equals(scrollGesturesEnabled, that.scrollGesturesEnabled) + && Objects.equals(tiltGesturesEnabled, that.tiltGesturesEnabled) + && Objects.equals(trackCameraPosition, that.trackCameraPosition) + && Objects.equals(zoomControlsEnabled, that.zoomControlsEnabled) + && Objects.equals(zoomGesturesEnabled, that.zoomGesturesEnabled) + && Objects.equals(myLocationEnabled, that.myLocationEnabled) + && Objects.equals(myLocationButtonEnabled, that.myLocationButtonEnabled) + && Objects.equals(padding, that.padding) + && Objects.equals(indoorViewEnabled, that.indoorViewEnabled) + && Objects.equals(trafficEnabled, that.trafficEnabled) + && Objects.equals(buildingsEnabled, that.buildingsEnabled) + && Objects.equals(liteModeEnabled, that.liteModeEnabled) + && Objects.equals(cloudMapId, that.cloudMapId) + && Objects.equals(style, that.style); } @Override public int hashCode() { - return Objects.hash(json); + return Objects.hash( + compassEnabled, + cameraTargetBounds, + mapType, + minMaxZoomPreference, + mapToolbarEnabled, + rotateGesturesEnabled, + scrollGesturesEnabled, + tiltGesturesEnabled, + trackCameraPosition, + zoomControlsEnabled, + zoomGesturesEnabled, + myLocationEnabled, + myLocationButtonEnabled, + padding, + indoorViewEnabled, + trafficEnabled, + buildingsEnabled, + liteModeEnabled, + cloudMapId, + style); } public static final class Builder { - private @Nullable Map json; + private @Nullable Boolean compassEnabled; @CanIgnoreReturnValue - public @NonNull Builder setJson(@NonNull Map setterArg) { - this.json = setterArg; + public @NonNull Builder setCompassEnabled(@Nullable Boolean setterArg) { + this.compassEnabled = setterArg; + return this; + } + + private @Nullable PlatformCameraTargetBounds cameraTargetBounds; + + @CanIgnoreReturnValue + public @NonNull Builder setCameraTargetBounds( + @Nullable PlatformCameraTargetBounds setterArg) { + this.cameraTargetBounds = setterArg; + return this; + } + + private @Nullable PlatformMapType mapType; + + @CanIgnoreReturnValue + public @NonNull Builder setMapType(@Nullable PlatformMapType setterArg) { + this.mapType = setterArg; + return this; + } + + private @Nullable PlatformZoomRange minMaxZoomPreference; + + @CanIgnoreReturnValue + public @NonNull Builder setMinMaxZoomPreference(@Nullable PlatformZoomRange setterArg) { + this.minMaxZoomPreference = setterArg; + return this; + } + + private @Nullable Boolean mapToolbarEnabled; + + @CanIgnoreReturnValue + public @NonNull Builder setMapToolbarEnabled(@Nullable Boolean setterArg) { + this.mapToolbarEnabled = setterArg; + return this; + } + + private @Nullable Boolean rotateGesturesEnabled; + + @CanIgnoreReturnValue + public @NonNull Builder setRotateGesturesEnabled(@Nullable Boolean setterArg) { + this.rotateGesturesEnabled = setterArg; + return this; + } + + private @Nullable Boolean scrollGesturesEnabled; + + @CanIgnoreReturnValue + public @NonNull Builder setScrollGesturesEnabled(@Nullable Boolean setterArg) { + this.scrollGesturesEnabled = setterArg; + return this; + } + + private @Nullable Boolean tiltGesturesEnabled; + + @CanIgnoreReturnValue + public @NonNull Builder setTiltGesturesEnabled(@Nullable Boolean setterArg) { + this.tiltGesturesEnabled = setterArg; + return this; + } + + private @Nullable Boolean trackCameraPosition; + + @CanIgnoreReturnValue + public @NonNull Builder setTrackCameraPosition(@Nullable Boolean setterArg) { + this.trackCameraPosition = setterArg; + return this; + } + + private @Nullable Boolean zoomControlsEnabled; + + @CanIgnoreReturnValue + public @NonNull Builder setZoomControlsEnabled(@Nullable Boolean setterArg) { + this.zoomControlsEnabled = setterArg; + return this; + } + + private @Nullable Boolean zoomGesturesEnabled; + + @CanIgnoreReturnValue + public @NonNull Builder setZoomGesturesEnabled(@Nullable Boolean setterArg) { + this.zoomGesturesEnabled = setterArg; + return this; + } + + private @Nullable Boolean myLocationEnabled; + + @CanIgnoreReturnValue + public @NonNull Builder setMyLocationEnabled(@Nullable Boolean setterArg) { + this.myLocationEnabled = setterArg; + return this; + } + + private @Nullable Boolean myLocationButtonEnabled; + + @CanIgnoreReturnValue + public @NonNull Builder setMyLocationButtonEnabled(@Nullable Boolean setterArg) { + this.myLocationButtonEnabled = setterArg; + return this; + } + + private @Nullable PlatformEdgeInsets padding; + + @CanIgnoreReturnValue + public @NonNull Builder setPadding(@Nullable PlatformEdgeInsets setterArg) { + this.padding = setterArg; + return this; + } + + private @Nullable Boolean indoorViewEnabled; + + @CanIgnoreReturnValue + public @NonNull Builder setIndoorViewEnabled(@Nullable Boolean setterArg) { + this.indoorViewEnabled = setterArg; + return this; + } + + private @Nullable Boolean trafficEnabled; + + @CanIgnoreReturnValue + public @NonNull Builder setTrafficEnabled(@Nullable Boolean setterArg) { + this.trafficEnabled = setterArg; + return this; + } + + private @Nullable Boolean buildingsEnabled; + + @CanIgnoreReturnValue + public @NonNull Builder setBuildingsEnabled(@Nullable Boolean setterArg) { + this.buildingsEnabled = setterArg; + return this; + } + + private @Nullable Boolean liteModeEnabled; + + @CanIgnoreReturnValue + public @NonNull Builder setLiteModeEnabled(@Nullable Boolean setterArg) { + this.liteModeEnabled = setterArg; + return this; + } + + private @Nullable String cloudMapId; + + @CanIgnoreReturnValue + public @NonNull Builder setCloudMapId(@Nullable String setterArg) { + this.cloudMapId = setterArg; + return this; + } + + private @Nullable String style; + + @CanIgnoreReturnValue + public @NonNull Builder setStyle(@Nullable String setterArg) { + this.style = setterArg; return this; } public @NonNull PlatformMapConfiguration build() { PlatformMapConfiguration pigeonReturn = new PlatformMapConfiguration(); - pigeonReturn.setJson(json); + pigeonReturn.setCompassEnabled(compassEnabled); + pigeonReturn.setCameraTargetBounds(cameraTargetBounds); + pigeonReturn.setMapType(mapType); + pigeonReturn.setMinMaxZoomPreference(minMaxZoomPreference); + pigeonReturn.setMapToolbarEnabled(mapToolbarEnabled); + pigeonReturn.setRotateGesturesEnabled(rotateGesturesEnabled); + pigeonReturn.setScrollGesturesEnabled(scrollGesturesEnabled); + pigeonReturn.setTiltGesturesEnabled(tiltGesturesEnabled); + pigeonReturn.setTrackCameraPosition(trackCameraPosition); + pigeonReturn.setZoomControlsEnabled(zoomControlsEnabled); + pigeonReturn.setZoomGesturesEnabled(zoomGesturesEnabled); + pigeonReturn.setMyLocationEnabled(myLocationEnabled); + pigeonReturn.setMyLocationButtonEnabled(myLocationButtonEnabled); + pigeonReturn.setPadding(padding); + pigeonReturn.setIndoorViewEnabled(indoorViewEnabled); + pigeonReturn.setTrafficEnabled(trafficEnabled); + pigeonReturn.setBuildingsEnabled(buildingsEnabled); + pigeonReturn.setLiteModeEnabled(liteModeEnabled); + pigeonReturn.setCloudMapId(cloudMapId); + pigeonReturn.setStyle(style); return pigeonReturn; } } @NonNull ArrayList toList() { - ArrayList toListResult = new ArrayList(1); - toListResult.add(json); + ArrayList toListResult = new ArrayList(20); + toListResult.add(compassEnabled); + toListResult.add(cameraTargetBounds); + toListResult.add(mapType); + toListResult.add(minMaxZoomPreference); + toListResult.add(mapToolbarEnabled); + toListResult.add(rotateGesturesEnabled); + toListResult.add(scrollGesturesEnabled); + toListResult.add(tiltGesturesEnabled); + toListResult.add(trackCameraPosition); + toListResult.add(zoomControlsEnabled); + toListResult.add(zoomGesturesEnabled); + toListResult.add(myLocationEnabled); + toListResult.add(myLocationButtonEnabled); + toListResult.add(padding); + toListResult.add(indoorViewEnabled); + toListResult.add(trafficEnabled); + toListResult.add(buildingsEnabled); + toListResult.add(liteModeEnabled); + toListResult.add(cloudMapId); + toListResult.add(style); return toListResult; } static @NonNull PlatformMapConfiguration fromList(@NonNull ArrayList __pigeon_list) { PlatformMapConfiguration pigeonResult = new PlatformMapConfiguration(); - Object json = __pigeon_list.get(0); - pigeonResult.setJson((Map) json); + Object compassEnabled = __pigeon_list.get(0); + pigeonResult.setCompassEnabled((Boolean) compassEnabled); + Object cameraTargetBounds = __pigeon_list.get(1); + pigeonResult.setCameraTargetBounds((PlatformCameraTargetBounds) cameraTargetBounds); + Object mapType = __pigeon_list.get(2); + pigeonResult.setMapType((PlatformMapType) mapType); + Object minMaxZoomPreference = __pigeon_list.get(3); + pigeonResult.setMinMaxZoomPreference((PlatformZoomRange) minMaxZoomPreference); + Object mapToolbarEnabled = __pigeon_list.get(4); + pigeonResult.setMapToolbarEnabled((Boolean) mapToolbarEnabled); + Object rotateGesturesEnabled = __pigeon_list.get(5); + pigeonResult.setRotateGesturesEnabled((Boolean) rotateGesturesEnabled); + Object scrollGesturesEnabled = __pigeon_list.get(6); + pigeonResult.setScrollGesturesEnabled((Boolean) scrollGesturesEnabled); + Object tiltGesturesEnabled = __pigeon_list.get(7); + pigeonResult.setTiltGesturesEnabled((Boolean) tiltGesturesEnabled); + Object trackCameraPosition = __pigeon_list.get(8); + pigeonResult.setTrackCameraPosition((Boolean) trackCameraPosition); + Object zoomControlsEnabled = __pigeon_list.get(9); + pigeonResult.setZoomControlsEnabled((Boolean) zoomControlsEnabled); + Object zoomGesturesEnabled = __pigeon_list.get(10); + pigeonResult.setZoomGesturesEnabled((Boolean) zoomGesturesEnabled); + Object myLocationEnabled = __pigeon_list.get(11); + pigeonResult.setMyLocationEnabled((Boolean) myLocationEnabled); + Object myLocationButtonEnabled = __pigeon_list.get(12); + pigeonResult.setMyLocationButtonEnabled((Boolean) myLocationButtonEnabled); + Object padding = __pigeon_list.get(13); + pigeonResult.setPadding((PlatformEdgeInsets) padding); + Object indoorViewEnabled = __pigeon_list.get(14); + pigeonResult.setIndoorViewEnabled((Boolean) indoorViewEnabled); + Object trafficEnabled = __pigeon_list.get(15); + pigeonResult.setTrafficEnabled((Boolean) trafficEnabled); + Object buildingsEnabled = __pigeon_list.get(16); + pigeonResult.setBuildingsEnabled((Boolean) buildingsEnabled); + Object liteModeEnabled = __pigeon_list.get(17); + pigeonResult.setLiteModeEnabled((Boolean) liteModeEnabled); + Object cloudMapId = __pigeon_list.get(18); + pigeonResult.setCloudMapId((String) cloudMapId); + Object style = __pigeon_list.get(19); + pigeonResult.setStyle((String) style); return pigeonResult; } } @@ -1550,35 +2229,26 @@ ArrayList toList() { *

Generated class from Pigeon that represents data sent in messages. */ public static final class PlatformZoomRange { - private @NonNull Double min; + private @Nullable Double min; - public @NonNull Double getMin() { + public @Nullable Double getMin() { return min; } - public void setMin(@NonNull Double setterArg) { - if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"min\" is null."); - } + public void setMin(@Nullable Double setterArg) { this.min = setterArg; } - private @NonNull Double max; + private @Nullable Double max; - public @NonNull Double getMax() { + public @Nullable Double getMax() { return max; } - public void setMax(@NonNull Double setterArg) { - if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"max\" is null."); - } + public void setMax(@Nullable Double setterArg) { this.max = setterArg; } - /** Constructor is non-public to enforce null safety; use Builder. */ - PlatformZoomRange() {} - @Override public boolean equals(Object o) { if (this == o) { @@ -1588,7 +2258,7 @@ public boolean equals(Object o) { return false; } PlatformZoomRange that = (PlatformZoomRange) o; - return min.equals(that.min) && max.equals(that.max); + return Objects.equals(min, that.min) && Objects.equals(max, that.max); } @Override @@ -1601,7 +2271,7 @@ public static final class Builder { private @Nullable Double min; @CanIgnoreReturnValue - public @NonNull Builder setMin(@NonNull Double setterArg) { + public @NonNull Builder setMin(@Nullable Double setterArg) { this.min = setterArg; return this; } @@ -1609,7 +2279,7 @@ public static final class Builder { private @Nullable Double max; @CanIgnoreReturnValue - public @NonNull Builder setMax(@NonNull Double setterArg) { + public @NonNull Builder setMax(@Nullable Double setterArg) { this.max = setterArg; return this; } @@ -1667,22 +2337,37 @@ protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { case (byte) 137: return PlatformTileOverlay.fromList((ArrayList) readValue(buffer)); case (byte) 138: - return PlatformLatLng.fromList((ArrayList) readValue(buffer)); + return PlatformEdgeInsets.fromList((ArrayList) readValue(buffer)); case (byte) 139: - return PlatformLatLngBounds.fromList((ArrayList) readValue(buffer)); + return PlatformLatLng.fromList((ArrayList) readValue(buffer)); case (byte) 140: - return PlatformCluster.fromList((ArrayList) readValue(buffer)); + return PlatformLatLngBounds.fromList((ArrayList) readValue(buffer)); case (byte) 141: - return PlatformMapConfiguration.fromList((ArrayList) readValue(buffer)); + return PlatformCluster.fromList((ArrayList) readValue(buffer)); case (byte) 142: - return PlatformPoint.fromList((ArrayList) readValue(buffer)); + return PlatformCameraTargetBounds.fromList((ArrayList) readValue(buffer)); case (byte) 143: - return PlatformTileLayer.fromList((ArrayList) readValue(buffer)); + return PlatformMapConfiguration.fromList((ArrayList) readValue(buffer)); case (byte) 144: - return PlatformZoomRange.fromList((ArrayList) readValue(buffer)); + return PlatformPoint.fromList((ArrayList) readValue(buffer)); case (byte) 145: - Object value = readValue(buffer); - return value == null ? null : PlatformRendererType.values()[(int) value]; + return PlatformTileLayer.fromList((ArrayList) readValue(buffer)); + case (byte) 146: + return PlatformZoomRange.fromList((ArrayList) readValue(buffer)); + case (byte) 147: + // Manual edit to fix https://github.com/flutter/flutter/issues/150108 + // the way the generator will fix it once the PR lands. + { + Object value = readValue(buffer); + return value == null ? null : PlatformMapType.values()[(int) value]; + } + case (byte) 148: + // Manual edit to fix https://github.com/flutter/flutter/issues/150108 + // the way the generator will fix it once the PR lands. + { + Object value = readValue(buffer); + return value == null ? null : PlatformRendererType.values()[(int) value]; + } default: return super.readValueOfType(type, buffer); } @@ -1717,29 +2402,38 @@ protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { } else if (value instanceof PlatformTileOverlay) { stream.write(137); writeValue(stream, ((PlatformTileOverlay) value).toList()); - } else if (value instanceof PlatformLatLng) { + } else if (value instanceof PlatformEdgeInsets) { stream.write(138); + writeValue(stream, ((PlatformEdgeInsets) value).toList()); + } else if (value instanceof PlatformLatLng) { + stream.write(139); writeValue(stream, ((PlatformLatLng) value).toList()); } else if (value instanceof PlatformLatLngBounds) { - stream.write(139); + stream.write(140); writeValue(stream, ((PlatformLatLngBounds) value).toList()); } else if (value instanceof PlatformCluster) { - stream.write(140); + stream.write(141); writeValue(stream, ((PlatformCluster) value).toList()); + } else if (value instanceof PlatformCameraTargetBounds) { + stream.write(142); + writeValue(stream, ((PlatformCameraTargetBounds) value).toList()); } else if (value instanceof PlatformMapConfiguration) { - stream.write(141); + stream.write(143); writeValue(stream, ((PlatformMapConfiguration) value).toList()); } else if (value instanceof PlatformPoint) { - stream.write(142); + stream.write(144); writeValue(stream, ((PlatformPoint) value).toList()); } else if (value instanceof PlatformTileLayer) { - stream.write(143); + stream.write(145); writeValue(stream, ((PlatformTileLayer) value).toList()); } else if (value instanceof PlatformZoomRange) { - stream.write(144); + stream.write(146); writeValue(stream, ((PlatformZoomRange) value).toList()); + } else if (value instanceof PlatformMapType) { + stream.write(147); + writeValue(stream, value == null ? null : ((PlatformMapType) value).index); } else if (value instanceof PlatformRendererType) { - stream.write(145); + stream.write(148); writeValue(stream, value == null ? null : ((PlatformRendererType) value).index); } else { super.writeValue(stream, value); 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 8e00a67f23b..c3b203888a9 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 @@ -4,10 +4,13 @@ package io.flutter.plugins.googlemaps; +import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_HYBRID; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import android.content.res.AssetManager; @@ -19,6 +22,7 @@ import android.util.Base64; import com.google.android.gms.maps.model.BitmapDescriptor; import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.LatLngBounds; import com.google.maps.android.clustering.algo.StaticCluster; import io.flutter.plugins.googlemaps.Convert.BitmapDescriptorFactoryWrapper; import io.flutter.plugins.googlemaps.Convert.FlutterInjectorWrapper; @@ -50,6 +54,8 @@ public class ConvertTest { @Mock private FlutterInjectorWrapper flutterInjectorWrapper; + @Mock private GoogleMapOptionsSink optionsSink; + AutoCloseable mockCloseable; // A 1x1 pixel (#8080ff) PNG image encoded in base64 @@ -324,6 +330,201 @@ public void GetBitmapFromBytesThrowsErrorIfInvalidImageData() throws Exception { fail("Expected an IllegalArgumentException to be thrown"); } + @Test + public void interpretMapConfiguration_handlesNulls() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder().build(); + Convert.interpretMapConfiguration(config, optionsSink); + verifyNoInteractions(optionsSink); + } + + @Test + public void interpretMapConfiguration_handlesCompassEnabled() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder().setCompassEnabled(false).build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setCompassEnabled(false); + } + + @Test + public void interpretMapConfiguration_handlesMapToolbarEnabled() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder().setMapToolbarEnabled(true).build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setMapToolbarEnabled(true); + } + + @Test + public void interpretMapConfiguration_handlesRotateGesturesEnabled() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder().setRotateGesturesEnabled(false).build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setRotateGesturesEnabled(false); + } + + @Test + public void interpretMapConfiguration_handlesScrollGesturesEnabled() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder().setScrollGesturesEnabled(true).build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setScrollGesturesEnabled(true); + } + + @Test + public void interpretMapConfiguration_handlesTiltGesturesEnabled() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder().setTiltGesturesEnabled(false).build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setTiltGesturesEnabled(false); + } + + @Test + public void interpretMapConfiguration_handlesTrackCameraPosition() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder().setTrackCameraPosition(true).build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setTrackCameraPosition(true); + } + + @Test + public void interpretMapConfiguration_handlesZoomControlsEnabled() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder().setZoomControlsEnabled(false).build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setZoomControlsEnabled(false); + } + + @Test + public void interpretMapConfiguration_handlesZoomGesturesEnabled() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder().setZoomGesturesEnabled(true).build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setZoomGesturesEnabled(true); + } + + @Test + public void interpretMapConfiguration_handlesMyLocationEnabled() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder().setMyLocationEnabled(false).build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setMyLocationEnabled(false); + } + + @Test + public void interpretMapConfiguration_handlesMyLocationButtonEnabled() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder().setMyLocationButtonEnabled(true).build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setMyLocationButtonEnabled(true); + } + + @Test + public void interpretMapConfiguration_handlesIndoorViewEnabled() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder().setIndoorViewEnabled(false).build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setIndoorEnabled(false); + } + + @Test + public void interpretMapConfiguration_handlesTrafficEnabled() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder().setTrafficEnabled(true).build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setTrafficEnabled(true); + } + + @Test + public void interpretMapConfiguration_handlesBuildingsEnabled() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder().setBuildingsEnabled(false).build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setBuildingsEnabled(false); + } + + @Test + public void interpretMapConfiguration_handlesLiteModeEnabled() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder().setLiteModeEnabled(true).build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setLiteModeEnabled(true); + } + + @Test + public void interpretMapConfiguration_handlesStyle() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder().setStyle("foo").build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setMapStyle("foo"); + } + + @Test + public void interpretMapConfiguration_handlesUnboundedCameraTargetBounds() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder() + .setCameraTargetBounds(new Messages.PlatformCameraTargetBounds.Builder().build()) + .build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setCameraTargetBounds(null); + } + + @Test + public void interpretMapConfiguration_handlesBoundedCameraTargetBounds() { + LatLngBounds bounds = new LatLngBounds(new LatLng(10, 20), new LatLng(30, 40)); + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder() + .setCameraTargetBounds( + new Messages.PlatformCameraTargetBounds.Builder() + .setBounds( + new Messages.PlatformLatLngBounds.Builder() + .setSouthwest( + new Messages.PlatformLatLng.Builder() + .setLatitude(bounds.southwest.latitude) + .setLongitude(bounds.southwest.longitude) + .build()) + .setNortheast( + new Messages.PlatformLatLng.Builder() + .setLatitude(bounds.northeast.latitude) + .setLongitude(bounds.northeast.longitude) + .build()) + .build()) + .build()) + .build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setCameraTargetBounds(bounds); + } + + @Test + public void interpretMapConfiguration_handlesMapType() { + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder() + .setMapType(Messages.PlatformMapType.HYBRID) + .build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setMapType(MAP_TYPE_HYBRID); + } + + @Test + public void interpretMapConfiguration_handlesPadding() { + final double top = 1.0; + final double bottom = 2.0; + final double left = 3.0; + final double right = 4.0; + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder() + .setPadding( + new Messages.PlatformEdgeInsets.Builder() + .setTop(top) + .setBottom(bottom) + .setLeft(left) + .setRight(right) + .build()) + .build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)) + .setPadding((float) top, (float) left, (float) bottom, (float) right); + } + private InputStream buildImageInputStream() { Bitmap fakeBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 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 30bc4b7c9cd..383d22d24ec 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 @@ -224,8 +224,8 @@ class GoogleMapsFlutterAndroid extends GoogleMapsFlutterPlatform { MapConfiguration configuration, { required int mapId, }) { - return updateMapOptions(_jsonForMapConfiguration(configuration), - mapId: mapId); + return _hostApi(mapId).updateMapConfiguration( + _platformMapConfigurationFromMapConfiguration(configuration)); } @override @@ -233,8 +233,8 @@ class GoogleMapsFlutterAndroid extends GoogleMapsFlutterPlatform { Map optionsUpdate, { required int mapId, }) { - return _hostApi(mapId) - .updateMapConfiguration(PlatformMapConfiguration(json: optionsUpdate)); + return _hostApi(mapId).updateMapConfiguration( + _platformMapConfigurationFromOptionsJson(optionsUpdate)); } @override @@ -863,6 +863,97 @@ PlatformTile _platformTileFromTile(Tile tile) { return PlatformTile(width: tile.width, height: tile.height, data: tile.data); } +PlatformLatLng _platformLatLngFromLatLng(LatLng latLng) { + return PlatformLatLng(latitude: latLng.latitude, longitude: latLng.longitude); +} + +PlatformLatLngBounds? _platformLatLngBoundsFromLatLngBounds( + LatLngBounds? bounds) { + if (bounds == null) { + return null; + } + return PlatformLatLngBounds( + northeast: _platformLatLngFromLatLng(bounds.northeast), + southwest: _platformLatLngFromLatLng(bounds.southwest)); +} + +PlatformCameraTargetBounds? _platformCameraTargetBoundsFromCameraTargetBounds( + CameraTargetBounds? bounds) { + return bounds == null + ? null + : PlatformCameraTargetBounds( + bounds: _platformLatLngBoundsFromLatLngBounds(bounds.bounds)); +} + +PlatformMapType? _platformMapTypeFromMapType(MapType? type) { + switch (type) { + case null: + return null; + case MapType.none: + return PlatformMapType.none; + case MapType.normal: + return PlatformMapType.normal; + case MapType.satellite: + return PlatformMapType.satellite; + case MapType.terrain: + return PlatformMapType.terrain; + case MapType.hybrid: + return PlatformMapType.hybrid; + } + // The enum comes from a different package, which could get a new value at + // any time, so provide a fallback that ensures this won't break when used + // with a version that contains new values. This is deliberately outside + // the switch rather than a `default` so that the linter will flag the + // switch as needing an update. + // ignore: dead_code + return PlatformMapType.normal; +} + +PlatformZoomRange? _platformZoomRangeFromMinMaxZoomPreference( + MinMaxZoomPreference? zoomPref) { + return zoomPref == null + ? null + : PlatformZoomRange(min: zoomPref.minZoom, max: zoomPref.maxZoom); +} + +PlatformEdgeInsets? _platformEdgeInsetsFromEdgeInsets(EdgeInsets? insets) { + return insets == null + ? null + : PlatformEdgeInsets( + top: insets.top, + bottom: insets.bottom, + left: insets.left, + right: insets.right); +} + +PlatformMapConfiguration _platformMapConfigurationFromMapConfiguration( + MapConfiguration config) { + return PlatformMapConfiguration( + compassEnabled: config.compassEnabled, + cameraTargetBounds: _platformCameraTargetBoundsFromCameraTargetBounds( + config.cameraTargetBounds), + mapType: _platformMapTypeFromMapType(config.mapType), + minMaxZoomPreference: + _platformZoomRangeFromMinMaxZoomPreference(config.minMaxZoomPreference), + mapToolbarEnabled: config.mapToolbarEnabled, + rotateGesturesEnabled: config.rotateGesturesEnabled, + scrollGesturesEnabled: config.scrollGesturesEnabled, + tiltGesturesEnabled: config.tiltGesturesEnabled, + trackCameraPosition: config.trackCameraPosition, + zoomControlsEnabled: config.zoomControlsEnabled, + zoomGesturesEnabled: config.zoomGesturesEnabled, + myLocationEnabled: config.myLocationEnabled, + myLocationButtonEnabled: config.myLocationButtonEnabled, + padding: _platformEdgeInsetsFromEdgeInsets(config.padding), + indoorViewEnabled: config.indoorViewEnabled, + trafficEnabled: config.trafficEnabled, + buildingsEnabled: config.buildingsEnabled, + liteModeEnabled: config.liteModeEnabled, + cloudMapId: config.cloudMapId, + style: config.style, + ); +} + Map _jsonForMapConfiguration(MapConfiguration config) { final EdgeInsets? padding = config.padding; return { @@ -909,6 +1000,100 @@ Map _jsonForMapConfiguration(MapConfiguration config) { }; } +// For supporting the deprecated updateMapOptions API. +PlatformMapConfiguration _platformMapConfigurationFromOptionsJson( + Map options) { + // All of these hard-coded values and structures come from + // google_maps_flutter_platform_interface/lib/src/types/utils/map_configuration_serialization.dart + // to support this legacy API that relied on cross-package magic strings. + final List? padding = + (options['padding'] as List?)?.cast(); + final int? mapType = options['mapType'] as int?; + return PlatformMapConfiguration( + compassEnabled: options['compassEnabled'] as bool?, + cameraTargetBounds: _platformCameraTargetBoundsFromCameraTargetBoundsJson( + options['cameraTargetBounds']), + mapType: mapType == null ? null : _platformMapTypeFromMapTypeIndex(mapType), + minMaxZoomPreference: _platformZoomRangeFromMinMaxZoomPreferenceJson( + options['minMaxZoomPreference']), + mapToolbarEnabled: options['mapToolbarEnabled'] as bool?, + rotateGesturesEnabled: options['rotateGesturesEnabled'] as bool?, + scrollGesturesEnabled: options['scrollGesturesEnabled'] as bool?, + tiltGesturesEnabled: options['tiltGesturesEnabled'] as bool?, + trackCameraPosition: options['trackCameraPosition'] as bool?, + zoomControlsEnabled: options['zoomControlsEnabled'] as bool?, + zoomGesturesEnabled: options['zoomGesturesEnabled'] as bool?, + myLocationEnabled: options['myLocationEnabled'] as bool?, + myLocationButtonEnabled: options['myLocationButtonEnabled'] as bool?, + padding: padding == null + ? null + : PlatformEdgeInsets( + top: padding[0], + left: padding[1], + bottom: padding[2], + right: padding[3]), + indoorViewEnabled: options['indoorEnabled'] as bool?, + trafficEnabled: options['trafficEnabled'] as bool?, + buildingsEnabled: options['buildingsEnabled'] as bool?, + liteModeEnabled: options['liteModeEnabled'] as bool?, + cloudMapId: options['cloudMapId'] as String?, + style: options['style'] as String?, + ); +} + +PlatformMapType _platformMapTypeFromMapTypeIndex(int index) { + // This is inherently fragile, but see comment in updateMapOptions. + return switch (index) { + 0 => PlatformMapType.none, + 1 => PlatformMapType.normal, + 2 => PlatformMapType.satellite, + 3 => PlatformMapType.terrain, + 4 => PlatformMapType.hybrid, + // For a new, unsupported type, just use normal. + _ => PlatformMapType.normal, + }; +} + +PlatformLatLng _platformLatLngFromLatLngJson(Object latLngJson) { + // See `LatLng.toJson`. + final List list = (latLngJson as List).cast(); + return PlatformLatLng(latitude: list[0], longitude: list[1]); +} + +PlatformLatLngBounds? _platformLatLngBoundsFromLatLngBoundsJson( + Object? boundsJson) { + if (boundsJson == null) { + return null; + } + // See `LatLngBounds.toJson`. + final List boundsList = (boundsJson as List).cast(); + return PlatformLatLngBounds( + southwest: _platformLatLngFromLatLngJson(boundsList[0]), + northeast: _platformLatLngFromLatLngJson(boundsList[1])); +} + +PlatformCameraTargetBounds? + _platformCameraTargetBoundsFromCameraTargetBoundsJson(Object? targetJson) { + if (targetJson == null) { + return null; + } + // See `CameraTargetBounds.toJson`. + return PlatformCameraTargetBounds( + bounds: _platformLatLngBoundsFromLatLngBoundsJson( + (targetJson as List)[0])); +} + +PlatformZoomRange? _platformZoomRangeFromMinMaxZoomPreferenceJson( + Object? zoomPrefsJson) { + if (zoomPrefsJson == null) { + return null; + } + // See `MinMaxZoomPreference.toJson`. + final List minMaxZoom = + (zoomPrefsJson as List).cast(); + return PlatformZoomRange(min: minMaxZoom[0], max: minMaxZoom[1]); +} + /// Update specification for a set of [TileOverlay]s. // TODO(stuartmorgan): Fix the missing export of this class in the platform // interface, and remove this copy. 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 index c54b01c196e..205800e7f0e 100644 --- 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 @@ -29,6 +29,15 @@ List wrapResponse( return [error.code, error.message, error.details]; } +/// Pigeon equivalent of MapType +enum PlatformMapType { + none, + normal, + satellite, + terrain, + hybrid, +} + enum PlatformRendererType { legacy, latest, @@ -275,6 +284,43 @@ class PlatformTileOverlay { } } +/// Pigeon equivalent of Flutter's EdgeInsets. +class PlatformEdgeInsets { + PlatformEdgeInsets({ + required this.top, + required this.bottom, + required this.left, + required this.right, + }); + + double top; + + double bottom; + + double left; + + double right; + + Object encode() { + return [ + top, + bottom, + left, + right, + ]; + } + + static PlatformEdgeInsets decode(Object result) { + result as List; + return PlatformEdgeInsets( + top: result[0]! as double, + bottom: result[1]! as double, + left: result[2]! as double, + right: result[3]! as double, + ); + } +} + /// Pigeon equivalent of LatLng. class PlatformLatLng { PlatformLatLng({ @@ -366,27 +412,144 @@ class PlatformCluster { } } +/// Pigeon equivalent of CameraTargetBounds. +/// +/// As with the Dart version, it exists to distinguish between not setting a +/// a target, and having an explicitly unbounded target (null [bounds]). +class PlatformCameraTargetBounds { + PlatformCameraTargetBounds({ + this.bounds, + }); + + PlatformLatLngBounds? bounds; + + Object encode() { + return [ + bounds, + ]; + } + + static PlatformCameraTargetBounds decode(Object result) { + result as List; + return PlatformCameraTargetBounds( + bounds: result[0] as PlatformLatLngBounds?, + ); + } +} + /// Pigeon equivalent of MapConfiguration. class PlatformMapConfiguration { PlatformMapConfiguration({ - required this.json, + this.compassEnabled, + this.cameraTargetBounds, + this.mapType, + this.minMaxZoomPreference, + this.mapToolbarEnabled, + this.rotateGesturesEnabled, + this.scrollGesturesEnabled, + this.tiltGesturesEnabled, + this.trackCameraPosition, + this.zoomControlsEnabled, + this.zoomGesturesEnabled, + this.myLocationEnabled, + this.myLocationButtonEnabled, + this.padding, + this.indoorViewEnabled, + this.trafficEnabled, + this.buildingsEnabled, + this.liteModeEnabled, + this.cloudMapId, + this.style, }); - /// The configuration options, as JSON. This should only be set from - /// _jsonForMapConfiguration, and the native code must intepret it according - /// to the internal implementation details of that method. - Map json; + bool? compassEnabled; + + PlatformCameraTargetBounds? cameraTargetBounds; + + PlatformMapType? mapType; + + PlatformZoomRange? minMaxZoomPreference; + + bool? mapToolbarEnabled; + + bool? rotateGesturesEnabled; + + bool? scrollGesturesEnabled; + + bool? tiltGesturesEnabled; + + bool? trackCameraPosition; + + bool? zoomControlsEnabled; + + bool? zoomGesturesEnabled; + + bool? myLocationEnabled; + + bool? myLocationButtonEnabled; + + PlatformEdgeInsets? padding; + + bool? indoorViewEnabled; + + bool? trafficEnabled; + + bool? buildingsEnabled; + + bool? liteModeEnabled; + + String? cloudMapId; + + String? style; Object encode() { return [ - json, + compassEnabled, + cameraTargetBounds, + mapType, + minMaxZoomPreference, + mapToolbarEnabled, + rotateGesturesEnabled, + scrollGesturesEnabled, + tiltGesturesEnabled, + trackCameraPosition, + zoomControlsEnabled, + zoomGesturesEnabled, + myLocationEnabled, + myLocationButtonEnabled, + padding, + indoorViewEnabled, + trafficEnabled, + buildingsEnabled, + liteModeEnabled, + cloudMapId, + style, ]; } static PlatformMapConfiguration decode(Object result) { result as List; return PlatformMapConfiguration( - json: (result[0] as Map?)!.cast(), + compassEnabled: result[0] as bool?, + cameraTargetBounds: result[1] as PlatformCameraTargetBounds?, + mapType: result[2] as PlatformMapType?, + minMaxZoomPreference: result[3] as PlatformZoomRange?, + mapToolbarEnabled: result[4] as bool?, + rotateGesturesEnabled: result[5] as bool?, + scrollGesturesEnabled: result[6] as bool?, + tiltGesturesEnabled: result[7] as bool?, + trackCameraPosition: result[8] as bool?, + zoomControlsEnabled: result[9] as bool?, + zoomGesturesEnabled: result[10] as bool?, + myLocationEnabled: result[11] as bool?, + myLocationButtonEnabled: result[12] as bool?, + padding: result[13] as PlatformEdgeInsets?, + indoorViewEnabled: result[14] as bool?, + trafficEnabled: result[15] as bool?, + buildingsEnabled: result[16] as bool?, + liteModeEnabled: result[17] as bool?, + cloudMapId: result[18] as String?, + style: result[19] as String?, ); } } @@ -458,13 +621,13 @@ class PlatformTileLayer { /// Possible outcomes of launching a URL. class PlatformZoomRange { PlatformZoomRange({ - required this.min, - required this.max, + this.min, + this.max, }); - double min; + double? min; - double max; + double? max; Object encode() { return [ @@ -476,8 +639,8 @@ class PlatformZoomRange { static PlatformZoomRange decode(Object result) { result as List; return PlatformZoomRange( - min: result[0]! as double, - max: result[1]! as double, + min: result[0] as double?, + max: result[1] as double?, ); } } @@ -513,29 +676,38 @@ class _PigeonCodec extends StandardMessageCodec { } else if (value is PlatformTileOverlay) { buffer.putUint8(137); writeValue(buffer, value.encode()); - } else if (value is PlatformLatLng) { + } else if (value is PlatformEdgeInsets) { buffer.putUint8(138); writeValue(buffer, value.encode()); - } else if (value is PlatformLatLngBounds) { + } else if (value is PlatformLatLng) { buffer.putUint8(139); writeValue(buffer, value.encode()); - } else if (value is PlatformCluster) { + } else if (value is PlatformLatLngBounds) { buffer.putUint8(140); writeValue(buffer, value.encode()); - } else if (value is PlatformMapConfiguration) { + } else if (value is PlatformCluster) { buffer.putUint8(141); writeValue(buffer, value.encode()); - } else if (value is PlatformPoint) { + } else if (value is PlatformCameraTargetBounds) { buffer.putUint8(142); writeValue(buffer, value.encode()); - } else if (value is PlatformTileLayer) { + } else if (value is PlatformMapConfiguration) { buffer.putUint8(143); writeValue(buffer, value.encode()); - } else if (value is PlatformZoomRange) { + } else if (value is PlatformPoint) { buffer.putUint8(144); writeValue(buffer, value.encode()); - } else if (value is PlatformRendererType) { + } else if (value is PlatformTileLayer) { buffer.putUint8(145); + writeValue(buffer, value.encode()); + } else if (value is PlatformZoomRange) { + buffer.putUint8(146); + writeValue(buffer, value.encode()); + } else if (value is PlatformMapType) { + buffer.putUint8(147); + writeValue(buffer, value.index); + } else if (value is PlatformRendererType) { + buffer.putUint8(148); writeValue(buffer, value.index); } else { super.writeValue(buffer, value); @@ -564,20 +736,27 @@ class _PigeonCodec extends StandardMessageCodec { case 137: return PlatformTileOverlay.decode(readValue(buffer)!); case 138: - return PlatformLatLng.decode(readValue(buffer)!); + return PlatformEdgeInsets.decode(readValue(buffer)!); case 139: - return PlatformLatLngBounds.decode(readValue(buffer)!); + return PlatformLatLng.decode(readValue(buffer)!); case 140: - return PlatformCluster.decode(readValue(buffer)!); + return PlatformLatLngBounds.decode(readValue(buffer)!); case 141: - return PlatformMapConfiguration.decode(readValue(buffer)!); + return PlatformCluster.decode(readValue(buffer)!); case 142: - return PlatformPoint.decode(readValue(buffer)!); + return PlatformCameraTargetBounds.decode(readValue(buffer)!); case 143: - return PlatformTileLayer.decode(readValue(buffer)!); + return PlatformMapConfiguration.decode(readValue(buffer)!); case 144: - return PlatformZoomRange.decode(readValue(buffer)!); + return PlatformPoint.decode(readValue(buffer)!); case 145: + return PlatformTileLayer.decode(readValue(buffer)!); + case 146: + return PlatformZoomRange.decode(readValue(buffer)!); + case 147: + final int? value = readValue(buffer) as int?; + return value == null ? null : PlatformMapType.values[value]; + case 148: final int? value = readValue(buffer) as int?; return value == null ? null : PlatformRendererType.values[value]; default: 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 index 3bd8cbf36d3..b4414d1992b 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/pigeons/messages.dart +++ b/packages/google_maps_flutter/google_maps_flutter_android/pigeons/messages.dart @@ -11,6 +11,15 @@ import 'package:pigeon/pigeon.dart'; copyrightHeader: 'pigeons/copyright.txt', )) +/// Pigeon equivalent of MapType +enum PlatformMapType { + none, + normal, + satellite, + terrain, + hybrid, +} + // Pigeon equivalent of the Java MapsInitializer.Renderer. enum PlatformRendererType { legacy, latest } @@ -120,6 +129,21 @@ class PlatformTileOverlay { final Map json; } +/// Pigeon equivalent of Flutter's EdgeInsets. +class PlatformEdgeInsets { + PlatformEdgeInsets({ + required this.top, + required this.bottom, + required this.left, + required this.right, + }); + + final double top; + final double bottom; + final double left; + final double right; +} + /// Pigeon equivalent of LatLng. class PlatformLatLng { PlatformLatLng({required this.latitude, required this.longitude}); @@ -154,16 +178,61 @@ class PlatformCluster { final List markerIds; } +/// Pigeon equivalent of CameraTargetBounds. +/// +/// As with the Dart version, it exists to distinguish between not setting a +/// a target, and having an explicitly unbounded target (null [bounds]). +class PlatformCameraTargetBounds { + PlatformCameraTargetBounds({required this.bounds}); + + final PlatformLatLngBounds? bounds; +} + /// Pigeon equivalent of MapConfiguration. class PlatformMapConfiguration { - PlatformMapConfiguration({required this.json}); + PlatformMapConfiguration({ + required this.compassEnabled, + required this.cameraTargetBounds, + required this.mapType, + required this.minMaxZoomPreference, + required this.mapToolbarEnabled, + required this.rotateGesturesEnabled, + required this.scrollGesturesEnabled, + required this.tiltGesturesEnabled, + required this.trackCameraPosition, + required this.zoomControlsEnabled, + required this.zoomGesturesEnabled, + required this.myLocationEnabled, + required this.myLocationButtonEnabled, + required this.padding, + required this.indoorViewEnabled, + required this.trafficEnabled, + required this.buildingsEnabled, + required this.liteModeEnabled, + required this.cloudMapId, + required this.style, + }); - /// The configuration options, as JSON. This should only be set from - /// _jsonForMapConfiguration, and the native code must intepret it according - /// to the internal implementation details of that method. - // TODO(stuartmorgan): Replace this with structured data. This exists only to - // allow incremental migration to Pigeon. - final Map json; + final bool? compassEnabled; + final PlatformCameraTargetBounds? cameraTargetBounds; + final PlatformMapType? mapType; + final PlatformZoomRange? minMaxZoomPreference; + final bool? mapToolbarEnabled; + final bool? rotateGesturesEnabled; + final bool? scrollGesturesEnabled; + final bool? tiltGesturesEnabled; + final bool? trackCameraPosition; + final bool? zoomControlsEnabled; + final bool? zoomGesturesEnabled; + final bool? myLocationEnabled; + final bool? myLocationButtonEnabled; + final PlatformEdgeInsets? padding; + final bool? indoorViewEnabled; + final bool? trafficEnabled; + final bool? buildingsEnabled; + final bool? liteModeEnabled; + final String? cloudMapId; + final String? style; } /// Pigeon representation of an x,y coordinate. @@ -193,8 +262,8 @@ class PlatformTileLayer { class PlatformZoomRange { PlatformZoomRange({required this.min, required this.max}); - final double min; - final double max; + final double? min; + final double? max; } /// Interface for non-test interactions with the native SDK. diff --git a/packages/google_maps_flutter/google_maps_flutter_android/test/google_maps_flutter_android_test.dart b/packages/google_maps_flutter/google_maps_flutter_android/test/google_maps_flutter_android_test.dart index 5e3943b26ab..32f3d10cc5e 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/test/google_maps_flutter_android_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter_android/test/google_maps_flutter_android_test.dart @@ -209,10 +209,12 @@ void main() { setUpMockMap(mapId: mapId); // Set some arbitrary options. - const MapConfiguration config = MapConfiguration( + final CameraTargetBounds cameraBounds = CameraTargetBounds(LatLngBounds( + southwest: const LatLng(10, 20), northeast: const LatLng(30, 40))); + final MapConfiguration config = MapConfiguration( compassEnabled: true, - liteModeEnabled: false, mapType: MapType.terrain, + cameraTargetBounds: cameraBounds, ); await maps.updateMapConfiguration(config, mapId: mapId); @@ -220,16 +222,21 @@ void main() { verify(api.updateMapConfiguration(captureAny)); final PlatformMapConfiguration passedConfig = verification.captured[0] as PlatformMapConfiguration; - final Map passedConfigJson = - passedConfig.json as Map; // Each set option should be present. - expect(passedConfigJson['compassEnabled'], true); - expect(passedConfigJson['liteModeEnabled'], false); - expect(passedConfigJson['mapType'], MapType.terrain.index); + expect(passedConfig.compassEnabled, true); + expect(passedConfig.mapType, PlatformMapType.terrain); + expect(passedConfig.cameraTargetBounds?.bounds?.northeast.latitude, + cameraBounds.bounds?.northeast.latitude); + expect(passedConfig.cameraTargetBounds?.bounds?.northeast.longitude, + cameraBounds.bounds?.northeast.longitude); + expect(passedConfig.cameraTargetBounds?.bounds?.southwest.latitude, + cameraBounds.bounds?.southwest.latitude); + expect(passedConfig.cameraTargetBounds?.bounds?.southwest.longitude, + cameraBounds.bounds?.southwest.longitude); // Spot-check that unset options are not be present. - expect(passedConfigJson['myLocationEnabled'], isNull); - expect(passedConfigJson['cameraTargetBounds'], isNull); - expect(passedConfigJson['padding'], isNull); + expect(passedConfig.myLocationEnabled, isNull); + expect(passedConfig.minMaxZoomPreference, isNull); + expect(passedConfig.padding, isNull); }); test('updateMapOptions passes expected arguments', () async { @@ -238,10 +245,12 @@ void main() { setUpMockMap(mapId: mapId); // Set some arbitrary options. + final CameraTargetBounds cameraBounds = CameraTargetBounds(LatLngBounds( + southwest: const LatLng(10, 20), northeast: const LatLng(30, 40))); final Map config = { 'compassEnabled': true, - 'liteModeEnabled': false, 'mapType': MapType.terrain.index, + 'cameraTargetBounds': cameraBounds.toJson(), }; await maps.updateMapOptions(config, mapId: mapId); @@ -249,16 +258,21 @@ void main() { verify(api.updateMapConfiguration(captureAny)); final PlatformMapConfiguration passedConfig = verification.captured[0] as PlatformMapConfiguration; - final Map passedConfigJson = - passedConfig.json as Map; // Each set option should be present. - expect(passedConfigJson['compassEnabled'], true); - expect(passedConfigJson['liteModeEnabled'], false); - expect(passedConfigJson['mapType'], MapType.terrain.index); + expect(passedConfig.compassEnabled, true); + expect(passedConfig.mapType, PlatformMapType.terrain); + expect(passedConfig.cameraTargetBounds?.bounds?.northeast.latitude, + cameraBounds.bounds?.northeast.latitude); + expect(passedConfig.cameraTargetBounds?.bounds?.northeast.longitude, + cameraBounds.bounds?.northeast.longitude); + expect(passedConfig.cameraTargetBounds?.bounds?.southwest.latitude, + cameraBounds.bounds?.southwest.latitude); + expect(passedConfig.cameraTargetBounds?.bounds?.southwest.longitude, + cameraBounds.bounds?.southwest.longitude); // Spot-check that unset options are not be present. - expect(passedConfigJson['myLocationEnabled'], isNull); - expect(passedConfigJson['cameraTargetBounds'], isNull); - expect(passedConfigJson['padding'], isNull); + expect(passedConfig.myLocationEnabled, isNull); + expect(passedConfig.minMaxZoomPreference, isNull); + expect(passedConfig.padding, isNull); }); test('updateCircles passes expected arguments', () async { From 72afd226fd98030a4c7c57a7e33a4627e5d898a5 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Mon, 22 Jul 2024 16:29:01 -0400 Subject: [PATCH 04/14] Convert platform view creation params to Pigeon on Android --- .../plugins/googlemaps/CirclesController.java | 10 - .../googlemaps/ClusterManagersController.java | 11 - .../flutter/plugins/googlemaps/Convert.java | 99 +---- .../plugins/googlemaps/GoogleMapBuilder.java | 28 +- .../googlemaps/GoogleMapController.java | 64 ++-- .../plugins/googlemaps/GoogleMapFactory.java | 49 +-- .../googlemaps/GoogleMapOptionsSink.java | 15 +- .../plugins/googlemaps/MarkersController.java | 10 - .../flutter/plugins/googlemaps/Messages.java | 345 +++++++++++++++++- .../googlemaps/PolygonsController.java | 10 - .../googlemaps/PolylinesController.java | 10 - .../googlemaps/TileOverlaysController.java | 9 - .../ClusterManagersControllerTest.java | 65 +--- .../googlemaps/GoogleMapControllerTest.java | 19 +- .../googlemaps/MarkersControllerTest.java | 53 +-- .../lib/src/google_maps_flutter_android.dart | 99 ++--- .../lib/src/messages.g.dart | 130 ++++++- .../lib/src/utils/cluster_manager_utils.dart | 19 - .../pigeons/messages.dart | 35 ++ 19 files changed, 648 insertions(+), 432 deletions(-) delete mode 100644 packages/google_maps_flutter/google_maps_flutter_android/lib/src/utils/cluster_manager_utils.dart diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/CirclesController.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/CirclesController.java index 734e36c809e..8b28fe6aada 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/CirclesController.java +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/CirclesController.java @@ -32,16 +32,6 @@ void setGoogleMap(GoogleMap googleMap) { this.googleMap = googleMap; } - void addJsonCircles(List circlesToAdd) { - if (circlesToAdd != null) { - for (Object circleToAdd : circlesToAdd) { - @SuppressWarnings("unchecked") - Map circleMap = (Map) circleToAdd; - addJsonCircle(circleMap); - } - } - } - void addCircles(@NonNull List circlesToAdd) { for (Messages.PlatformCircle circleToAdd : circlesToAdd) { addJsonCircle(circleToAdd.getJson()); 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 448d34aebb1..cd81eba7940 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 @@ -78,17 +78,6 @@ private void initListenersForClusterManager( clusterManager.setOnClusterItemClickListener(clusterItemClickListener); } - /** Adds new ClusterManagers to the controller. */ - void addJsonClusterManagers(@NonNull List clusterManagersToAdd) { - for (Object clusterToAdd : clusterManagersToAdd) { - String clusterManagerId = getClusterManagerId(clusterToAdd); - if (clusterManagerId == null) { - throw new IllegalArgumentException("clusterManagerId was null"); - } - addClusterManager(clusterManagerId); - } - } - /** Adds new ClusterManagers to the controller. */ void addClusterManagers(@NonNull List clusterManagersToAdd) { for (Messages.PlatformClusterManager clusterToAdd : clusterManagersToAdd) { 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 529100a0c68..caa4f0b02a9 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 @@ -306,6 +306,16 @@ private static boolean toBoolean(Object o) { return (Boolean) o; } + static @NonNull CameraPosition cameraPositionFromPigeon( + @NonNull Messages.PlatformCameraPosition position) { + final CameraPosition.Builder builder = CameraPosition.builder(); + builder.bearing(position.getBearing().floatValue()); + builder.target(latLngFromPigeon(position.getTarget())); + builder.tilt(position.getTilt().floatValue()); + builder.zoom(position.getZoom().floatValue()); + return builder.build(); + } + static CameraPosition toCameraPosition(Object o) { final Map data = toMap(o); final CameraPosition.Builder builder = CameraPosition.builder(); @@ -537,95 +547,6 @@ private static String toString(Object o) { return (String) o; } - static void interpretGoogleMapOptions(Object o, GoogleMapOptionsSink sink) { - final Map data = toMap(o); - final Object cameraTargetBounds = data.get("cameraTargetBounds"); - if (cameraTargetBounds != null) { - final List targetData = toList(cameraTargetBounds); - sink.setCameraTargetBounds(toLatLngBounds(targetData.get(0))); - } - final Object compassEnabled = data.get("compassEnabled"); - if (compassEnabled != null) { - sink.setCompassEnabled(toBoolean(compassEnabled)); - } - final Object mapToolbarEnabled = data.get("mapToolbarEnabled"); - if (mapToolbarEnabled != null) { - sink.setMapToolbarEnabled(toBoolean(mapToolbarEnabled)); - } - final Object mapType = data.get("mapType"); - if (mapType != null) { - sink.setMapType(toInt(mapType)); - } - final Object minMaxZoomPreference = data.get("minMaxZoomPreference"); - if (minMaxZoomPreference != null) { - final List zoomPreferenceData = toList(minMaxZoomPreference); - sink.setMinMaxZoomPreference( // - toFloatWrapper(zoomPreferenceData.get(0)), // - toFloatWrapper(zoomPreferenceData.get(1))); - } - final Object padding = data.get("padding"); - if (padding != null) { - final List paddingData = toList(padding); - sink.setPadding( - toFloat(paddingData.get(0)), - toFloat(paddingData.get(1)), - toFloat(paddingData.get(2)), - toFloat(paddingData.get(3))); - } - final Object rotateGesturesEnabled = data.get("rotateGesturesEnabled"); - if (rotateGesturesEnabled != null) { - sink.setRotateGesturesEnabled(toBoolean(rotateGesturesEnabled)); - } - final Object scrollGesturesEnabled = data.get("scrollGesturesEnabled"); - if (scrollGesturesEnabled != null) { - sink.setScrollGesturesEnabled(toBoolean(scrollGesturesEnabled)); - } - final Object tiltGesturesEnabled = data.get("tiltGesturesEnabled"); - if (tiltGesturesEnabled != null) { - sink.setTiltGesturesEnabled(toBoolean(tiltGesturesEnabled)); - } - final Object trackCameraPosition = data.get("trackCameraPosition"); - if (trackCameraPosition != null) { - sink.setTrackCameraPosition(toBoolean(trackCameraPosition)); - } - final Object zoomGesturesEnabled = data.get("zoomGesturesEnabled"); - if (zoomGesturesEnabled != null) { - sink.setZoomGesturesEnabled(toBoolean(zoomGesturesEnabled)); - } - final Object liteModeEnabled = data.get("liteModeEnabled"); - if (liteModeEnabled != null) { - sink.setLiteModeEnabled(toBoolean(liteModeEnabled)); - } - final Object myLocationEnabled = data.get("myLocationEnabled"); - if (myLocationEnabled != null) { - sink.setMyLocationEnabled(toBoolean(myLocationEnabled)); - } - final Object zoomControlsEnabled = data.get("zoomControlsEnabled"); - if (zoomControlsEnabled != null) { - sink.setZoomControlsEnabled(toBoolean(zoomControlsEnabled)); - } - final Object myLocationButtonEnabled = data.get("myLocationButtonEnabled"); - if (myLocationButtonEnabled != null) { - sink.setMyLocationButtonEnabled(toBoolean(myLocationButtonEnabled)); - } - final Object indoorEnabled = data.get("indoorEnabled"); - if (indoorEnabled != null) { - sink.setIndoorEnabled(toBoolean(indoorEnabled)); - } - final Object trafficEnabled = data.get("trafficEnabled"); - if (trafficEnabled != null) { - sink.setTrafficEnabled(toBoolean(trafficEnabled)); - } - final Object buildingsEnabled = data.get("buildingsEnabled"); - if (buildingsEnabled != null) { - sink.setBuildingsEnabled(toBoolean(buildingsEnabled)); - } - final Object style = data.get("style"); - if (style != null) { - sink.setMapStyle(toString(style)); - } - } - static void interpretMapConfiguration( @NonNull Messages.PlatformMapConfiguration config, @NonNull GoogleMapOptionsSink sink) { final Messages.PlatformCameraTargetBounds cameraTargetBounds = config.getCameraTargetBounds(); diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapBuilder.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapBuilder.java index 02477418d42..ebdc31f7733 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapBuilder.java +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapBuilder.java @@ -6,13 +6,13 @@ import android.content.Context; import android.graphics.Rect; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.google.android.gms.maps.GoogleMapOptions; import com.google.android.gms.maps.model.CameraPosition; import com.google.android.gms.maps.model.LatLngBounds; import io.flutter.plugin.common.BinaryMessenger; import java.util.List; -import java.util.Map; class GoogleMapBuilder implements GoogleMapOptionsSink { private final GoogleMapOptions options = new GoogleMapOptions(); @@ -22,12 +22,12 @@ class GoogleMapBuilder implements GoogleMapOptionsSink { private boolean indoorEnabled = true; private boolean trafficEnabled = false; private boolean buildingsEnabled = true; - private Object initialMarkers; - private Object initialClusterManagers; - private Object initialPolygons; - private Object initialPolylines; - private Object initialCircles; - private List> initialTileOverlays; + private List initialMarkers; + private List initialClusterManagers; + private List initialPolygons; + private List initialPolylines; + private List initialCircles; + private List initialTileOverlays; private Rect padding = new Rect(0, 0, 0, 0); private @Nullable String style; @@ -160,32 +160,34 @@ public void setMyLocationButtonEnabled(boolean myLocationButtonEnabled) { } @Override - public void setInitialMarkers(Object initialMarkers) { + public void setInitialMarkers(@NonNull List initialMarkers) { this.initialMarkers = initialMarkers; } @Override - public void setInitialClusterManagers(Object initialClusterManagers) { + public void setInitialClusterManagers( + @NonNull List initialClusterManagers) { this.initialClusterManagers = initialClusterManagers; } @Override - public void setInitialPolygons(Object initialPolygons) { + public void setInitialPolygons(@NonNull List initialPolygons) { this.initialPolygons = initialPolygons; } @Override - public void setInitialPolylines(Object initialPolylines) { + public void setInitialPolylines(@NonNull List initialPolylines) { this.initialPolylines = initialPolylines; } @Override - public void setInitialCircles(Object initialCircles) { + public void setInitialCircles(@NonNull List initialCircles) { this.initialCircles = initialCircles; } @Override - public void setInitialTileOverlays(List> initialTileOverlays) { + public void setInitialTileOverlays( + @NonNull List initialTileOverlays) { this.initialTileOverlays = initialTileOverlays; } 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 fceb45e0db2..c2b1c12c0e9 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 @@ -51,7 +51,6 @@ import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Set; @@ -95,12 +94,12 @@ class GoogleMapController private final TileOverlaysController tileOverlaysController; private MarkerManager markerManager; private MarkerManager.Collection markerCollection; - private List initialMarkers; - private List initialClusterManagers; - private List initialPolygons; - private List initialPolylines; - private List initialCircles; - private List> initialTileOverlays; + private @Nullable List initialMarkers; + private @Nullable List initialClusterManagers; + private @Nullable List initialPolygons; + private @Nullable List initialPolylines; + private @Nullable List initialCircles; + private @Nullable List initialTileOverlays; // Null except between initialization and onMapReady. private @Nullable String initialMapStyle; private boolean lastSetStyleSucceeded; @@ -617,22 +616,23 @@ public void setZoomControlsEnabled(boolean zoomControlsEnabled) { } @Override - public void setInitialMarkers(Object initialMarkers) { - ArrayList markers = (ArrayList) initialMarkers; - this.initialMarkers = markers != null ? new ArrayList<>(markers) : null; + public void setInitialMarkers(@NonNull List initialMarkers) { + this.initialMarkers = initialMarkers; if (googleMap != null) { updateInitialMarkers(); } } private void updateInitialMarkers() { - markersController.addJsonMarkers(initialMarkers); + if (initialMarkers != null) { + markersController.addMarkers(initialMarkers); + } } @Override - public void setInitialClusterManagers(Object initialClusterManagers) { - ArrayList clusterManagers = (ArrayList) initialClusterManagers; - this.initialClusterManagers = clusterManagers != null ? new ArrayList<>(clusterManagers) : null; + public void setInitialClusterManagers( + @NonNull List initialClusterManagers) { + this.initialClusterManagers = initialClusterManagers; if (googleMap != null) { updateInitialClusterManagers(); } @@ -640,51 +640,55 @@ public void setInitialClusterManagers(Object initialClusterManagers) { private void updateInitialClusterManagers() { if (initialClusterManagers != null) { - clusterManagersController.addJsonClusterManagers(initialClusterManagers); + clusterManagersController.addClusterManagers(initialClusterManagers); } } @Override - public void setInitialPolygons(Object initialPolygons) { - ArrayList polygons = (ArrayList) initialPolygons; - this.initialPolygons = polygons != null ? new ArrayList<>(polygons) : null; + public void setInitialPolygons(@NonNull List initialPolygons) { + this.initialPolygons = initialPolygons; if (googleMap != null) { updateInitialPolygons(); } } private void updateInitialPolygons() { - polygonsController.addJsonPolygons(initialPolygons); + if (initialPolygons != null) { + polygonsController.addPolygons(initialPolygons); + } } @Override - public void setInitialPolylines(Object initialPolylines) { - ArrayList polylines = (ArrayList) initialPolylines; - this.initialPolylines = polylines != null ? new ArrayList<>(polylines) : null; + public void setInitialPolylines(@NonNull List initialPolylines) { + this.initialPolylines = initialPolylines; if (googleMap != null) { updateInitialPolylines(); } } private void updateInitialPolylines() { - polylinesController.addJsonPolylines(initialPolylines); + if (initialPolylines != null) { + polylinesController.addPolylines(initialPolylines); + } } @Override - public void setInitialCircles(Object initialCircles) { - ArrayList circles = (ArrayList) initialCircles; - this.initialCircles = circles != null ? new ArrayList<>(circles) : null; + public void setInitialCircles(@NonNull List initialCircles) { + this.initialCircles = initialCircles; if (googleMap != null) { updateInitialCircles(); } } private void updateInitialCircles() { - circlesController.addJsonCircles(initialCircles); + if (initialCircles != null) { + circlesController.addCircles(initialCircles); + } } @Override - public void setInitialTileOverlays(List> initialTileOverlays) { + public void setInitialTileOverlays( + @NonNull List initialTileOverlays) { this.initialTileOverlays = initialTileOverlays; if (googleMap != null) { updateInitialTileOverlays(); @@ -692,7 +696,9 @@ public void setInitialTileOverlays(List> initialTileOverlays) { } private void updateInitialTileOverlays() { - tileOverlaysController.addJsonTileOverlays(initialTileOverlays); + if (initialTileOverlays != null) { + tileOverlaysController.addTileOverlays(initialTileOverlays); + } } @SuppressLint("MissingPermission") diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapFactory.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapFactory.java index b8d6485d35e..8b1ecbe682c 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapFactory.java +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapFactory.java @@ -9,11 +9,9 @@ import androidx.annotation.Nullable; import com.google.android.gms.maps.model.CameraPosition; import io.flutter.plugin.common.BinaryMessenger; -import io.flutter.plugin.common.StandardMessageCodec; import io.flutter.plugin.platform.PlatformView; import io.flutter.plugin.platform.PlatformViewFactory; -import java.util.List; -import java.util.Map; +import java.util.Objects; public class GoogleMapFactory extends PlatformViewFactory { @@ -23,47 +21,34 @@ public class GoogleMapFactory extends PlatformViewFactory { GoogleMapFactory( BinaryMessenger binaryMessenger, Context context, LifecycleProvider lifecycleProvider) { - super(StandardMessageCodec.INSTANCE); + super(Messages.MapsApi.getCodec()); this.binaryMessenger = binaryMessenger; this.lifecycleProvider = lifecycleProvider; this.googleMapInitializer = new GoogleMapInitializer(context, binaryMessenger); } - @SuppressWarnings("unchecked") @Override @NonNull public PlatformView create(@NonNull Context context, int id, @Nullable Object args) { - Map params = (Map) args; + final Messages.PlatformMapViewCreationParams params = + Objects.requireNonNull((Messages.PlatformMapViewCreationParams) args); final GoogleMapBuilder builder = new GoogleMapBuilder(); - final Object options = params.get("options"); - Convert.interpretGoogleMapOptions(options, builder); - if (params.containsKey("initialCameraPosition")) { - CameraPosition position = Convert.toCameraPosition(params.get("initialCameraPosition")); - builder.setInitialCameraPosition(position); - } - if (params.containsKey("clusterManagersToAdd")) { - builder.setInitialClusterManagers(params.get("clusterManagersToAdd")); - } - if (params.containsKey("markersToAdd")) { - builder.setInitialMarkers(params.get("markersToAdd")); - } - if (params.containsKey("polygonsToAdd")) { - builder.setInitialPolygons(params.get("polygonsToAdd")); - } - if (params.containsKey("polylinesToAdd")) { - builder.setInitialPolylines(params.get("polylinesToAdd")); - } - if (params.containsKey("circlesToAdd")) { - builder.setInitialCircles(params.get("circlesToAdd")); - } - if (params.containsKey("tileOverlaysToAdd")) { - builder.setInitialTileOverlays((List>) params.get("tileOverlaysToAdd")); - } - final Object cloudMapId = ((Map) options).get("cloudMapId"); + final Messages.PlatformMapConfiguration mapConfig = params.getMapConfiguration(); + Convert.interpretMapConfiguration(mapConfig, builder); + CameraPosition position = Convert.cameraPositionFromPigeon(params.getInitialCameraPosition()); + builder.setInitialCameraPosition(position); + builder.setInitialClusterManagers(params.getInitialClusterManagers()); + builder.setInitialMarkers(params.getInitialMarkers()); + builder.setInitialPolygons(params.getInitialPolygons()); + builder.setInitialPolylines(params.getInitialPolylines()); + builder.setInitialCircles(params.getInitialCircles()); + builder.setInitialTileOverlays(params.getInitialTileOverlays()); + + final String cloudMapId = mapConfig.getCloudMapId(); if (cloudMapId != null) { - builder.setMapId((String) cloudMapId); + builder.setMapId(cloudMapId); } return builder.build(id, context, binaryMessenger, lifecycleProvider); diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapOptionsSink.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapOptionsSink.java index 9f744a653b3..6287967eb11 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapOptionsSink.java +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapOptionsSink.java @@ -4,10 +4,10 @@ package io.flutter.plugins.googlemaps; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.google.android.gms.maps.model.LatLngBounds; import java.util.List; -import java.util.Map; /** Receiver of GoogleMap configuration options. */ interface GoogleMapOptionsSink { @@ -47,17 +47,18 @@ interface GoogleMapOptionsSink { void setBuildingsEnabled(boolean buildingsEnabled); - void setInitialMarkers(Object initialMarkers); + void setInitialMarkers(@NonNull List initialMarkers); - void setInitialClusterManagers(Object initialClusterManagers); + void setInitialClusterManagers( + @NonNull List initialClusterManagers); - void setInitialPolygons(Object initialPolygons); + void setInitialPolygons(@NonNull List initialPolygons); - void setInitialPolylines(Object initialPolylines); + void setInitialPolylines(@NonNull List initialPolylines); - void setInitialCircles(Object initialCircles); + void setInitialCircles(@NonNull List initialCircles); - void setInitialTileOverlays(List> initialTileOverlays); + void setInitialTileOverlays(@NonNull List initialTileOverlays); void setMapStyle(@Nullable String style); } diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/MarkersController.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/MarkersController.java index d6546cc621b..6edee43be2d 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/MarkersController.java +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/MarkersController.java @@ -44,16 +44,6 @@ void setCollection(MarkerManager.Collection markerCollection) { this.markerCollection = markerCollection; } - void addJsonMarkers(List markersToAdd) { - if (markersToAdd != null) { - for (Object markerToAdd : markersToAdd) { - @SuppressWarnings("unchecked") - Map markerMap = (Map) markerToAdd; - addJsonMarker(markerMap); - } - } - } - void addMarkers(@NonNull List markersToAdd) { for (Messages.PlatformMarker markerToAdd : markersToAdd) { addJsonMarker(markerToAdd.getJson()); 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 index 2e11402ac0d..bc32acf4455 100644 --- 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 @@ -1455,6 +1455,269 @@ ArrayList toList() { } } + /** + * Information passed to the platform view creation. + * + *

Generated class from Pigeon that represents data sent in messages. + */ + public static final class PlatformMapViewCreationParams { + private @NonNull PlatformCameraPosition initialCameraPosition; + + public @NonNull PlatformCameraPosition getInitialCameraPosition() { + return initialCameraPosition; + } + + public void setInitialCameraPosition(@NonNull PlatformCameraPosition setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"initialCameraPosition\" is null."); + } + this.initialCameraPosition = setterArg; + } + + private @NonNull PlatformMapConfiguration mapConfiguration; + + public @NonNull PlatformMapConfiguration getMapConfiguration() { + return mapConfiguration; + } + + public void setMapConfiguration(@NonNull PlatformMapConfiguration setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"mapConfiguration\" is null."); + } + this.mapConfiguration = setterArg; + } + + private @NonNull List initialCircles; + + public @NonNull List getInitialCircles() { + return initialCircles; + } + + public void setInitialCircles(@NonNull List setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"initialCircles\" is null."); + } + this.initialCircles = setterArg; + } + + private @NonNull List initialMarkers; + + public @NonNull List getInitialMarkers() { + return initialMarkers; + } + + public void setInitialMarkers(@NonNull List setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"initialMarkers\" is null."); + } + this.initialMarkers = setterArg; + } + + private @NonNull List initialPolygons; + + public @NonNull List getInitialPolygons() { + return initialPolygons; + } + + public void setInitialPolygons(@NonNull List setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"initialPolygons\" is null."); + } + this.initialPolygons = setterArg; + } + + private @NonNull List initialPolylines; + + public @NonNull List getInitialPolylines() { + return initialPolylines; + } + + public void setInitialPolylines(@NonNull List setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"initialPolylines\" is null."); + } + this.initialPolylines = setterArg; + } + + private @NonNull List initialTileOverlays; + + public @NonNull List getInitialTileOverlays() { + return initialTileOverlays; + } + + public void setInitialTileOverlays(@NonNull List setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"initialTileOverlays\" is null."); + } + this.initialTileOverlays = setterArg; + } + + private @NonNull List initialClusterManagers; + + public @NonNull List getInitialClusterManagers() { + return initialClusterManagers; + } + + public void setInitialClusterManagers(@NonNull List setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"initialClusterManagers\" is null."); + } + this.initialClusterManagers = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PlatformMapViewCreationParams() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PlatformMapViewCreationParams that = (PlatformMapViewCreationParams) o; + return initialCameraPosition.equals(that.initialCameraPosition) + && mapConfiguration.equals(that.mapConfiguration) + && initialCircles.equals(that.initialCircles) + && initialMarkers.equals(that.initialMarkers) + && initialPolygons.equals(that.initialPolygons) + && initialPolylines.equals(that.initialPolylines) + && initialTileOverlays.equals(that.initialTileOverlays) + && initialClusterManagers.equals(that.initialClusterManagers); + } + + @Override + public int hashCode() { + return Objects.hash( + initialCameraPosition, + mapConfiguration, + initialCircles, + initialMarkers, + initialPolygons, + initialPolylines, + initialTileOverlays, + initialClusterManagers); + } + + public static final class Builder { + + private @Nullable PlatformCameraPosition initialCameraPosition; + + @CanIgnoreReturnValue + public @NonNull Builder setInitialCameraPosition(@NonNull PlatformCameraPosition setterArg) { + this.initialCameraPosition = setterArg; + return this; + } + + private @Nullable PlatformMapConfiguration mapConfiguration; + + @CanIgnoreReturnValue + public @NonNull Builder setMapConfiguration(@NonNull PlatformMapConfiguration setterArg) { + this.mapConfiguration = setterArg; + return this; + } + + private @Nullable List initialCircles; + + @CanIgnoreReturnValue + public @NonNull Builder setInitialCircles(@NonNull List setterArg) { + this.initialCircles = setterArg; + return this; + } + + private @Nullable List initialMarkers; + + @CanIgnoreReturnValue + public @NonNull Builder setInitialMarkers(@NonNull List setterArg) { + this.initialMarkers = setterArg; + return this; + } + + private @Nullable List initialPolygons; + + @CanIgnoreReturnValue + public @NonNull Builder setInitialPolygons(@NonNull List setterArg) { + this.initialPolygons = setterArg; + return this; + } + + private @Nullable List initialPolylines; + + @CanIgnoreReturnValue + public @NonNull Builder setInitialPolylines(@NonNull List setterArg) { + this.initialPolylines = setterArg; + return this; + } + + private @Nullable List initialTileOverlays; + + @CanIgnoreReturnValue + public @NonNull Builder setInitialTileOverlays(@NonNull List setterArg) { + this.initialTileOverlays = setterArg; + return this; + } + + private @Nullable List initialClusterManagers; + + @CanIgnoreReturnValue + public @NonNull Builder setInitialClusterManagers( + @NonNull List setterArg) { + this.initialClusterManagers = setterArg; + return this; + } + + public @NonNull PlatformMapViewCreationParams build() { + PlatformMapViewCreationParams pigeonReturn = new PlatformMapViewCreationParams(); + pigeonReturn.setInitialCameraPosition(initialCameraPosition); + pigeonReturn.setMapConfiguration(mapConfiguration); + pigeonReturn.setInitialCircles(initialCircles); + pigeonReturn.setInitialMarkers(initialMarkers); + pigeonReturn.setInitialPolygons(initialPolygons); + pigeonReturn.setInitialPolylines(initialPolylines); + pigeonReturn.setInitialTileOverlays(initialTileOverlays); + pigeonReturn.setInitialClusterManagers(initialClusterManagers); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(8); + toListResult.add(initialCameraPosition); + toListResult.add(mapConfiguration); + toListResult.add(initialCircles); + toListResult.add(initialMarkers); + toListResult.add(initialPolygons); + toListResult.add(initialPolylines); + toListResult.add(initialTileOverlays); + toListResult.add(initialClusterManagers); + return toListResult; + } + + static @NonNull PlatformMapViewCreationParams fromList( + @NonNull ArrayList __pigeon_list) { + PlatformMapViewCreationParams pigeonResult = new PlatformMapViewCreationParams(); + Object initialCameraPosition = __pigeon_list.get(0); + pigeonResult.setInitialCameraPosition((PlatformCameraPosition) initialCameraPosition); + Object mapConfiguration = __pigeon_list.get(1); + pigeonResult.setMapConfiguration((PlatformMapConfiguration) mapConfiguration); + Object initialCircles = __pigeon_list.get(2); + pigeonResult.setInitialCircles((List) initialCircles); + Object initialMarkers = __pigeon_list.get(3); + pigeonResult.setInitialMarkers((List) initialMarkers); + Object initialPolygons = __pigeon_list.get(4); + pigeonResult.setInitialPolygons((List) initialPolygons); + Object initialPolylines = __pigeon_list.get(5); + pigeonResult.setInitialPolylines((List) initialPolylines); + Object initialTileOverlays = __pigeon_list.get(6); + pigeonResult.setInitialTileOverlays((List) initialTileOverlays); + Object initialClusterManagers = __pigeon_list.get(7); + pigeonResult.setInitialClusterManagers((List) initialClusterManagers); + return pigeonResult; + } + } + /** * Pigeon equivalent of MapConfiguration. * @@ -2347,21 +2610,23 @@ protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { case (byte) 142: return PlatformCameraTargetBounds.fromList((ArrayList) readValue(buffer)); case (byte) 143: - return PlatformMapConfiguration.fromList((ArrayList) readValue(buffer)); + return PlatformMapViewCreationParams.fromList((ArrayList) readValue(buffer)); case (byte) 144: - return PlatformPoint.fromList((ArrayList) readValue(buffer)); + return PlatformMapConfiguration.fromList((ArrayList) readValue(buffer)); case (byte) 145: - return PlatformTileLayer.fromList((ArrayList) readValue(buffer)); + return PlatformPoint.fromList((ArrayList) readValue(buffer)); case (byte) 146: - return PlatformZoomRange.fromList((ArrayList) readValue(buffer)); + return PlatformTileLayer.fromList((ArrayList) readValue(buffer)); case (byte) 147: + return PlatformZoomRange.fromList((ArrayList) readValue(buffer)); + case (byte) 148: // Manual edit to fix https://github.com/flutter/flutter/issues/150108 // the way the generator will fix it once the PR lands. { Object value = readValue(buffer); return value == null ? null : PlatformMapType.values()[(int) value]; } - case (byte) 148: + case (byte) 149: // Manual edit to fix https://github.com/flutter/flutter/issues/150108 // the way the generator will fix it once the PR lands. { @@ -2417,23 +2682,26 @@ protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { } else if (value instanceof PlatformCameraTargetBounds) { stream.write(142); writeValue(stream, ((PlatformCameraTargetBounds) value).toList()); - } else if (value instanceof PlatformMapConfiguration) { + } else if (value instanceof PlatformMapViewCreationParams) { stream.write(143); + writeValue(stream, ((PlatformMapViewCreationParams) value).toList()); + } else if (value instanceof PlatformMapConfiguration) { + stream.write(144); writeValue(stream, ((PlatformMapConfiguration) value).toList()); } else if (value instanceof PlatformPoint) { - stream.write(144); + stream.write(145); writeValue(stream, ((PlatformPoint) value).toList()); } else if (value instanceof PlatformTileLayer) { - stream.write(145); + stream.write(146); writeValue(stream, ((PlatformTileLayer) value).toList()); } else if (value instanceof PlatformZoomRange) { - stream.write(146); + stream.write(147); writeValue(stream, ((PlatformZoomRange) value).toList()); } else if (value instanceof PlatformMapType) { - stream.write(147); + stream.write(148); writeValue(stream, value == null ? null : ((PlatformMapType) value).index); } else if (value instanceof PlatformRendererType) { - stream.write(148); + stream.write(149); writeValue(stream, value == null ? null : ((PlatformRendererType) value).index); } else { super.writeValue(stream, value); @@ -3629,6 +3897,61 @@ public void error(Throwable error) { } } } + /** + * Dummy interface to force generation of the platform view creation params, which are not used in + * any Pigeon calls, only the platform view creation call made internally by Flutter. + * + *

Generated interface from Pigeon that represents a handler of messages from Flutter. + */ + public interface MapsPlatformViewApi { + + void createView(@Nullable PlatformMapViewCreationParams type); + + /** The codec used by MapsPlatformViewApi. */ + static @NonNull MessageCodec getCodec() { + return PigeonCodec.INSTANCE; + } + /** + * Sets up an instance of `MapsPlatformViewApi` to handle messages through the + * `binaryMessenger`. + */ + static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable MapsPlatformViewApi api) { + setUp(binaryMessenger, "", api); + } + + static void setUp( + @NonNull BinaryMessenger binaryMessenger, + @NonNull String messageChannelSuffix, + @Nullable MapsPlatformViewApi api) { + messageChannelSuffix = messageChannelSuffix.isEmpty() ? "" : "." + messageChannelSuffix; + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.google_maps_flutter_android.MapsPlatformViewApi.createView" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PlatformMapViewCreationParams typeArg = (PlatformMapViewCreationParams) args.get(0); + try { + api.createView(typeArg); + wrapped.add(0, null); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } /** * Inspector API only intended for use in integration tests. * diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/PolygonsController.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/PolygonsController.java index 23626edeb70..57d7a6a5271 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/PolygonsController.java +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/PolygonsController.java @@ -32,16 +32,6 @@ void setGoogleMap(GoogleMap googleMap) { this.googleMap = googleMap; } - void addJsonPolygons(List polygonsToAdd) { - if (polygonsToAdd != null) { - for (Object polygonToAdd : polygonsToAdd) { - @SuppressWarnings("unchecked") - Map polygonMap = (Map) polygonToAdd; - addJsonPolygon(polygonMap); - } - } - } - void addPolygons(@NonNull List polygonsToAdd) { for (Messages.PlatformPolygon polygonToAdd : polygonsToAdd) { addJsonPolygon(polygonToAdd.getJson()); diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/PolylinesController.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/PolylinesController.java index cd388f1eae0..646f14c4497 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/PolylinesController.java +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/PolylinesController.java @@ -36,16 +36,6 @@ void setGoogleMap(GoogleMap googleMap) { this.googleMap = googleMap; } - void addJsonPolylines(List polylinesToAdd) { - if (polylinesToAdd != null) { - for (Object polylineToAdd : polylinesToAdd) { - @SuppressWarnings("unchecked") - Map polylineMap = (Map) polylineToAdd; - addJsonPolyline(polylineMap); - } - } - } - void addPolylines(@NonNull List polylinesToAdd) { for (Messages.PlatformPolyline polylineToAdd : polylinesToAdd) { addJsonPolyline(polylineToAdd.getJson()); 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 1d44e56b51a..fcc5c212d8d 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 @@ -29,15 +29,6 @@ void setGoogleMap(GoogleMap googleMap) { this.googleMap = googleMap; } - void addJsonTileOverlays(List> tileOverlaysToAdd) { - if (tileOverlaysToAdd == null) { - return; - } - for (Map tileOverlayToAdd : tileOverlaysToAdd) { - addJsonTileOverlay(tileOverlayToAdd); - } - } - void addTileOverlays(@NonNull List tileOverlaysToAdd) { for (Messages.PlatformTileOverlay tileOverlayToAdd : tileOverlaysToAdd) { @SuppressWarnings("unchecked") 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 4133392e310..cee54cb685b 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 @@ -37,7 +37,6 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentMatchers; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; @@ -49,81 +48,22 @@ public class ClusterManagersControllerTest { private ClusterManagersController controller; private GoogleMap googleMap; private MarkerManager markerManager; - private MarkerManager.Collection markerCollection; private AssetManager assetManager; private final float density = 1; @Before public void setUp() { - MockitoAnnotations.openMocks(this); context = ApplicationProvider.getApplicationContext(); assetManager = context.getAssets(); flutterApi = spy(new MapsCallbackApi(mock(BinaryMessenger.class))); controller = spy(new ClusterManagersController(flutterApi, context)); googleMap = mock(GoogleMap.class); markerManager = new MarkerManager(googleMap); - markerCollection = markerManager.newCollection(); controller.init(googleMap, markerManager); } @Test - @SuppressWarnings("unchecked") - public void AddJsonClusterManagersAndMarkers() throws InterruptedException { - final String clusterManagerId = "cm_1"; - final String markerId1 = "mid_1"; - final String markerId2 = "mid_2"; - - final LatLng latLng1 = new LatLng(1.1, 2.2); - final LatLng latLng2 = new LatLng(3.3, 4.4); - - final List location1 = new ArrayList<>(); - location1.add(latLng1.latitude); - location1.add(latLng1.longitude); - - final List location2 = new ArrayList<>(); - location2.add(latLng2.latitude); - location2.add(latLng2.longitude); - - when(googleMap.getCameraPosition()) - .thenReturn(CameraPosition.builder().target(new LatLng(0, 0)).build()); - Map initialClusterManager = new HashMap<>(); - initialClusterManager.put("clusterManagerId", clusterManagerId); - List clusterManagersToAdd = new ArrayList<>(); - clusterManagersToAdd.add(initialClusterManager); - controller.addJsonClusterManagers(clusterManagersToAdd); - - MarkerBuilder markerBuilder1 = new MarkerBuilder(markerId1, clusterManagerId); - MarkerBuilder markerBuilder2 = new MarkerBuilder(markerId2, clusterManagerId); - - final Map markerData1 = - createMarkerData(markerId1, location1, clusterManagerId); - final Map markerData2 = - createMarkerData(markerId2, location2, clusterManagerId); - - Convert.interpretMarkerOptions(markerData1, markerBuilder1, assetManager, density); - Convert.interpretMarkerOptions(markerData2, markerBuilder2, assetManager, density); - - controller.addItem(markerBuilder1); - controller.addItem(markerBuilder2); - - Set> clusters = - controller.getClustersWithClusterManagerId(clusterManagerId); - assertEquals("Amount of clusters should be 1", 1, clusters.size()); - - 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, cluster.getSize()); - } - - @Test - @SuppressWarnings("unchecked") - public void AddClusterManagersAndMarkers() throws InterruptedException { + public void AddClusterManagersAndMarkers() { final String clusterManagerId = "cm_1"; final String markerId1 = "mid_1"; final String markerId2 = "mid_2"; @@ -177,8 +117,7 @@ public void AddClusterManagersAndMarkers() throws InterruptedException { } @Test - @SuppressWarnings("unchecked") - public void OnClusterClickCallsMethodChannel() throws InterruptedException { + public void OnClusterClickCallsMethodChannel() { String clusterManagerId = "cm_1"; LatLng clusterPosition = new LatLng(43.00, -87.90); LatLng markerPosition1 = new LatLng(43.05, -87.95); 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 865920ee631..f8998a9d987 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 @@ -6,7 +6,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -22,9 +21,7 @@ import com.google.maps.android.clustering.ClusterManager; import io.flutter.plugin.common.BinaryMessenger; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -103,19 +100,19 @@ public void tearDown() throws Exception { } @Test - public void DisposeReleaseTheMap() throws InterruptedException { + public void DisposeReleaseTheMap() { GoogleMapController googleMapController = getGoogleMapController(); googleMapController.onMapReady(mockGoogleMap); - assertTrue(googleMapController != null); + assertNotNull(googleMapController); googleMapController.dispose(); assertNull(googleMapController.getView()); } @Test - public void OnDestroyReleaseTheMap() throws InterruptedException { + public void OnDestroyReleaseTheMap() { GoogleMapController googleMapController = getGoogleMapController(); googleMapController.onMapReady(mockGoogleMap); - assertTrue(googleMapController != null); + assertNotNull(googleMapController); googleMapController.onDestroy(activity); assertNull(googleMapController.getView()); } @@ -194,15 +191,15 @@ public void OnMapReadySetsClusterItemRenderedListener() { @Test public void SetInitialClusterManagers() { GoogleMapController googleMapController = getGoogleMapControllerWithMockedDependencies(); - Map initialClusterManager = new HashMap<>(); - initialClusterManager.put("clusterManagerId", "cm_1"); - List initialClusterManagers = new ArrayList<>(); + Messages.PlatformClusterManager initialClusterManager = + new Messages.PlatformClusterManager.Builder().setIdentifier("cm_1").build(); + List initialClusterManagers = new ArrayList<>(); initialClusterManagers.add(initialClusterManager); googleMapController.setInitialClusterManagers(initialClusterManagers); googleMapController.onMapReady(mockGoogleMap); // Verify if the ClusterManagersController.addClusterManagers method is called with initial cluster managers. - verify(mockClusterManagersController, times(1)).addJsonClusterManagers(any()); + verify(mockClusterManagersController, times(1)).addClusterManagers(any()); } @Test diff --git a/packages/google_maps_flutter/google_maps_flutter_android/android/src/test/java/io/flutter/plugins/googlemaps/MarkersControllerTest.java b/packages/google_maps_flutter/google_maps_flutter_android/android/src/test/java/io/flutter/plugins/googlemaps/MarkersControllerTest.java index 820ef50c451..1a50fbc9f7a 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/android/src/test/java/io/flutter/plugins/googlemaps/MarkersControllerTest.java +++ b/packages/google_maps_flutter/google_maps_flutter_android/android/src/test/java/io/flutter/plugins/googlemaps/MarkersControllerTest.java @@ -24,7 +24,6 @@ import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugins.googlemaps.Messages.MapsCallbackApi; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -34,7 +33,6 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; @@ -53,7 +51,6 @@ public class MarkersControllerTest { @Before public void setUp() { - MockitoAnnotations.openMocks(this); assetManager = ApplicationProvider.getApplicationContext().getAssets(); context = ApplicationProvider.getApplicationContext(); flutterApi = spy(new MapsCallbackApi(mock(BinaryMessenger.class))); @@ -77,11 +74,13 @@ public void controller_OnMarkerDragStart() { when(googleMap.addMarker(any(MarkerOptions.class))).thenReturn(marker); final LatLng latLng = new LatLng(1.1, 2.2); - final Map markerOptions = new HashMap<>(); + final Map markerOptions = new HashMap<>(); markerOptions.put("markerId", googleMarkerId); - final List markers = Arrays.asList(markerOptions); - controller.addJsonMarkers(markers); + final List markers = + Collections.singletonList( + new Messages.PlatformMarker.Builder().setJson(markerOptions).build()); + controller.addMarkers(markers); controller.onMarkerDragStart(googleMarkerId, latLng); Mockito.verify(flutterApi) @@ -98,11 +97,13 @@ public void controller_OnMarkerDragEnd() { when(googleMap.addMarker(any(MarkerOptions.class))).thenReturn(marker); final LatLng latLng = new LatLng(1.1, 2.2); - final Map markerOptions = new HashMap<>(); + final Map markerOptions = new HashMap<>(); markerOptions.put("markerId", googleMarkerId); - final List markers = Arrays.asList(markerOptions); - controller.addJsonMarkers(markers); + final List markers = + Collections.singletonList( + new Messages.PlatformMarker.Builder().setJson(markerOptions).build()); + controller.addMarkers(markers); controller.onMarkerDragEnd(googleMarkerId, latLng); Mockito.verify(flutterApi) @@ -119,11 +120,13 @@ public void controller_OnMarkerDrag() { when(googleMap.addMarker(any(MarkerOptions.class))).thenReturn(marker); final LatLng latLng = new LatLng(1.1, 2.2); - final Map markerOptions = new HashMap<>(); + final Map markerOptions = new HashMap<>(); markerOptions.put("markerId", googleMarkerId); - final List markers = Arrays.asList(markerOptions); - controller.addJsonMarkers(markers); + final List markers = + Collections.singletonList( + new Messages.PlatformMarker.Builder().setJson(markerOptions).build()); + controller.addMarkers(markers); controller.onMarkerDrag(googleMarkerId, latLng); Mockito.verify(flutterApi) @@ -132,11 +135,13 @@ public void controller_OnMarkerDrag() { @Test(expected = IllegalArgumentException.class) public void controller_AddMarkerThrowsErrorIfMarkerIdIsNull() { - final Map markerOptions = new HashMap<>(); + final Map markerOptions = new HashMap<>(); - final List markers = Arrays.asList(markerOptions); + final List markers = + Collections.singletonList( + new Messages.PlatformMarker.Builder().setJson(markerOptions).build()); try { - controller.addJsonMarkers(markers); + controller.addMarkers(markers); } catch (IllegalArgumentException e) { assertEquals("markerId was null", e.getMessage()); throw e; @@ -162,10 +167,12 @@ public void controller_AddChangeAndRemoveMarkerWithClusterManagerId() { markerOptions1.put("position", location1); markerOptions1.put("clusterManagerId", clusterManagerId); - final List markers = Arrays.asList(markerOptions1); + final List markers = + Collections.singletonList( + new Messages.PlatformMarker.Builder().setJson(markerOptions1).build()); // Add marker and capture the markerBuilder - controller.addJsonMarkers(markers); + controller.addMarkers(markers); ArgumentCaptor captor = ArgumentCaptor.forClass(MarkerBuilder.class); Mockito.verify(clusterManagersController, times(1)).addItem(captor.capture()); MarkerBuilder capturedMarkerBuilder = captor.getValue(); @@ -192,7 +199,7 @@ public void controller_AddChangeAndRemoveMarkerWithClusterManagerId() { Mockito.verify(marker, times(1)).setPosition(latLng2); // Remove marker - controller.removeMarkers(Arrays.asList(googleMarkerId)); + controller.removeMarkers(Collections.singletonList(googleMarkerId)); Mockito.verify(clusterManagersController, times(1)) .removeItem( @@ -212,11 +219,13 @@ public void controller_AddChangeAndRemoveMarkerWithoutClusterManagerId() { when(marker.getId()).thenReturn(googleMarkerId); when(googleMap.addMarker(any(MarkerOptions.class))).thenReturn(marker); - final Map markerOptions1 = new HashMap<>(); + final Map markerOptions1 = new HashMap<>(); markerOptions1.put("markerId", googleMarkerId); - final List markers = Arrays.asList(markerOptions1); - controller.addJsonMarkers(markers); + final List markers = + Collections.singletonList( + new Messages.PlatformMarker.Builder().setJson(markerOptions1).build()); + controller.addMarkers(markers); // clusterManagersController should not be called when adding the marker Mockito.verify(clusterManagersController, times(0)).addItem(any()); @@ -234,7 +243,7 @@ public void controller_AddChangeAndRemoveMarkerWithoutClusterManagerId() { controller.changeMarkers(markerUpdates); Mockito.verify(marker, times(1)).setAlpha(alpha); - controller.removeMarkers(Arrays.asList(googleMarkerId)); + controller.removeMarkers(Collections.singletonList(googleMarkerId)); // clusterManagersController should not be called when removing the marker Mockito.verify(clusterManagersController, times(0)).removeItem(any()); 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 383d22d24ec..5e8f24729a0 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 @@ -14,7 +14,6 @@ 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 // methods. Channel serialization details should all be package-internal. @@ -488,24 +487,30 @@ class GoogleMapsFlutterAndroid extends GoogleMapsFlutterPlatform { Widget _buildView( int creationId, PlatformViewCreatedCallback onPlatformViewCreated, { + required PlatformMapConfiguration mapConfiguration, required MapWidgetConfiguration widgetConfiguration, MapObjects mapObjects = const MapObjects(), - Map mapOptions = const {}, }) { - // TODO(stuartmorgan): Convert this to Pigeon-generated structures once - // https://github.com/flutter/flutter/issues/150631 is fixed. - final Map creationParams = { - 'initialCameraPosition': - widgetConfiguration.initialCameraPosition.toMap(), - 'options': mapOptions, - 'markersToAdd': serializeMarkerSet(mapObjects.markers), - 'polygonsToAdd': serializePolygonSet(mapObjects.polygons), - 'polylinesToAdd': serializePolylineSet(mapObjects.polylines), - 'circlesToAdd': serializeCircleSet(mapObjects.circles), - 'tileOverlaysToAdd': serializeTileOverlaySet(mapObjects.tileOverlays), - 'clusterManagersToAdd': - serializeClusterManagerSet(mapObjects.clusterManagers), - }; + final PlatformMapViewCreationParams creationParams = + PlatformMapViewCreationParams( + initialCameraPosition: _platformCameraPositionFromCameraPosition( + widgetConfiguration.initialCameraPosition), + mapConfiguration: mapConfiguration, + initialMarkers: + mapObjects.markers.map(_platformMarkerFromMarker).toList(), + initialPolygons: + mapObjects.polygons.map(_platformPolygonFromPolygon).toList(), + initialPolylines: + mapObjects.polylines.map(_platformPolylineFromPolyline).toList(), + initialCircles: + mapObjects.circles.map(_platformCircleFromCircle).toList(), + initialTileOverlays: mapObjects.tileOverlays + .map(_platformTileOverlayFromTileOverlay) + .toList(), + initialClusterManagers: mapObjects.clusterManagers + .map(_platformClusterManagerFromClusterManager) + .toList(), + ); const String viewType = 'plugins.flutter.dev/google_maps_android'; if (useAndroidViewSurface) { @@ -528,7 +533,7 @@ class GoogleMapsFlutterAndroid extends GoogleMapsFlutterPlatform { viewType: viewType, layoutDirection: widgetConfiguration.textDirection, creationParams: creationParams, - creationParamsCodec: const StandardMessageCodec(), + creationParamsCodec: MapsApi.pigeonChannelCodec, onFocus: () => params.onFocusChanged(true), ); controller.addOnPlatformViewCreatedListener( @@ -567,7 +572,8 @@ class GoogleMapsFlutterAndroid extends GoogleMapsFlutterPlatform { onPlatformViewCreated, widgetConfiguration: widgetConfiguration, mapObjects: mapObjects, - mapOptions: _jsonForMapConfiguration(mapConfiguration), + mapConfiguration: + _platformMapConfigurationFromMapConfiguration(mapConfiguration), ); } @@ -599,7 +605,7 @@ class GoogleMapsFlutterAndroid extends GoogleMapsFlutterPlatform { circles: circles, clusterManagers: clusterManagers, tileOverlays: tileOverlays), - mapOptions: mapOptions, + mapConfiguration: _platformMapConfigurationFromOptionsJson(mapOptions), ); } @@ -954,52 +960,6 @@ PlatformMapConfiguration _platformMapConfigurationFromMapConfiguration( ); } -Map _jsonForMapConfiguration(MapConfiguration config) { - final EdgeInsets? padding = config.padding; - return { - if (config.compassEnabled != null) 'compassEnabled': config.compassEnabled!, - if (config.mapToolbarEnabled != null) - 'mapToolbarEnabled': config.mapToolbarEnabled!, - if (config.cameraTargetBounds != null) - 'cameraTargetBounds': config.cameraTargetBounds!.toJson(), - if (config.mapType != null) 'mapType': config.mapType!.index, - if (config.minMaxZoomPreference != null) - 'minMaxZoomPreference': config.minMaxZoomPreference!.toJson(), - if (config.rotateGesturesEnabled != null) - 'rotateGesturesEnabled': config.rotateGesturesEnabled!, - if (config.scrollGesturesEnabled != null) - 'scrollGesturesEnabled': config.scrollGesturesEnabled!, - if (config.tiltGesturesEnabled != null) - 'tiltGesturesEnabled': config.tiltGesturesEnabled!, - if (config.zoomControlsEnabled != null) - 'zoomControlsEnabled': config.zoomControlsEnabled!, - if (config.zoomGesturesEnabled != null) - 'zoomGesturesEnabled': config.zoomGesturesEnabled!, - if (config.liteModeEnabled != null) - 'liteModeEnabled': config.liteModeEnabled!, - if (config.trackCameraPosition != null) - 'trackCameraPosition': config.trackCameraPosition!, - if (config.myLocationEnabled != null) - 'myLocationEnabled': config.myLocationEnabled!, - if (config.myLocationButtonEnabled != null) - 'myLocationButtonEnabled': config.myLocationButtonEnabled!, - if (padding != null) - 'padding': [ - padding.top, - padding.left, - padding.bottom, - padding.right, - ], - if (config.indoorViewEnabled != null) - 'indoorEnabled': config.indoorViewEnabled!, - if (config.trafficEnabled != null) 'trafficEnabled': config.trafficEnabled!, - if (config.buildingsEnabled != null) - 'buildingsEnabled': config.buildingsEnabled!, - if (config.cloudMapId != null) 'cloudMapId': config.cloudMapId!, - if (config.style != null) 'style': config.style!, - }; -} - // For supporting the deprecated updateMapOptions API. PlatformMapConfiguration _platformMapConfigurationFromOptionsJson( Map options) { @@ -1041,6 +1001,15 @@ PlatformMapConfiguration _platformMapConfigurationFromOptionsJson( ); } +PlatformCameraPosition _platformCameraPositionFromCameraPosition( + CameraPosition position) { + return PlatformCameraPosition( + bearing: position.bearing, + target: _platformLatLngFromLatLng(position.target), + tilt: position.tilt, + zoom: position.zoom); +} + PlatformMapType _platformMapTypeFromMapTypeIndex(int index) { // This is inherently fragile, but see comment in updateMapOptions. return switch (index) { 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 index 205800e7f0e..ea99eca40a5 100644 --- 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 @@ -437,6 +437,66 @@ class PlatformCameraTargetBounds { } } +/// Information passed to the platform view creation. +class PlatformMapViewCreationParams { + PlatformMapViewCreationParams({ + required this.initialCameraPosition, + required this.mapConfiguration, + required this.initialCircles, + required this.initialMarkers, + required this.initialPolygons, + required this.initialPolylines, + required this.initialTileOverlays, + required this.initialClusterManagers, + }); + + PlatformCameraPosition initialCameraPosition; + + PlatformMapConfiguration mapConfiguration; + + List initialCircles; + + List initialMarkers; + + List initialPolygons; + + List initialPolylines; + + List initialTileOverlays; + + List initialClusterManagers; + + Object encode() { + return [ + initialCameraPosition, + mapConfiguration, + initialCircles, + initialMarkers, + initialPolygons, + initialPolylines, + initialTileOverlays, + initialClusterManagers, + ]; + } + + static PlatformMapViewCreationParams decode(Object result) { + result as List; + return PlatformMapViewCreationParams( + initialCameraPosition: result[0]! as PlatformCameraPosition, + mapConfiguration: result[1]! as PlatformMapConfiguration, + initialCircles: (result[2] as List?)!.cast(), + initialMarkers: (result[3] as List?)!.cast(), + initialPolygons: (result[4] as List?)!.cast(), + initialPolylines: + (result[5] as List?)!.cast(), + initialTileOverlays: + (result[6] as List?)!.cast(), + initialClusterManagers: + (result[7] as List?)!.cast(), + ); + } +} + /// Pigeon equivalent of MapConfiguration. class PlatformMapConfiguration { PlatformMapConfiguration({ @@ -691,23 +751,26 @@ class _PigeonCodec extends StandardMessageCodec { } else if (value is PlatformCameraTargetBounds) { buffer.putUint8(142); writeValue(buffer, value.encode()); - } else if (value is PlatformMapConfiguration) { + } else if (value is PlatformMapViewCreationParams) { buffer.putUint8(143); writeValue(buffer, value.encode()); - } else if (value is PlatformPoint) { + } else if (value is PlatformMapConfiguration) { buffer.putUint8(144); writeValue(buffer, value.encode()); - } else if (value is PlatformTileLayer) { + } else if (value is PlatformPoint) { buffer.putUint8(145); writeValue(buffer, value.encode()); - } else if (value is PlatformZoomRange) { + } else if (value is PlatformTileLayer) { buffer.putUint8(146); writeValue(buffer, value.encode()); - } else if (value is PlatformMapType) { + } else if (value is PlatformZoomRange) { buffer.putUint8(147); + writeValue(buffer, value.encode()); + } else if (value is PlatformMapType) { + buffer.putUint8(148); writeValue(buffer, value.index); } else if (value is PlatformRendererType) { - buffer.putUint8(148); + buffer.putUint8(149); writeValue(buffer, value.index); } else { super.writeValue(buffer, value); @@ -746,17 +809,19 @@ class _PigeonCodec extends StandardMessageCodec { case 142: return PlatformCameraTargetBounds.decode(readValue(buffer)!); case 143: - return PlatformMapConfiguration.decode(readValue(buffer)!); + return PlatformMapViewCreationParams.decode(readValue(buffer)!); case 144: - return PlatformPoint.decode(readValue(buffer)!); + return PlatformMapConfiguration.decode(readValue(buffer)!); case 145: - return PlatformTileLayer.decode(readValue(buffer)!); + return PlatformPoint.decode(readValue(buffer)!); case 146: - return PlatformZoomRange.decode(readValue(buffer)!); + return PlatformTileLayer.decode(readValue(buffer)!); case 147: + return PlatformZoomRange.decode(readValue(buffer)!); + case 148: final int? value = readValue(buffer) as int?; return value == null ? null : PlatformMapType.values[value]; - case 148: + case 149: final int? value = readValue(buffer) as int?; return value == null ? null : PlatformRendererType.values[value]; default: @@ -1905,6 +1970,49 @@ class MapsInitializerApi { } } +/// Dummy interface to force generation of the platform view creation params, +/// which are not used in any Pigeon calls, only the platform view creation +/// call made internally by Flutter. +class MapsPlatformViewApi { + /// Constructor for [MapsPlatformViewApi]. 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. + MapsPlatformViewApi( + {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 createView(PlatformMapViewCreationParams? type) async { + final String __pigeon_channelName = + 'dev.flutter.pigeon.google_maps_flutter_android.MapsPlatformViewApi.createView$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([type]) 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; + } + } +} + /// Inspector API only intended for use in integration tests. class MapsInspectorApi { /// Constructor for [MapsInspectorApi]. The [binaryMessenger] named argument is diff --git a/packages/google_maps_flutter/google_maps_flutter_android/lib/src/utils/cluster_manager_utils.dart b/packages/google_maps_flutter/google_maps_flutter_android/lib/src/utils/cluster_manager_utils.dart deleted file mode 100644 index 1aab89354a0..00000000000 --- a/packages/google_maps_flutter/google_maps_flutter_android/lib/src/utils/cluster_manager_utils.dart +++ /dev/null @@ -1,19 +0,0 @@ -// 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:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; - -/// Converts a Set of Cluster Managers into object serializable in JSON. -Object serializeClusterManagerSet(Set clusterManagers) { - return clusterManagers - .map((ClusterManager cm) => _serializeClusterManager(cm)) - .toList(); -} - -/// Converts a Cluster Manager into object serializable in JSON. -Object _serializeClusterManager(ClusterManager clusterManager) { - final Map json = {}; - json['clusterManagerId'] = clusterManager.clusterManagerId.value; - return json; -} 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 index b4414d1992b..e98cb6e20d4 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/pigeons/messages.dart +++ b/packages/google_maps_flutter/google_maps_flutter_android/pigeons/messages.dart @@ -188,6 +188,32 @@ class PlatformCameraTargetBounds { final PlatformLatLngBounds? bounds; } +/// Information passed to the platform view creation. +class PlatformMapViewCreationParams { + PlatformMapViewCreationParams({ + required this.initialCameraPosition, + required this.mapConfiguration, + required this.initialCircles, + required this.initialMarkers, + required this.initialPolygons, + required this.initialPolylines, + required this.initialTileOverlays, + required this.initialClusterManagers, + }); + + final PlatformCameraPosition initialCameraPosition; + final PlatformMapConfiguration mapConfiguration; + // TODO(stuartmorgan): Make the generic types non-nullable once supported. + // https://github.com/flutter/flutter/issues/97848 + // The consuming code treats the entries as non-nullable. + final List initialCircles; + final List initialMarkers; + final List initialPolygons; + final List initialPolylines; + final List initialTileOverlays; + final List initialClusterManagers; +} + /// Pigeon equivalent of MapConfiguration. class PlatformMapConfiguration { PlatformMapConfiguration({ @@ -438,6 +464,15 @@ abstract class MapsInitializerApi { PlatformRendererType? type); } +/// Dummy interface to force generation of the platform view creation params, +/// which are not used in any Pigeon calls, only the platform view creation +/// call made internally by Flutter. +@HostApi() +abstract class MapsPlatformViewApi { + // This is never actually called. + void createView(PlatformMapViewCreationParams? type); +} + /// Inspector API only intended for use in integration tests. @HostApi() abstract class MapsInspectorApi { From e8a5e8dc908d3ff6e7faaf4d4484cbc83a912a07 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 24 Jul 2024 11:27:45 -0400 Subject: [PATCH 05/14] Convert platform view creation params to Pigeon on iOS --- ...TGoogleMapJSONConversionsConversionTests.m | 34 ++--- .../ios14/ios/RunnerTests/GoogleMapsTests.m | 27 +++- .../ios/Classes/FLTGoogleMapJSONConversions.h | 6 +- .../ios/Classes/FLTGoogleMapJSONConversions.m | 17 ++- .../FLTGoogleMapTileOverlayController.h | 1 - .../FLTGoogleMapTileOverlayController.m | 14 -- .../ios/Classes/GoogleMapCircleController.h | 1 - .../ios/Classes/GoogleMapCircleController.m | 15 --- .../ios/Classes/GoogleMapController.h | 2 +- .../ios/Classes/GoogleMapController.m | 122 +++--------------- .../ios/Classes/GoogleMapController_Test.h | 2 +- .../ios/Classes/GoogleMapMarkerController.h | 1 - .../ios/Classes/GoogleMapMarkerController.m | 15 --- .../ios/Classes/GoogleMapPolygonController.h | 1 - .../ios/Classes/GoogleMapPolygonController.m | 13 -- .../ios/Classes/GoogleMapPolylineController.h | 1 - .../ios/Classes/GoogleMapPolylineController.m | 13 -- .../ios/Classes/messages.g.h | 37 ++++++ .../ios/Classes/messages.g.m | 111 ++++++++++++++-- .../lib/src/google_maps_flutter_ios.dart | 85 +++++------- .../lib/src/messages.g.dart | 120 +++++++++++++++-- .../pigeons/messages.dart | 33 +++++ 22 files changed, 386 insertions(+), 285 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/FLTGoogleMapJSONConversionsConversionTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/FLTGoogleMapJSONConversionsConversionTests.m index d6594387330..d219c655a21 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/FLTGoogleMapJSONConversionsConversionTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/FLTGoogleMapJSONConversionsConversionTests.m @@ -52,13 +52,6 @@ - (void)testPointFromArray { XCTAssertEqual(point.y, 2); } -- (void)testArrayFromLocation { - CLLocationCoordinate2D location = CLLocationCoordinate2DMake(1, 2); - NSArray *array = [FLTGoogleMapJSONConversions arrayFromLocation:location]; - XCTAssertEqual([array[0] integerValue], 1); - XCTAssertEqual([array[1] integerValue], 2); -} - - (void)testColorFromRGBA { NSNumber *rgba = @(0x01020304); UIColor *color = [FLTGoogleMapJSONConversions colorFromRGBA:rgba]; @@ -152,6 +145,25 @@ - (void)testCameraPostionFromDictionary { XCTAssertEqualWithAccuracy(cameraPosition.viewingAngle, 5, accuracy); } +- (void)testGetCameraPostionForPigeonCameraPosition { + FGMPlatformCameraPosition *pigeonCameraPosition = [FGMPlatformCameraPosition + makeWithBearing:1.0 + target:[FGMPlatformLatLng makeWithLatitude:2.0 longitude:3.0] + tilt:4.0 + zoom:5.0]; + + GMSCameraPosition *cameraPosition = + FGMGetCameraPositionForPigeonCameraPosition(pigeonCameraPosition); + + XCTAssertEqualWithAccuracy(cameraPosition.target.latitude, pigeonCameraPosition.target.latitude, + DBL_EPSILON); + XCTAssertEqualWithAccuracy(cameraPosition.target.longitude, pigeonCameraPosition.target.longitude, + DBL_EPSILON); + XCTAssertEqualWithAccuracy(cameraPosition.zoom, pigeonCameraPosition.zoom, DBL_EPSILON); + XCTAssertEqualWithAccuracy(cameraPosition.bearing, pigeonCameraPosition.bearing, DBL_EPSILON); + XCTAssertEqualWithAccuracy(cameraPosition.viewingAngle, pigeonCameraPosition.tilt, DBL_EPSILON); +} + - (void)testCGPointForPigeonPoint { FGMPlatformPoint *pigeonPoint = [FGMPlatformPoint makeWithX:1.0 y:2.0]; @@ -175,14 +187,6 @@ - (void)testCoordinateBoundsFromLatLongs { XCTAssertEqualWithAccuracy(bounds.northEast.longitude, 4, accuracy); } -- (void)testMapViewTypeFromTypeValue { - XCTAssertEqual(kGMSTypeNormal, [FLTGoogleMapJSONConversions mapViewTypeFromTypeValue:@1]); - XCTAssertEqual(kGMSTypeSatellite, [FLTGoogleMapJSONConversions mapViewTypeFromTypeValue:@2]); - XCTAssertEqual(kGMSTypeTerrain, [FLTGoogleMapJSONConversions mapViewTypeFromTypeValue:@3]); - XCTAssertEqual(kGMSTypeHybrid, [FLTGoogleMapJSONConversions mapViewTypeFromTypeValue:@4]); - XCTAssertEqual(kGMSTypeNone, [FLTGoogleMapJSONConversions mapViewTypeFromTypeValue:@5]); -} - - (void)testMapViewTypeFromPigeonType { XCTAssertEqual(kGMSTypeNormal, FGMGetMapViewTypeForPigeonMapType(FGMPlatformMapTypeNormal)); XCTAssertEqual(kGMSTypeSatellite, FGMGetMapViewTypeForPigeonMapType(FGMPlatformMapTypeSatellite)); diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/GoogleMapsTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/GoogleMapsTests.m index b3ac89e2441..07dac2dcf96 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/GoogleMapsTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/GoogleMapsTests.m @@ -40,10 +40,11 @@ - (void)testFrameObserver { initWithFrame:frame camera:[[GMSCameraPosition alloc] initWithLatitude:0 longitude:0 zoom:0]]; #pragma clang diagnostic pop - FLTGoogleMapController *controller = [[FLTGoogleMapController alloc] initWithMapView:mapView - viewIdentifier:0 - arguments:nil - registrar:registrar]; + FLTGoogleMapController *controller = + [[FLTGoogleMapController alloc] initWithMapView:mapView + viewIdentifier:0 + creationParameters:[self emptyCreationParameters] + registrar:registrar]; for (NSInteger i = 0; i < 10; ++i) { [controller view]; @@ -85,4 +86,22 @@ - (void)testHandleResultTileDownsamplesWideGamutImages { XCTAssert(bitsPerComponent == 8); } +/// Creates an empty creation paramaters object for tests where the values don't matter, just that +/// there's a valid object to pass in. +- (FGMPlatformMapViewCreationParams *)emptyCreationParameters { + return [FGMPlatformMapViewCreationParams + makeWithInitialCameraPosition:[FGMPlatformCameraPosition + makeWithBearing:0.0 + target:[FGMPlatformLatLng makeWithLatitude:0.0 + longitude:0.0] + tilt:0.0 + zoom:0.0] + mapConfiguration:[[FGMPlatformMapConfiguration alloc] init] + initialCircles:@[] + initialMarkers:@[] + initialPolygons:@[] + initialPolylines:@[] + initialTileOverlays:@[]]; +} + @end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.h index 5c9db91363b..b2f954f8783 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.h @@ -36,6 +36,10 @@ extern FGMPlatformLatLngBounds *FGMGetPigeonLatLngBoundsForCoordinateBounds( extern FGMPlatformCameraPosition *FGMGetPigeonCameraPositionForPosition( GMSCameraPosition *position); +/// Creates a GMSCameraPosition from its Pigeon representation. +extern GMSCameraPosition *FGMGetCameraPositionForPigeonCameraPosition( + FGMPlatformCameraPosition *position); + /// Creates a GMSMapViewType from its Pigeon representation. extern GMSMapViewType FGMGetMapViewTypeForPigeonMapType(FGMPlatformMapType type); @@ -43,13 +47,11 @@ extern GMSMapViewType FGMGetMapViewTypeForPigeonMapType(FGMPlatformMapType type) + (CLLocationCoordinate2D)locationFromLatLong:(NSArray *)latlong; + (CGPoint)pointFromArray:(NSArray *)array; -+ (NSArray *)arrayFromLocation:(CLLocationCoordinate2D)location; + (UIColor *)colorFromRGBA:(NSNumber *)data; + (NSArray *)pointsFromLatLongs:(NSArray *)data; + (NSArray *> *)holesFromPointsArray:(NSArray *)data; + (nullable GMSCameraPosition *)cameraPostionFromDictionary:(nullable NSDictionary *)channelValue; + (GMSCoordinateBounds *)coordinateBoundsFromLatLongs:(NSArray *)latlongs; -+ (GMSMapViewType)mapViewTypeFromTypeValue:(NSNumber *)value; + (nullable GMSCameraUpdate *)cameraUpdateFromArray:(NSArray *)channelValue; /// Return GMS strokestyle object array populated using the patterns and stroke colors passed in. diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.m index e6b4c853806..68ab457d086 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.m @@ -45,6 +45,14 @@ CLLocationCoordinate2D FGMGetCoordinateForPigeonLatLng(FGMPlatformLatLng *latLng zoom:position.zoom]; } +GMSCameraPosition *FGMGetCameraPositionForPigeonCameraPosition( + FGMPlatformCameraPosition *position) { + return [GMSCameraPosition cameraWithTarget:FGMGetCoordinateForPigeonLatLng(position.target) + zoom:position.zoom + bearing:position.bearing + viewingAngle:position.tilt]; +} + extern GMSMapViewType FGMGetMapViewTypeForPigeonMapType(FGMPlatformMapType type) { switch (type) { case FGMPlatformMapTypeNone: @@ -70,10 +78,6 @@ + (CGPoint)pointFromArray:(NSArray *)array { return CGPointMake([array[0] doubleValue], [array[1] doubleValue]); } -+ (NSArray *)arrayFromLocation:(CLLocationCoordinate2D)location { - return @[ @(location.latitude), @(location.longitude) ]; -} - + (UIColor *)colorFromRGBA:(NSNumber *)numberColor { unsigned long value = [numberColor unsignedLongValue]; return [UIColor colorWithRed:((float)((value & 0xFF0000) >> 16)) / 255.0 @@ -122,11 +126,6 @@ + (GMSCoordinateBounds *)coordinateBoundsFromLatLongs:(NSArray *)latlongs { coordinate:[FLTGoogleMapJSONConversions locationFromLatLong:latlongs[1]]]; } -+ (GMSMapViewType)mapViewTypeFromTypeValue:(NSNumber *)typeValue { - int value = [typeValue intValue]; - return (GMSMapViewType)(value == 0 ? 5 : value); -} - + (nullable GMSCameraUpdate *)cameraUpdateFromArray:(NSArray *)channelValue { NSString *update = channelValue[0]; if ([update isEqualToString:@"newCameraPosition"]) { diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapTileOverlayController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapTileOverlayController.h index e375f7df6e1..223de202bfc 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapTileOverlayController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapTileOverlayController.h @@ -30,7 +30,6 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithMapView:(GMSMapView *)mapView callbackHandler:(FGMMapsCallbackApi *)callbackHandler registrar:(NSObject *)registrar; -- (void)addJSONTileOverlays:(NSArray *> *)tileOverlaysToAdd; - (void)addTileOverlays:(NSArray *)tileOverlaysToAdd; - (void)changeTileOverlays:(NSArray *)tileOverlaysToChange; - (void)removeTileOverlayWithIdentifiers:(NSArray *)identifiers; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapTileOverlayController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapTileOverlayController.m index 10523124980..9897cd93da6 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapTileOverlayController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapTileOverlayController.m @@ -180,20 +180,6 @@ - (instancetype)initWithMapView:(GMSMapView *)mapView return self; } -- (void)addJSONTileOverlays:(NSArray *> *)tileOverlaysToAdd { - for (NSDictionary *tileOverlay in tileOverlaysToAdd) { - NSString *identifier = [FLTTileOverlaysController identifierForTileOverlay:tileOverlay]; - FLTTileProviderController *tileProvider = - [[FLTTileProviderController alloc] initWithTileOverlayIdentifier:identifier - callbackHandler:self.callbackHandler]; - FLTGoogleMapTileOverlayController *controller = - [[FLTGoogleMapTileOverlayController alloc] initWithTileLayer:tileProvider - mapView:self.mapView - options:tileOverlay]; - self.tileOverlayIdentifierToController[identifier] = controller; - } -} - - (void)addTileOverlays:(NSArray *)tileOverlaysToAdd { for (FGMPlatformTileOverlay *tileOverlay in tileOverlaysToAdd) { NSString *identifier = [FLTTileOverlaysController identifierForTileOverlay:tileOverlay.json]; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapCircleController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapCircleController.h index a53199f077d..c40340e08db 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapCircleController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapCircleController.h @@ -21,7 +21,6 @@ - (instancetype)initWithMapView:(GMSMapView *)mapView callbackHandler:(FGMMapsCallbackApi *)callbackHandler registrar:(NSObject *)registrar; -- (void)addJSONCircles:(NSArray *> *)circlesToAdd; - (void)addCircles:(NSArray *)circlesToAdd; - (void)changeCircles:(NSArray *)circlesToChange; - (void)removeCirclesWithIdentifiers:(NSArray *)identifiers; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapCircleController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapCircleController.m index ae4c9c2f9ba..ca71d315022 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapCircleController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapCircleController.m @@ -125,21 +125,6 @@ - (instancetype)initWithMapView:(GMSMapView *)mapView return self; } -- (void)addJSONCircles:(NSArray *> *)circlesToAdd { - for (NSDictionary *circle in circlesToAdd) { - CLLocationCoordinate2D position = [FLTCirclesController getPosition:circle]; - CLLocationDistance radius = [FLTCirclesController getRadius:circle]; - NSString *circleId = [FLTCirclesController getCircleId:circle]; - FLTGoogleMapCircleController *controller = - [[FLTGoogleMapCircleController alloc] initCircleWithPosition:position - radius:radius - circleId:circleId - mapView:self.mapView - options:circle]; - self.circleIdToController[circleId] = controller; - } -} - - (void)addCircles:(NSArray *)circlesToAdd { for (FGMPlatformCircle *circle in circlesToAdd) { CLLocationCoordinate2D position = [FLTCirclesController getPosition:circle.json]; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController.h index 4fdc08721d3..07c92929718 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController.h @@ -16,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN @interface FLTGoogleMapController : NSObject - (instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId - arguments:(nullable id)args + creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters registrar:(NSObject *)registrar; - (void)showAtOrigin:(CGPoint)origin; - (void)hide; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController.m index 02e668cc21b..d6c524f806b 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController.m @@ -29,7 +29,7 @@ - (instancetype)initWithRegistrar:(NSObject *)registrar } - (NSObject *)createArgsCodec { - return [FlutterStandardMessageCodec sharedInstance]; + return FGMGetMessagesCodec(); } - (NSObject *)createWithFrame:(CGRect)frame @@ -41,7 +41,7 @@ - (instancetype)initWithRegistrar:(NSObject *)registrar return [[FLTGoogleMapController alloc] initWithFrame:frame viewIdentifier:viewId - arguments:args + creationParameters:args registrar:self.registrar]; } @@ -136,27 +136,30 @@ @implementation FLTGoogleMapController - (instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId - arguments:(id _Nullable)args + creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters registrar:(NSObject *)registrar { GMSCameraPosition *camera = - [FLTGoogleMapJSONConversions cameraPostionFromDictionary:args[@"initialCameraPosition"]]; + FGMGetCameraPositionForPigeonCameraPosition(creationParameters.initialCameraPosition); GMSMapViewOptions *options = [[GMSMapViewOptions alloc] init]; options.frame = frame; options.camera = camera; - NSString *cloudMapId = args[@"options"][@"cloudMapId"]; + NSString *cloudMapId = creationParameters.mapConfiguration.cloudMapId; if (cloudMapId) { options.mapID = [GMSMapID mapIDWithIdentifier:cloudMapId]; } GMSMapView *mapView = [[GMSMapView alloc] initWithOptions:options]; - return [self initWithMapView:mapView viewIdentifier:viewId arguments:args registrar:registrar]; + return [self initWithMapView:mapView + viewIdentifier:viewId + creationParameters:creationParameters + registrar:registrar]; } - (instancetype)initWithMapView:(GMSMapView *_Nonnull)mapView viewIdentifier:(int64_t)viewId - arguments:(id _Nullable)args + creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters registrar:(NSObject *_Nonnull)registrar { if (self = [super init]) { _mapView = mapView; @@ -164,7 +167,7 @@ - (instancetype)initWithMapView:(GMSMapView *_Nonnull)mapView _mapView.accessibilityElementsHidden = NO; // TODO(cyanglaz): avoid sending message to self in the middle of the init method. // https://github.com/flutter/flutter/issues/104121 - [self interpretMapOptionsJSON:args[@"options"]]; + [self interpretMapConfiguration:creationParameters.mapConfiguration]; NSString *pigeonSuffix = [NSString stringWithFormat:@"%lld", viewId]; _dartCallbackHandler = [[FGMMapsCallbackApi alloc] initWithBinaryMessenger:registrar.messenger messageChannelSuffix:pigeonSuffix]; @@ -187,26 +190,11 @@ - (instancetype)initWithMapView:(GMSMapView *_Nonnull)mapView [[FLTTileOverlaysController alloc] initWithMapView:_mapView callbackHandler:_dartCallbackHandler registrar:registrar]; - id markersToAdd = args[@"markersToAdd"]; - if ([markersToAdd isKindOfClass:[NSArray class]]) { - [_markersController addJSONMarkers:markersToAdd]; - } - id polygonsToAdd = args[@"polygonsToAdd"]; - if ([polygonsToAdd isKindOfClass:[NSArray class]]) { - [_polygonsController addJSONPolygons:polygonsToAdd]; - } - id polylinesToAdd = args[@"polylinesToAdd"]; - if ([polylinesToAdd isKindOfClass:[NSArray class]]) { - [_polylinesController addJSONPolylines:polylinesToAdd]; - } - id circlesToAdd = args[@"circlesToAdd"]; - if ([circlesToAdd isKindOfClass:[NSArray class]]) { - [_circlesController addJSONCircles:circlesToAdd]; - } - id tileOverlaysToAdd = args[@"tileOverlaysToAdd"]; - if ([tileOverlaysToAdd isKindOfClass:[NSArray class]]) { - [_tileOverlaysController addJSONTileOverlays:tileOverlaysToAdd]; - } + [_markersController addMarkers:creationParameters.initialMarkers]; + [_polygonsController addPolygons:creationParameters.initialPolygons]; + [_polylinesController addPolylines:creationParameters.initialPolylines]; + [_circlesController addCircles:creationParameters.initialCircles]; + [_tileOverlaysController addTileOverlays:creationParameters.initialTileOverlays]; [_mapView addObserver:self forKeyPath:@"frame" options:0 context:nil]; @@ -496,84 +484,6 @@ - (void)interpretMapConfiguration:(FGMPlatformMapConfiguration *)config { } } -- (void)interpretMapOptionsJSON:(NSDictionary *)data { - NSArray *cameraTargetBounds = FGMGetValueOrNilFromDict(data, @"cameraTargetBounds"); - if (cameraTargetBounds) { - [self - setCameraTargetBounds:cameraTargetBounds.count > 0 && cameraTargetBounds[0] != [NSNull null] - ? [FLTGoogleMapJSONConversions - coordinateBoundsFromLatLongs:cameraTargetBounds.firstObject] - : nil]; - } - NSNumber *compassEnabled = FGMGetValueOrNilFromDict(data, @"compassEnabled"); - if (compassEnabled) { - [self setCompassEnabled:[compassEnabled boolValue]]; - } - id indoorEnabled = FGMGetValueOrNilFromDict(data, @"indoorEnabled"); - if (indoorEnabled) { - [self setIndoorEnabled:[indoorEnabled boolValue]]; - } - id trafficEnabled = FGMGetValueOrNilFromDict(data, @"trafficEnabled"); - if (trafficEnabled) { - [self setTrafficEnabled:[trafficEnabled boolValue]]; - } - id buildingsEnabled = FGMGetValueOrNilFromDict(data, @"buildingsEnabled"); - if (buildingsEnabled) { - [self setBuildingsEnabled:[buildingsEnabled boolValue]]; - } - id mapType = FGMGetValueOrNilFromDict(data, @"mapType"); - if (mapType) { - [self setMapType:[FLTGoogleMapJSONConversions mapViewTypeFromTypeValue:mapType]]; - } - NSArray *zoomData = FGMGetValueOrNilFromDict(data, @"minMaxZoomPreference"); - if (zoomData) { - float minZoom = (zoomData[0] == [NSNull null]) ? kGMSMinZoomLevel : [zoomData[0] floatValue]; - float maxZoom = (zoomData[1] == [NSNull null]) ? kGMSMaxZoomLevel : [zoomData[1] floatValue]; - [self setMinZoom:minZoom maxZoom:maxZoom]; - } - NSArray *paddingData = FGMGetValueOrNilFromDict(data, @"padding"); - if (paddingData) { - float top = (paddingData[0] == [NSNull null]) ? 0 : [paddingData[0] floatValue]; - float left = (paddingData[1] == [NSNull null]) ? 0 : [paddingData[1] floatValue]; - float bottom = (paddingData[2] == [NSNull null]) ? 0 : [paddingData[2] floatValue]; - float right = (paddingData[3] == [NSNull null]) ? 0 : [paddingData[3] floatValue]; - [self setPaddingTop:top left:left bottom:bottom right:right]; - } - - NSNumber *rotateGesturesEnabled = FGMGetValueOrNilFromDict(data, @"rotateGesturesEnabled"); - if (rotateGesturesEnabled) { - [self setRotateGesturesEnabled:[rotateGesturesEnabled boolValue]]; - } - NSNumber *scrollGesturesEnabled = FGMGetValueOrNilFromDict(data, @"scrollGesturesEnabled"); - if (scrollGesturesEnabled) { - [self setScrollGesturesEnabled:[scrollGesturesEnabled boolValue]]; - } - NSNumber *tiltGesturesEnabled = FGMGetValueOrNilFromDict(data, @"tiltGesturesEnabled"); - if (tiltGesturesEnabled) { - [self setTiltGesturesEnabled:[tiltGesturesEnabled boolValue]]; - } - NSNumber *trackCameraPosition = FGMGetValueOrNilFromDict(data, @"trackCameraPosition"); - if (trackCameraPosition) { - [self setTrackCameraPosition:[trackCameraPosition boolValue]]; - } - NSNumber *zoomGesturesEnabled = FGMGetValueOrNilFromDict(data, @"zoomGesturesEnabled"); - if (zoomGesturesEnabled) { - [self setZoomGesturesEnabled:[zoomGesturesEnabled boolValue]]; - } - NSNumber *myLocationEnabled = FGMGetValueOrNilFromDict(data, @"myLocationEnabled"); - if (myLocationEnabled) { - [self setMyLocationEnabled:[myLocationEnabled boolValue]]; - } - NSNumber *myLocationButtonEnabled = FGMGetValueOrNilFromDict(data, @"myLocationButtonEnabled"); - if (myLocationButtonEnabled) { - [self setMyLocationButtonEnabled:[myLocationButtonEnabled boolValue]]; - } - NSString *style = FGMGetValueOrNilFromDict(data, @"style"); - if (style) { - [self setMapStyle:style]; - } -} - @end #pragma mark - diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController_Test.h index 1377b68e9b6..a9d7ecd2b67 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController_Test.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController_Test.h @@ -17,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN /// @param registrar The plugin registrar passed from Flutter. - (instancetype)initWithMapView:(GMSMapView *)mapView viewIdentifier:(int64_t)viewId - arguments:(id _Nullable)args + creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters registrar:(NSObject *)registrar; @end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapMarkerController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapMarkerController.h index 1b87ab1bb94..87acbe18202 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapMarkerController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapMarkerController.h @@ -26,7 +26,6 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithMapView:(GMSMapView *)mapView callbackHandler:(FGMMapsCallbackApi *)callbackHandler registrar:(NSObject *)registrar; -- (void)addJSONMarkers:(NSArray *> *)markersToAdd; - (void)addMarkers:(NSArray *)markersToAdd; - (void)changeMarkers:(NSArray *)markersToChange; - (void)removeMarkersWithIdentifiers:(NSArray *)identifiers; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapMarkerController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapMarkerController.m index 46ac7b24ee5..58827366f34 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapMarkerController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapMarkerController.m @@ -452,21 +452,6 @@ - (instancetype)initWithMapView:(GMSMapView *)mapView return self; } -- (void)addJSONMarkers:(NSArray *> *)markersToAdd { - for (NSDictionary *marker in markersToAdd) { - CLLocationCoordinate2D position = [FLTMarkersController getPosition:marker]; - NSString *identifier = marker[@"markerId"]; - FLTGoogleMapMarkerController *controller = - [[FLTGoogleMapMarkerController alloc] initWithPosition:position - identifier:identifier - mapView:self.mapView]; - [controller interpretMarkerOptions:marker - registrar:self.registrar - screenScale:[self getScreenScale]]; - self.markerIdentifierToController[identifier] = controller; - } -} - - (void)addMarkers:(NSArray *)markersToAdd { for (FGMPlatformMarker *marker in markersToAdd) { CLLocationCoordinate2D position = [FLTMarkersController getPosition:marker.json]; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolygonController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolygonController.h index 4d1b0fd5f00..afc8024d2b5 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolygonController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolygonController.h @@ -19,7 +19,6 @@ - (instancetype)initWithMapView:(GMSMapView *)mapView callbackHandler:(FGMMapsCallbackApi *)callbackHandler registrar:(NSObject *)registrar; -- (void)addJSONPolygons:(NSArray *> *)polygonsToAdd; - (void)addPolygons:(NSArray *)polygonsToAdd; - (void)changePolygons:(NSArray *)polygonsToChange; - (void)removePolygonWithIdentifiers:(NSArray *)identifiers; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolygonController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolygonController.m index 19380aad6d0..a66b7f5d39d 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolygonController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolygonController.m @@ -140,19 +140,6 @@ - (instancetype)initWithMapView:(GMSMapView *)mapView return self; } -- (void)addJSONPolygons:(NSArray *> *)polygonsToAdd { - for (NSDictionary *polygon in polygonsToAdd) { - GMSMutablePath *path = [FLTPolygonsController getPath:polygon]; - NSString *identifier = polygon[@"polygonId"]; - FLTGoogleMapPolygonController *controller = - [[FLTGoogleMapPolygonController alloc] initWithPath:path - identifier:identifier - mapView:self.mapView]; - [controller interpretPolygonOptions:polygon registrar:self.registrar]; - self.polygonIdentifierToController[identifier] = controller; - } -} - - (void)addPolygons:(NSArray *)polygonsToAdd { for (FGMPlatformPolygon *polygon in polygonsToAdd) { GMSMutablePath *path = [FLTPolygonsController getPath:polygon.json]; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController.h index 8557be961e4..da86f41b819 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController.h @@ -25,7 +25,6 @@ - (instancetype)initWithMapView:(GMSMapView *)mapView callbackHandler:(FGMMapsCallbackApi *)callbackHandler registrar:(NSObject *)registrar; -- (void)addJSONPolylines:(NSArray *> *)polylinesToAdd; - (void)addPolylines:(NSArray *)polylinesToAdd; - (void)changePolylines:(NSArray *)polylinesToChange; - (void)removePolylineWithIdentifiers:(NSArray *)identifiers; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController.m index 51cec3baae1..44a31b18b53 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController.m @@ -136,19 +136,6 @@ - (instancetype)initWithMapView:(GMSMapView *)mapView return self; } -- (void)addJSONPolylines:(NSArray *> *)polylinesToAdd { - for (NSDictionary *polyline in polylinesToAdd) { - GMSMutablePath *path = [FLTPolylinesController pathForPolyline:polyline]; - NSString *identifier = polyline[@"polylineId"]; - FLTGoogleMapPolylineController *controller = - [[FLTGoogleMapPolylineController alloc] initWithPath:path - identifier:identifier - mapView:self.mapView]; - [controller interpretPolylineOptions:polyline registrar:self.registrar]; - self.polylineIdentifierToController[identifier] = controller; - } -} - - (void)addPolylines:(NSArray *)polylinesToAdd { for (FGMPlatformPolyline *polyline in polylinesToAdd) { GMSMutablePath *path = [FLTPolylinesController pathForPolyline:polyline.json]; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/messages.g.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/messages.g.h index c01282df525..92ac74806be 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/messages.g.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/messages.g.h @@ -40,6 +40,7 @@ typedef NS_ENUM(NSUInteger, FGMPlatformMapType) { @class FGMPlatformLatLng; @class FGMPlatformLatLngBounds; @class FGMPlatformCameraTargetBounds; +@class FGMPlatformMapViewCreationParams; @class FGMPlatformMapConfiguration; @class FGMPlatformPoint; @class FGMPlatformTileLayer; @@ -176,6 +177,27 @@ typedef NS_ENUM(NSUInteger, FGMPlatformMapType) { @property(nonatomic, strong, nullable) FGMPlatformLatLngBounds *bounds; @end +/// Information passed to the platform view creation. +@interface FGMPlatformMapViewCreationParams : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithInitialCameraPosition:(FGMPlatformCameraPosition *)initialCameraPosition + mapConfiguration:(FGMPlatformMapConfiguration *)mapConfiguration + initialCircles:(NSArray *)initialCircles + initialMarkers:(NSArray *)initialMarkers + initialPolygons:(NSArray *)initialPolygons + initialPolylines:(NSArray *)initialPolylines + initialTileOverlays: + (NSArray *)initialTileOverlays; +@property(nonatomic, strong) FGMPlatformCameraPosition *initialCameraPosition; +@property(nonatomic, strong) FGMPlatformMapConfiguration *mapConfiguration; +@property(nonatomic, copy) NSArray *initialCircles; +@property(nonatomic, copy) NSArray *initialMarkers; +@property(nonatomic, copy) NSArray *initialPolygons; +@property(nonatomic, copy) NSArray *initialPolylines; +@property(nonatomic, copy) NSArray *initialTileOverlays; +@end + /// Pigeon equivalent of MapConfiguration. @interface FGMPlatformMapConfiguration : NSObject + (instancetype)makeWithCompassEnabled:(nullable NSNumber *)compassEnabled @@ -402,6 +424,21 @@ extern void SetUpFGMMapsApiWithSuffix(id binaryMessenger FlutterError *_Nullable))completion; @end +/// Dummy interface to force generation of the platform view creation params, +/// which are not used in any Pigeon calls, only the platform view creation +/// call made internally by Flutter. +@protocol FGMMapsPlatformViewApi +- (void)createViewType:(nullable FGMPlatformMapViewCreationParams *)type + error:(FlutterError *_Nullable *_Nonnull)error; +@end + +extern void SetUpFGMMapsPlatformViewApi(id binaryMessenger, + NSObject *_Nullable api); + +extern void SetUpFGMMapsPlatformViewApiWithSuffix(id binaryMessenger, + NSObject *_Nullable api, + NSString *messageChannelSuffix); + /// Inspector API only intended for use in integration tests. @protocol FGMMapsInspectorApi /// @return `nil` only when `error != nil`. diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/messages.g.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/messages.g.m index f26d8f1bb85..db766a6f54a 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/messages.g.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/messages.g.m @@ -122,6 +122,12 @@ + (nullable FGMPlatformCameraTargetBounds *)nullableFromList:(NSArray *)list - (NSArray *)toList; @end +@interface FGMPlatformMapViewCreationParams () ++ (FGMPlatformMapViewCreationParams *)fromList:(NSArray *)list; ++ (nullable FGMPlatformMapViewCreationParams *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + @interface FGMPlatformMapConfiguration () + (FGMPlatformMapConfiguration *)fromList:(NSArray *)list; + (nullable FGMPlatformMapConfiguration *)nullableFromList:(NSArray *)list; @@ -437,6 +443,52 @@ + (nullable FGMPlatformCameraTargetBounds *)nullableFromList:(NSArray *)list } @end +@implementation FGMPlatformMapViewCreationParams ++ (instancetype)makeWithInitialCameraPosition:(FGMPlatformCameraPosition *)initialCameraPosition + mapConfiguration:(FGMPlatformMapConfiguration *)mapConfiguration + initialCircles:(NSArray *)initialCircles + initialMarkers:(NSArray *)initialMarkers + initialPolygons:(NSArray *)initialPolygons + initialPolylines:(NSArray *)initialPolylines + initialTileOverlays: + (NSArray *)initialTileOverlays { + FGMPlatformMapViewCreationParams *pigeonResult = [[FGMPlatformMapViewCreationParams alloc] init]; + pigeonResult.initialCameraPosition = initialCameraPosition; + pigeonResult.mapConfiguration = mapConfiguration; + pigeonResult.initialCircles = initialCircles; + pigeonResult.initialMarkers = initialMarkers; + pigeonResult.initialPolygons = initialPolygons; + pigeonResult.initialPolylines = initialPolylines; + pigeonResult.initialTileOverlays = initialTileOverlays; + return pigeonResult; +} ++ (FGMPlatformMapViewCreationParams *)fromList:(NSArray *)list { + FGMPlatformMapViewCreationParams *pigeonResult = [[FGMPlatformMapViewCreationParams alloc] init]; + pigeonResult.initialCameraPosition = GetNullableObjectAtIndex(list, 0); + pigeonResult.mapConfiguration = GetNullableObjectAtIndex(list, 1); + pigeonResult.initialCircles = GetNullableObjectAtIndex(list, 2); + pigeonResult.initialMarkers = GetNullableObjectAtIndex(list, 3); + pigeonResult.initialPolygons = GetNullableObjectAtIndex(list, 4); + pigeonResult.initialPolylines = GetNullableObjectAtIndex(list, 5); + pigeonResult.initialTileOverlays = GetNullableObjectAtIndex(list, 6); + return pigeonResult; +} ++ (nullable FGMPlatformMapViewCreationParams *)nullableFromList:(NSArray *)list { + return (list) ? [FGMPlatformMapViewCreationParams fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + self.initialCameraPosition ?: [NSNull null], + self.mapConfiguration ?: [NSNull null], + self.initialCircles ?: [NSNull null], + self.initialMarkers ?: [NSNull null], + self.initialPolygons ?: [NSNull null], + self.initialPolylines ?: [NSNull null], + self.initialTileOverlays ?: [NSNull null], + ]; +} +@end + @implementation FGMPlatformMapConfiguration + (instancetype)makeWithCompassEnabled:(nullable NSNumber *)compassEnabled cameraTargetBounds:(nullable FGMPlatformCameraTargetBounds *)cameraTargetBounds @@ -633,14 +685,16 @@ - (nullable id)readValueOfType:(UInt8)type { case 140: return [FGMPlatformCameraTargetBounds fromList:[self readValue]]; case 141: - return [FGMPlatformMapConfiguration fromList:[self readValue]]; + return [FGMPlatformMapViewCreationParams fromList:[self readValue]]; case 142: - return [FGMPlatformPoint fromList:[self readValue]]; + return [FGMPlatformMapConfiguration fromList:[self readValue]]; case 143: - return [FGMPlatformTileLayer fromList:[self readValue]]; + return [FGMPlatformPoint fromList:[self readValue]]; case 144: + return [FGMPlatformTileLayer fromList:[self readValue]]; + case 145: return [FGMPlatformZoomRange fromList:[self readValue]]; - case 145: { + case 146: { NSNumber *enumAsNumber = [self readValue]; return enumAsNumber == nil ? nil @@ -692,21 +746,24 @@ - (void)writeValue:(id)value { } else if ([value isKindOfClass:[FGMPlatformCameraTargetBounds class]]) { [self writeByte:140]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[FGMPlatformMapConfiguration class]]) { + } else if ([value isKindOfClass:[FGMPlatformMapViewCreationParams class]]) { [self writeByte:141]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[FGMPlatformPoint class]]) { + } else if ([value isKindOfClass:[FGMPlatformMapConfiguration class]]) { [self writeByte:142]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[FGMPlatformTileLayer class]]) { + } else if ([value isKindOfClass:[FGMPlatformPoint class]]) { [self writeByte:143]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[FGMPlatformZoomRange class]]) { + } else if ([value isKindOfClass:[FGMPlatformTileLayer class]]) { [self writeByte:144]; [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[FGMPlatformZoomRange class]]) { + [self writeByte:145]; + [self writeValue:[value toList]]; } else if ([value isKindOfClass:[FGMPlatformMapTypeBox class]]) { FGMPlatformMapTypeBox *box = (FGMPlatformMapTypeBox *)value; - [self writeByte:145]; + [self writeByte:146]; [self writeValue:(value == nil ? [NSNull null] : [NSNumber numberWithInteger:box.value])]; } else { [super writeValue:value]; @@ -1653,6 +1710,42 @@ - (void)tileWithOverlayIdentifier:(NSString *)arg_tileOverlayId } @end +void SetUpFGMMapsPlatformViewApi(id binaryMessenger, + NSObject *api) { + SetUpFGMMapsPlatformViewApiWithSuffix(binaryMessenger, api, @""); +} + +void SetUpFGMMapsPlatformViewApiWithSuffix(id binaryMessenger, + NSObject *api, + NSString *messageChannelSuffix) { + messageChannelSuffix = messageChannelSuffix.length > 0 + ? [NSString stringWithFormat:@".%@", messageChannelSuffix] + : @""; + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.google_maps_flutter_ios." + @"MapsPlatformViewApi.createView", + messageChannelSuffix] + binaryMessenger:binaryMessenger + codec:FGMGetMessagesCodec()]; + if (api) { + NSCAssert( + [api respondsToSelector:@selector(createViewType:error:)], + @"FGMMapsPlatformViewApi api (%@) doesn't respond to @selector(createViewType:error:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + FGMPlatformMapViewCreationParams *arg_type = GetNullableObjectAtIndex(args, 0); + FlutterError *error; + [api createViewType:arg_type error:&error]; + callback(wrapResult(nil, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } +} void SetUpFGMMapsInspectorApi(id binaryMessenger, NSObject *api) { SetUpFGMMapsInspectorApiWithSuffix(binaryMessenger, api, @""); diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/lib/src/google_maps_flutter_ios.dart b/packages/google_maps_flutter/google_maps_flutter_ios/lib/src/google_maps_flutter_ios.dart index 72ef27687c3..a371560d118 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/lib/src/google_maps_flutter_ios.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios/lib/src/google_maps_flutter_ios.dart @@ -409,27 +409,34 @@ class GoogleMapsFlutterIOS extends GoogleMapsFlutterPlatform { Widget _buildView( int creationId, PlatformViewCreatedCallback onPlatformViewCreated, { + required PlatformMapConfiguration mapConfiguration, required MapWidgetConfiguration widgetConfiguration, MapObjects mapObjects = const MapObjects(), - Map mapOptions = const {}, }) { - final Map creationParams = { - 'initialCameraPosition': - widgetConfiguration.initialCameraPosition.toMap(), - 'options': mapOptions, - 'markersToAdd': serializeMarkerSet(mapObjects.markers), - 'polygonsToAdd': serializePolygonSet(mapObjects.polygons), - 'polylinesToAdd': serializePolylineSet(mapObjects.polylines), - 'circlesToAdd': serializeCircleSet(mapObjects.circles), - 'tileOverlaysToAdd': serializeTileOverlaySet(mapObjects.tileOverlays), - }; + final PlatformMapViewCreationParams creationParams = + PlatformMapViewCreationParams( + initialCameraPosition: _platformCameraPositionFromCameraPosition( + widgetConfiguration.initialCameraPosition), + mapConfiguration: mapConfiguration, + initialMarkers: + mapObjects.markers.map(_platformMarkerFromMarker).toList(), + initialPolygons: + mapObjects.polygons.map(_platformPolygonFromPolygon).toList(), + initialPolylines: + mapObjects.polylines.map(_platformPolylineFromPolyline).toList(), + initialCircles: + mapObjects.circles.map(_platformCircleFromCircle).toList(), + initialTileOverlays: mapObjects.tileOverlays + .map(_platformTileOverlayFromTileOverlay) + .toList(), + ); return UiKitView( viewType: 'plugins.flutter.dev/google_maps_ios', onPlatformViewCreated: onPlatformViewCreated, gestureRecognizers: widgetConfiguration.gestureRecognizers, creationParams: creationParams, - creationParamsCodec: const StandardMessageCodec(), + creationParamsCodec: MapsApi.pigeonChannelCodec, ); } @@ -446,7 +453,8 @@ class GoogleMapsFlutterIOS extends GoogleMapsFlutterPlatform { onPlatformViewCreated, widgetConfiguration: widgetConfiguration, mapObjects: mapObjects, - mapOptions: _jsonForMapConfiguration(mapConfiguration), + mapConfiguration: + _platformMapConfigurationFromMapConfiguration(mapConfiguration), ); } @@ -476,7 +484,7 @@ class GoogleMapsFlutterIOS extends GoogleMapsFlutterPlatform { polylines: polylines, circles: circles, tileOverlays: tileOverlays), - mapOptions: mapOptions, + mapConfiguration: _platformMapConfigurationFromOptionsJson(mapOptions), ); } @@ -774,46 +782,6 @@ PlatformMapConfiguration _platformMapConfigurationFromMapConfiguration( ); } -Map _jsonForMapConfiguration(MapConfiguration config) { - final EdgeInsets? padding = config.padding; - return { - if (config.compassEnabled != null) 'compassEnabled': config.compassEnabled!, - if (config.cameraTargetBounds != null) - 'cameraTargetBounds': config.cameraTargetBounds!.toJson(), - if (config.mapType != null) 'mapType': config.mapType!.index, - if (config.minMaxZoomPreference != null) - 'minMaxZoomPreference': config.minMaxZoomPreference!.toJson(), - if (config.rotateGesturesEnabled != null) - 'rotateGesturesEnabled': config.rotateGesturesEnabled!, - if (config.scrollGesturesEnabled != null) - 'scrollGesturesEnabled': config.scrollGesturesEnabled!, - if (config.tiltGesturesEnabled != null) - 'tiltGesturesEnabled': config.tiltGesturesEnabled!, - if (config.zoomGesturesEnabled != null) - 'zoomGesturesEnabled': config.zoomGesturesEnabled!, - if (config.trackCameraPosition != null) - 'trackCameraPosition': config.trackCameraPosition!, - if (config.myLocationEnabled != null) - 'myLocationEnabled': config.myLocationEnabled!, - if (config.myLocationButtonEnabled != null) - 'myLocationButtonEnabled': config.myLocationButtonEnabled!, - if (padding != null) - 'padding': [ - padding.top, - padding.left, - padding.bottom, - padding.right, - ], - if (config.indoorViewEnabled != null) - 'indoorEnabled': config.indoorViewEnabled!, - if (config.trafficEnabled != null) 'trafficEnabled': config.trafficEnabled!, - if (config.buildingsEnabled != null) - 'buildingsEnabled': config.buildingsEnabled!, - if (config.cloudMapId != null) 'cloudMapId': config.cloudMapId!, - if (config.style != null) 'style': config.style!, - }; -} - // For supporting the deprecated updateMapOptions API. PlatformMapConfiguration _platformMapConfigurationFromOptionsJson( Map options) { @@ -852,6 +820,15 @@ PlatformMapConfiguration _platformMapConfigurationFromOptionsJson( ); } +PlatformCameraPosition _platformCameraPositionFromCameraPosition( + CameraPosition position) { + return PlatformCameraPosition( + bearing: position.bearing, + target: _platformLatLngFromLatLng(position.target), + tilt: position.tilt, + zoom: position.zoom); +} + PlatformMapType _platformMapTypeFromMapTypeIndex(int index) { // This is inherently fragile, but see comment in updateMapOptions. return switch (index) { diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/lib/src/messages.g.dart b/packages/google_maps_flutter/google_maps_flutter_ios/lib/src/messages.g.dart index 991b057f432..f4c5c81e7f4 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/lib/src/messages.g.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios/lib/src/messages.g.dart @@ -373,6 +373,60 @@ class PlatformCameraTargetBounds { } } +/// Information passed to the platform view creation. +class PlatformMapViewCreationParams { + PlatformMapViewCreationParams({ + required this.initialCameraPosition, + required this.mapConfiguration, + required this.initialCircles, + required this.initialMarkers, + required this.initialPolygons, + required this.initialPolylines, + required this.initialTileOverlays, + }); + + PlatformCameraPosition initialCameraPosition; + + PlatformMapConfiguration mapConfiguration; + + List initialCircles; + + List initialMarkers; + + List initialPolygons; + + List initialPolylines; + + List initialTileOverlays; + + Object encode() { + return [ + initialCameraPosition, + mapConfiguration, + initialCircles, + initialMarkers, + initialPolygons, + initialPolylines, + initialTileOverlays, + ]; + } + + static PlatformMapViewCreationParams decode(Object result) { + result as List; + return PlatformMapViewCreationParams( + initialCameraPosition: result[0]! as PlatformCameraPosition, + mapConfiguration: result[1]! as PlatformMapConfiguration, + initialCircles: (result[2] as List?)!.cast(), + initialMarkers: (result[3] as List?)!.cast(), + initialPolygons: (result[4] as List?)!.cast(), + initialPolylines: + (result[5] as List?)!.cast(), + initialTileOverlays: + (result[6] as List?)!.cast(), + ); + } +} + /// Pigeon equivalent of MapConfiguration. class PlatformMapConfiguration { PlatformMapConfiguration({ @@ -606,20 +660,23 @@ class _PigeonCodec extends StandardMessageCodec { } else if (value is PlatformCameraTargetBounds) { buffer.putUint8(140); writeValue(buffer, value.encode()); - } else if (value is PlatformMapConfiguration) { + } else if (value is PlatformMapViewCreationParams) { buffer.putUint8(141); writeValue(buffer, value.encode()); - } else if (value is PlatformPoint) { + } else if (value is PlatformMapConfiguration) { buffer.putUint8(142); writeValue(buffer, value.encode()); - } else if (value is PlatformTileLayer) { + } else if (value is PlatformPoint) { buffer.putUint8(143); writeValue(buffer, value.encode()); - } else if (value is PlatformZoomRange) { + } else if (value is PlatformTileLayer) { buffer.putUint8(144); writeValue(buffer, value.encode()); - } else if (value is PlatformMapType) { + } else if (value is PlatformZoomRange) { buffer.putUint8(145); + writeValue(buffer, value.encode()); + } else if (value is PlatformMapType) { + buffer.putUint8(146); writeValue(buffer, value.index); } else { super.writeValue(buffer, value); @@ -654,14 +711,16 @@ class _PigeonCodec extends StandardMessageCodec { case 140: return PlatformCameraTargetBounds.decode(readValue(buffer)!); case 141: - return PlatformMapConfiguration.decode(readValue(buffer)!); + return PlatformMapViewCreationParams.decode(readValue(buffer)!); case 142: - return PlatformPoint.decode(readValue(buffer)!); + return PlatformMapConfiguration.decode(readValue(buffer)!); case 143: - return PlatformTileLayer.decode(readValue(buffer)!); + return PlatformPoint.decode(readValue(buffer)!); case 144: - return PlatformZoomRange.decode(readValue(buffer)!); + return PlatformTileLayer.decode(readValue(buffer)!); case 145: + return PlatformZoomRange.decode(readValue(buffer)!); + case 146: final int? value = readValue(buffer) as int?; return value == null ? null : PlatformMapType.values[value]; default: @@ -1686,6 +1745,49 @@ abstract class MapsCallbackApi { } } +/// Dummy interface to force generation of the platform view creation params, +/// which are not used in any Pigeon calls, only the platform view creation +/// call made internally by Flutter. +class MapsPlatformViewApi { + /// Constructor for [MapsPlatformViewApi]. 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. + MapsPlatformViewApi( + {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 createView(PlatformMapViewCreationParams? type) async { + final String __pigeon_channelName = + 'dev.flutter.pigeon.google_maps_flutter_ios.MapsPlatformViewApi.createView$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([type]) 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; + } + } +} + /// Inspector API only intended for use in integration tests. class MapsInspectorApi { /// Constructor for [MapsInspectorApi]. The [binaryMessenger] named argument is diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/pigeons/messages.dart b/packages/google_maps_flutter/google_maps_flutter_ios/pigeons/messages.dart index 9b34082a7a2..fc343356030 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/pigeons/messages.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios/pigeons/messages.dart @@ -161,6 +161,30 @@ class PlatformCameraTargetBounds { final PlatformLatLngBounds? bounds; } +/// Information passed to the platform view creation. +class PlatformMapViewCreationParams { + PlatformMapViewCreationParams({ + required this.initialCameraPosition, + required this.mapConfiguration, + required this.initialCircles, + required this.initialMarkers, + required this.initialPolygons, + required this.initialPolylines, + required this.initialTileOverlays, + }); + + final PlatformCameraPosition initialCameraPosition; + final PlatformMapConfiguration mapConfiguration; + // TODO(stuartmorgan): Make the generic types non-nullable once supported. + // https://github.com/flutter/flutter/issues/97848 + // The consuming code treats the entries as non-nullable. + final List initialCircles; + final List initialMarkers; + final List initialPolygons; + final List initialPolylines; + final List initialTileOverlays; +} + /// Pigeon equivalent of MapConfiguration. class PlatformMapConfiguration { PlatformMapConfiguration({ @@ -412,6 +436,15 @@ abstract class MapsCallbackApi { String tileOverlayId, PlatformPoint location, int zoom); } +/// Dummy interface to force generation of the platform view creation params, +/// which are not used in any Pigeon calls, only the platform view creation +/// call made internally by Flutter. +@HostApi() +abstract class MapsPlatformViewApi { + // This is never actually called. + void createView(PlatformMapViewCreationParams? type); +} + /// Inspector API only intended for use in integration tests. @HostApi() abstract class MapsInspectorApi { From bb40332a692e93731ce578b555e83225f65b364b Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 24 Jul 2024 12:43:58 -0400 Subject: [PATCH 06/14] Version bumps --- .../google_maps_flutter_android/CHANGELOG.md | 4 ++++ .../google_maps_flutter_android/pubspec.yaml | 2 +- .../google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md | 4 ++++ .../google_maps_flutter/google_maps_flutter_ios/pubspec.yaml | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) 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 5e2d26e13a8..0e3abcaa8c2 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.13.0 + +* Updates platform view creation parameters to use Pigeon. + ## 2.12.0 * Converts Java->Dart calls to Pigeon. 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 c02a159c839..a61aed1b7b0 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.12.0 +version: 2.13.0 environment: sdk: ^3.4.0 diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md index 9ee2a86e4f1..44af985ffe3 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.11.0 + +* Updates platform view creation parameters to use Pigeon. + ## 2.10.0 * Converts Obj-C->Dart calls to Pigeon. diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_ios/pubspec.yaml index d73df0ee638..3bde8108803 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_ios/pubspec.yaml @@ -2,7 +2,7 @@ name: google_maps_flutter_ios description: iOS implementation of the google_maps_flutter plugin. repository: https://github.com/flutter/packages/tree/main/packages/google_maps_flutter/google_maps_flutter_ios issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22 -version: 2.10.0 +version: 2.11.0 environment: sdk: ^3.2.3 From 085864be276ab4392a2928afdfccc72c5baa1eea Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 24 Jul 2024 14:14:41 -0400 Subject: [PATCH 07/14] Fix Dart unit tests --- .../google_maps_flutter_android/CHANGELOG.md | 2 +- .../lib/src/google_maps_flutter_android.dart | 2 +- .../test/google_maps_flutter_android_test.dart | 18 ++++++++---------- .../google_maps_flutter_ios/CHANGELOG.md | 2 +- .../test/google_maps_flutter_ios_test.dart | 18 ++++++++---------- 5 files changed, 19 insertions(+), 23 deletions(-) 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 0e3abcaa8c2..9c76252dc79 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter_android/CHANGELOG.md @@ -1,6 +1,6 @@ ## 2.13.0 -* Updates platform view creation parameters to use Pigeon. +* Updates map configuration and platform view creation parameters to use Pigeon. ## 2.12.0 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 5e8f24729a0..69cc7d214c4 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 @@ -554,7 +554,7 @@ class GoogleMapsFlutterAndroid extends GoogleMapsFlutterPlatform { gestureRecognizers: widgetConfiguration.gestureRecognizers, layoutDirection: widgetConfiguration.textDirection, creationParams: creationParams, - creationParamsCodec: const StandardMessageCodec(), + creationParamsCodec: MapsApi.pigeonChannelCodec, ); } } diff --git a/packages/google_maps_flutter/google_maps_flutter_android/test/google_maps_flutter_android_test.dart b/packages/google_maps_flutter/google_maps_flutter_android/test/google_maps_flutter_android_test.dart index 32f3d10cc5e..b6808bc61ee 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/test/google_maps_flutter_android_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter_android/test/google_maps_flutter_android_test.dart @@ -659,17 +659,15 @@ void main() { methodCall.arguments as Map); if (args.containsKey('params')) { final Uint8List paramsUint8List = args['params'] as Uint8List; - const StandardMessageCodec codec = StandardMessageCodec(); final ByteData byteData = ByteData.sublistView(paramsUint8List); - final Map creationParams = - Map.from( - codec.decodeMessage(byteData) as Map); - if (creationParams.containsKey('options')) { - final Map options = Map.from( - creationParams['options'] as Map); - if (options.containsKey('cloudMapId')) { - passedCloudMapIdCompleter - .complete(options['cloudMapId'] as String); + final PlatformMapViewCreationParams? creationParams = + MapsApi.pigeonChannelCodec.decodeMessage(byteData) + as PlatformMapViewCreationParams?; + if (creationParams != null) { + final String? passedMapId = + creationParams.mapConfiguration.cloudMapId; + if (passedMapId != null) { + passedCloudMapIdCompleter.complete(passedMapId); } } } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md index 44af985ffe3..35078d19687 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md @@ -1,6 +1,6 @@ ## 2.11.0 -* Updates platform view creation parameters to use Pigeon. +* Updates map configuration and platform view creation parameters to use Pigeon. ## 2.10.0 diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/test/google_maps_flutter_ios_test.dart b/packages/google_maps_flutter/google_maps_flutter_ios/test/google_maps_flutter_ios_test.dart index e13f11e4944..7a2f26809dd 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/test/google_maps_flutter_ios_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios/test/google_maps_flutter_ios_test.dart @@ -550,17 +550,15 @@ void main() { methodCall.arguments as Map); if (args.containsKey('params')) { final Uint8List paramsUint8List = args['params'] as Uint8List; - const StandardMessageCodec codec = StandardMessageCodec(); final ByteData byteData = ByteData.sublistView(paramsUint8List); - final Map creationParams = - Map.from( - codec.decodeMessage(byteData) as Map); - if (creationParams.containsKey('options')) { - final Map options = Map.from( - creationParams['options'] as Map); - if (options.containsKey('cloudMapId')) { - passedCloudMapIdCompleter - .complete(options['cloudMapId'] as String); + final PlatformMapViewCreationParams? creationParams = + MapsApi.pigeonChannelCodec.decodeMessage(byteData) + as PlatformMapViewCreationParams?; + if (creationParams != null) { + final String? passedMapId = + creationParams.mapConfiguration.cloudMapId; + if (passedMapId != null) { + passedCloudMapIdCompleter.complete(passedMapId); } } } From 6c032cc1f8f985e35460141470a2d033b7804145 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 24 Jul 2024 14:35:48 -0400 Subject: [PATCH 08/14] Fix doc comment --- .../ios/Classes/GoogleMapController_Test.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController_Test.h index a9d7ecd2b67..da4da303ff7 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController_Test.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapController_Test.h @@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN /// /// @param mapView A map view that will be displayed by the controller /// @param viewId A unique identifier for the controller. -/// @param args Parameters for initialising the map view. +/// @param creationParameters Parameters for initialising the map view. /// @param registrar The plugin registrar passed from Flutter. - (instancetype)initWithMapView:(GMSMapView *)mapView viewIdentifier:(int64_t)viewId From df2b709693c456d2f52aa9b113235996e09447bd Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 24 Jul 2024 14:38:53 -0400 Subject: [PATCH 09/14] Update iOS 15 tests too --- .../ios15/ios/RunnerTests/GoogleMapsTests.m | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios15/ios/RunnerTests/GoogleMapsTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios15/ios/RunnerTests/GoogleMapsTests.m index b3ac89e2441..07dac2dcf96 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios15/ios/RunnerTests/GoogleMapsTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios15/ios/RunnerTests/GoogleMapsTests.m @@ -40,10 +40,11 @@ - (void)testFrameObserver { initWithFrame:frame camera:[[GMSCameraPosition alloc] initWithLatitude:0 longitude:0 zoom:0]]; #pragma clang diagnostic pop - FLTGoogleMapController *controller = [[FLTGoogleMapController alloc] initWithMapView:mapView - viewIdentifier:0 - arguments:nil - registrar:registrar]; + FLTGoogleMapController *controller = + [[FLTGoogleMapController alloc] initWithMapView:mapView + viewIdentifier:0 + creationParameters:[self emptyCreationParameters] + registrar:registrar]; for (NSInteger i = 0; i < 10; ++i) { [controller view]; @@ -85,4 +86,22 @@ - (void)testHandleResultTileDownsamplesWideGamutImages { XCTAssert(bitsPerComponent == 8); } +/// Creates an empty creation paramaters object for tests where the values don't matter, just that +/// there's a valid object to pass in. +- (FGMPlatformMapViewCreationParams *)emptyCreationParameters { + return [FGMPlatformMapViewCreationParams + makeWithInitialCameraPosition:[FGMPlatformCameraPosition + makeWithBearing:0.0 + target:[FGMPlatformLatLng makeWithLatitude:0.0 + longitude:0.0] + tilt:0.0 + zoom:0.0] + mapConfiguration:[[FGMPlatformMapConfiguration alloc] init] + initialCircles:@[] + initialMarkers:@[] + initialPolygons:@[] + initialPolylines:@[] + initialTileOverlays:@[]]; +} + @end From 6954c4a794b280db6b3d1c3c1c5b7af7c5708a9d Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 30 Jul 2024 13:58:26 -0400 Subject: [PATCH 10/14] New unit test, minor test file cleanup --- .../plugins/googlemaps/ConvertTest.java | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) 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 c3b203888a9..de41c990e15 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 @@ -59,7 +59,7 @@ public class ConvertTest { AutoCloseable mockCloseable; // A 1x1 pixel (#8080ff) PNG image encoded in base64 - private String base64Image = generateBase64Image(); + private final String base64Image = generateBase64Image(); @Before public void before() { @@ -75,7 +75,7 @@ public void tearDown() throws Exception { public void ConvertToPointsConvertsThePointsWithFullPrecision() { double latitude = 43.03725568057; double longitude = -87.90466904649; - ArrayList point = new ArrayList(); + ArrayList point = new ArrayList<>(); point.add(latitude); point.add(longitude); ArrayList> pointsList = new ArrayList<>(); @@ -239,7 +239,7 @@ public void GetBitmapFromAssetNoScaling() throws Exception { } @Test - public void GetBitmapFromBytesAuto() throws Exception { + public void GetBitmapFromBytesAuto() { byte[] bmpData = Base64.decode(base64Image, Base64.DEFAULT); Map assetDetails = new HashMap<>(); @@ -256,7 +256,7 @@ public void GetBitmapFromBytesAuto() throws Exception { } @Test - public void GetBitmapFromBytesAutoAndWidth() throws Exception { + public void GetBitmapFromBytesAutoAndWidth() { byte[] bmpData = Base64.decode(base64Image, Base64.DEFAULT); Map assetDetails = new HashMap<>(); @@ -274,7 +274,7 @@ public void GetBitmapFromBytesAutoAndWidth() throws Exception { } @Test - public void GetBitmapFromBytesAutoAndHeight() throws Exception { + public void GetBitmapFromBytesAutoAndHeight() { byte[] bmpData = Base64.decode(base64Image, Base64.DEFAULT); Map assetDetails = new HashMap<>(); @@ -292,7 +292,7 @@ public void GetBitmapFromBytesAutoAndHeight() throws Exception { } @Test - public void GetBitmapFromBytesNoScaling() throws Exception { + public void GetBitmapFromBytesNoScaling() { byte[] bmpData = Base64.decode(base64Image, Base64.DEFAULT); Map assetDetails = new HashMap<>(); @@ -309,7 +309,7 @@ public void GetBitmapFromBytesNoScaling() throws Exception { } @Test(expected = IllegalArgumentException.class) // Expecting an IllegalArgumentException - public void GetBitmapFromBytesThrowsErrorIfInvalidImageData() throws Exception { + public void GetBitmapFromBytesThrowsErrorIfInvalidImageData() { String invalidBase64Image = "not valid image data"; byte[] bmpData = Base64.decode(invalidBase64Image, Base64.DEFAULT); @@ -525,13 +525,25 @@ public void interpretMapConfiguration_handlesPadding() { .setPadding((float) top, (float) left, (float) bottom, (float) right); } + @Test + public void interpretMapConfiguration_handlesMinMaxZoomPreference() { + final double min = 1.0; + final double max = 2.0; + final Messages.PlatformMapConfiguration config = + new Messages.PlatformMapConfiguration.Builder() + .setMinMaxZoomPreference( + new Messages.PlatformZoomRange.Builder().setMin(min).setMax(max).build()) + .build(); + Convert.interpretMapConfiguration(config, optionsSink); + verify(optionsSink, times(1)).setMinMaxZoomPreference((float) min, (float) max); + } + private InputStream buildImageInputStream() { Bitmap fakeBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); fakeBitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream); byte[] byteArray = byteArrayOutputStream.toByteArray(); - InputStream fakeStream = new ByteArrayInputStream(byteArray); - return fakeStream; + return new ByteArrayInputStream(byteArray); } // Helper method to generate 1x1 pixel base64 encoded png test image @@ -552,8 +564,6 @@ private String generateBase64Image() { byte[] pngBytes = outputStream.toByteArray(); // Encode the PNG bytes as a base64 string - String base64Image = Base64.encodeToString(pngBytes, Base64.DEFAULT); - - return base64Image; + return Base64.encodeToString(pngBytes, Base64.DEFAULT); } } From d5cde49684ca2bb0760120b616338ecbf6336718 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 30 Jul 2024 14:09:36 -0400 Subject: [PATCH 11/14] Fix bug --- .../java/io/flutter/plugins/googlemaps/Convert.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) 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 caa4f0b02a9..38a81bda5c7 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 @@ -367,8 +367,8 @@ private static float toFloat(Object o) { return ((Number) o).floatValue(); } - private static Float toFloatWrapper(Object o) { - return (o == null) ? null : toFloat(o); + private static @Nullable Float nullableDoubleToFloat(@Nullable Double d) { + return (d == null) ? null : d.floatValue(); } private static int toInt(Object o) { @@ -568,10 +568,9 @@ static void interpretMapConfiguration( } final Messages.PlatformZoomRange minMaxZoomPreference = config.getMinMaxZoomPreference(); if (minMaxZoomPreference != null) { - final List zoomPreferenceData = toList(minMaxZoomPreference); - sink.setMinMaxZoomPreference( // - toFloatWrapper(zoomPreferenceData.get(0)), // - toFloatWrapper(zoomPreferenceData.get(1))); + sink.setMinMaxZoomPreference( + nullableDoubleToFloat(minMaxZoomPreference.getMin()), + nullableDoubleToFloat(minMaxZoomPreference.getMax())); } final Messages.PlatformEdgeInsets padding = config.getPadding(); if (padding != null) { From fd0f0f47c7b5efbda94b20dfe716c08454fee016 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 8 Aug 2024 11:40:13 -0400 Subject: [PATCH 12/14] Remove obsolete test file --- .../test/cluster_manager_utils_test.dart | 44 ------------------- 1 file changed, 44 deletions(-) delete mode 100644 packages/google_maps_flutter/google_maps_flutter_ios/test/cluster_manager_utils_test.dart diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/test/cluster_manager_utils_test.dart b/packages/google_maps_flutter/google_maps_flutter_ios/test/cluster_manager_utils_test.dart deleted file mode 100644 index d7ea7c0379f..00000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios/test/cluster_manager_utils_test.dart +++ /dev/null @@ -1,44 +0,0 @@ -// 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:flutter_test/flutter_test.dart'; -import 'package:google_maps_flutter_ios/src/utils/cluster_manager.dart'; -import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - test('serializeClusterManager', () async { - const ClusterManager manager = - ClusterManager(clusterManagerId: ClusterManagerId('1234')); - final Object json = serializeClusterManager(manager); - - expect(json, { - 'clusterManagerId': '1234', - }); - }); - - test('serializeClusterManagerSet', () async { - const ClusterManager manager = - ClusterManager(clusterManagerId: ClusterManagerId('1234')); - const ClusterManager manager2 = - ClusterManager(clusterManagerId: ClusterManagerId('5678')); - const ClusterManager manager3 = - ClusterManager(clusterManagerId: ClusterManagerId('9012')); - final Object json = serializeClusterManagerSet( - {manager, manager2, manager3}); - - expect(json, [ - { - 'clusterManagerId': '1234', - }, - { - 'clusterManagerId': '5678', - }, - { - 'clusterManagerId': '9012', - } - ]); - }); -} From db7fbcfcda5a8952aacf0195b7075198c63ef3d9 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 8 Aug 2024 11:54:18 -0400 Subject: [PATCH 13/14] iOS 15 native tests --- .../example/ios15/ios/RunnerTests/GoogleMapsTests.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios15/ios/RunnerTests/GoogleMapsTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios15/ios/RunnerTests/GoogleMapsTests.m index 07dac2dcf96..d922838b44c 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios15/ios/RunnerTests/GoogleMapsTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios15/ios/RunnerTests/GoogleMapsTests.m @@ -101,7 +101,9 @@ - (FGMPlatformMapViewCreationParams *)emptyCreationParameters { initialMarkers:@[] initialPolygons:@[] initialPolylines:@[] - initialTileOverlays:@[]]; + initialHeatmap:@[] + initialTileOverlays:@[] + initialClusterManagers:@[]]; } @end From 11f4ecf36893c02d3ad3bbbb676b40a91f4ea22c Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Thu, 8 Aug 2024 12:26:41 -0400 Subject: [PATCH 14/14] Typo --- .../example/ios15/ios/RunnerTests/GoogleMapsTests.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios15/ios/RunnerTests/GoogleMapsTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios15/ios/RunnerTests/GoogleMapsTests.m index d922838b44c..c175550dd2c 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios15/ios/RunnerTests/GoogleMapsTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios15/ios/RunnerTests/GoogleMapsTests.m @@ -101,7 +101,7 @@ - (FGMPlatformMapViewCreationParams *)emptyCreationParameters { initialMarkers:@[] initialPolygons:@[] initialPolylines:@[] - initialHeatmap:@[] + initialHeatmaps:@[] initialTileOverlays:@[] initialClusterManagers:@[]]; }