first commit
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import '../models/gps_coordinate.dart';
|
||||
|
||||
/// خدمة GPS الحقيقي مع دعم التتبع المستمر
|
||||
class GpsService extends GetxService {
|
||||
StreamSubscription<Position>? _positionSub;
|
||||
final _isTracking = false.obs;
|
||||
final _currentPosition = Rxn<Position>();
|
||||
final _lastError = ''.obs;
|
||||
|
||||
bool get isTracking => _isTracking.value;
|
||||
Position? get currentPosition => _currentPosition.value;
|
||||
String get lastError => _lastError.value;
|
||||
|
||||
Function(GpsCoordinate)? onNewCoordinate;
|
||||
|
||||
Future<bool> checkAndRequestPermissions() async {
|
||||
if (!await Geolocator.isLocationServiceEnabled()) {
|
||||
_lastError.value = 'Location services disabled';
|
||||
return false;
|
||||
}
|
||||
var perm = await Geolocator.checkPermission();
|
||||
if (perm == LocationPermission.denied) {
|
||||
perm = await Geolocator.requestPermission();
|
||||
if (perm == LocationPermission.denied) {
|
||||
_lastError.value = 'Permission denied';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (perm == LocationPermission.deniedForever) {
|
||||
_lastError.value = 'Permission permanently denied';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<GpsCoordinate?> getCurrentPosition() async {
|
||||
try {
|
||||
if (!await checkAndRequestPermissions()) return null;
|
||||
final pos = await Geolocator.getCurrentPosition(
|
||||
desiredAccuracy: LocationAccuracy.high,
|
||||
timeLimit: const Duration(seconds: 15),
|
||||
);
|
||||
_currentPosition.value = pos;
|
||||
return _toCoord(pos);
|
||||
} catch (e) {
|
||||
_lastError.value = e.toString();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> startTracking({int distanceFilter = 5}) async {
|
||||
if (_isTracking.value) return true;
|
||||
if (!await checkAndRequestPermissions()) return false;
|
||||
|
||||
try {
|
||||
late LocationSettings settings;
|
||||
if (defaultTargetPlatform == TargetPlatform.android) {
|
||||
settings = AndroidSettings(
|
||||
accuracy: LocationAccuracy.high,
|
||||
distanceFilter: distanceFilter,
|
||||
intervalDuration: const Duration(seconds: 3),
|
||||
foregroundNotificationConfig: const ForegroundNotificationConfig(
|
||||
notificationText: 'SportPath is tracking your workout',
|
||||
notificationTitle: 'Workout Active',
|
||||
enableWakeLock: true,
|
||||
),
|
||||
);
|
||||
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
|
||||
settings = AppleSettings(
|
||||
accuracy: LocationAccuracy.high,
|
||||
distanceFilter: distanceFilter,
|
||||
activityType: ActivityType.fitness,
|
||||
pauseLocationUpdatesAutomatically: false,
|
||||
showBackgroundLocationIndicator: true,
|
||||
);
|
||||
} else {
|
||||
settings = LocationSettings(
|
||||
accuracy: LocationAccuracy.high,
|
||||
distanceFilter: distanceFilter,
|
||||
);
|
||||
}
|
||||
|
||||
_positionSub = Geolocator.getPositionStream(
|
||||
locationSettings: settings,
|
||||
).listen(_onPosition, onError: (e) {
|
||||
_lastError.value = e.toString();
|
||||
});
|
||||
|
||||
_isTracking.value = true;
|
||||
return true;
|
||||
} catch (e) {
|
||||
_lastError.value = e.toString();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stopTracking() async {
|
||||
await _positionSub?.cancel();
|
||||
_positionSub = null;
|
||||
_isTracking.value = false;
|
||||
}
|
||||
|
||||
void _onPosition(Position pos) {
|
||||
_currentPosition.value = pos;
|
||||
final coord = _toCoord(pos);
|
||||
if (coord.isAccurate && coord.isValid) {
|
||||
onNewCoordinate?.call(coord);
|
||||
}
|
||||
}
|
||||
|
||||
GpsCoordinate _toCoord(Position p) => GpsCoordinate(
|
||||
latitude: p.latitude,
|
||||
longitude: p.longitude,
|
||||
altitude: p.altitude,
|
||||
accuracy: p.accuracy,
|
||||
speed: p.speed >= 0 ? p.speed : null,
|
||||
heading: p.heading >= 0 ? p.heading : null,
|
||||
timestamp: p.timestamp,
|
||||
);
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
stopTracking();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user