見出し画像

[Flutter]google_maps_flutterでPlatformExceptionエラーの解決

Flutterに簡単にGoogle Mapを導入できるgoogle_maps_flutterというパッケージがあります。

自分はAndroidでこのパッケージを使っていたのですが、FlutterをiOS対応させてGoogle Mapを開いたら以下のエラーが出ました。Androidだけのときは出なかったのになんでや〜と思いながら手を動かしたら解決したので、その方法についてご説明します。

エラー

 PlatformException(Invalid markerId, hideInfoWindow called with invalid markerId, null, null)

まずPlatformExceptionとは何か。PlatformException classのドキュメント1文目には以下とありますがよくわからん。

Thrown to indicate that a platform interaction failed in the platform plugin.
プラットフォームプラグインでプラットフォームインタラクションが失敗したことを示すためにスローされます。

https://api.flutter.dev/flutter/services/PlatformException-class.html

Flutterでプラットフォーム特有のAPIやプラグインを使用した場合、iOSやAndroidといったネイティブプラットフォーム側で出るエラーなのだと思います。
今回、iOSでgoogle_maps_flutterを使用した時発生したので、iOS側で何かしらエラーが出ていると捉えました。

エラー文のPlatformException()の中を見ると、Invalid markerId, hideInfoWindow called with invalid markerIdとあります。
markerIdとは、google_maps_flutterにmarkerId classがあり、Google Map上に表示するピン(marker)を識別するために必要となるIDのことです。

marker

hideInfoWindowは、markerをタップしたら表示されるinfoWindowを非表示にするためにあり、GoogleMapController classのメソッドです。
infoWindowは、marker上部に表示されるウィンドウです。

infoWindow


自分は、画面をonTapした時にhideMarkerInfoWindowを呼び出してinfoWindowを非表示にできるようにしておりましたが、hideMarkerInfoWindow()に設定すべきmarkerIdを"marker"などと適当に設定していました。

GoogleMap(
                onMapCreated: (GoogleMapController controller) {
                  mapController = controller;
                },
                padding: const EdgeInsets.only(bottom: 100),
                mapType: MapType.normal,
                initialCameraPosition: CameraPosition(
                  target: _initialPosition,
                  zoom: 14.4746,
                ),
                onTap: (LatLng latLng) {
                  mapController!.hideMarkerInfoWindow(
                    const MarkerId("marker"), ///here
                  );
                },
                myLocationEnabled: true,
                myLocationButtonEnabled: true,
                markers: markers,
              ),

Androidではこれで動いていたのですが、iOSでは許されなかったようで、ちゃんと設定したらエラーが解消しました。

@override
  Widget build(BuildContext context) {
    return Center(
      child: StreamBuilder<QuerySnapshot>(
        stream: stream,
        builder: (context, snapshot) {
          if (!snapshot.hasData) {
            return const Center(
              child: CircularProgressIndicator(
                backgroundColor: Colors.lightGreenAccent,
              ),
            );
          }
          final markers = _buildMarkers(snapshot.data!.docs);
          return SafeArea(
            child: Stack(children: [
              GoogleMap(
                onMapCreated: (GoogleMapController controller) {
                  mapController = controller;
                },
                padding: const EdgeInsets.only(bottom: 100),
                mapType: MapType.normal,
                initialCameraPosition: CameraPosition(
                  target: _initialPosition,
                  zoom: 14.4746,
                ),
                onTap: (LatLng latLng) {
                  for (var marker in markers) {
                    mapController!.hideMarkerInfoWindow(marker.markerId);
                  } //marker.markerIdへと変更
                },
                myLocationEnabled: true,
                myLocationButtonEnabled: true,
                markers: markers,
              ),
              getDigitalCoinFromUsersFirestore(),
            ]),
          );
        },
      ),
    );
  }
}
  Set<Marker> _buildMarkers(List<DocumentSnapshot> documents) {
    return documents.map(
      (DocumentSnapshot document) {
        return Marker(
          markerId: MarkerId(document.id),
          position: LatLng(
            document["position"]["geopoint"].latitude,
            document["position"]["geopoint"].longitude,
          ),
          onTap: () {
            _showImageDialog(context, document);
          },
          infoWindow: InfoWindow(
            title: "ユーザー名: ${document['username']}",
            snippet: "コメント: ${document['comment']}",
          ),
        );
      },
    ).toSet();
  }

自分はCloud firestoreにデータを保存しており、StreamBuilderでデータを取り出してGoogle Map上に表示するようにしています。
以下のコードにおいて、_buildMarkersメソッドに渡したmarkerIdのデータと同じmarkerIdをhideMarkerInfoWindowにも渡したらOKでした。

 onTap: (LatLng latLng) {
                  for (var marker in markers) {
                    mapController!.hideMarkerInfoWindow(marker.markerId);
                  } //marker.markerIdへと変更
                },


この記事が気に入ったらサポートをしてみませんか?