In my application the foreground service still shown after the scheduled time. No stop is called in the native level too.
{
// === Location Tracking ===
desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
distanceFilter: 60, // 200 meters (replaces time-based 10-min interval)
stationaryRadius: 25, // iOS: minimum distance to move from stationary
disableElasticity: true, // Allow elastic distance filter based on speed
// === Motion Detection (Battery Optimization) ===
stopOnStationary: false, // Stop GPS when device is stationary
activityRecognitionInterval: 10000,
disableMotionActivityUpdates: false, // Use motion API for battery optimization
stopTimeout: 3, // Minutes to wait before considering stationary (reduced from 13)
// === Heartbeat (Stationary Motion Check) ===
// While stationary, the plugin turns GPS off and relies on a geofence.
// On Xiaomi/MIUI, geofence exits can be delayed 5-30 min.
// Heartbeat forces a periodic wake-up so we can manually poll location.
heartbeatInterval: 120, // seconds — wake up every 2 min while stationary
// === Working Hours Schedule ===
// Format: "DAY(s) START-END" where Sunday=1, Monday=2, ..., Saturday=7.
schedule : ["1-7 07:00-23:45"],
scheduleUseAlarmManager: true, // Android: use AlarmManager for precision
// desiredOdometerAccuracy: 10,
// === HTTP Configuration ===
url: apiUrl,
method: "POST",
httpTimeout: 60000,
// Headers with auth token and custom app headers
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
// Additional params added to every location
params: {},
extras: {},
// HTTP root property - wrap locations in { locations: [...] }
httpRootProperty: "locations",
// Custom location template to match API format
// Template renders location data with <%= tag %> syntax
locationTemplate: JSON.stringify({
latitude: "<%= latitude %>",
longitude: "<%= longitude %>",
app_timestamp: "<%= timestamp %>",
source_type: "SCHEDULED",
uuid: "<%= uuid %>", // Unique identifier for each location event
}),
// === Auto-Start & Persistence ===
startOnBoot: true,
stopOnTerminate: false,
enableHeadless: true, // Android: continue tracking after app termination
forceReloadOnBoot: true, // Force full plugin reload after device reboot (Xiaomi fix)
// === Offline Queue ===
maxRecordsToPersist: 1000,
autoSync: true, // Auto-upload to server
autoSyncThreshold: 5, // Upload immediately (no batching delay)
batchSync: true, // Enable batch mode to force array format
maxBatchSize: 5, // Send one location at a time, but wrapped in array
maxDaysToPersist: 3, // Delete old locations after 3 days
// === Foreground Service (Android) ===
foregroundService: true,
backgroundPermissionRationale: {
title: "Allow location access all the time?",
message:
"Rezolv needs background location during work hours to track field visits, support attendance compliance, and sync updates even when the app is closed.",
positiveAction: "Allow all the time",
negativeAction: "Cancel",
},
notification: {
title: "Location Tracking Active",
text: "Tracking your field location",
priority: BackgroundGeolocation.NOTIFICATION_PRIORITY_MAX,
sticky: true,
},
// === Debug / Native logging ===
debug: false,
logMaxDays: 7,
// Force native SDK logging to verbose so support dumps always contain full BG traces.
logLevel: BackgroundGeolocation.LOG_LEVEL_VERBOSE,
}
03-01 22:42:10.919 INFO [LoggerFacade$a a]
╔═════════════════════════════════════════════
║ TSLocationManager version: 3.7.0 (444)
╠═════════════════════════════════════════════
╟─ Xiaomi 23049PCD8I @ 15 (react)
{
"activityRecognitionInterval": 10000,
"allowIdenticalLocations": false,
"authorization": {},
"autoSync": true,
"autoSyncThreshold": 5,
"backgroundPermissionRationale": {
"title": "Allow location access all the time?",
"message": " background location during work hours to sync updates even when the app is closed.",
"positiveAction": "Allow all the time",
"negativeAction": "Cancel"
},
"batchSync": true,
"configUrl": "",
"crashDetector": {
"enabled": false,
"accelerometerThresholdHigh": 20,
"accelerometerThresholdLow": 4.5,
"gyroscopeThresholdHigh": 20,
"gyroscopeThresholdLow": 4.5
},
"debug": false,
"deferTime": 0,
"desiredAccuracy": -1,
"desiredOdometerAccuracy": 100,
"disableAutoSyncOnCellular": false,
"disableElasticity": true,
"disableLocationAuthorizationAlert": false,
"disableMotionActivityUpdates": false,
"disableProviderChangeRecord": false,
"disableStopDetection": false,
"distanceFilter": 60,
"elasticityMultiplier": 1,
"enableHeadless": true,
"enableTimestampMeta": false,
"extras": {},
"fastestLocationUpdateInterval": -1,
"foregroundService": true,
"geofenceInitialTriggerEntry": true,
"geofenceModeHighAccuracy": false,
"geofenceProximityRadius": 1000,
"geofenceTemplate": "",
"headers": {
"Authorization": "XDF",
"Content-Type": "application\/json",
"X-App": "field-app",
"X-App-Version": "1.1.3"
},
"headlessJobService": "com.transistorsoft.rnbackgroundgeolocation.HeadlessTask",
"heartbeatInterval": -1,
"httpRootProperty": "locations",
"httpTimeout": 60000,
"isMoving": false,
"locationAuthorizationRequest": "Always",
"locationTemplate": "{\"latitude\":\"<%= latitude %>\",\"longitude\":\"<%= longitude %>\",\"app_timestamp\":\"<%= timestamp %>\",\"source_type\":\"SCHEDULED\",\"uuid\":\"<%= uuid %>\"}",
"locationTimeout": 60,
"locationUpdateInterval": 1000,
"locationsOrderDirection": "ASC",
"logLevel": 5,
"logMaxDays": 7,
"maxBatchSize": 5,
"maxDaysToPersist": 3,
"maxMonitoredGeofences": 97,
"maxRecordsToPersist": 1000,
"method": "POST",
"minimumActivityRecognitionConfidence": 75,
"motionTriggerDelay": 0,
"notification": {
"layout": "",
"title": "Location Tracking Active",
"text": "Tracking your field location",
"color": "",
"channelName": "TSLocationManager",
"channelId": "",
"smallIcon": "",
"largeIcon": "",
"priority": -1,
"sticky": true,
"strings": {},
"actions": []
},
"params": {},
"persist": true,
"persistMode": 2,
"schedule": [
"1-7 07:00-23:45"
],
"scheduleUseAlarmManager": true,
"speedJumpFilter": 300,
"startOnBoot": true,
"stationaryRadius": 25,
"stopAfterElapsedMinutes": 0,
"stopOnStationary": false,
"stopOnTerminate": false,
"stopTimeout": 13,
"triggerActivities": "in_vehicle, on_bicycle, on_foot, running, walking",
"url": "https:\/\/domain\/api\/v1\/agents\/locations-new",
"useSignificantChangesOnly": false,
"enabled": true,
"schedulerEnabled": false,
"trackingMode": 1,
"didShowBackgroundPermissionRationale": false,
"odometer": 10875.517578125,
"isFirstBoot": false,
"didLaunchInBackground": false,
"didDeviceReboot": true
}
03-01 22:42:10.920 DEBUG [HttpService startMonitoringConnectivityChanges]
🎾 Start monitoring connectivity changes
03-01 22:42:10.921 INFO [LoggerFacade$a a]
╔═════════════════════════════════════════════
║ DEVICE SENSORS
╠═════════════════════════════════════════════
╟─ ✅ ACCELEROMETER: {Sensor name="bmi26x Accelerometer Non-wakeup", vendor="BOSCH", version=65813, type=1, maxRange=156.9064, resolution=0.0047856453, power=0.18, minDelay=5000}
╟─ ✅ GYROSCOPE: {Sensor name="bmi26x Gyroscope Non-wakeup", vendor="BOSCH", version=65813, type=4, maxRange=34.90656, resolution=0.0010652636, power=0.9, minDelay=5000}
╟─ ✅ MAGNETOMETER: {Sensor name="qmc630x Magnetometer Non-wakeup", vendor="QST", version=131329, type=2, maxRange=3000.0, resolution=0.1, power=1.5, minDelay=10000}
╟─ ✅ SIGNIFICANT_MOTION: {Sensor name="sns_smd Wakeup", vendor="QTI", version=1, type=17, maxRange=1.0, resolution=1.0, power=0.025, minDelay=-1}
╚═════════════════════════════════════════════
03-01 22:42:10.922 INFO [LoggerFacade$a a]
-----------
03-01 23:44:36.423 INFO [ScheduleEvent a]
║ ⏰ OneShot event fired: HEARTBEAT
03-01 23:44:36.426 INFO [TSScheduleManager oneShot]
⏰ Scheduled OneShot: HEARTBEAT in 120000ms
03-01 23:44:36.429 DEBUG [HeartbeatService onHeartbeat] ❤️
03-01 23:46:27.045 INFO [HeartbeatService start]
🎾 Start heartbeat (120s)
03-01 23:46:27.047 INFO [TSScheduleManager cancelOneShot]
⏰ Cancel OneShot: HEARTBEAT
03-01 23:46:27.050 INFO [TSScheduleManager oneShot]
⏰ Scheduled OneShot: HEARTBEAT in 120000ms
03-01 23:46:27.053 INFO [TrackingService changePace]
🔵 setPace: false → false
03-01 23:46:39.650 INFO [TSScheduleManager oneShot]
⏰ Scheduled OneShot: TERMINATE_EVENT in 10000ms
03-01 23:46:49.695 INFO [ScheduleEvent a]
║ ⏰ OneShot event fired: TERMINATE_EVENT
03-01 23:46:49.696 DEBUG [TerminateEvent$a onChange]
ℹ️ TERMINATE_EVENT ignored (MainActivity is still active).
03-01 23:49:57.079 INFO [ScheduleEvent a]
║ ⏰ OneShot event fired: HEARTBEAT
03-01 23:49:57.092 INFO [TSScheduleManager oneShot]
⏰ Scheduled OneShot: HEARTBEAT in 120000ms
03-01 23:49:57.097 DEBUG [HeartbeatService onHeartbeat] ❤️
Required Reading
Plugin Version
4.19.4
Mobile operating-system(s)
Device Manufacturer(s) and Model(s)
Xiaomi POCO f5
Device operating-systems(s)
android 15
React Native / Expo version
Expo 53
What do you require assistance about?
I want to know if the scheduled stop, will it kill the foreground service ?
In my application the foreground service still shown after the scheduled time. No stop is called in the native level too.
[Optional] Plugin Code and/or Config
[Optional] Relevant log output