// Tutorial //

How To Get a User's Location with the Geolocator Plugin in Flutter

Published on September 24, 2019 · Updated on March 16, 2021
Default avatar
By PaulHalliday
Developer and author at DigitalOcean.
How To Get a User's Location with the Geolocator Plugin in Flutter

Introduction

Geolocation is the process of identifying a user’s current physical location when they are interacting with your application.

There is a geolocator package and a geocoding package for Flutter that can be used for geolocation.

In this article, you will create an example Flutter app that uses the geolocator and geocoding packages to determine the location of a user.

Prerequisites

To complete this tutorial, you will need:

This tutorial was verified with Flutter v1.22.2, Android SDK v30.0.2, and Android Studio v4.1. The code in this tutorial has been updated to support geolocator 6+ and geocoding 1+.

Step 1 — Setting Up the Project

Once you have your environment set up for Flutter, you can run the following to create a new application:

  1. flutter create flutter_geolocator_example

Navigate to the new project directory:

  1. cd flutter_geolocator_example

Using flutter create will produce a demo application that will display the number of times a button is clicked.

Open pubspec.yaml in your code editor and add the following plugins:

pubspec.yaml
dependencies:
  flutter:
    sdk: flutter

  geocoding: ^1.0.5
  geolocator: ^6.1.1

Note: You will need to make sure that your Android project uses AndroidX for this. If you have created a Flutter application after version 1.7, this comes by default. If not, follow this guide: AndroidX Migration.

You will then need to add permissions to both Android and iOS by editing ios/Runner/Info.plist and android/app/src/main/AndroidManifest.xml.

iOS Permissions

Open Info.plist in your code editor and add NSLocationWhenInUseUsageDescription, NSLocationAlwaysUsageDescription, and NSLocationAlwaysAndWhenInUseUsageDescription:

Starting with iOS and the Info.plist, add the following key/value pairs and customize them to your liking:

ios/Runner/Info.plist
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location when open.</string>

<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs access to location when in the background.</string>

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs access to location when open and in the background.</string>

If you do not intend to support iOS applications older than iOS 10 and you do not want to get user location when the application is not in use, you can forego the addition of NSLocationAlwaysUsageDescription and NSLocationAlwaysAndWhenInUseUsageDescription.

Android Permissions

Open AndroidManifest.xml in your code editor and add one of the following.

ACCESS_FINE_LOCATION:

android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Or ACCESS_COARSE_LOCATION:

android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

ACCESS_FINE_LOCATION is the most precise, whereas ACCESS_COARSE_LOCATION gives results equal to about a city block.

With this setup complete, you can create the widget that will trigger and display the user’s current location.

Step 2 — Scaffolding the Project

Next, you will need to update the main.dart file and create a new home_page.dart file.

Open main.dart in your code editor and import home_page.dart and change the home from MyHomePage to HomePage:

lib/main.dart
import 'package:flutter/material.dart';
import 'home_page.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: HomePage(),
    );
  }
}

Then, create a new home_page.dart file and add the following code:

lib/home_page.dart
import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Location"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            FlatButton(
              child: Text("Get location"),
              onPressed: () {
                // Get location here
              },
            ),
          ],
        ),
      ),
    );
  }
}

This will create a button with the message "Get location".

Step 3 — Getting the Latitude and Longitude

The next step is adding the geolocation functionality.

You can accomplish that by creating an instance of Geolocator and calling getCurrentPosition. This should ask the user whether they are interested in using the Location feature and if so, get the current location as a Position.

Revisit home_page.dart and add _getCurrentLocation():

lib/home_page.dart
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';

class HomePage extends StatefulWidget {
  
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  Position _currentPosition;

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Location"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            if (_currentPosition != null) Text(
              "LAT: ${_currentPosition.latitude}, LNG: ${_currentPosition.longitude}"
            ),
            FlatButton(
              child: Text("Get location"),
              onPressed: () {
                _getCurrentLocation();
              },
            ),
          ],
        ),
      ),
    );
  }

  _getCurrentLocation() {
    Geolocator
      .getCurrentPosition(desiredAccuracy: LocationAccuracy.best, forceAndroidLocationManager: true)
      .then((Position position) {
        setState(() {
          _currentPosition = position;
        });
      }).catchError((e) {
        print(e);
      });
  }
}

Compile your code and have it run in an emulator:

Two screenshots of the application running in an emulator. The first screenshot depicts a prompt for allowing the app the access location. The second screenshot depicts a latitude and longitude for the location of the user.

