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: