How to Get User’s Current Location Address in Flutter — Geolocator & Geocoding

Location-based services are one of the most significant and potent components of modern mobile applications. The most well-known apps all make advantage of the user’s location services to perform certain functions, like contextualising learning and research, localising mobile advertising, and making recommendations for nearby locations.

Geolocation and reverse geocoding are the two processes for determining a user’s current physical location.

Luckily, geolocator and geocoding tools for flutter exist and can carry out these tasks. Platform-specific location services and geocoding/reverse-geocoding tools are easily accessible using these packages.

This tutorial will teach us how to utilize geolocators and geocoding packages to obtain the user’s current location address and display it on the screen.

Setting up the project

To begin, we must add the required dependencies, the geolocator and geocoding packages to your pubspec.yaml file.

dependencies:
  geolocator: ^8.2.0
  geocoding: ^2.0.4

Or simply run the following command:

$ flutter pub add geolocator
$ flutter pub add geocoding
// This will add the same line to your package's pubspec.yaml

Next, we need to add permission configuration for Android and iOS.

For Android

Initially, we must include the lines listed below in your gradle.properties file:

android.useAndroidX=true
android.enableJetifier=true

Next, ensure that your android/app/build.gradle file’s compileSdkVersion is set to 31:

android {
  compileSdkVersion 31
  
  ...
}

Then, we need to add either the ACCESS_FINE_LOCATION or the ACCESS_COARSE_LOCATION permission your android/app/src/main/AndroidManifest.xml file

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

The most accurate is ACCESS_FINE_LOCATION, whereas ACCESS_COARSE_LOCATION yields values that are about equivalent to a city block.

For iOS

To get the device’s position, we must add the lines listed below to 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>

Lastly, replace the content of your main.dart file with the following code and we’re all set.

import 'package:flutter/material.dart';
import 'package:flutter_location_practice/location_page.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Location Demo',
      debugShowCheckedModeBanner: false,
      home: LocationPage(),
    );
  }
}
Dart

Handle location services and permissions

We need the user’s consent before we may obtain their location. Therefore, we’ll design a procedure to look up and ask for permission to use location services. First, make a new location_page StatefulWidget class file.Add the following code for the user interface (UI) to dart in the project’s library folder:

class LocationPage extends StatefulWidget {
  ...
class _LocationPageState extends State<LocationPage> {
  @override
  Widget build(BuildContext context) {
     return Scaffold(
       appBar: AppBar(title: const Text("Location Page")),
       body: SafeArea(
         child: Center(
           child: Column(
             mainAxisAlignment: MainAxisAlignment.center,
             children: [
               const Text('LAT: '),
               const Text('LNG: '),
               const Text('ADDRESS: '),  
               const SizedBox(height: 32), 
               ElevatedButton(
                 onPressed: () {},  
                 child: const Text("Get Current Location"),
               )
             ],
           ),
         ),
       ),
    );
  }
}
Dart

This will produce a Text widget with the address, latitude, and longitude shown, along with a button for retrieving the user’s current position.

Next, develop a procedure to ascertain and solicit the user’s consent.

Future<bool> _handleLocationPermission() async {
  bool serviceEnabled;
  LocationPermission permission;
  
  serviceEnabled = await Geolocator.isLocationServiceEnabled();
  if (!serviceEnabled) {
    ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
        content: Text('Location services are disabled. Please enable the services')));
    return false;
  }
  permission = await Geolocator.checkPermission();
  if (permission == LocationPermission.denied) {
    permission = await Geolocator.requestPermission();
    if (permission == LocationPermission.denied) {   
      ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Location permissions are denied')));
      return false;
    }
  }
  if (permission == LocationPermission.deniedForever) {
    ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
        content: Text('Location permissions are permanently denied, we cannot request permissions.')));
    return false;
  }
  return true;
}
Dart

This method shows the snackbar and returns false after first determining whether the location service is enabled or disabled. Subsequently, we invoke the checkPermission() function to verify whether the user has already authorised us to obtain the device’s location. We use the requestPermission() function to ask for permission to access the device’s location if the permission is denied. We display the snackbar and return false in the event that the permission is permanently refused. Else, we return true, indicating that the permissions have been granted.

Get user’s latitude and longitude

It is now necessary to incorporate the geolocation feature. You only need to call the getCurrentPosition() method to find out where the device is right now. To illustrate:

import 'package:geolocator/geolocator.dart';
Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
Dart

First, we create variables for storing the current address and position.

