Flutter Location Tracker - Track Current Location

Last updated Sep 01, 2021

In this Flutter Tutorial we will learn how to use Google Maps in Flutter and track location by retrive current location from the device using Flutter Location package and display it on Google Maps using Marker Icon. This example track the liva location of the user and display on device on every 1 second. For this example we will use two packages Google Maps and Location packages. Check my previous example Integrate Google Maps in Flutter

What we will cover

  • Load Google Maps
  • Disply Marker on Maps
  • Fetch Current Location
  • Track Location and Update on Maps

 

Let's get started

 

Download Source code

 

Step 1: Create Flutter application

Step 2: Add required packages in pubspec.yaml file and run flutter pub add

dev_dependencies:
flutter_test:
sdk: flutter
location: ^4.3.0
google_maps_flutter: ^2.0.6

 

 

Step 3:  Now lets open Android directory if you are going to be implementing for Android and if you are going to implement ios relevant iOS side and read package description how to setup native side. Here we will be implementing Android side in this tutorial

Now add required permissions in the manifest file

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

 

Add Maps Api in meta data

meta-data android:name="com.google.android.geo.API_KEY"
android:value=""/>

 

Refer my previous post about How to fetch Maps API key

 

Step 4: Load Google Maps

Let's add below code to load Google Maps

GoogleMap(
 
  initialCameraPosition: _kGooglePlex,
  onMapCreated: (GoogleMapController controller) {
    _controller.complete(controller);
  },
  
),

 

GoogleMap widget wil load different types of Maps, we will load this by handle the mapType property

enum MapType {
  /// Do not display map tiles.
  none,
/// Normal tiles (traffic and labels, subtle terrain information).
  normal,
 /// Satellite imaging tiles (aerial photos)
  satellite,
 /// Terrain tiles (indicates type and height of terrain)
  terrain,
 /// Hybrid tiles (satellite images with some labels/overlays)
  hybrid,
}

 

 

Add Markers to Google Maps?

To create marker object we need to create MarkerId to handle the markers

MarkerId markerId1=MarkerId("Current");
Marker marker1=Marker(
    markerId: markerId1,
    position: LatLng(17.385044, 78.486671),
    icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed),
    infoWindow: InfoWindow(
        title: "Hytech City",onTap: (){


    },snippet: "Snipet Hitech City"
    ));

 

here is the code to add Markers to Map

GoogleMap(
  mapType: MapType.normal,
  initialCameraPosition: _kGooglePlex,
  onMapCreated: (GoogleMapController controller) {
    _controller.complete(controller);
  },
  markers: Set.of(markers.values),
)

 

 

 

Step 5: Fetch Current Location

Now we are able to load Google Maps on device. Now we need to fetch the current location of the device. To fetch current location we need to take location permissions and check the Enable Location services in the device.

Check the Location services enabled by

initPlatformState() async {
  await _locationService.changeSettings(accuracy: LocationAccuracy.high, interval: 1000);

  LocationData? locationData;
  try {
    bool serviceEnabled = await _locationService.serviceEnabled();
    if (serviceEnabled) {
      PermissionStatus p;

      _permissionGranted = (await _locationService.requestPermission());
      if (_permissionGranted!.index==0) {
        locationData = await _locationService.getLocation();
       
      }
    }
    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!;
    }
  
  }


}

 

After that now we need to check location updates by using the below code

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

      });
    }
  });
}

 

Step 6: Now run application and you can see the location updates of the device. To track location in background mode we need to enable enableBackgroundMode({bool enable}) API service and add required permissions in manifest file

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

 

 

Flutter Location Tracker

 

Complete code

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:location/location.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';


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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Google Maps Demo',
      home: MapSample(),
    );
  }
}

class MapSample extends StatefulWidget {
  @override
  State createState() => MapSampleState();
}

class MapSampleState extends State {
  Completer _controller = Completer();

  static final CameraPosition _kGooglePlex = CameraPosition(
    target: LatLng(17.385044, 78.486671),
    zoom: 18,
  );



  Map markers = {};
  late MarkerId markerId1;
  late Marker marker1;
  Location _locationService  = new Location();
  LocationData? initialLocation;
  LocationData? _currentLocation;
  late MapType maptype;
  bool updateStarted=false;

