72 lines
2.4 KiB
Dart
72 lines
2.4 KiB
Dart
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<Position> 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<void> requestPermissions() async {
|
|
await [
|
|
Permission.locationWhenInUse,
|
|
].request();
|
|
}
|
|
}
|