Skip to content

[google_maps_flutter] Add onPointOfInterestTap callback#11860

Closed
tenninebt wants to merge 2 commits into
flutter:mainfrom
tenninebt:google-maps-on-poi-tap
Closed

[google_maps_flutter] Add onPointOfInterestTap callback#11860
tenninebt wants to merge 2 commits into
flutter:mainfrom
tenninebt:google-maps-on-poi-tap

Conversation

@tenninebt
Copy link
Copy Markdown

@tenninebt tenninebt commented Jun 8, 2026

Summary

Adds onPointOfInterestTap to the google_maps_flutter federated plugin, forwarding place ID only via a new PointOfInterestId type (per maintainer feedback on #4052 / #10963).

  • platform_interface: PointOfInterestId, PointOfInterestTapEvent, onPointOfInterestTap({required int mapId}) stream, method-channel wiring
  • android: OnPoiClickListener → Pigeon → Dart
  • ios (+ sdk9 / sdk10 / shared_code): didTapPOIWithPlaceID delegate → Pigeon → Dart
  • web: emits POI tap when map click IconMouseEvent has placeId; skips plain map tap
  • app-facing: GoogleMap.onPointOfInterestTap callback + controller subscription
  • tests: Dart unit tests on all packages; Android Robolectric OnPoiClickCallsFlutterApi; iOS testDidTapPOIForwardsPlaceId; web integration tests in example/latest
  • example: POI tap logging added to map_click.dart

This is a combination PR for federated-plugin review. Path-based dependency_overrides are included for CI/local testing per changing federated plugins and should be split/removed before landing individual package PRs.

Fixes flutter/flutter#60695

Test plan

  • flutter_plugin_tools.dart analyze (7 packages)
  • flutter_plugin_tools.dart dart-test (11 packages)
  • flutter_plugin_tools.dart validate
  • flutter_plugin_tools.dart license-check
  • Android native unit tests (OnPoiClickCallsFlutterApi, JDK 21)
  • iOS native unit test (testDidTapPOIForwardsPlaceId, after pod install)
  • google_maps_flutter_ios run_tests.dart sync validation
  • LUCI presubmit (dart shards, web integration, Android platform tests, publish-check expected override warning)

Made with Cursor

@google-cla
Copy link
Copy Markdown

google-cla Bot commented Jun 8, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@tenninebt
Copy link
Copy Markdown
Author

@googlebot rescan

@tenninebt tenninebt force-pushed the google-maps-on-poi-tap branch 3 times, most recently from ee382ab to d3ae779 Compare June 8, 2026 01:53
@tenninebt tenninebt marked this pull request as ready for review June 8, 2026 01:54
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for tapping points of interest (POI) on the map across the federated Google Maps packages, introducing PointOfInterestId and PointOfInterestTapEvent along with platform-specific implementations and tests. The code review feedback highlights several critical improvements: adding missing dart:js_interop imports in the web controller to prevent compilation errors, subscribing to the POI tap stream unconditionally in the main controller to support dynamic callback updates, and adding defensive null/nil checks in both the Android and iOS platform implementations to prevent potential crashes.

Comment on lines +292 to +300
if (event.hasProperty('placeId'.toJS).toDart) {
final String? placeId = (event as gmaps.IconMouseEvent).placeId;
if (placeId != null) {
_streamController.add(
PointOfInterestTapEvent(_mapId, PointOfInterestId(placeId)),
);
return;
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The use of hasProperty and toJS requires importing dart:js_interop and dart:js_interop_unsafe in this file. Please ensure these imports are added at the top of google_maps_controller.dart to prevent compilation errors on the web platform:

import 'dart:js_interop';
import 'dart:js_interop_unsafe';

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

google_maps_controller.dart is a part of google_maps_flutter_web.dart, which already imports dart:js_interop and dart:js_interop_unsafe (lines 9–10). Part files inherit library imports. hasProperty / toJS compile fine; web tests passed.

Comment on lines +62 to +70
if (_googleMapState.widget.onPointOfInterestTap != null) {
_streamSubscriptions.add(
GoogleMapsFlutterPlatform.instance
.onPointOfInterestTap(mapId: mapId)
.listen(
(PointOfInterestTapEvent e) => _googleMapState.onPointOfInterestTap(e.value),
),
);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Unlike high-frequency camera events, tap events (such as onTap, onLongPress, onMarkerTap, etc.) are subscribed to unconditionally in GoogleMapController. Subscribing to onPointOfInterestTap conditionally introduces a bug where dynamically setting or updating the callback after the map is created will not work, as the subscription is only set up during initialization.

Please subscribe to onPointOfInterestTap unconditionally, matching the pattern of other tap events.

    _streamSubscriptions.add(
      GoogleMapsFlutterPlatform.instance
          .onPointOfInterestTap(mapId: mapId)
          .listen(
            (PointOfInterestTapEvent e) => _googleMapState.onPointOfInterestTap(e.value),
          ),
    );

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 71ea56b

Comment on lines +389 to +393
@Override
public void onPoiClick(PointOfInterest pointOfInterest) {
flutterApi.onPointOfInterestTap(
pointOfInterest.placeId, (Result<Unit> result) -> Unit.INSTANCE);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To prevent potential NullPointerException crashes, defensively check if pointOfInterest and pointOfInterest.placeId are non-null before invoking the Flutter API.

Suggested change
@Override
public void onPoiClick(PointOfInterest pointOfInterest) {
flutterApi.onPointOfInterestTap(
pointOfInterest.placeId, (Result<Unit> result) -> Unit.INSTANCE);
}
@Override
public void onPoiClick(PointOfInterest pointOfInterest) {
if (pointOfInterest != null && pointOfInterest.placeId != null) {
flutterApi.onPointOfInterestTap(
pointOfInterest.placeId, (Result<Unit> result) -> Unit.INSTANCE);
}
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 71ea56b

Comment on lines +567 to +572
- (void)mapView:(GMSMapView *)mapView
didTapPOIWithPlaceID:(NSString *)placeID
name:(NSString *)name
location:(CLLocationCoordinate2D)location {
[self.mapEventHandler didTapPointOfInterestWithPlaceId:placeID];
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If placeID is ever nil, sending it directly to the Pigeon channel will pass [NSNull null], which causes a crash or assertion failure on the Dart side because the Pigeon parameter is non-nullable.

Please defensively check that placeID is not nil before forwarding the event. Please apply this check across all iOS implementation packages (google_maps_flutter_ios, google_maps_flutter_ios_sdk9, google_maps_flutter_ios_sdk10, and google_maps_flutter_ios_shared_code).

- (void)mapView:(GMSMapView *)mapView
    didTapPOIWithPlaceID:(NSString *)placeID
                    name:(NSString *)name
                location:(CLLocationCoordinate2D)location {
  if (placeID != nil) {
    [self.mapEventHandler didTapPointOfInterestWithPlaceId:placeID];
  }
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 71ea56b

Expose a place-ID-only POI tap stream across the federated plugin stack
(Android, iOS, web) so apps can react when users tap built-in map POIs.

Fixes flutter/flutter#60695
@tenninebt tenninebt force-pushed the google-maps-on-poi-tap branch from d3ae779 to 35bfd3c Compare June 8, 2026 02:00
@stuartmorgan-g
Copy link
Copy Markdown
Collaborator

Unfortunately your patch does not currently meet our quality bar. While it's fine to use AI tools as part of developing a PR, we still require all PRs to follow our standard PR process. Please review our AI contribution guidelines and file a new PR whose description follows our template (including completing the checklist), and we'll be happy to take a look. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[google_maps_flutter] Add callback for click on google poi's on the map

2 participants