103 lines
2.8 KiB
Dart
103 lines
2.8 KiB
Dart
import 'package:geolocator/geolocator.dart';
|
|
import 'dart:math';
|
|
|
|
class LocationService {
|
|
static final LocationService _instance = LocationService._internal();
|
|
|
|
factory LocationService() => _instance;
|
|
LocationService._internal();
|
|
|
|
// Request location permission
|
|
Future<bool> requestLocationPermission() async {
|
|
final permission = await Geolocator.checkPermission();
|
|
|
|
if (permission == LocationPermission.denied) {
|
|
final result = await Geolocator.requestPermission();
|
|
return result == LocationPermission.whileInUse ||
|
|
result == LocationPermission.always;
|
|
} else if (permission == LocationPermission.deniedForever) {
|
|
// Permission permanently denied, open app settings
|
|
await Geolocator.openLocationSettings();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Get current location (tries multiple strategies before giving up)
|
|
Future<Position?> getCurrentLocation() async {
|
|
try {
|
|
final hasPermission = await requestLocationPermission();
|
|
if (!hasPermission) return null;
|
|
|
|
Position? position;
|
|
|
|
try {
|
|
position = await Geolocator.getCurrentPosition(
|
|
desiredAccuracy: LocationAccuracy.high,
|
|
timeLimit: const Duration(seconds: 12),
|
|
);
|
|
} catch (_) {
|
|
try {
|
|
position = await Geolocator.getCurrentPosition(
|
|
desiredAccuracy: LocationAccuracy.medium,
|
|
timeLimit: const Duration(seconds: 10),
|
|
);
|
|
} catch (_) {}
|
|
}
|
|
|
|
position ??= await Geolocator.getLastKnownPosition();
|
|
|
|
if (position == null) {
|
|
try {
|
|
final stream = Geolocator.getPositionStream(
|
|
locationSettings: const LocationSettings(
|
|
accuracy: LocationAccuracy.medium,
|
|
distanceFilter: 10,
|
|
),
|
|
);
|
|
position = await stream.first.timeout(const Duration(seconds: 8));
|
|
} catch (_) {}
|
|
}
|
|
|
|
return position;
|
|
} catch (_) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Calculate distance between two coordinates (in km)
|
|
static double calculateDistance(
|
|
double lat1,
|
|
double lon1,
|
|
double lat2,
|
|
double lon2,
|
|
) {
|
|
const earthRadius = 6371; // 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));
|
|
final distance = earthRadius * c;
|
|
|
|
return distance;
|
|
}
|
|
|
|
static double _degreesToRadians(double degrees) {
|
|
return degrees * pi / 180;
|
|
}
|
|
|
|
// Check if location services are enabled
|
|
Future<bool> isLocationServiceEnabled() async {
|
|
return await Geolocator.isLocationServiceEnabled();
|
|
}
|
|
}
|