Overview
The location sharing feature allows passengers and drivers to share their real-time location during active trips. This enables:
- Passengers to see driver’s approaching location
- Drivers to navigate to passenger pickup location
- Real-time trip tracking for safety
Location Sharing URL
The location sharing module is available at:
{baseUrl}/location_sharing
Configuration:
class AppConfig {
static String get locationSharingUrl => '$baseUrl/location_sharing';
static String buildShareUrl(String token) =>
'${websiteUrl.trimRight()}/share/$token';
static String buildDeepLink(String token) => 'viax://share/$token';
}
Generate Sharing Token
The exact endpoint for generating location sharing tokens depends on your backend implementation. Typically, this would be part of the trip creation or assignment process.
Sharing Token Structure
class LocationShareToken {
final String token; // Unique share token
final int tripId; // Associated trip ID
final DateTime expiresAt; // Token expiration
final String shareUrl; // Full sharing URL
final String deepLink; // Deep link for app
LocationShareToken({
required this.token,
required this.tripId,
required this.expiresAt,
}) : shareUrl = AppConfig.buildShareUrl(token),
deepLink = AppConfig.buildDeepLink(token);
}
Update Driver Location
POST /conductor/update_location.php
Update the driver’s real-time location during an active trip.
Request Body
Request Example
Future<void> updateDriverLocation(
int conductorId,
double lat,
double lng,
) async {
await http.post(
Uri.parse('https://76.13.114.194/conductor/update_location.php'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'conductor_id': conductorId,
'latitud': lat,
'longitud': lng,
}),
);
}
// Usage with location tracking:
StreamSubscription<Position>? _locationSubscription;
void startLocationTracking(int conductorId) {
_locationSubscription = Geolocator.getPositionStream(
locationSettings: LocationSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 10, // Update every 10 meters
),
).listen((position) {
updateDriverLocation(
conductorId,
position.latitude,
position.longitude,
);
});
}
void stopLocationTracking() {
_locationSubscription?.cancel();
}
Location Tracking Best Practices
Update Frequency
Don’t update location too frequently to avoid:
- Excessive battery drain
- High network usage
- Server overload
Recommended settings:
- Distance filter: 10-20 meters
- Time interval: 5-10 seconds
- Accuracy: High (for active trips)
const LocationSettings optimalSettings = LocationSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 15, // meters
timeLimit: Duration(seconds: 5),
);
Battery Optimization
class AdaptiveLocationTracker {
LocationSettings getSettings(TripStatus status) {
switch (status) {
case TripStatus.enCurso:
// High accuracy during active trip
return LocationSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 10,
);
case TripStatus.aceptado:
case TripStatus.enRuta:
// Medium accuracy when approaching
return LocationSettings(
accuracy: LocationAccuracy.medium,
distanceFilter: 20,
);
default:
// Low accuracy when idle
return LocationSettings(
accuracy: LocationAccuracy.low,
distanceFilter: 100,
);
}
}
}
Real-Time Location Display
Passenger View (Track Driver)
class DriverTrackingMap extends StatefulWidget {
final int tripId;
@override
_DriverTrackingMapState createState() => _DriverTrackingMapState();
}
class _DriverTrackingMapState extends State<DriverTrackingMap> {
GoogleMapController? _mapController;
Timer? _updateTimer;
LatLng? _driverLocation;
@override
void initState() {
super.initState();
_startTracking();
}
void _startTracking() {
_updateTimer = Timer.periodic(
Duration(seconds: 5),
(_) => _fetchDriverLocation(),
);
}
Future<void> _fetchDriverLocation() async {
// Fetch driver location from trip data
final trip = await getTripById(widget.tripId);
if (trip.conductorId != null) {
// Update map with driver location
setState(() {
_driverLocation = LatLng(
trip.driverLatitud ?? 0,
trip.driverLongitud ?? 0,
);
});
_mapController?.animateCamera(
CameraUpdate.newLatLng(_driverLocation!),
);
}
}
@override
void dispose() {
_updateTimer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GoogleMap(
onMapCreated: (controller) => _mapController = controller,
markers: {
if (_driverLocation != null)
Marker(
markerId: MarkerId('driver'),
position: _driverLocation!,
icon: BitmapDescriptor.defaultMarkerWithHue(
BitmapDescriptor.hueBlue,
),
),
},
// ... other map properties
);
}
}
Share Location Link
Generate a shareable link for real-time location tracking:
Future<String> generateShareLink(int tripId) async {
// Generate unique token for this trip
final token = generateSecureToken();
// Store token with trip association
await storeShareToken(token, tripId);
// Build public share URL
final shareUrl = AppConfig.buildShareUrl(token);
return shareUrl;
}
Future<void> shareLocationWithContact(String shareUrl) async {
await Share.share(
'Sigue mi viaje en tiempo real: $shareUrl',
subject: 'Compartir ubicación - Viax',
);
}
Privacy and Security
Privacy Considerations:
- Location data should only be shared during active trips
- Share tokens should expire after trip completion
- Implement rate limiting to prevent abuse
- Allow users to stop sharing at any time
Token Expiration
class ShareToken {
final String token;
final DateTime expiresAt;
bool get isExpired => DateTime.now().isAfter(expiresAt);
static ShareToken create(int tripId, {Duration validFor = const Duration(hours: 3)}) {
return ShareToken(
token: generateToken(),
expiresAt: DateTime.now().add(validFor),
);
}
}
WebSocket Integration (Future)
For real-time updates with lower latency, consider implementing WebSocket support:final channel = WebSocketChannel.connect(
Uri.parse('wss://76.13.114.194/ws/location/$tripId'),
);
channel.stream.listen((data) {
final location = jsonDecode(data);
updateDriverMarker(location);
});
Error Handling
Future<void> safeUpdateLocation(
int conductorId,
double lat,
double lng,
) async {
try {
await updateDriverLocation(conductorId, lat, lng);
} catch (e) {
// Log error but don't interrupt the app
print('Failed to update location: $e');
// Retry logic could be added here
}
}
See Also