M Karimi
M Karimi

Reputation: 3513

It is Possible to use Bing Maps in flutter app

I want to use Bing Maps in Flutter with all properties like current location and custom marker.

It is Possible to use Bing Maps in flutter app? I want to use a flutter package that it supports android, ios and web. For example by flutter_map package can I use Bing Maps? Anybody has any suggestions?

Upvotes: 0

Views: 914

Answers (2)

Bilal Şimşek
Bilal Şimşek

Reputation: 5943

Yes, its possible now

I m using flutter_map for pin clustering features. I use BingMapTile with api key, Here is the steps.

  1. Create an api key following instructions at this link
  2. copy and paste the code below to your project
     enum BingMapsImagerySet {
          road('RoadOnDemand', zoomBounds: (min: 0, max: 21)),
          aerial('Aerial', zoomBounds: (min: 0, max: 20)),
          aerialLabels('AerialWithLabelsOnDemand', zoomBounds: (min: 0, max: 20)),
          canvasDark('CanvasDark', zoomBounds: (min: 0, max: 21)),
          canvasLight('CanvasLight', zoomBounds: (min: 0, max: 21)),
          canvasGray('CanvasGray', zoomBounds: (min: 0, max: 21)),
          ordnanceSurvey('OrdnanceSurvey', zoomBounds: (min: 12, max: 17));
        
          final String urlValue;
          final ({int min, int max}) zoomBounds;
        
          const BingMapsImagerySet(this.urlValue, {required this.zoomBounds});
        }
        
        // Custom tile provider that contains the quadkeys logic
        // Note that you can also extend from the CancellableNetworkTileProvider
        class BingMapsTileProvider extends NetworkTileProvider {
          BingMapsTileProvider({super.headers});
        
          String _getQuadKey(int x, int y, int z) {
            final quadKey = StringBuffer();
            for (int i = z; i > 0; i--) {
              int digit = 0;
              final int mask = 1 << (i - 1);
              if ((x & mask) != 0) digit++;
              if ((y & mask) != 0) digit += 2;
              quadKey.write(digit);
            }
            return quadKey.toString();
          }
        
          @override
          Map<String, String> generateReplacementMap(
            String urlTemplate,
            TileCoordinates coordinates,
            TileLayer options,
          ) =>
              super.generateReplacementMap(urlTemplate, coordinates, options)
                ..addAll(
                  {
                    'culture': 'en-GB', // Or your culture value of choice
                    'subdomain': options.subdomains[
                        (coordinates.x + coordinates.y) % options.subdomains.length],
                    'quadkey': _getQuadKey(coordinates.x, coordinates.y, coordinates.z),
                  },
                );
        }
        
        // Custom `TileLayer` wrapper that can be inserted into a `FlutterMap`
        class BingMapsTileLayer extends StatelessWidget {
          const BingMapsTileLayer({
            super.key,
            required this.apiKey,
            required this.imagerySet,
          });
        
          final String apiKey;
          final BingMapsImagerySet imagerySet;
        
          @override
          Widget build(BuildContext context) {
            return FutureBuilder(
              future: http.get(
                Uri.parse(
                  'http://dev.virtualearth.net/REST/V1/Imagery/Metadata/${imagerySet.urlValue}?output=json&include=ImageryProviders&key=$apiKey',
                ),
              ),
              builder: (context, response) {
                if (response.data == null) return const Placeholder();
        
                return TileLayer(
                  urlTemplate: (((((jsonDecode(response.data!.body)
                                  as Map<String, dynamic>)['resourceSets']
                              as List<dynamic>)[0] as Map<String, dynamic>)['resources']
                          as List<dynamic>)[0] as Map<String, dynamic>)['imageUrl']
                      as String,
                  tileProvider: BingMapsTileProvider(),
                  subdomains: const ['t0', 't1', 't2', 't3'],
                  minNativeZoom: imagerySet.zoomBounds.min,
                  maxNativeZoom: imagerySet.zoomBounds.max,
                );
              },
            );
          }
        }

reference for the code

use it in your map widget

 Card(
        child: SizedBox.expand(
            child:
             FlutterMap(
              options: MapOptions(
                initialRotation:90 ,
              initialCameraFit: CameraFit.bounds(bounds:  LatLngBounds(LatLng(41, 26.2), LatLng(36.77,47.0)),
        
        
            ),
        
        
                initialZoom:5,
                maxZoom: 15,
              ),
              children: <Widget>[

              BingMapsTileLayer(apiKey: bingMapKey,imagerySet: BingMapsImagerySet.aerial,),

                MarkerClusterLayerWidget(
                  options: MarkerClusterLayerOptions(
                    maxClusterRadius: 45,
                    size: const Size(40, 40),
                    alignment: Alignment.center,
                    padding: const EdgeInsets.all(50),
                    maxZoom: 15,        
                    markers: getMarkers(),
                    builder: (context, markers) {
                      return Container(
                        decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(20),
                            color: Colors.blue),
                        child: Center(
                          child: Text(
                            markers.length.toString(),
                            style: const TextStyle(color: Colors.white),
                          ),
                        ),
                      );
                    },
                  ),
                ),
              ],
            )
          ),
      ).p(20),

    );

Upvotes: 0

rbrundritt
rbrundritt

Reputation: 17954

It is possible to load Bing Maps tiles as a layer within the open source Flutter Map SDK. https://github.com/fleaflet/flutter_map

To use Bing Maps you first have to call the Imagery metadata service to register the map session and to get the latest map tile URLs as per this document: https://learn.microsoft.com/en-us/bingmaps/rest-services/directly-accessing-the-bing-maps-tiles

From there you can use the map tile URL as a tile layer within the flutter map SDK like the other examples.

Alternatively, you may also want to consider using Azure Maps in this case. Licensing is much easier, the data is pretty much the same as Bing Maps, and billing is based on map tile consumption which can be much cheaper than session based pricing as map tiles automatically get cached. There is an Azure Maps example in the map README page for the Flutter Map SDK.

Upvotes: 2

Related Questions