Google Maps and Geolocation in Flutter

In this post we will explore how to implement Geolocation in Flutter and plot the location on a Google Map. Before you begin, make sure that you have a Google Maps API Key. You'll need that key to utilize their APIs. To get your API key, visit the Google Maps Platform home page and click the Get Started button. The maps platform site will lead you through the setup process. You will need different API keys based on what platform you are building for. For future reference here are instructions for both Android and iOS but we'll walk through setting up the keys after we create a bar bones app.

Creating an App

Before we can add API keys to an app, we need to create at least a bare bones app. If you have not done this before, I have some instructions here for creating a new Flutter app: From Zero to App With Flutter

Adding the Google Maps Plugin

Google Maps can be added to your Flutter app by means of the Google Maps Plugin. This plugin is built and maintained by the Flutter team but be warned, as of this writing it is in 'developer preview', meaning you shouldn't expect it to be fully production ready. But for the basic map functionality we need, it is currently working well enough.

To add this plugin, open up your pubspec.yaml file and add the plugin. Such as:

dependencies:
  flutter:
    sdk: flutter

  # Google Maps plugin
  google_maps_flutter: ^0.5.21+8

Be sure to routinely check the plugin site to ensure you are using the latest version!

Make sure at this point you update your flutter packages by running the following command:

flutter packages get

Now that we have the plugin and our API keys, let's finish our setup so we can get into some coding!

Setting the API Key for Android Development

To add your Android API Key to your app Open up the following file - android\app\src\main\AndroidManifest.xml

Add in the following line as a child of the application XML tag and make sure to replace the value with your API key.

<meta-data android:name="com.google.android.geo.API_KEY"
               android:value="YOUR-KEY-HERE"/>

Setting the API Key for iOS Development

Under iOS (assuming your are using Swift), your API key goes into the ios/Runner/AppDelegate.swift file:

import UIKit
import Flutter
import GoogleMaps

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
  ) -> Bool {
    GMSServices.provideAPIKey("YOUR KEY HERE")
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

More information on setting up the API keys (as well as an example for iOS developers not using Swift) can be found on the Google Maps plugin's home page.

Adding a Google Map Widget

Open you your lib\main.dart file and replace its contents with the following code excerpt. This code creates a Google Map and centers it on New York City.

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Geolocation Google Maps Demo',
      home: MyMap(),
    );
  }
}

class MyMap extends StatefulWidget {
  @override
  State<MyMap> createState() => MyMapSampleState();
}

class MyMapSampleState extends State<MyMap> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: GoogleMap(
        mapType: MapType.hybrid,
        initialCameraPosition: CameraPosition(
          target: LatLng(40.688841, -74.044015),
          zoom: 11,
        ),
      ),
    );
  }
}

If you run the app, you should see something similar to the following. If you don't see a map, check to make sure you followed the instructions correctly and are using a valid/working API key.

Sample App showing Google Map

So far in this app we have hard coded the latitude and longitude for our map. Let's change this and geolocate your current position.

Adding Support for Geolocation

In order to perform geolocation we are going to depend on the Flutter Geolocator plugin. Open back up your pubspec.yaml file and add this plugin directly below the Google Maps plugin we added earlier:

# Geolocator plugin
  geolocator: ^5.1.4+2

And once again update your flutter packages by running the following command:

flutter packages get

Geolocating

Let's add a FloatingActionButton to the app and assign its click handler to get the users current location.

Here is the code for our addition of our FloatingActionButton:

floatingActionButton: FloatingActionButton(
        onPressed: _getLocation,
        tooltip: 'Get Location',
        child: Icon(Icons.flag),
      ),

And our click handler for our new button:

  void _getLocation() async {
    var currentLocation = await Geolocator()
        .getCurrentPosition(desiredAccuracy: LocationAccuracy.best);

    setState(() {
      _markers.clear();
      final marker = Marker(
          markerId: MarkerId("curr_loc"),
          position: LatLng(currentLocation.latitude, currentLocation.longitude),
          infoWindow: InfoWindow(title: 'Your Location'),
      );
      _markers["Current Location"] = marker;
    });
  }

Let's dissect the above code. Firstly, we use the Geolocator plugin to get the current position of the device running the app. We've set the accuracy of the location returned to best which gives us an accuracy of ~0m.

Android Developers

In order for this to work, you need to update your AndroidManifest.xml file located under android/app/src/main and the following line under the tag:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

iOS Developers

For iOS you will need to add the NSLocationWhenInUseUsageDescription to your Info.plist file. The Info.plist file can be found under located under ios/Runner/Base.lproj. Like this:

<key>NSLocationWhenInUseUsageDescription</key>
<string>To access your current location.</string>

More information on setting up permissions and various options available to you with this plugin can be found on the plugin's home page.

Going back to our _getLocation code, once we have the current location we proceed to plot our location by creating a new Marker. The bare minimum you will want is to define the following:

  • markerId - identifies the marker and must be unique across all markers
  • position - dictates the position of the marker on the map.
  • infoWindow - text for the popup window that appears when a marker is clicked

As you can see, we add the Marker we just created to our list of _markers. Let's now handle the definition of the _markers field. Place the following code at the top of the MyMapSampleState class:

final Map<String, Marker> _markers = {};

And let's make our Google Map definition aware of these map markers. Head down to the section where we define the Google Map and set the markers property as follows:

GoogleMap(
    mapType: MapType.hybrid,
    initialCameraPosition: CameraPosition(
      target: LatLng(40.688841, -74.044015),
      zoom: 11,
    ),
    markers: _markers.values.toSet(),
),

Running the App

That's all there is to adding a map and geolocating. Mostly due to the power of plugins, we were able to achieve this sample app in less than 60 lines of code. Run the app and give it a test drive (you may have to pan/zoom the map to your current position to see your marker).

Sample App showing Map Marker

Future Improvements

There is a lot more you can do with these two plugins. Some things to consider:

  • Better error handling in the event the user is not allowing device location
  • Geocoding to get the address of the current position
  • Once the position is changed, pan the map camera to the position

I may cover these in future blog posts if the interest seems to be there... But for now, enjoy!

1 thought on “Google Maps and Geolocation in Flutter”

Leave a Reply

Your email address will not be published. Required fields are marked *