registerHeadlessTask static method
Registers a function to receive events from BackgroundGeolocation while in the terminated ("Headless") state.
Note: Requires AppConfig.enableHeadless:true. See the Android Headless Mode Guide.
In main.dart, create a global function beside void main() {} (Must be defined as a distinct function, not an anonymous callback), annotated with @pragma('vm:entry-point') — without it, release builds can strip the function. This function will receive all events from BackgroundGeolocation in the headless state, and provided with a HeadlessEvent containing a HeadlessEvent.name and HeadlessEvent.event.
After running your app with runApp, register your headless-task with registerHeadlessTask. Within your callback, you're free to interact with the complete BackgroundGeolocation API.
WARNING: You must registerHeadlessTask in your main.dart. Do not place it in your application components.
Example
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg;
/// Receives all events from BackgroundGeolocation while app is terminated.
/// Must be a top-level or static function marked vm:entry-point, or release builds strip it.
@pragma('vm:entry-point')
void headlessTask(bg.HeadlessEvent headlessEvent) async {
print('[HeadlessTask]: $headlessEvent');
// Implement a 'case' for only those events you're interested in.
switch(headlessEvent.name) {
case bg.Event.TERMINATE:
bg.State state = headlessEvent.event;
print('- State: $state');
break;
case bg.Event.HEARTBEAT:
bg.HeartbeatEvent event = headlessEvent.event;
print('- HeartbeatEvent: $event');
break;
case bg.Event.LOCATION:
bg.Location location = headlessEvent.event;
print('- Location: $location');
break;
case bg.Event.MOTIONCHANGE:
bg.Location location = headlessEvent.event;
print('- Location: $location');
break;
case bg.Event.GEOFENCE:
bg.GeofenceEvent geofenceEvent = headlessEvent.event;
print('- GeofenceEvent: $geofenceEvent');
break;
case bg.Event.GEOFENCESCHANGE:
bg.GeofencesChangeEvent event = headlessEvent.event;
print('- GeofencesChangeEvent: $event');
break;
case bg.Event.SCHEDULE:
bg.State state = headlessEvent.event;
print('- State: $state');
break;
case bg.Event.ACTIVITYCHANGE:
bg.ActivityChangeEvent event = headlessEvent.event;
print('ActivityChangeEvent: $event');
break;
case bg.Event.HTTP:
bg.HttpEvent response = headlessEvent.event;
print('HttpEvent: $response');
break;
case bg.Event.POWERSAVECHANGE:
bool enabled = headlessEvent.event;
print('PowerSaveChangeEvent: $enabled');
break;
case bg.Event.CONNECTIVITYCHANGE:
bg.ConnectivityChangeEvent event = headlessEvent.event;
print('ConnectivityChangeEvent: $event');
break;
case bg.Event.ENABLEDCHANGE:
bool enabled = headlessEvent.event;
print('EnabledChangeEvent: $enabled');
break;
}
}
void main() {
runApp(HelloWorld());
// Register your headlessTask:
bg.BackgroundGeolocation.registerHeadlessTask(headlessTask);
}
Note: The HeadlessEvent.event is of the same class as provided by BackgroundGeolocation's main event-listeners. You can manually cast this instance as shown in the switch above.
- onLocation
- onMotionChange
- onHttp
- onActivityChange
- onProviderChange
- onHeartbeat
- onGeofence
- onGeofencesChange
- onEnabledChange
- onConnectivityChange
- onNotificationAction
WARNING:
-
You cannot register more than one headless-task.
-
You cannot reference your UI within your headless-task. There is no UI.
-
Do not register an inline
functionto registerHeadlessTask -- the Flutter framework will fail to address it:
// NO! This will not work.
bg.BackgroundGeolocation.registerHeadlessTask((bg.HeadlessEvent event) {
print('$event');
});
// YES!
@pragma('vm:entry-point')
void myHeadlessTask(bg.HeadlessEvent headlessEvent) async {
print('$headlessEvent');
}
bg.BackgroundGeolocation.registerHeadlessTask(myHeadlessTask);
Implementation
static Future<bool> registerHeadlessTask(
void Function(HeadlessEvent) callback) async {
Completer completer = Completer<bool>();
// Two callbacks: the provided headless-task + _headlessRegistrationCallback
List<int> args = [
PluginUtilities.getCallbackHandle(_headlessCallbackDispatcher)!
.toRawHandle(),
PluginUtilities.getCallbackHandle(callback)!.toRawHandle()
];
_methodChannel
.invokeMethod<bool>('registerHeadlessTask', args)
.then((bool? success) {
completer.complete(true);
}).catchError((error) {
print('[BackgroundGeolocation registerHeadlessTask] ‼️ $error');
completer.complete(false);
});
return completer.future as FutureOr<bool>;
}