Files
tripz-llc/apps/driver/lib/features/home/data/driver_location_service.dart
T

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