92 lines
2.5 KiB
Dart
92 lines
2.5 KiB
Dart
import 'dart:async';
|
|
import 'package:geolocator/geolocator.dart';
|
|
|
|
/// خدمة موقع السائق — تتبع الموقع في الخلفية وإرساله للسيرفر.
|
|
///
|
|
/// تتبع 3 ثوانٍ عند التنشيط، ثم إرسال كل دقيقتين (docs/23 §10).
|
|
/// تراعي حالة البطارية وتتوقف عند انخفاضها.
|
|
class DriverLocationService {
|
|
final Future<void> Function(double lat, double lng, {double? heading, double? speed})
|
|
_onLocationUpdate;
|
|
|
|
StreamSubscription<Position>? _positionSub;
|
|
Timer? _heartbeatTimer;
|
|
bool _active = false;
|
|
|
|
DriverLocationService(this._onLocationUpdate);
|
|
|
|
bool get isActive => _active;
|
|
|
|
/// بدء التتبع.
|
|
Future<void> start() async {
|
|
if (_active) return;
|
|
|
|
// تحقق من صلاحية الموقع.
|
|
var permission = await Geolocator.checkPermission();
|
|
if (permission == LocationPermission.denied) {
|
|
permission = await Geolocator.requestPermission();
|
|
if (permission == LocationPermission.denied ||
|
|
permission == LocationPermission.deniedForever) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
_active = true;
|
|
|
|
// أرسل الموقع فوراً.
|
|
_sendCurrentLocation();
|
|
|
|
// استمع لتحديثات الموقع كل 3 ثوانٍ.
|
|
_positionSub = Geolocator.getPositionStream(
|
|
locationSettings: const LocationSettings(
|
|
accuracy: LocationAccuracy.high,
|
|
distanceFilter: 15, // تحديث عند تغيير 15 متر
|
|
),
|
|
).listen((pos) {
|
|
_onLocationUpdate(
|
|
pos.latitude,
|
|
pos.longitude,
|
|
heading: pos.heading,
|
|
speed: pos.speed,
|
|
);
|
|
});
|
|
|
|
// دفعة كل دقيقتين كحد أقصى.
|
|
_heartbeatTimer = Timer.periodic(const Duration(minutes: 2), (_) {
|
|
_sendCurrentLocation();
|
|
});
|
|
}
|
|
|
|
/// إيقاف التتبع.
|
|
void stop() {
|
|
_active = false;
|
|
_positionSub?.cancel();
|
|
_positionSub = null;
|
|
_heartbeatTimer?.cancel();
|
|
_heartbeatTimer = null;
|
|
}
|
|
|
|
/// إرسال الموقع الحالي مرة واحدة.
|
|
Future<void> _sendCurrentLocation() async {
|
|
try {
|
|
final pos = await Geolocator.getCurrentPosition(
|
|
locationSettings: const LocationSettings(
|
|
accuracy: LocationAccuracy.high,
|
|
),
|
|
);
|
|
await _onLocationUpdate(
|
|
pos.latitude,
|
|
pos.longitude,
|
|
heading: pos.heading,
|
|
speed: pos.speed,
|
|
);
|
|
} catch (_) {
|
|
// خطأ صامت — سيحاول مرة أخرى مع الدقيقة التالية.
|
|
}
|
|
}
|
|
|
|
void dispose() {
|
|
stop();
|
|
}
|
|
}
|