-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[google_maps_flutter] Ground overlay support - platform impls #8563
base: main
Are you sure you want to change the base?
[google_maps_flutter] Ground overlay support - platform impls #8563
Conversation
a859a4d
to
43522ae
Compare
Looking at web stuff! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Android and iOS LGTM; I did a full review of both. Please wait for @ditman's review covering web before landing though.
* @return the identifier of the ground overlay. | ||
* @throws IllegalArgumentException if required fields are missing or invalid. | ||
*/ | ||
static String interpretGroundOverlayOptions( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return and the parameters should get nullability annotations.
*/ | ||
@VisibleForTesting | ||
public static @NonNull Messages.PlatformDoublePair buildGroundOverlayAnchorForPigeon( | ||
GroundOverlay groundOverlay) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@NonNull
} | ||
|
||
// Helper method to generate 1x1 pixel base64 encoded png test image | ||
private String generateBase64Image() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be pulled out of the other file into a test helper file, rather than duplicating the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to TestImageUtils.java
@property(nonatomic, strong, nullable) NSNumber *zoomLevel; | ||
|
||
/// Initializes an instance of this class with a GMSGroundOverlay, a map view, and identifier. | ||
- (instancetype _Nullable)initWithGroundOverlay:(GMSGroundOverlay *)groundOverlay |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does nullable instancetype
not work? (I can never remember the exact set of cases where nullable
doesn't work).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the nullable annotation from these instance initialisations as they do not explicitly return nil.
There isn't any handling for null instances on code either.
I would assume that self = [super init];
returns instance, and if not, something is really broken.
bitmapScaling: MapBitmapScaling.none, | ||
); | ||
|
||
if (groundOverlayInfo.position != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: If you make locals for groundOverlay.position
and groundOverlay.bounds
just before the if block, and use the locals everywhere after that (including the conditions), you won't need most of the force-unwraps below.
(@ash-google Feel free to review as well, I just had already looked over the mobile platforms in the main PR so I went ahead and did a review here to cover those.) |
sink.setClickable(groundOverlay.getClickable()); | ||
sink.setImage(toBitmapDescriptor(groundOverlay.getImage(), assetManager, density, wrapper)); | ||
if (groundOverlay.getPosition() != null) { | ||
assert groundOverlay.getWidth() != null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should have an assertion message indicating why it is required or at least log an error saying that width is required.
// adjust the width accordingly. | ||
double west = bounds.southwest.longitude; | ||
double east = bounds.northeast.longitude; | ||
double width = (west <= east) ? (east - west) : (360.0 - (west - east)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we extract these constants into local constants with good naming so it's easier to understand why we need these magic numbers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ash-google is this what you were looking for? cdf4d25
Did a second look over Android and LGTM. Let's wait for @ditman for web. |
There is some crash issues on Android integration tests: Linux_android android_device_tests_shard_1 master |
It's flutter/flutter#159731. We're seeing flare-ups of this on other PRs that touch maps, so I don't think it's related. We've seen spikes in this crash in our CI before, potentially due to server-side changes in Google Maps. |
I tested this implementation a bit on Android. Unfortunately, I ran into an issue which occurs when ground overlay images change quickly (<250ms interval). This results in a quick but noticeable black flicker. The images are stored in-memory as The I am not sure what causes this, maybe the thread that updates the ground overlays doesn't manage to decode bitmaps from raw data quickly enough? I attached a video demonstrating this on Xiaomi 12T. Maybe I could try creating minimal reproducible example if needed. out.mp4 |
sink.setClickable(groundOverlay.getClickable()); | ||
sink.setImage(toBitmapDescriptor(groundOverlay.getImage(), assetManager, density, wrapper)); | ||
if (groundOverlay.getPosition() != null) { | ||
assert groundOverlay.getWidth() != null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By default asserts are stripped in java. If you want to check this value then you will need to throw an exception or log or do some other form of error handling.
boolean isCreatedWithBounds) { | ||
|
||
// Dummy image is used as image is required field of PlatformGroundOverlay and converting image | ||
// back to image descriptor is not currently supported. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a link to what layer of the stack does not support this functionality? Also why is it safe to use a dummy image?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is used only by inpector api, for testing purposes. App facing widget stores groundoverlays on dart implementation, and there is no real reason to fetch the data back, other than testing.
Image is mandatory field on PlatformGroundOverlay (and it should be kept non-nullable), therefore image must be set for the object.
The image is description either contains set of bytes, or path to asset. This info is converted to format google maps uses (BitmapDescription), and the original data is not stored on native code.
So converting read and possibly rescaled asset bitmap back orginal instruction with asset url is not currently possible without storing the original PlatformImageDescriptor to memory; which is not optimal.
Therefore using dummy image here should be fine?
Messages.PlatformGroundOverlay result = | ||
Convert.groundOverlayToPigeon(mockGroundOverlay, "overlay_1", false); | ||
|
||
Assert.assertEquals("overlay_1", result.getGroundOverlayId()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider extracting a helper method that takes a actual ground overlay object and expected values and handles the assertions for equals. It would make new tests easier to write/review.
@@ -21,6 +20,7 @@ const double _kInitialZoomLevel = 5; | |||
const CameraPosition _kInitialCameraPosition = | |||
CameraPosition(target: _kInitialMapCenter, zoom: _kInitialZoomLevel); | |||
const String _kCloudMapId = '000000000000000'; // Dummy map ID. | |||
const double _floatTolerance = 1e-8; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a comment for why this value was chosen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -995,7 +995,7 @@ void googleMapsTests() { | |||
}, | |||
// TODO(cyanglaz): un-skip the test when we can test this on CI with API key enabled. | |||
// https://github.com/flutter/flutter/issues/57057 | |||
skip: Platform.isAndroid); | |||
skip: true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean to skip this for all platforms? if so should it be deleted instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this was committed by accident. Not related to this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a legacy of this file starting its life as a copy of the integration tests in google_maps_flutter
. In the context of google_maps_flutter_android
, Platform.isAndroid
is just a confusing way of writing true
, so this change was good.
if so should it be deleted instead?
I would prefer we keep it, because of the TODO above. We are starting to see features that do not work without an API key, so we will need to fix the CI limitation at some point. (I was working on it with infra folks a while ago, but that got derailed.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is true; but already reverted this change before I saw @stuartmorgan:n comment about this, as this was chore change, not related to ground overlay at all. I can commit this back, if it is ok to have unrelated changes in the PR as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's fine either way; if you've already reverted it don't worry about adding it back unless you feel like it.
assert(_groundOverlay != null); | ||
setState(() { | ||
_groundOverlay = _groundOverlay!.copyWith( | ||
bearingParam: _groundOverlay!.bearing >= 350 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a comment explaining where these magic numbers come from?
I believe this is just bumping the bearing 10 degrees and making sure we dont go over 360 but that is after reading the whole pr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this ok?
This PR contains platform implementations for the ground overlays support (#8432).
Linked issue: flutter/flutter#26479
Pre-launch Checklist
dart format
.)[shared_preferences]
pubspec.yaml
with an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.CHANGELOG.md
to add a description of the change, following repository CHANGELOG style, or this PR is exempt from CHANGELOG changes.///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.