When you interact with the Get location button, you may initially see a prompt requesting access to your app. Once you allow access to your location, the latitude and longitude of your current location will appear on the screen.

Step 4 — Converting Latitude and Longitude to a Human-readable Address

The next step is converting the coordinates to display an address.

Passing latitude and longitude coordinates to placemarkFromCoordinates will return a Placemark. Placemark contains information like locality, postalCode, and country.

Revisit home_page.dart and add _getAddressFromLatLng_():

lib/home_page.dart
import 'package:flutter/material.dart';
import 'package:geocoding/geocoding.dart';
import 'package:geolocator/geolocator.dart';

class HomePage extends StatefulWidget {
  
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  Position _currentPosition;
  String _currentAddress;

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Location"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            if (_currentAddress != null) Text(
              _currentAddress
            ),
            FlatButton(
              child: Text("Get location"),
              onPressed: () {
                _getCurrentLocation();
              },
            ),
          ],
        ),
      ),
    );
  }

  _getCurrentLocation() {
    Geolocator
      .getCurrentPosition(desiredAccuracy: LocationAccuracy.best, forceAndroidLocationManager: true)
      .then((Position position) {
        setState(() {
          _currentPosition = position;
          _getAddressFromLatLng();
        });
      }).catchError((e) {
        print(e);
      });
  }

  _getAddressFromLatLng() async {
    try {
      List<Placemark> placemarks = await placemarkFromCoordinates(
        _currentPosition.latitude,
        _currentPosition.longitude
      );

      Placemark place = placemarks[0];

      setState(() {
        _currentAddress = "${place.locality}, ${place.postalCode}, ${place.country}";
      });
    } catch (e) {
      print(e);
    }
  }
}

Compile your code and have it run in an emulator:

Screenshot of the application running in an emulator with an address of San Francisco, 94108, United States displayed.

When you interact with the Get location button, you may initially see a prompt requesting access to your app. Once you allow access to your location, your locality, postalCode, and county will be displayed on the screen.

Conclusion

In this tutorial, you used geolocator and geocoding packages in a Flutter application.

If you’d like to learn more about Flutter, check out our Flutter topic page for exercises and programming projects.

If you’ve enjoyed this tutorial and our broader community, consider checking out our DigitalOcean products which can also help you achieve your development goals.

Learn more here


About the authors
Default avatar
Developer and author at DigitalOcean.

Still looking for an answer?

Was this helpful?
8 Comments

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

good!

Updates

  1. If you get error

Error: Property ‘longitude’ cannot be accessed on ‘Position?’ because it is potentially null.

Change home_page.dart line no 23 to

"LAT: ${_currentPosition!.latitude}, LNG: ${_currentPosition!.longitude}"

You can use the ! as a way of saying “I know it can be null, but I also know that at this point it definitely isn’t”.

  1. To request device location permission, add this to _getCurrentLocation() method and make it async

LocationPermission permission; permission = await Geolocator.requestPermission();

_getCurrentLocation() async{

LocationPermission permission;
permission = await Geolocator.requestPermission();

Geolocator
      .getCurrentPosition(desiredAccuracy: LocationAccuracy.best, forceAndroidLocationManager: true)
      .then((Position position) {
        setState(() {
          _currentPosition = position;
        });
      }).catchError((e) {
        print(e);
      });
  }
  1. And change home_page.dart line no 25 FlatButton to TextButton

The FlatButton, RaisedButton and OutlineButton widgets have been replaced by TextButton, ElevatedButton, and OutlinedButton respectively.

dear fellow developer, interesting tutorial. I encounter error when reaching step 4 with error message: LateInitializationError: Field ‘_currentPosition@22424138’ has not initialized.

How do I use geo-locators to prove that an individual has actually been in a certain location even though they are not there anymore.

Good tutorial. Any chance you could do an update to demonstrate how to handle location permissions? Specifically if a user has previously denied permission, and now would like the app to guide them to enable that permission. I’ve tried a few things with the updated geolocation package 7.0.3 but can’t seem to make it work the way I’ve seen other apps handle this.

How can I get location automatically in the background without any user interaction even when the device is rebooted ?

you should use geocoding library now too otherwise will break

import 'package:geolocator/geolocator.dart';

Same way to try but below error coming

MissingPluginException(No implementation found for method checkPermissionStatus on channel com.baseflow.flutter/location_permissions