  late StreamSubscription _locationSubscription;
  PermissionStatus? _permissionGranted ;
  String error="";
  @override
  void initState() {

    super.initState();
    maptype=MapType.normal;
     markerId1=MarkerId("Current");
     marker1=Marker(
        markerId: markerId1,
        position: LatLng(17.385044, 78.486671),
        icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen),
        infoWindow: InfoWindow(
            title: "Hytech City",onTap: (){


        },snippet: "Snipet Hitech City"
        ));
    markers[markerId1]=marker1;
  }
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: AppBar(elevation:0,
        backgroundColor: Colors.teal,title: Text("Flutter Track Location",
          style: TextStyle(color: Colors.white),),
        actions: [
          PopupMenuButton(
            itemBuilder: (builder){
            return  >[
              PopupMenuItem(
                value: 0,
                child: Text('Hybrid'),
              ),
              PopupMenuItem(
                value: 1,
                child: Text('Normal'),
              ), PopupMenuItem(
                value: 2,
                child: Text('Satellite'),
              ),PopupMenuItem(
                value: 3,
                child: Text('Terrain'),
              ),
            ];
          },onSelected: (value){
              switch(value)
              {
                case 0:
                  setState(() {
                    maptype=MapType.hybrid;
                  });
                  break;
                case 1:
                  setState(() {
                    maptype=MapType.normal;
                  });
                  break;
                case 2:
                  setState(() {
                    maptype=MapType.satellite;
                  });
                  break;
                case 3:
                  setState(() {
                    maptype=MapType.terrain;
                  });
                  break;
              }

          },)
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.only(top:8.0),
        child: Stack(
         children: [
           GoogleMap(
             mapType: maptype,
             initialCameraPosition: _kGooglePlex,
             onMapCreated: (GoogleMapController controller) {
               _controller.complete(controller);
             },
             markers: Set.of(markers.values),
           ),
           Align(alignment: Alignment.topCenter,
               child: Container(
              color: Colors.white60,
                 child: new Text(_currentLocation != null
                 ? 'Current location: \nlat: ${_currentLocation!.latitude}\n  long: ${_currentLocation!.longitude} '
                 : 'Error: $error\n', textAlign: TextAlign.center,style: TextStyle(color: Colors.pink,fontSize: 20),),
               ))
         ],
        ),
      ),
      floatingActionButton: FloatingActionButton.extended(
        backgroundColor: !updateStarted?Colors.blue:Colors.red,
        onPressed: !updateStarted?_startTrack:_stopTrack,
        label: Text(!updateStarted?'Start Track!':'Stop Track'),
        icon: Icon(Icons.directions_boat,),
      ),
    );
  }

  initPlatformState() async {
    await _locationService.changeSettings(accuracy: LocationAccuracy.high, interval: 1000);

    LocationData? locationData;
    try {
      bool serviceEnabled = await _locationService.serviceEnabled();
      if (serviceEnabled) {
        PermissionStatus p;

        _permissionGranted = (await _locationService.requestPermission());
        if (_permissionGranted!.index==0) {
          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;

          markers.clear();
          MarkerId markerId1=MarkerId("Current");
          Marker marker1=Marker(
              markerId: markerId1,
              position: LatLng(17.385044, 78.486671),
              icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed),
              );
          markers[markerId1]=marker1;
          animateCamera(marker1);

        });
      }
    });
  }


  slowRefresh() async {
    if(_locationSubscription!=null)
      _locationSubscription.cancel();
    await _locationService.changeSettings(accuracy: LocationAccuracy.balanced, interval: 10000);
    enableLocationSubscription();
  }
  Future<void> _startTrack() async {
    initPlatformState();
    setState(() {
      updateStarted=true;
    });

  } Future<void> _stopTrack() async {
    if(_locationSubscription!=null)
      _locationSubscription.cancel();

    setState(() {
      updateStarted=false;
    });

  }
  animateCamera(marker1) async
  {
    final GoogleMapController controller = await _controller.future;
    controller.animateCamera(CameraUpdate.newCameraPosition(marker1));
  }
}

 

Conclusion: In this tutorial we learned how to load Google Maps and fetch current location and track current location of the user device and update it on Google Maps with Marker.

 

More Flutter Google Maps Examples
 

Show Multiple Markers on Maps Flutter

How to fetch current location Address

How do i share current location address with flutter

 

Article Contributed By :
https://www.rrtutors.com/site_assets/profile/assets/img/avataaars.svg

3437 Views