Tuesday, 24 September, 2019 UTC


Summary

Ever wanted to get a user’s location within your Flutter application? We’re going to be building an application that does exactly that by taking advantage of the Geolocator plugin.
Creating a new Flutter project
As always, we’ll start off by setting up a new project and adding the plugin:
# New Flutter project $ flutter create my_location_project # Open this up inside of VS Code $ cd my_location_project && code . 
Adding the Geolocator plugin
Head over to your pubspec.yaml and add the following plugin:
dependencies: flutter: sdk: flutter geolocator: ^5.1.3 
Note: You'll need to make sure that your Android project uses AndroidX for this. If you've created a Flutter application after version 1.7, this comes by default, if not, follow this guide: AndroidX Migration.
We’ll 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

Starting with iOS and the Info.plist, add the following key/value pairs and customize them to your liking:
<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 don’t intend to support iOS applications older than iOS 10 and you don’t want to get user location when the application isn’t in use, you can forego the addition of NSLocationAlwaysUsageDescription and NSLocationAlwaysAndWhenInUseUsageDescription.

Android Permissions

For android, head on over to your AndroidManifest.xml and add either of these permissions:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
What’s the difference between these two? ACCESS_FINE_LOCATION is the most precise, whereas ACCESS_COARSE_LOCATION gives results equal to about a city block.
We’re now ready to get started!
Scaffolding our Project
We’ll update our main.dart file to contain our new HomePage widget found within home_page.dart:
import 'package:flutter/material.dart'; import 'home_page.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: HomePage(), ); } } 
Our HomePage widget will look something like this:
import 'package:flutter/material.dart'; class HomePage extends StatefulWidget { @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { @override 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 }, ), ], ), ), ); } } 
Getting the Current Location
Now that we’ve established the basics for our project, let’s go ahead and update our HomePage widget to get the current location of a user.
We can do that by creating an instance of Geolocator and calling getCurrentPosition. This should ask the user whether they’re interested in using the Location feature, and if so, get the current location as a Position.
Here’s how it looks:
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:geolocator/geolocator.dart'; class HomePage extends StatefulWidget { @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { Position _currentPosition; @override 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() { final Geolocator geolocator = Geolocator()..forceAndroidLocationManager; geolocator .getCurrentPosition(desiredAccuracy: LocationAccuracy.best) .then((Position position) { setState(() { _currentPosition = position; }); }).catchError((e) { print(e); }); } } 
We should now be able to see the latitude and longitude on screen:
Converting this Into an Address
We don’t have to stop there though! We can get a Placemark which is essentially an approximation of the user’s current location from the latitude and longitude. Let’s see this in action:
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:geolocator/geolocator.dart'; class HomePage extends StatefulWidget { @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { final Geolocator geolocator = Geolocator()..forceAndroidLocationManager; Position _currentPosition; String _currentAddress; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Location"), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ if (_currentPosition != null) Text(_currentAddress), FlatButton( child: Text("Get location"), onPressed: () { _getCurrentLocation(); }, ), ], ), ), ); } _getCurrentLocation() { geolocator .getCurrentPosition(desiredAccuracy: LocationAccuracy.best) .then((Position position) { setState(() { _currentPosition = position; }); _getAddressFromLatLng(); }).catchError((e) { print(e); }); } _getAddressFromLatLng() async { try { List<Placemark> p = await geolocator.placemarkFromCoordinates( _currentPosition.latitude, _currentPosition.longitude); Placemark place = p[0]; setState(() { _currentAddress = "${place.locality}, ${place.postalCode}, ${place.country}"; }); } catch (e) { print(e); } } } 
After getting the latitude and longitude, we’re now using _getAddressFromLatLng() to convert this into an address and display it on screen.
Here’s how it looks: