Sei sulla pagina 1di 19

28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

Implement Real-time Location Updates


on Google Maps in your Flutter Apps
Roman Jaquez Follow
Dec 6 · 9 min read

Move your Google Map pins Uber-style!

https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 1/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 2/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

or those of you who want to develop the next generation of location-based

F
apps, such as the next ride-hailing application, building it with Flutter
couldn’t be easier, thanks to the help of available Flutter packages that
facilitate its execution such as the Flutter Location Plugin that wraps
the complexities of location handling from your device and exposes its
capabilities in a simple to use API.

Let’s proceed!

Note: This post assumes you already have the maps set up in your project using
the Google Maps Flutter Package, as well as have your own Google Maps API
key. If not, follow this link on how to set up your Flutter project to work with
Google Maps. Other dependencies include the Flutter Polyline Points package
as well as the Flutter Location Plugin mentioned above. Github project for this
tutorial here.

Initial Setup
Make sure you prep your environment accordingly in order to enable
location tracking on both IOS and Android by following the steps in the
package’s README regarding the Android manifest file and the iOS
Info.plist.
https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 3/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

Once setup, make sure your dependencies are correctly stated on your
pubspec.yaml.

...
dependencies:
flutter:
sdk: flutter
google_maps_flutter: ^0.5.11+1
location: ^2.3.5
flutter_polyline_points: ^0.1.0
...

Note: As of this writing, the versions of the packages above were the ones
available — please update accordingly.

Setting up the Map in a Stateful Widget


I defined a StatefulWidget called MapPage with its corresponding State
class, where I imported the required packages, as well as some upfront
constants I’ll be using throughout my widget, such as the camera related
configurations (I wanted to give my map a tilted look and a specific zoom)
plus some hardcoded source and destination location (for the sake of this
tutorial).

https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 4/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

import
‘package:flutter_polyline_points/flutter_polyline_points.dart’;
import ‘package:google_maps_flutter/google_maps_flutter.dart’;
import ‘package:location/location.dart’;
import ‘package:flutter/material.dart’;
import ‘dart:async’;

const double CAMERA_ZOOM = 16;


const double CAMERA_TILT = 80;
const double CAMERA_BEARING = 30;
const LatLng SOURCE_LOCATION = LatLng(42.747932,-71.167889);
const LatLng DEST_LOCATION = LatLng(37.335685,-122.0605916);

class MapPage extends StatefulWidget {


@override
State<StatefulWidget> createState() => MapPageState();
}

class MapPageState extends State<MapPage> {

... (rest of the code will live here) ...

I also need references to my GoogleMapController, as well as a collection


of markers that I’ll be updating frequently. I’ll also be showing some custom
pin icons / markers as well as polylines to draw the route on my map
between source and destination, and of course I’ll be needing my Google
Maps API key.
https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 5/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

But the most important properties to pay attention to are the Location and
LocationData properties below. The Location’s location property will hold
a reference to the location information in a very encapsulated way, by
providing a set of APIs to retrieve the user’s current location as well as
hooks to obtain notifications to real-time changes in their location. The
LocationData’s currentLocation is how the Location reference exposes the
user’s location information, providing properties such as the lat, long,
speed, accuracy, altitude, etc. I’ll also hold on to the destination location in a
reference of type LocationData for consistency.

...(rest of the code omitted for brevity) ...

Completer<GoogleMapController> _controller = Completer();


Set<Marker> _markers = Set<Marker>();

// for my drawn routes on the map


Set<Polyline> _polylines = Set<Polyline>();
List<LatLng> polylineCoordinates = [];
PolylinePoints polylinePoints;

String googleAPIKey = “<YOUR_API_KEY>”;

// for my custom marker pins


BitmapDescriptor sourceIcon;
BitmapDescriptor destinationIcon;

https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 6/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

// the user's initial location and current location


// as it moves
LocationData currentLocation;

// a reference to the destination location


LocationData destinationLocation;

// wrapper around the location API


Location location;

Let’s proceed to handle the initial state of this widget and set some listeners.

In the code below, I’m overriding the initState() as commonly done in a


StatefulWidget, where I create an instance of Location so I can get the
user’s location (setInitialLocation)and listen for updates on location
changes (onLocationChanged). I also set upfront what my custom marker
pins will look like for later use (setSourceAndDestinationIcons). Notice
how by subscribing to the location’s onLocationChanged event I receive
the current user’s position (the cLoc parameter of type LocationData) ,
from which I can later on extract the lat and long position and use it to move
the pin across the map as the user moves in almost real time. We’ll look at
the updatePinOnMap method further down below.

https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 7/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

... (rest of the code omitted for brevity) ...

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

// create an instance of Location


location = new Location();
polylinePoints = PolylinePoints();

// subscribe to changes in the user's location


// by "listening" to the location's onLocationChanged event
location.onLocationChanged().listen((LocationData cLoc) {
// cLoc contains the lat and long of the
// current user's position in real time,
// so we're holding on to it
currentLocation = cLoc;
updatePinOnMap();
});

// set custom marker pins


setSourceAndDestinationIcons();

// set the initial location


setInitialLocation();
}

void setSourceAndDestinationIcons() async {


sourceIcon = await BitmapDescriptor.fromAssetImage(
ImageConfiguration(devicePixelRatio: 2.5),
'assets/driving_pin.png');

destinationIcon = await BitmapDescriptor.fromAssetImage(


ImageConfiguration(devicePixelRatio: 2.5),
'assets/destination_map_marker.png');
}
https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 8/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

void setInitialLocation() async {

// set the initial location by pulling the user's


// current location from the location's getLocation()
currentLocation = await location.getLocation();

// hard-coded destination for this example


destinationLocation = LocationData.fromMap({
"latitude": DEST_LOCATION.latitude,
"longitude": DEST_LOCATION.longitude
});
}

The onLocationChanged event fires as many times as the location receives


a position change, and you can change the defaults by calling the location’s
changeSettings method and changing values such as the accuracy (how
accurate the location tracking measurement is; high by default), interval
(how frequent the location is updated, 1 sec. by default, or in milliseconds
,1000) and distantFilter (in meters, by default 0, which ensures the
location is being updated only if there’s a change in location within the
meters value specified).

Now, let’s proceed to build our widget.

Inserting the Map in our Widget

https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 9/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

Let’s override the build method, where the Google Map will be displayed
full screen on our widget. I wrap my Google Map inside a Stack as the body
of a Scaffold so as not to limit myself and to overlay things on top of my
map (more on that later).

... (rest of the code omitted for brevity) ...

@override
Widget build(BuildContext context) {

CameraPosition initialCameraPosition = CameraPosition(


zoom: CAMERA_ZOOM,
tilt: CAMERA_TILT,
bearing: CAMERA_BEARING,
target: SOURCE_LOCATION
);

if (currentLocation != null) {
initialCameraPosition = CameraPosition(
target: LatLng(currentLocation.latitude,
currentLocation.longitude),
zoom: CAMERA_ZOOM,
tilt: CAMERA_TILT,
bearing: CAMERA_BEARING
);
}

return Scaffold(
body: Stack(
children: <Widget>[
GoogleMap(
https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 10/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

myLocationEnabled: true,
compassEnabled: true,
tiltGesturesEnabled: false,
markers: _markers,
polylines: _polylines,
mapType: MapType.normal,
initialCameraPosition: initialCameraPosition,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);

// my map has completed being created;


// i'm ready to show the pins on the map
showPinsOnMap();
})
],
),
);
}

...

Notice how I set up the initial camera position based on the current user’s
initial location if it’s available at the time the widget builds the Map
(initialCameraPosition), otherwise I have a default start location to go
with just in case. The piece of code to pay attention here is the
onMapCreated event, which I handle by obtaining the reference to the
Google Map’s controller, and since the map is ready to be manipulated
when this gets called, I proceed to show my pins on the map
(showPinsOnMap).
https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 11/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

In the showPinsOnMap, all I’m doing is setting my markers to their initial


positions as well as laying down the route lines on the map — more like
prepping the stage for the main act: moving the marker along with the user
upon the location changing.

void showPinsOnMap() {

// get a LatLng for the source location


// from the LocationData currentLocation object
var pinPosition = LatLng(currentLocation.latitude,
currentLocation.longitude);

// get a LatLng out of the LocationData object


var destPosition = LatLng(destinationLocation.latitude,
destinationLocation.longitude);

// add the initial source location pin


_markers.add(Marker(
markerId: MarkerId('sourcePin'),
position: pinPosition,
icon: sourceIcon
));

// destination pin
_markers.add(Marker(
markerId: MarkerId('destPin'),
position: destPosition,
icon: destinationIcon
));

https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 12/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

// set the route lines on the map from source to destination


// for more info follow this tutorial
setPolylines();
}

...

For drawing my polylines / routes on the map, I’m using both LocationData
references (currentLocation and destinationLocation) to get the complete
route between those two points (follow this tutorial for more reference).

... (rest of the code omitted for brevity)...

