Flutter Background Geofencing
A Flutter plugin for native background geofencing with battery-efficient hardware-assisted location monitoring on Android and iOS.
Features
✅ Native Platform APIs - Android: GeofencingClient (API 19+), iOS: CLLocationManager (iOS 4.0+)
✅ Background Support - True background monitoring with foreground service (Android) and region monitoring (iOS)
✅ Battery Efficient - Uses hardware-assisted geofencing APIs, no continuous location polling
✅ Event-driven Architecture - Clean separation: plugin provides events, your app handles business logic
✅ Fallback Notifications - Native notifications when Flutter app is killed
✅ Dynamic Configuration - Runtime control over notifications and monitoring settings
Installation
Add this to your package's pubspec.yaml file:
dependencies:
flutter_background_geofencing: ^1.0.0
Then run:
flutter pub get
Platform Setup
Android
Add permissions to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
Set minSdkVersion to 19 or higher in android/app/build.gradle:
android {
defaultConfig {
minSdkVersion 19
}
}
iOS
Add location permissions to ios/Runner/Info.plist:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs location access for geofencing</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs location access for geofencing</string>
Usage
Basic Setup
import 'package:flutter_background_geofencing/flutter_background_geofencing.dart';
class LocationService {
final GeofencingService _service = GeofencingService();
Future<void> initialize() async {
// 1. Initialize
await _service.initialize();
// 2. Request permissions
await _service.requestPermissions();
// 3. Start background service
await _service.startService(
notificationTitle: 'Location Monitoring',
notificationText: 'Monitoring geofence regions',
);
// 4. Listen for events
_service.onGeofenceEvent.listen(_handleGeofenceEvent);
}
void _handleGeofenceEvent(GeofenceEvent event) {
if (event.type == GeofenceEventType.enter) {
// Handle entry - show notification, trigger action, etc.
print('Entered region: ${event.regionId}');
}
}
}
Adding Geofence Regions
// Add a circular geofence region
final region = GeofenceRegion(
id: 'office',
latitude: 37.7749,
longitude: -122.4194,
radius: 100.0, // meters
data: {'name': 'Office Location'},
);
await _service.addGeofence(region);
Fallback Notifications (App Killed)
// Configure fallback notifications for when app is killed
await _service.startService(
notificationTitle: 'Location Monitoring',
notificationText: 'Monitoring regions',
enableFallbackNotifications: true,
fallbackNotificationTitle: 'Location Alert',
fallbackNotificationBody: 'You entered {regionName}',
);
API Reference
GeofencingService
Main service class for geofencing functionality.
| Method | Description |
|---|---|
initialize() |
Initialize the service |
startService() |
Start background monitoring |
stopService() |
Stop monitoring |
addGeofence(region) |
Add a geofence region |
removeGeofence(id) |
Remove a region by ID |
requestPermissions() |
Request location permissions |
GeofenceRegion
Represents a circular geofence region.
GeofenceRegion({
required String id, // Unique identifier
required double latitude, // Center latitude
required double longitude, // Center longitude
required double radius, // Radius in meters
Map<String, dynamic>? data, // Custom data
})
GeofenceEvent
Event triggered when crossing geofence boundaries.
class GeofenceEvent {
final GeofenceEventType type; // enter, exit, dwell
final String regionId; // Region identifier
final DateTime timestamp; // Event time
final GeofenceLocation? location; // Triggering location
}
Platform Limitations
| Platform | Max Regions | Min Radius | Background Requirement |
|---|---|---|---|
| Android | 100 | 100m (recommended) | ACCESS_BACKGROUND_LOCATION (API 29+) |
| iOS | 20 | 1m (100m+ recommended) | "Always" location authorization |
Troubleshooting
Common Issues
Geofences not triggering:
- Ensure proper location permissions (Always/Background)
- Use minimum 100m radius for reliability
- Test with realistic movement (not simulator location changes)
Service stops on Android:
- Disable battery optimization for your app
- Ensure foreground service notification isn't dismissed
iOS background limitations:
- Enable Background App Refresh
- iOS may delay events for battery conservation
Permission Handling
Android API 29+: Request in two steps:
- First:
ACCESS_FINE_LOCATION - Then:
ACCESS_BACKGROUND_LOCATION
iOS: Always request "Always" authorization for geofencing.
Example
See the example directory for a complete implementation.
License
This project is licensed under the MIT License - see the LICENSE file for details.