import 'dart:async'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:geolocator/geolocator.dart'; import 'package:permission_handler/permission_handler.dart'; final locationServiceProvider = Provider((ref) { return LocationService(); }); final locationStreamProvider = StreamProvider((ref) { final service = ref.watch(locationServiceProvider); return service.getFilteredPositionStream(); }); class LocationService { Position? _lastValidPosition; // Filtering thresholds static const double _maxAcceptableAccuracy = 20.0; // meters static const double _maxRealisticSpeed = 100.0; // roughly 223 MPH in m/s static const double _maxAcceleration = 20.0; // m/s^2 (unrealistic jump) Future requestPermissions() async { final status = await Permission.locationWhenInUse.request(); if (status.isGranted) { // Optional: request background if needed later return true; } return false; } Stream getFilteredPositionStream() { final LocationSettings locationSettings = AndroidSettings( accuracy: LocationAccuracy.bestForNavigation, distanceFilter: 0, intervalDuration: const Duration(milliseconds: 200), // 5Hz updates // (Optional) foregroundNotificationConfig if we implement background tracking ); return Geolocator.getPositionStream(locationSettings: locationSettings) .where(_isValidPosition); } bool _isValidPosition(Position position) { if (position.accuracy > _maxAcceptableAccuracy) { return false; // Reject extremely poor accuracy } if (position.speed > _maxRealisticSpeed) { return false; // Reject impossible speeds } if (_lastValidPosition != null) { // Avoid division by zero and ensure positive time diff final timeDiff = (position.timestamp.difference(_lastValidPosition!.timestamp)).inMilliseconds / 1000.0; if (timeDiff > 0) { final accel = (position.speed - _lastValidPosition!.speed).abs() / timeDiff; if (accel > _maxAcceleration) { return false; // Reject impossible acceleration spikes } } } _lastValidPosition = position; return true; } }