Working with Geolocation and Geocoding in Flutter (And Integration with Maps)

A guide to working with location and integrating it with Google Maps

Deven Joshi
Jan 7 · 6 min read

Working with a user’s location is a common task that many apps require, yet the steps to implement a well working solution in an app is often confusing and has too much boilerplate required to set up. Most Flutter packages abstract away most or all of the boilerplate required and directly give users the most optimised solution and less hassle to deal with. Often this means some fine grained control is lost through abstraction, but most times it is not needed anyway.

You can look through a tutorial for implementing location in native android to see the immense and often not needed amount of information presented to app developers who simply want the user’s location or want to track it.

Today, we’ll look through implementing getting location, location tracking and geocoding in Flutter for both Android and iOS using two different plugins which give us a varied amount of control over the underlying APIs and then see the implementation of location with maps where we’ll track a user using a marker on a map.

Let’s get started.

Plugin 1: ‘location’

The ‘location’ plugin is the simplest way to get and track a user’s location without the hassle of any boilerplate code.

Setting up is simple enough:

  1. Add plugin to the pubspec.yaml
dependencies:
location:
^1.4.1

2. Add a permission to Android Manifest:

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

3. Add permissions to iOS Info.plist

<key>NSLocationAlwaysUsageDescription</key>
<string>Needed to access location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Needed to access location</string>

And you’re done.

In Android 6.0+, we need to ask access to location in runtime, which this package handles on its own.

Getting a one-time location

It allows us to get two things:

  1. A one-time location of the user
  2. A stream allowing us to listen to the location of the user.

Let’s create a simple app which gets the one-time location of the user like above.

Like we discussed, this package does not need much setup and the code is rather straightforward.

First, simply initialise a Location object.

var location = new Location();

location is not the location of the user itself but a class that helps us get it.

The location is returned as a map with keys like “latitude”, “longitude”, etc.

Map<String, double> userLocation;

And finally, getting the location is as simple as:

userLocation = await location.getLocation();

That’s it.

For the complete code:

Here, we get the latitude and longitude. Other factors available are:

  currentLocation["latitude"];
currentLocation["longitude"];
currentLocation["accuracy"];
currentLocation["altitude"];
currentLocation["speed"];
currentLocation["speed_accuracy"]; //Not for iOS

Listening to location updates

Listening to location updates is not that different from getting location, we simply use a stream object provided by the plugin to listen to updates.

location.onLocationChanged().listen((Map<String,double> currentLocation) {
print(currentLocation["latitude"]);
print(currentLocation["longitude"]);
print(currentLocation["accuracy"]);
print(currentLocation["altitude"]);
print(currentLocation["speed"]);
print(currentLocation["speed_accuracy"]);
});

An example page of this would be:

Which gives a similar page to the one we made with the first example, but this time, we listen for location.

This plugin was a simple one to use without much setup or control and was straightforward in use and intention. Next, we’ll see another which gives more control over the APIs involved and also allows for geocoding.

Plugin 2: ‘geolocator’

Setup

The setup for this plugin is more or less the same as the location. If you plan to use coarse location as well, add

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

to AndroidManifest.xml .

First, we will do the same two tasks with this plugin, which is more or less the same:

Get location once

Use the Geolocator object instead of Location and instead of a Map<String,double> , we get back a Position object.

Geolocator geolocator = Geolocator();

Position userLocation;

And we do this to take location:

currentLocation = await geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.best);

Here, we can also set the location accuracy depending on the accuracy we need.

Get Location Updates

Updates are similar to the ‘location’ package but with enhanced options.

geolocator.getPositionStream().listen((position) {
// Do something here
});

We can set the accuracy, time interval between updates, whether we want to force usage of Android location manager, etc.

geolocator
.getPositionStream(LocationOptions(
accuracy: LocationAccuracy.best, timeInterval: 1000))
.listen((position) {
// Do something here
});

Working with Geocoding

Geocoding is essentially the process of getting physical map co-ordinates and details for an address.

List<Placemark> placemark = await Geolocator().placemarkFromAddress("Gronausestraat 710, Enschede");

You can get all the details about the place as:

print(placemark[0].country);
print(placemark[0].position);
print(placemark[0].locality);
print(placemark[0].administrativeArea);
print(placemark[0].postalCode);
print(placemark[0].name);
print(placemark[0].subAdministratieArea);
print(placemark[0].isoCountryCode);
print(placemark[0].subLocality);
print(placemark[0].subThoroughfare);
print(placemark[0].thoroughfare);

We can also get the details of a place from the coordinates:

List<Placemark> placemark = await Geolocator().placemarkFromCoordinates(52.2165157, 6.9437819);

Getting the distance between coordinates

This plugin also allows us to calculate the distance between two coordinates as:

double distanceInMeters = await Geolocator().distanceBetween(52.2165157, 6.9437819, 52.3546274, 4.8285838);

Integrating location updates with Google Maps

To integrate Google Maps with location updates, we need to use the google_maps_flutter package and your choice of location plugin.

Let’s just use the ‘location’ package for now.

A precursor to this part is my “Exploring Google Maps in Flutter” article and I highly recommend you use it to set up Maps in your app.

To integrate maps with location tracking, we simply need to use both the plugins in conjunction.

Let’s move a marker as the user changes location.

First, we create our MapController and Location objects to manipulate maps and location. (Assign mapController when map is initialised, as given in the upper article)

GoogleMapController mapController;
Location location = Location();

Next, we add a marker to store the current marker:

Marker marker;

Now, we listen to location updates.

location.onLocationChanged().listen((location) async {
// Do something here
});

This is how we will move the marker when location is updated:

  1. Remove the current marker if not null as there is now a new location it needs to be at.
  2. Add marker at latitude and longitude.
  3. Move camera to new marker location and set other characteristics like zoom, bearing and tilt. (Details about this given in GMaps article)
location.onLocationChanged().listen((location) async {
// Step 1
if(marker != null) {
mapController.removeMarker(marker);
}
// Step 2
marker = await mapController?.addMarker(MarkerOptions(
position: LatLng(location["latitude"], location["longitude"]),
));
//Step 3
mapController?.moveCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(
location["latitude"],
location["longitude"],
),
zoom: 20.0,
),
),
);
});

And now the marker will update location when the user moves!

Here’s the complete demo page code:

That’s it for this article! I hope you enjoyed it, and leave a few claps if you did. Follow me for more Flutter articles and comment for any feedback you might have about this article.

Note: I’ve been working on a Deep Dive series for Flutter widgets for a while now, and if you haven’t seen it before, please give it a read. Here are a few articles from the series.

Feel free to check out my other profiles as well:

This story is published in The Startup, Medium’s largest entrepreneurship publication followed by +408,714 people.

Subscribe to receive our top stories here.

The Startup

Medium's largest active publication, followed by +477K people. Follow to join our community.

Deven Joshi

Written by

Mobile Developer (Flutter + Android) | Technical Writer | Speaker | #Hack19 Winner | AAD graduate

The Startup

Medium's largest active publication, followed by +477K people. Follow to join our community.