class _LocationPageState extends State<LocationPage> {
  String? _currentAddress;
  Position? _currentPosition;
Dart

The _getCurrentLocation() function is then created, and it calls the _handleLocationPermission() method to see if permission has been given or not. If so, we build a geolocator instance, call the getCurrentPosition() function, and obtain the position as of right now.

Future<void> _getCurrentPosition() async {
  final hasPermission = await _handleLocationPermission();
  if (!hasPermission) return;
  await Geolocator.getCurrentPosition(
          desiredAccuracy: LocationAccuracy.high)
      .then((Position position) {
    setState(() => _currentPosition = position);
  }).catchError((e) {
    debugPrint(e);
  });
}
Dart

Next, to display the latitude and longitude derived from the _currentPosition variable, just swap out the Column widget with the adjacent code.

child: Column(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    Text('LAT: ${_currentPosition?.latitude ?? ""}'),
    Text('LNG: ${_currentPosition?.longitude ?? ""}'),
    Text('ADDRESS: ${_currentAddress ?? ""}'),
    const SizedBox(height: 32),
    ElevatedButton(
      onPressed: _getCurrentPosition,
      child: const Text("Get Current Location"),
    )
  ],
),
Dart

When you pressed the Get Current Location button, you will initially see a location access request to your app. Once you allow, the latitude and longitude of your current location will appear on the screen.

Convert latitude and longitude to a human-readable address

Creating an address from the latitude and longitude coordinates is the final step. You can accomplish this by invoking the geocoding package’s placemarkFromCoordinates() function. To illustrate:

import 'package:geocoding/geocoding.dart';
List<Placemark> placemarks = await placemarkFromCoordinates(27, 20.9437819);
Dart

To set the _currentAddress with the Placemark details, including street, locale, postalCode, country, and more, create a _getAddressFromLatLng() function that takes Position as an input, calls the placemarkFromCoordinates() method, and ends there.

Future<void> _getAddressFromLatLng(Position position) async {
  await placemarkFromCoordinates(
          _currentPosition!.latitude, _currentPosition!.longitude)
      .then((List<Placemark> placemarks) {
    Placemark place = placemarks[0];
    setState(() {
      _currentAddress =
         '${place.street}, ${place.subLocality},
          ${place.subAdministrativeArea}, ${place.postalCode}';
    });
  }).catchError((e) {
    debugPrint(e);
  });
 }
}
Dart

Then, we just need to call the _getAddressFromLatLng() method inside the _getCurrentLocation() method.

Future<void> _getCurrentPosition() async {
  ...
  
  await Geolocator.getCurrentPosition(
          desiredAccuracy: LocationAccuracy.high)
      .then((Position position) {
    setState(() => _currentPosition = position);
    _getAddressFromLatLng(_currentPosition!);
  }).catchError((e) {
    debugPrint(e);
  });
}
Dart

After all, this is how the location_page.dart looks.

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

class LocationPage extends StatefulWidget {
  const LocationPage({Key? key}) : super(key: key);

  @override
  State<LocationPage> createState() => _LocationPageState();
}

class _LocationPageState extends State<LocationPage> {
  String? _currentAddress;
  Position? _currentPosition;

  Future<bool> _handleLocationPermission() async {
    bool serviceEnabled;
    LocationPermission permission;

    serviceEnabled = await Geolocator.isLocationServiceEnabled();
    if (!serviceEnabled) {
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
          content: Text(
              'Location services are disabled. Please enable the services')));
      return false;
    }
    permission = await Geolocator.checkPermission();
    if (permission == LocationPermission.denied) {
      permission = await Geolocator.requestPermission();
      if (permission == LocationPermission.denied) {
        ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text('Location permissions are denied')));
        return false;
      }
    }
    if (permission == LocationPermission.deniedForever) {
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
          content: Text(
              'Location permissions are permanently denied, we cannot request permissions.')));
      return false;
    }
    return true;
  }

  Future<void> _getCurrentPosition() async {
    final hasPermission = await _handleLocationPermission();

    if (!hasPermission) return;
    await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high)
        .then((Position position) {
      setState(() => _currentPosition = position);
      _getAddressFromLatLng(_currentPosition!);
    }).catchError((e) {
      debugPrint(e);
    });
  }

  Future<void> _getAddressFromLatLng(Position position) async {
    await placemarkFromCoordinates(
            _currentPosition!.latitude, _currentPosition!.longitude)
        .then((List<Placemark> placemarks) {
      Placemark place = placemarks[0];
      setState(() {
        _currentAddress =
            '${place.street}, ${place.subLocality}, ${place.subAdministrativeArea}, ${place.postalCode}';
      });
    }).catchError((e) {
      debugPrint(e);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Location Page")),
      body: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text('LAT: ${_currentPosition?.latitude ?? ""}'),
              Text('LNG: ${_currentPosition?.longitude ?? ""}'),
              Text('ADDRESS: ${_currentAddress ?? ""}'),
              const SizedBox(height: 32),
              ElevatedButton(
                onPressed: _getCurrentPosition,
                child: const Text("Get Current Location"),
              )
            ],
          ),
        ),
      ),
    );
  }
}
Dart

Congratulations! You now know how to retrieve the user’s current position from within a Flutter app. This is merely a brief overview of the geolocation and geocoding software packages. However, I hope this post assisted you in getting started with these Flutter packages ????.

1 thought on “How to Get User’s Current Location Address in Flutter — Geolocator & Geocoding”

Comments are closed.