registerHeadlessTask static method

Future<bool> registerHeadlessTask(
  1. void callback(
    1. HeadlessEvent
    )
)

Registers a function to receive events from BackgroundGeolocation while in the terminated ("Headless") state.

Note: Requires Config.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). 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_background_geolocation/flutter_background_geolocation.dart' as bg;

/// Receives all events from BackgroundGeolocation while app is terminated:
void headlessTask(HeadlessEvent headlessEvent) async {
  print('[HeadlessTask]: ${headlessEvent}');

  // Implement a 'case' for only those events you're interested in.
  switch(headlessEvent.name) {
    case Event.TERMINATE:
      State state = headlessEvent.event;
      print('- State: ${state}');
      break;
    case Event.HEARTBEAT:
      HeartbeatEvent event = headlessEvent.event;
      print('- HeartbeatEvent: ${event}');
      break;
    case Event.LOCATION:
      Location location = headlessEvent.event;
      print('- Location: ${location}');
      break;
    case Event.MOTIONCHANGE:
      Location location = headlessEvent.event;
      print('- Location: ${location}');
      break;
    case Event.GEOFENCE:
      GeofenceEvent geofenceEvent = headlessEvent.event;
      print('- GeofenceEvent: ${geofenceEvent}');
      break;
    case Event.GEOFENCESCHANGE:
      GeofencesChangeEvent event = headlessEvent.event;
      print('- GeofencesChangeEvent: ${event}');
      break;
    case Event.SCHEDULE:
      State state = headlessEvent.event;
      print('- State: ${state}');
      break;
    case Event.ACTIVITYCHANGE:
      ActivityChangeEvent event = headlessEvent.event;
      print('ActivityChangeEvent: ${event}');
      break;
    case Event.HTTP:
      HttpEvent response = headlessEvent.event;
      print('HttpEvent: ${response}');
      break;
    case Event.POWERSAVECHANGE:
      bool enabled = headlessEvent.event;
      print('ProviderChangeEvent: ${enabled}');
      break;
    case Event.CONNECTIVITYCHANGE:
      ConnectivityChangeEvent event = headlessEvent.event;
      print('ConnectivityChangeEvent: ${event}');
      break;
    case Event.ENABLEDCHANGE:
      bool enabled = headlessEvent.event;
      print('EnabledChangeEvent: ${enabled}');
      break;
  }
}

void main() {
  runApp(HelloWorld());

  // Register your headlessTask:
  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.

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 function to registerHeadlessTask -- the Flutter framework will fail to address it:

// NO!  This will not work.
BackgroundGeolocation.registerHeadlessTask((HeadlessEvent event) {
  print('${event}');
});

// YES!
void myHeadlessTask(HeadlessEvent headlessEvent) async {
  print('${event}');
}

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>;
}