Today we will learn how to use Reverse Geocoding to get address from Geo Coordinates, let’s get started!

As always you can find the whole code for this tutorial on github at: Reverse Geo Coding.

Things we will cover:

How to:

Get users current location. Use reverse geocoding to get the current address of the user. Get the coordinates of a marker on a map and use it to get its address.

Packages we will use:

Geocoder: Forward and reverse geocoding. Link: https://pub.dev/packages/geocoder

Google Maps Flutter: A Flutter plugin that provides a Google Maps widget. Link: https://pub.dev/packages/google_maps_flutter

Location: This plugin for Flutter handles getting location on Android and iOS. It also provides callbacks when location is changed. Link: https://pub.dev/packages/location

Getting Started:

Let’s start with the easiest part which is the UI. There is nothing fancy since we are only going to focus on practicality today.

On main.dart, under our Column we have 4 children:

An Expanded FutureBuilder that returns either a CircularProgressIndicator while we get the current user’s location or the Map that will show our user’s location as well allowing to add a Marker to it. A Text widget that will show the resulting address. Two full width buttons that we will use to call the reverse geocoding function.

Here is the list of variables used in this code:

Future _getUserLocation → The future used by our FutureBuilder. LatLng _markerLocation → The coordinates of the map marker. LatLng _userLocation → The current user location. String _resultAddress → The resulting address from the reverse geocoding function.

Now let’s jump to the functions.

Function 1: getUserLocation()

This function runs on InitState to ensure that we have the user’s location before we start.

Future getUserLocation() async { Location location = new Location(); bool _serviceEnabled; PermissionStatus _permissionGranted; _serviceEnabled = await location.serviceEnabled(); if (!_serviceEnabled) { _serviceEnabled = await location.requestService(); if (!_serviceEnabled) { return null; } } _permissionGranted = await location.hasPermission(); if (_permissionGranted == PermissionStatus.denied) { _permissionGranted = await location.requestPermission(); if (_permissionGranted != PermissionStatus.granted) { return null; } } final result = await location.getLocation(); _userLocation = LatLng(result.latitude, result.longitude); return result; }

Once this function is called it starts by checking if the location service is enabled, if it isn’t then it asks the system to enable it, if the user refuses then the function returns null.

_serviceEnabled = await location.serviceEnabled(); if (!_serviceEnabled) { _serviceEnabled = await location.requestService(); if (!_serviceEnabled) { return null; } }

After that, it checks if the user has given location permissions to our app, if not then it requests it, if the user doesn’t grant the permission then the function returns null.

_permissionGranted = await location.hasPermission(); if (_permissionGranted == PermissionStatus.denied) { _permissionGranted = await location.requestPermission(); if (_permissionGranted != PermissionStatus.granted) { return null; } }

Finally, after going through all these checks we can finally request the user’s location and return it.

final result = await location.getLocation();

Function 2: getSetAddress()

This is the actual reverse geocoding function and it’s really easy to understand.

getSetAddress(Coordinates coordinates) async { final addresses = await Geocoder.local.findAddressesFromCoordinates(coordinates); setState(() { _resultAddress = addresses.first.addressLine; }); }

The function takes a Coordinate argument and passes it to the Geocoder.local.findAddressesFromCoordinates Future function.

After awaiting this future and setting its value to the final variable addresses, we can call setState and give the _resultAddress variable the addresses.first.addressLine value.

Each time the user clicks on either of the two buttons we check if the appropriate variable is set i.e: _userLocation != null or _markerLocation != null. Then we call the function as follows:

Getting the address of the user:

SizedBox( width: double.infinity, child: RaisedButton( child: Text("Get My Location Address"), onPressed: () async { if (_userLocation != null) { getSetAddress(Coordinates( _userLocation.latitude, _userLocation.longitude)); } }, ), ),

Getting the marker’s address:

SizedBox( width: double.infinity, child: RaisedButton( child: Text("Get Marker Address"), onPressed: () async { if (_markerLocation != null) { getSetAddress(Coordinates( _markerLocation.latitude, _markerLocation.longitude)); } }, ), ),

MyMap widget:

This widget takes 3 named parameters:

markerLocation → The location of the marker on the map. userLocation → The user’s current location. onTap → onTap call back that updates the markerLocation on the MyApp widget.

class MyMap extends StatefulWidget { final markerLocation, userLocation, onTap; const MyMap({Key key, this.markerLocation, this.userLocation, this.onTap}) : super(key: key); @override _MyMapState createState() => _MyMapState(); } class _MyMapState extends State { @override Widget build(BuildContext context) { return GoogleMap( initialCameraPosition: CameraPosition( target: widget.userLocation ?? LatLng(14, 20), ), myLocationEnabled: true, markers: widget.markerLocation != null ? [ Marker( markerId: MarkerId("Tap Location"), position: widget.markerLocation), ].toSet() : null, onTap: widget.onTap, ); } }

Once we have all of those parameters we just pass them to the GoogleMap widget which show a map centered at the user’s current location or at these coordinates: Lat 14, Lng: 20.

Result:

Current Address

Home Screen

Marker Address

Wrapping up:

This tutorial was pretty quick and different from the usual UI stuff that I do.

Please let me know in the comments or on Twitter if you want me to cover more stuff like this.

Don’t forget to support me by buying a cup of coffee at BuyMeACoffee. Until next time, keep coding!