import 'dart:math'; import 'package:geolocator/geolocator.dart'; import 'package:permission_handler/permission_handler.dart'; /// A dedicated service for handling all location-based functionalities. class LocationService { /// Checks for and requests location permissions, then fetches the current GPS position. /// This includes an offline-first approach by trying to get the last known position. Future getCurrentLocation() async { bool serviceEnabled; LocationPermission permission; // Check if location services are enabled on the device. serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) { return Future.error('Location services are disabled.'); } permission = await Geolocator.checkPermission(); if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); if (permission == LocationPermission.denied) { return Future.error('Location permissions are denied'); } } if (permission == LocationPermission.deniedForever) { return Future.error( 'Location permissions are permanently denied, we cannot request permissions.'); } // Attempt to get the last known position for a fast, offline-capable response. Position? position = await Geolocator.getLastKnownPosition(); // If no last known position, fetch the current position. position ??= await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.high); return position; } /// Calculates the distance in kilometers between two latitude/longitude pairs. double calculateDistance(double lat1, double lon1, double lat2, double lon2) { const earthRadius = 6371; // Radius of the Earth in km final dLat = _degreesToRadians(lat2 - lat1); final dLon = _degreesToRadians(lon2 - lon1); final a = sin(dLat / 2) * sin(dLat / 2) + cos(_degreesToRadians(lat1)) * cos(_degreesToRadians(lat2)) * sin(dLon / 2) * sin(dLon / 2); final c = 2 * atan2(sqrt(a), sqrt(1 - a)); return earthRadius * c; // Distance in km } double _degreesToRadians(double degree) { return degree * pi / 180; } /// A helper method to request location permissions explicitly if needed. Future requestPermissions() async { await [ Permission.locationWhenInUse, ].request(); } }