Required Reading
Plugin Version
5.0.1
Mobile operating-system(s)
Device Manufacturer(s) and Model(s)
SM A556E
Device operating-systems(s)
android 16
What do you require assistance about?
After upgrading to version 5.0.1, I'm experiencing two issues on Android:
geofenceTemplate is being completely ignored - Android sends the full default payload with nested objects instead of the custom template
onProviderChange event does not trigger when the app is in background or terminated state on Android
Both the geofence template feature works correctly on iOS, but the provider change issue is Android-only.
Expected Behavior (iOS - Working Correctly)
iOS sends the custom template as configured:
[
{
"mock": "false",
"userId": 6170,
"event": "geofence",
"geofenceIdentifier": "WORK",
"key": "TEST",
"lat": 33.88657231524748,
"lng": 35.51786011859788,
"timestamp": "2026-01-22T09:48:46.046Z",
"geofenceAction": "ENTER"
}
]
Actual Behavior
{
"location": [
{
"is_moving": true,
"uuid": "9bae532e-7dc2-4a7d-b60b-6c50014c76c2",
"timestamp": "2026-01-22T09:50:50.449Z",
"recorded_at": "2026-01-22T09:50:50.602Z",
"age": 0.153,
"odometer": 0,
"odometer_error": 0,
"coords": {
"latitude": 33.8865387,
"longitude": 35.5178374,
"accuracy": 11.49,
"speed": -1,
"speed_accuracy": 1.5,
"heading": -1,
"heading_accuracy": 45,
"altitude": 118.8,
"ellipsoidal_altitude": 118.8,
"altitude_accuracy": 1
},
"activity": {
"type": "still",
"confidence": 100
},
"battery": {
"is_charging": true,
"level": 0.54
},
"extras": {
"userId": 6169,
"key": "TEST"
}
}
]
}
[Optional] Plugin Code and/or Config
bg.BackgroundGeolocation.onHttp(onHttp);
bg.BackgroundGeolocation.onProviderChange(onProviderChange);
bg.BackgroundGeolocation.addGeofence(bg.Geofence(
identifier: "WORK",
radius: geofenceRadius,
latitude: lat,
longitude: lng,
notifyOnEntry: true,
notifyOnExit: true,
notifyOnDwell: false))
.then((bool success) async {
if (success) {
print("🟢 Geofence added successfully.");
}
}).catchError((error) async {
print("Error adding geofence: $error");
});
bg.BackgroundGeolocation.ready(bg.Config(
geolocation: bg.GeoConfig(
desiredAccuracy: bg.DesiredAccuracy.high,
distanceFilter: 10,
locationAuthorizationRequest: "Always",
),
persistence: bg.PersistenceConfig(
maxDaysToPersist: 3,
geofenceTemplate: '{ "lat":<%= latitude %>, "lng":<%= longitude %>,"timestamp": "<%= timestamp %>","mock": "<%= mock %>", "geofenceIdentifier":"<%= geofence.identifier %>","geofenceAction":"<%= geofence.action %>","event":"<%= event %>"}',
extras: {
"userId": userId,
"key": key,
},
disableProviderChangeRecord: false,
),
app: bg.AppConfig(
stopOnTerminate: false,
startOnBoot: true,
preventSuspend: true,
enableHeadless: true,
backgroundPermissionRationale: bg.PermissionRationale(
message: 'Your location information will be kept secure and will not be shared with any third-party services without your explicit consent.'),
heartbeatInterval: 600,
),
http: bg.HttpConfig(
url:'${Generic.geofenceEvent}',,
headers: {"content-type": "application/json"},
rootProperty: ".",
autoSync: true,
batchSync: true,
),
logger: bg.LoggerConfig(
debug: true,
logLevel: bg.LogLevel.verbose,
),
activity: bg.ActivityConfig(
activityRecognitionInterval: 0,
stopDetectionDelay: 0,
stopOnStationary: false,
),
)).then((bg.State state) async {
if (!state.enabled) {
bg.BackgroundGeolocation.startGeofences();
}
});
}
MAIN:
@pragma('vm:entry-point')
void backgroundGeolocationHeadlessTask(bg.HeadlessEvent headlessEvent) async {
bg.Logger.debug("====Background Headless Task: ${headlessEvent}====");
print('📬 --> $headlessEvent');
try {
switch (headlessEvent.name) {
case bg.Event.GEOFENCE:
bg.GeofenceEvent geofenceEvent = headlessEvent.event;
print(geofenceEvent);
break;
case bg.Event.HTTP:
bg.HttpEvent response = headlessEvent.event;
print(response);
GeofenceController.onHttp(response);
break;
case bg.Event.PROVIDERCHANGE:
try {
bg.ProviderChangeEvent event = headlessEvent.event;
await GeofenceController.onProviderChange(event);
print(event);
} catch (e) {
bg.Logger.error("Provider Change Critical Error: $e");
}
break;
// ... other cases
}
} catch (e) {
bg.Logger.error("====Background Headless [ ERROR ! ] Error in headless task ! : $e====");
print("[ ERROR ! ] Error in headless task ! : $e");
}
}
[Optional] Relevant log output
Required Reading
Plugin Version
5.0.1
Mobile operating-system(s)
Device Manufacturer(s) and Model(s)
SM A556E
Device operating-systems(s)
android 16
What do you require assistance about?
After upgrading to version 5.0.1, I'm experiencing two issues on Android:
geofenceTemplate is being completely ignored - Android sends the full default payload with nested objects instead of the custom template
onProviderChange event does not trigger when the app is in background or terminated state on Android
Both the geofence template feature works correctly on iOS, but the provider change issue is Android-only.
Expected Behavior (iOS - Working Correctly)
iOS sends the custom template as configured:
[
{
"mock": "false",
"userId": 6170,
"event": "geofence",
"geofenceIdentifier": "WORK",
"key": "TEST",
"lat": 33.88657231524748,
"lng": 35.51786011859788,
"timestamp": "2026-01-22T09:48:46.046Z",
"geofenceAction": "ENTER"
}
]
Actual Behavior
{
"location": [
{
"is_moving": true,
"uuid": "9bae532e-7dc2-4a7d-b60b-6c50014c76c2",
"timestamp": "2026-01-22T09:50:50.449Z",
"recorded_at": "2026-01-22T09:50:50.602Z",
"age": 0.153,
"odometer": 0,
"odometer_error": 0,
"coords": {
"latitude": 33.8865387,
"longitude": 35.5178374,
"accuracy": 11.49,
"speed": -1,
"speed_accuracy": 1.5,
"heading": -1,
"heading_accuracy": 45,
"altitude": 118.8,
"ellipsoidal_altitude": 118.8,
"altitude_accuracy": 1
},
"activity": {
"type": "still",
"confidence": 100
},
"battery": {
"is_charging": true,
"level": 0.54
},
"extras": {
"userId": 6169,
"key": "TEST"
}
}
]
}
[Optional] Plugin Code and/or Config
[Optional] Relevant log output