void setPolylines() async {

List<PointLatLng> result = await


polylinePoints.getRouteBetweenCoordinates(
googleAPIKey,
currentLocation.latitude,
currentLocation.longitude,
destinationLocation.latitude,
destinationLocation.longitude);

if(result.isNotEmpty){
result.forEach((PointLatLng point){
polylineCoordinates.add(
LatLng(point.latitude,point.longitude)
);
});

https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 13/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

setState(() {
_polylines.add(Polyline(
width: 5, // set the width of the polylines
polylineId: PolylineId(“poly”),
color: Color.fromARGB(255, 40, 122, 198),
points: polylineCoordinates
));
});
}
}

Moving the Google Map Marker Upon Location Changing


Every movement the user makes within the boundaries specified within a
period of time (based on accuracy, interval and distantFilter) will be
captured by the device, and a notification will be triggered, exposed by the
onLocationChanged event from the Location reference above.

If you recall, we wire up a handler to the onLocationChanged().listen()


event, which yields a LocationData object every time there’s a change (this
event gets triggered multiple times), containing the last recorded user’s
location information. We hold on to it in the currentLocation property, and
proceed to call the method updatePinOnMap.

...(rest of the code omitted for brevity)...

https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 14/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

void updatePinOnMap() async {

// create a new CameraPosition instance


// every time the location changes, so the camera
// follows the pin as it moves with an animation

CameraPosition cPosition = CameraPosition(


zoom: CAMERA_ZOOM,
tilt: CAMERA_TILT,
bearing: CAMERA_BEARING,
target: LatLng(currentLocation.latitude,
currentLocation.longitude),
);

final GoogleMapController controller = await _controller.future;


controller.animateCamera(CameraUpdate.newCameraPosition(cPosition));

// do this inside the setState() so Flutter gets notified


// that a widget update is due
setState(() {

// updated position
var pinPosition = LatLng(currentLocation.latitude,
currentLocation.longitude);

// the trick is to remove the marker (by id)


// and add it again at the updated location
_markers.removeWhere(
(m) => m.markerId.toString() == ‘sourcePin’);

_markers.add(Marker(
markerId: MarkerId(‘sourcePin’),
position: pinPosition, // updated position
icon: sourceIcon
));

https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 15/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

});
}

Let’s dissect it for a bit: the first thing we do upon executing the
updatePinOnMap method is create a new CameraLocation object using
the updated user’s location (currentLocation)and animating the camera so
it moves along with the marker pin. If we don’t do this, we will see the pin
just move out of view and we end up staring at a blank map.

Now, the whole trick to simulate the movement of the ping upon the
location changing is removing the existing marker and adding it again
using the updated coordinates. We remove it by finding it within our list of
markers by id (sourcePin) so we don’t remove the destination pin or other
pins we may decide to place on our map, then spawning a new one using
the updated location coordinates and re-adding it to our markers’
collection. We do all this within the setState() method to notify Flutter that
a widget rebuild is due.

Performance Considerations: We mentioned earlier the ways you can tweak


how frequently you track your user’s location if performance is something you
are concerned about. It will be based on your application’s needs and whether

https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 16/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

you want to compromise accuracy for performance (as long as you don’t drain
your user’s battery in the process!

Other things to consider: Make sure to always implement requesting location


permission explicitly from the user and implementing a smooth fallback
mechanism for when the user declines sharing their location. This plugin tries
to handle most cases for you, but it is always a good practice to implement it.

Bonus: Add Custom Window Upon Tapping on a Moving Marker


I implemented parts of another tutorial I wrote about adding a custom info
window to a Google Map’s marker pin to this implementation, and it came
out great! As the pin moved, I was able to invoke the custom info window
and see the lat and long change in real time as I moved. I encourage you to
use it as well if the need arises.

https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 17/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

And that’s it! This is a very basic implementation of a location-based


application that handles user’s location changes in real-time. A follow-up
tutorial would be one where we reflect the user’s location updates on
another device using a real-time backend such as Firebase and keep both in
sync , so stay tuned!
https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 18/19
28/12/2019 Implement Real-time Location Updates on Google Maps in your Flutter Apps

Here’s the link to the Github Project for this tutorial for your reference.

Hope you have found this tutorial useful for your own projects.
Happy Fluttering!
)

Flutter Flutter Wi Flutter Ui Google Maps

Discover Medium Make Medium yours Become a member


Welcome to a place where words matter. Follow all the topics you care about, and Get unlimited access to the best stories
On Medium, smart voices and original we’ll deliver the best stories for you to on Medium — and support writers while
ideas take center stage - with no ads in your homepage and inbox. Explore you’re at it. Just $5/month. Upgrade
sight. Watch

About Help Legal

https://medium.com/@romanejaquez/implement-real-time-location-updates-on-google-maps-in-flutter-235c8a09173e 19/19

Potrebbero piacerti anche