Overview
Trackmart’s tracking system provides real-time location monitoring for active deliveries. Using Mapbox for map visualization and Firebase Realtime Database for location updates, buyers can see exactly where their driver is and when to expect delivery.
Tracking Architecture
The tracking system uses a combination of technologies:
Mapbox Interactive map rendering with custom styling
Firebase Realtime DB Live location updates from drivers
Geolocator Device GPS for buyer location
Map Implementation
Basic Map Setup
The map is implemented using Flutter Map with Mapbox tiles:
FlutterMap (
options : new MapOptions (
center : _center ?? new LatLng (widget.dlat, widget.dlong),
zoom : 15.0 ,
),
mapController : _mapController,
layers : [
new TileLayerOptions (
urlTemplate : "https://api.tiles.mapbox.com/v4/"
"{id}/{z}/{x}/{y}@2x.png?access_token={accessToken}" ,
additionalOptions : {
'accessToken' : 'YOUR_MAPBOX_TOKEN' ,
'id' : 'mapbox.streets' ,
},
),
// Additional layers...
],
)
Replace 'YOUR_MAPBOX_TOKEN' with your actual Mapbox access token. Keep tokens secure and use environment variables in production.
Real-Time Location Updates
Driver locations are streamed from Firebase:
@override
void initState () {
FirebaseDatabase .instance
. reference ()
. child ( 'Drivers' )
. child (widget.driverId)
.onValue
. listen ((e) {
if (mounted) {
Map < String , dynamic > map = e.snapshot.value. cast < String , dynamic >();
_updateLocation ( Position (
longitude : map[ 'long' ]. toDouble (),
latitude : map[ 'lat' ]. toDouble ()));
}
});
super . initState ();
}
Location updates are received in real-time as drivers move. The onValue listener ensures the map always shows the current position.
Location Update Handler
_updateLocation ( Position position) {
setState (() {
dlat = position.latitude;
dlong = position.longitude;
});
var url =
'https://api.mapbox.com/directions/v5/mapbox/driving/ ${ dlong } , ${ dlat } ; ${ widget . ulong } , ${ widget . ulat } ?access_token=YOUR_TOKEN' ;
http. get (url). then ((response) {
route = json. decode (response.body)[ 'routes' ][ 0 ];
var k = PolylinePoints (). decodePolyline (route[ 'geometry' ]);
setState (() {
points = List . generate (k.length, (i) {
return LatLng (k[i].latitude, k[i].longitude);
});
distance = ' ${( route [ 'distance' ] / 1000 ). toStringAsFixed ( 2 )} km' ;
duration = ' ${( route [ 'duration' ] / 60 ). toStringAsFixed ( 0 )} min' ;
});
});
}
Route Visualization
The app draws a polyline showing the route from driver to buyer:
Fetch Route
Query Mapbox Directions API with driver and buyer coordinates
Decode Polyline
Convert encoded polyline geometry to LatLng points
Render on Map
Display the route as a colored polyline overlay
PolylineLayerOptions (polylines : [
new Polyline (
points : points,
strokeWidth : 5.0 ,
color : Theme . of (context).accentColor,
)
])
Map Markers
Two markers indicate buyer and driver locations:
Buyer Marker
Driver Marker
new Marker (
width : 60.0 ,
height : 60.0 ,
point : new LatLng (widget.ulat, widget.ulong),
builder : (ctx) => new Container (
child : GestureDetector (
child : Column (
mainAxisSize : MainAxisSize .min,
children : [
Text ( 'You' ,
style : TextStyle (backgroundColor : Colors .white)),
Icon (
Icons .person_pin_circle,
color : Theme . of (context).accentColor,
size : 30 ,
),
],
),
onTap : () {
print ( 'hi' );
}),
),
)
new Marker (
width : 60.0 ,
height : 60.0 ,
point : new LatLng (dlat, dlong),
builder : (ctx) => new Container (
child : GestureDetector (
child : Column (
mainAxisSize : MainAxisSize .min,
children : [
Text (widget.driver, maxLines : 1 ,
style : TextStyle (backgroundColor : Colors .white)),
Icon (
Icons .local_shipping,
color : Theme . of (context).accentColor,
size : 30 ,
),
],
),
),
),
)
Distance and ETA
The tracking view displays real-time distance and estimated time of arrival:
FlatButton . icon (
color : Colors .white,
onPressed : _eta,
icon : Icon (
Icons .access_time,
color : Theme . of (context).accentColor,
),
label : Text ( ' ${ distance ?? '' } ( ${ duration ?? '' } ' ),
)
ETA Calculation
void _eta () {
if (route != null )
showDialog (
context : context,
builder : (context) {
return SimpleDialog (
title : Text ( 'ETA' ),
contentPadding : EdgeInsets . all ( 12 ),
children : < Widget > [
Text (
' ${ DateFormat ( 'h:mm a' ). format ( DateTime . now (). add ( Duration ( seconds : route [ 'duration' ]. toInt ())))} ' ,
style : TextStyle (
color : Theme . of (context).accentColor,
fontWeight : FontWeight .bold,
fontSize : 24 ),
),
],
);
},
);
}
The ETA dialog shows the expected arrival time in 12-hour format (e.g., “2:45 PM”) by adding the route duration to the current time.
Finding Nearest Drivers
Buyers can view all available drivers on a map:
FirebaseDatabase .instance
. reference ()
. child ( 'Drivers' )
. orderByChild ( 'status' )
. equalTo ( true )
.onValue
. listen ((e) {
Map < String , dynamic > map = e.snapshot.value ? . cast < String , dynamic >();
if (map != null ) {
map. forEach ((key, values) {
var url =
'https://api.mapbox.com/directions/v5/mapbox/driving/ ${ values [ 'long' ]} , ${ values [ 'lat' ]} ; ${ widget . ulong } , ${ widget . ulat } ?access_token=YOUR_TOKEN' ;
http. get (url). then ((response) {
var route = json. decode (response.body)[ 'routes' ][ 0 ];
if (mounted) setState (() {
distances. add ( ' ${( route [ 'distance' ] / 1000 ). toStringAsFixed ( 2 )} km' );
durations. add ((route[ 'duration' ] / 60 ). toInt ());
// Add driver to map...
});
});
});
}
});
Driver Cards Each driver marker shows name, distance, and ETA when tapped
Quick Selection Tap a driver marker to view details and confirm selection
Map Controls
The tracking interface includes navigation controls:
IconButton (
iconSize : 40 ,
icon : Icon ( Icons .my_location,
color : Theme . of (context).accentColor),
onPressed : () {
_mapController. move (
LatLng (widget.ulat, widget.ulong), _mapController.zoom);
}),
Buyer Location Tracking
The app also tracks the buyer’s location:
_updateLocation ( Position position) {
if (mounted)
setState (() {
currentLat = position.latitude;
currentLong = position.longitude;
});
databaseReference
. child ( 'buyers' )
. child (currentUserId)
. update ({
'lat' : position.latitude,
'long' : position.longitude,
})
. then ((v) {})
. catchError ((e) {
print (e. toString ());
});
}
Buyer location updates are pushed to Firebase so drivers can see the delivery destination in real-time.
Location Filtering
Uses distanceFilter: 10 to only update when position changes by 10+ meters
Mounted Checks
Always checks if (mounted) before calling setState() to prevent memory leaks
Stream Disposal
Properly cancels position subscriptions in dispose() method
Next Steps
Delivery Management Learn about delivery workflows and status updates
In-App Messaging Chat with drivers during delivery