Newby Coder header banner

Flutter Device Location

Getting location of Android/iOS device in Flutter

Using location package, Flutter Apps can retrieve location of an user

It can also be used to subscribe to location changes

Creating new Flutter App

Check Flutter installation to setup Flutter

Use flutter create command to create a Flutter project (here device_location_app) :

flutter create device_location_app

Dependency


Permission

Requesting permission to access location in Android

Find and open device_location_app (project directory) → android → app → src → main → AndroidManifest.xml

Add ACCESS_FINE_LOCATION permission (before <application tag)

device_location_app/android/app/src/main/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.file_picker_app">
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Requesting location permission in iOS

Find and open device_location_app (flutter project directory) → ios → Runner → Info.plist

Add NSLocationWhenInUseUsageDescription to request permission from user to enable geolocation when using the app

device_location_app/android/app/src/main/AndroidManifest.xml
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string></string>

Implementation

Importing Package

Import the package into dart code

import 'package:location/location.dart';

Check location permission

Check if user has granted location permission, request for permission if not

Location _locationService  = new Location();
bool serviceEnabled = await _locationService.serviceEnabled();
if (serviceEnabled) {
  _permissionGranted = await _locationService.requestPermission();
} 

Get current location

Location _locationService  = new Location();
LocationData locationData = await _locationService.getLocation();

Subscribe to location changes

To listen for network state changes, subscribe to the stream that is exposed by connectivity plugin

Location _locationService  = new Location();
StreamSubscription<LocationData> _locationSubscription =
  _locationService.onLocationChanged().listen((LocationData locationData) async {
    setState(() {
      _currentLocation = locationData;
    });
}); 

App Code

date_picker_app/lib/main.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:location/location.dart';


void main() {
  runApp(new DeviceLocationApp());
}

class DeviceLocationApp extends StatefulWidget {
  @override
  _DeviceLocationAppState createState() => new _DeviceLocationAppState();
}

class _DeviceLocationAppState extends State<DeviceLocationApp> {
  Location _locationService  = new Location();
  LocationData initialLocation;
  LocationData _currentLocation;

  StreamSubscription<LocationData> _locationSubscription;
  bool _permissionGranted = false;
  String error;


  @override
  void initState() {
    super.initState();
    initPlatformState();
  }

  // Platform messages are asynchronous, so method is declared as async
  initPlatformState() async {
    await _locationService.changeSettings(accuracy: LocationAccuracy.HIGH, interval: 1000);

    LocationData locationData;
    try {
      bool serviceEnabled = await _locationService.serviceEnabled();
      if (serviceEnabled) {
        _permissionGranted = await _locationService.requestPermission();
        if (_permissionGranted) {
          locationData = await _locationService.getLocation();
          enableLocationSubscription();
        }
      }
      else {
        bool serviceRequestGranted = await _locationService.requestService();
        if(serviceRequestGranted) {
          initPlatformState();
        }
      }
    }
    on PlatformException catch (e) {
      print(e);
      if (e.code == 'PERMISSION_DENIED') {
        error = e.message;
      }
      else if (e.code == 'SERVICE_STATUS_ERROR') {
        error = e.message;
      }
      locationData = null;
    }

    setState(() {
        initialLocation = locationData;
    });
  }

  enableLocationSubscription() async {
    _locationSubscription = _locationService.onLocationChanged().listen((LocationData result) async {
      if(mounted){
        setState(() {
          _currentLocation = result;
        });
      }
    });
  }


  slowRefresh() async {
    _locationSubscription.cancel();
    await _locationService.changeSettings(accuracy: LocationAccuracy.BALANCED, interval: 10000);
    enableLocationSubscription();
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> widgets = [];

    widgets.add(new Center(
        child: new Text(initialLocation != null
            ? 'Start location: ${initialLocation.latitude} & ${initialLocation.longitude}\n'
            : 'Error: $error\n')));

    widgets.add(new Center(
        child: new Text(_currentLocation != null
            ? 'Continuous location: \nlat: ${_currentLocation.latitude} & long: ${_currentLocation.longitude} \nalt: ${_currentLocation.altitude}m\n'
            : 'Error: $error\n', textAlign: TextAlign.center)));

    widgets.add(new Center(
      child: new Text(_permissionGranted ? 'Has permission : Yes' : "Has permission : No")));

    widgets.add(new Center(
      child: new RaisedButton(
        child: new Text("Slow refresh rate and accuracy"),
        onPressed: () => slowRefresh()
      )
    ));

    return MaterialApp(
      home: new Scaffold(
          appBar: new AppBar(
            title: new Text('Device Location example app'),
          ),
          body: new Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: widgets,
            ),
          ),
          floatingActionButton: new FloatingActionButton(
            onPressed: () => _locationSubscription.cancel(),
            tooltip: 'Stop Track Location',
            child: Icon(Icons.stop),
          ),
          floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
      )
    );
  }
}

Run instructions

Ensure a supported device is connected or emulator/simulator is started

Go to project directory

Use flutter run command to run

flutter run

It builds and runs app on an available android/ios device


Screenshot/image

Android

cl-flutter-device-location

iOS

cm-flutter-device-location-as1cm-flutter-device-location-as2