tasq/lib/services/background_location_service.dart

76 lines
2.6 KiB
Dart

import 'package:flutter/foundation.dart';
import 'package:geolocator/geolocator.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:workmanager/workmanager.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
/// Unique task name for the background location update.
const _taskName = 'com.tasq.backgroundLocationUpdate';
/// Top-level callback required by Workmanager. Must be a top-level or static
/// function.
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
try {
// Re-initialize Supabase in the isolate
await dotenv.load();
final url = dotenv.env['SUPABASE_URL'] ?? '';
final anonKey = dotenv.env['SUPABASE_ANON_KEY'] ?? '';
if (url.isEmpty || anonKey.isEmpty) return Future.value(true);
await Supabase.initialize(url: url, anonKey: anonKey);
final client = Supabase.instance.client;
// Must have an active session
final session = client.auth.currentSession;
if (session == null) return Future.value(true);
final serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) return Future.value(true);
final permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied ||
permission == LocationPermission.deniedForever) {
return Future.value(true);
}
final position = await Geolocator.getCurrentPosition(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.high,
),
);
await client.rpc(
'update_live_position',
params: {'p_lat': position.latitude, 'p_lng': position.longitude},
);
} catch (e) {
debugPrint('Background location update error: $e');
}
return Future.value(true);
});
}
/// Initialize Workmanager and register periodic background location task.
Future<void> initBackgroundLocationService() async {
await Workmanager().initialize(callbackDispatcher, isInDebugMode: false);
}
/// Register a periodic task to report location every ~15 minutes
/// (Android minimum for periodic Workmanager tasks).
Future<void> startBackgroundLocationUpdates() async {
await Workmanager().registerPeriodicTask(
_taskName,
_taskName,
frequency: const Duration(minutes: 15),
constraints: Constraints(networkType: NetworkType.connected),
existingWorkPolicy: ExistingWorkPolicy.keep,
);
}
/// Cancel the periodic background location task.
Future<void> stopBackgroundLocationUpdates() async {
await Workmanager().cancelByUniqueName(_taskName);
}