Background location-tracking module for iOS and Android.

Installing the Plugin

đź“‚ pubspec.yaml:

Note: See Versions for latest available version.

dependencies: flutter_background_geolocation: '^1.3.2'

Setup Guides

Android

It's required to request the ACCESS_FINE_LOCATION permission in AndroidManifest.xml:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

Also add the following class in the same directory as MainActivity.java and name it Application.java:

public class Application extends FlutterApplication 
                         implements PluginRegistrantCallback {
  @Override
  public void onCreate() {
    super.onCreate();
    GeofencingService.setPluginRegistrant(this);
  }

  @Override
  public void registerWith(PluginRegistry registry) {
    GeneratedPluginRegistrant.registerWith(registry);
  }
}

The purpose of extending FlutterApplication is to set a reference to the application’s plugin registrant within GeofencingService. This is needed to register the application’s plugins with the geofencing plugin’s background isolate, which makes it possible to use other plugins in the context of that isolate.

Finally, set the following field in AndroidManifest.xml to use the new Application instead of the default FlutterApplication:

<application
android:name=".Application"
…

iOS

Requesting the relevant permissions on iOS requires some simple modifications to Info.plist in the ios directory of the application. First, add the following lines to request background location updates:

<dict>
…
  <key>UIRequiredDeviceCapabilities</key>
  <array>
    <string>location-services</string>
    <string>gps</string>
    <string>armv7</string>
  </array>
  <key>UIBackgroundModes</key>
  <array>
    <string>location</string>
  </array>
…
</dict>

Then set the NSLocation description messages:

<dict>
…
  <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
  <string>YOUR DESCRIPTION HERE</string>
  <key>NSLocationWhenInUseUsageDescription</key>
  <string>YOUR DESCRIPTION HERE</string>
…
</dict>

These descriptions are shown to the user when the application requests access to their location. If they’re not provided, geofencing registration will fail silently!

import UIKit
import Flutter
import gps_service_plugin

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    
    // Register the plugins with the AppDelegate
    registerPlugins(self)
    
    // Set registerPlugins as a callback within GeofencingPlugin. This allows
    // for the Geofencing plugin to register the plugins with the background
    // FlutterEngine instance created to handle events. If this step is skipped,
    // other plugins will not work in the geofencing callbacks!
    SwiftGpsServicePlugin.setPluginRegistrantCallback(registerPlugins)
    
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

func registerPlugins(_ registry: FlutterPluginRegistry) {
    GeneratedPluginRegistrant.register(with: registry)
}

Finally, set a reference to the application’s plugin registrant within SwiftGpsServicePlugin from the application’s AppDelegate. This is needed to register the application’s plugins with the geofencing plugin’s background isolate, which makes it possible to use other plugins in the context of that isolate.

Dart

First of all initialize the plugin in initState with static callback function:

  static _onLocation({Position pos, String msg}) async {
    print('pos: $pos, msg: $msg');
  }
  
  @override
  void initState() {
    GpsManager.initialize(FirebaseHelper.onLocation);
    super.initState();
  }

And don't forget to dispose it:

  @override
  void dispose() {
    GpsManager.dispose();
    super.dispose();
  }

Then you can start and stop location tracking:

  void _startLocationTracking() async {
    final isTrackingLocation = await GpsManager.isTreckingLocation();
    if (!isTrackingLocation) {
      GpsManager.startListeningLocation();
    }
  }

  void _stopLocationTracking() async {
    final isTrackingLocation = await GpsManager.isTreckingLocation();
    if (isTrackingLocation) {
      GpsManager.stopListeningLocation();
    }
  }

Libraries

callback_dispatcher
gps_manager
i18n