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 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 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 stopBackgroundLocationUpdates() async { await Workmanager().cancelByUniqueName(_taskName); }