From 08a4326da4d6d11d2c11d50c57a89ecafc9f3cb1 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Sat, 14 Mar 2026 00:59:39 -0400 Subject: [PATCH] feat: Add task execution callback registration to BackgroundTaskService and update geofence dispatcher to use it --- .../background_task_service.dart | 12 +++++ .../services/background_geofence_service.dart | 48 +++++++++---------- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/apps/mobile/packages/core/lib/src/services/device/background_task/background_task_service.dart b/apps/mobile/packages/core/lib/src/services/device/background_task/background_task_service.dart index 0e753716..d47602f5 100644 --- a/apps/mobile/packages/core/lib/src/services/device/background_task/background_task_service.dart +++ b/apps/mobile/packages/core/lib/src/services/device/background_task/background_task_service.dart @@ -55,4 +55,16 @@ class BackgroundTaskService extends BaseDeviceService { Future cancelAll() async { return action(() => Workmanager().cancelAll()); } + + /// Registers the task execution callback for the background isolate. + /// + /// Must be called inside the top-level callback dispatcher function. + /// The [callback] receives the task name and optional input data, and + /// must return `true` on success or `false` on failure. + void executeTask( + Future Function(String task, Map? inputData) + callback, + ) { + Workmanager().executeTask(callback); + } } diff --git a/apps/mobile/packages/features/staff/clock_in/lib/src/data/services/background_geofence_service.dart b/apps/mobile/packages/features/staff/clock_in/lib/src/data/services/background_geofence_service.dart index 63a7a408..ec2d9fe2 100644 --- a/apps/mobile/packages/features/staff/clock_in/lib/src/data/services/background_geofence_service.dart +++ b/apps/mobile/packages/features/staff/clock_in/lib/src/data/services/background_geofence_service.dart @@ -1,6 +1,6 @@ // ignore_for_file: avoid_print import 'package:krow_core/core.dart'; -import 'package:workmanager/workmanager.dart'; +import 'package:krow_domain/src/core/models/device_location.dart'; /// Top-level callback dispatcher for background geofence tasks. /// @@ -13,7 +13,7 @@ import 'package:workmanager/workmanager.dart'; /// is retained solely for this entry-point pattern. @pragma('vm:entry-point') void backgroundGeofenceDispatcher() { - Workmanager().executeTask( + const BackgroundTaskService().executeTask( (String task, Map? inputData) async { print('[BackgroundGeofence] Task triggered: $task'); print('[BackgroundGeofence] Input data: $inputData'); @@ -39,7 +39,7 @@ void backgroundGeofenceDispatcher() { try { const LocationService locationService = LocationService(); - final location = await locationService.getCurrentLocation(); + final DeviceLocation location = await locationService.getCurrentLocation(); print( '[BackgroundGeofence] Current position: ' 'lat=${location.latitude}, lng=${location.longitude}', @@ -93,6 +93,15 @@ void backgroundGeofenceDispatcher() { /// Uses core services for foreground operations. The background isolate logic /// lives in the top-level [backgroundGeofenceDispatcher] function above. class BackgroundGeofenceService { + + /// Creates a [BackgroundGeofenceService] instance. + BackgroundGeofenceService({ + required BackgroundTaskService backgroundTaskService, + required NotificationService notificationService, + required StorageService storageService, + }) : _backgroundTaskService = backgroundTaskService, + _notificationService = notificationService, + _storageService = storageService; /// The core background task service for scheduling periodic work. final BackgroundTaskService _backgroundTaskService; @@ -103,25 +112,25 @@ class BackgroundGeofenceService { final StorageService _storageService; /// Storage key for the target latitude. - static const _keyTargetLat = 'geofence_target_lat'; + static const String _keyTargetLat = 'geofence_target_lat'; /// Storage key for the target longitude. - static const _keyTargetLng = 'geofence_target_lng'; + static const String _keyTargetLng = 'geofence_target_lng'; /// Storage key for the shift identifier. - static const _keyShiftId = 'geofence_shift_id'; + static const String _keyShiftId = 'geofence_shift_id'; /// Storage key for the active tracking flag. - static const _keyTrackingActive = 'geofence_tracking_active'; + static const String _keyTrackingActive = 'geofence_tracking_active'; /// Unique task name for the periodic background check. - static const taskUniqueName = 'geofence_background_check'; + static const String taskUniqueName = 'geofence_background_check'; /// Task name identifier for the workmanager callback. - static const taskName = 'geofenceCheck'; + static const String taskName = 'geofenceCheck'; /// Notification ID for clock-in greeting notifications. - static const _clockInNotificationId = 1; + static const int _clockInNotificationId = 1; /// Notification ID for left-geofence warnings. static const int leftGeofenceNotificationId = 2; @@ -130,16 +139,7 @@ class BackgroundGeofenceService { static const double geofenceRadiusMeters = 500; /// Notification ID for clock-out notifications. - static const _clockOutNotificationId = 3; - - /// Creates a [BackgroundGeofenceService] instance. - BackgroundGeofenceService({ - required BackgroundTaskService backgroundTaskService, - required NotificationService notificationService, - required StorageService storageService, - }) : _backgroundTaskService = backgroundTaskService, - _notificationService = notificationService, - _storageService = storageService; + static const int _clockOutNotificationId = 3; /// Starts periodic 15-minute background geofence checks. /// @@ -150,7 +150,7 @@ class BackgroundGeofenceService { required double targetLng, required String shiftId, }) async { - await Future.wait([ + await Future.wait(>[ _storageService.setDouble(_keyTargetLat, targetLat), _storageService.setDouble(_keyTargetLng, targetLng), _storageService.setString(_keyShiftId, shiftId), @@ -161,7 +161,7 @@ class BackgroundGeofenceService { uniqueName: taskUniqueName, taskName: taskName, frequency: const Duration(seconds: 10), - inputData: { + inputData: { 'targetLat': targetLat, 'targetLng': targetLng, 'shiftId': shiftId, @@ -175,7 +175,7 @@ class BackgroundGeofenceService { Future stopBackgroundTracking() async { await _backgroundTaskService.cancelByUniqueName(taskUniqueName); - await Future.wait([ + await Future.wait(>[ _storageService.remove(_keyTargetLat), _storageService.remove(_keyTargetLng), _storageService.remove(_keyShiftId), @@ -185,7 +185,7 @@ class BackgroundGeofenceService { /// Whether background tracking is currently active. Future get isTrackingActive async { - final active = await _storageService.getBool(_keyTrackingActive); + final bool? active = await _storageService.getBool(_keyTrackingActive); return active ?? false; }