environment_monitoring_app/lib/services/location_service.dart
2025-08-04 15:11:24 +08:00

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();
}
}