advanced_background_locator 0.1.4
advanced_background_locator: ^0.1.4 copied to clipboard
Flutter plugin for location tracking that keeps running in the background (Android foreground service, iOS background location updates).
advanced_background_locator #
A Flutter plugin that keeps receiving location updates while the app is in the background.
- Android: a foreground service (
foregroundServiceType="location") with a persistent notification runs a background Flutter isolate. Locations come from the Fused Location Provider (Google Play services) or the platformLocationManager. - iOS:
CLLocationManagerwithallowsBackgroundLocationUpdates, plus significant location changes and region monitoring to relaunch the app.
Your callbacks run in a separate background isolate, not in your UI isolate. Use IsolateNameServer/SendPort (see the example) to send data back to the UI.
Requirements #
| Minimum | |
|---|---|
| Flutter / Dart | 3.32 / 3.8 |
| Android | API 24, built with compileSdk 36 |
| iOS | 13.0 |
Installation #
dependencies:
advanced_background_locator: ^0.1.4
Android setup #
The plugin manifest already declares the foreground service, the boot receiver and these permissions:
ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, FOREGROUND_SERVICE, FOREGROUND_SERVICE_LOCATION, POST_NOTIFICATIONS, WAKE_LOCK, RECEIVE_BOOT_COMPLETED.
If you upgraded from 0.0.x, remove the IsolateHolderService <service> and BootBroadcastReceiver <receiver> entries from your app manifest.
-
If you need location while the app is not visible and want tracking to resume after a reboot, declare background location in
android/app/src/main/AndroidManifest.xml. Google Play reviews apps that use it, so only add it if your feature needs it:<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> -
Make the main activity
singleTopso notification taps reach the running app:<activity android:name=".MainActivity" android:launchMode="singleTop" ...> -
Request permissions at runtime (for example with
permission_handler) before callingregisterLocationUpdate:ACCESS_FINE_LOCATIONorACCESS_COARSE_LOCATION(required, otherwise aPERMISSION_DENIEDPlatformExceptionis thrown),POST_NOTIFICATIONSon Android 13+ (otherwise the service runs but its notification is hidden),- optionally
ACCESS_BACKGROUND_LOCATION("Allow all the time"), which Android 11+ only grants in a separate request after foreground location.
Platform rules to keep in mind:
- Android 12+: a foreground service cannot be started while the app is in the background. Call
registerLocationUpdatewhile your UI is visible; otherwise aSERVICE_START_FAILEDPlatformExceptionis thrown. - Android 14+: the service is started with the
locationtype, which requires a granted location permission at that moment. - Reboot: tracking is resumed after
BOOT_COMPLETEDonly if it was running before the reboot (it was not stopped withunRegisterLocationUpdate) and background location is granted. wakeLockTime(minutes) limits how long the partial wake lock is held.- Stopped in the background? Some manufacturers (Xiaomi, Huawei, Samsung, …) stop background work aggressively.
background_doctordiagnoses why background work stopped and why the app was killed.
iOS setup #
The iOS implementation could not be compiled on the maintainer's current (Windows) machine since 0.1.0, including the Swift Package Manager support added in 0.1.3. Please report any build problems.
The plugin supports both CocoaPods and Swift Package Manager.
-
Add usage descriptions and the location background mode to
ios/Runner/Info.plist:<key>NSLocationWhenInUseUsageDescription</key> <string>Why your app needs location while in use.</string> <key>NSLocationAlwaysAndWhenInUseUsageDescription</key> <string>Why your app needs location in the background.</string> <key>UIBackgroundModes</key> <array> <string>location</string> </array> -
Register plugins for the background isolate in
AppDelegate.swift, so plugins such aspath_providerwork in your callbacks:import Flutter import UIKit import advanced_background_locator func registerPlugins(registry: FlutterPluginRegistry) { if !registry.hasPlugin("BackgroundLocatorPlugin") { GeneratedPluginRegistrant.register(with: registry) } } @main @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) BackgroundLocatorPlugin.setPluginRegistrantCallback(registerPlugins) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } -
registerLocationUpdatecallsrequestAlwaysAuthorization. iOS first grants "While Using" and may later ask the user to upgrade to "Always".
Usage #
All callbacks must be top-level or static functions annotated with @pragma('vm:entry-point'), so they can be looked up from the background isolate (and are not removed by tree shaking in release builds). Passing a closure throws an ArgumentError.
import 'package:advanced_background_locator/advanced_background_locator.dart';
@pragma('vm:entry-point')
void onLocation(LocationDto location) {
// Runs in the background isolate.
print('${location.latitude}, ${location.longitude}');
}
@pragma('vm:entry-point')
void onInit(Map<String, dynamic> data) {}
@pragma('vm:entry-point')
void onDispose() {}
@pragma('vm:entry-point')
void onNotificationTap() {}
Future<void> start() async {
await AdvancedBackgroundLocator.initialize();
await AdvancedBackgroundLocator.registerLocationUpdate(
onLocation,
initCallback: onInit,
initDataCallback: {'startedAt': DateTime.now().toIso8601String()},
disposeCallback: onDispose,
autoStop: false, // true: stop when the app goes to the background
iosSettings: const IOSSettings(
accuracy: LocationAccuracy.NAVIGATION,
distanceFilter: 0,
showsBackgroundLocationIndicator: true,
stopWithTerminate: false,
),
androidSettings: const AndroidSettings(
accuracy: LocationAccuracy.NAVIGATION,
interval: 5, // seconds
distanceFilter: 0, // meters
wakeLockTime: 60, // minutes
client: LocationClient.google, // or LocationClient.android
androidNotificationSettings: AndroidNotificationSettings(
notificationChannelName: 'Location tracking',
notificationTitle: 'Tracking location',
notificationMsg: 'Your location is being recorded',
notificationIcon: '', // mipmap/drawable name, defaults to the app icon
notificationTapCallback: onNotificationTap,
),
),
);
}
Future<void> stop() => AdvancedBackgroundLocator.unRegisterLocationUpdate();
Call initialize() before registerLocationUpdate(), otherwise a NOT_INITIALIZED PlatformException is thrown.
Calling registerLocationUpdate() again while tracking is running restarts tracking with the new settings and callbacks
(on Android the previous disposeCallback and the new initCallback are called).
The plugin itself shows no text except the Android foreground service notification. Its default texts are English; pass
AndroidNotificationSettings (and updateNotificationText) strings in your app's language. The example app does this with
gen-l10n (English and Turkish).
On Android, LocationClient.google falls back to the platform LocationManager on devices without Google Play services.
Other APIs:
AdvancedBackgroundLocator.isServiceRunning()/isRegisterLocationUpdate()AdvancedBackgroundLocator.updateNotificationText(title:, msg:, bigMsg:)(Android only)
LocationDto #
latitude, longitude, accuracy, altitude, speed, speedAccuracy, heading, time (milliseconds since epoch), isMocked (Android, iOS 15+), provider (Android only, empty on iOS).
Accuracy mapping #
LocationAccuracy |
Android (Priority) |
iOS |
|---|---|---|
POWERSAVE |
PRIORITY_PASSIVE |
kCLLocationAccuracyKilometer |
LOW |
PRIORITY_LOW_POWER |
kCLLocationAccuracyHundredMeters |
BALANCED |
PRIORITY_BALANCED_POWER_ACCURACY |
kCLLocationAccuracyNearestTenMeters |
HIGH |
PRIORITY_HIGH_ACCURACY |
kCLLocationAccuracyBest |
NAVIGATION |
PRIORITY_HIGH_ACCURACY |
kCLLocationAccuracyBestForNavigation |
Use with other packages #
These pure Dart packages work with the LocationDto stream of this plugin and do not depend on it:
-
advanced_geofence: turns locations intoenter,exitanddwellevents for circle and polygon geofences. Run it inside the background callback:@pragma('vm:entry-point') void onLocation(LocationDto dto) { final result = engine.process(GeoPoint( dto.latitude, dto.longitude, accuracy: dto.accuracy, time: DateTime.fromMillisecondsSinceEpoch(dto.time.toInt()), )); // handle result.events, save engine.state } -
route_simulator: plays realistic fake routes for tests, demos and the Android emulator.SimulatedLocation.toMap()uses the same keys, soLocationDto.fromJson(location.toMap())works.
Other packages #
More packages by the same publisher:
google_maps_polyline: Google Directions routes and polyline encode/decode (pure Dart)marker_crafter: Custom Google Maps markers drawn with Canvasanimated_route_marker: Smoothly animated map marker along a route or live GPSadvanced_geofence: Pure Dart geofencing engine: enter, exit and dwell eventsroute_simulator: Realistic fake GPS streams for testing and demosbackground_doctor: Diagnoses why background work stops on Android and why the app was killedscan_tally: Continuous barcode scanning for stock counts: dedupe, tally, feedback, GS1scan_tally_mobile_scanner: mobile_scanner camera adapter for scan_tallyturkish_kit: Turkish validators, money in words, casing, provinces, holidays (pure Dart)turkish_kit_flutter: Flutter widgets for turkish_kit: Turkish money field and input formattersflutter_toastify: Animated toast notifications
Example #
See the example directory for a complete app (English and Turkish) that logs locations to a file and shows them in the UI.
License #
MIT, see LICENSE.
Türkçe #
Uygulama arka plandayken de konum güncellemesi almaya devam eden bir Flutter eklentisi. Android'de kalıcı bildirimli bir ön plan servisi
(foregroundServiceType="location"), iOS'ta CLLocationManager arka plan konum güncellemeleri kullanılır. Callback'ler ayrı bir arka plan
isolate'inde çalışır; bu yüzden üst düzey ya da statik ve @pragma('vm:entry-point') ile işaretlenmiş fonksiyonlar olmalıdır.
Kurulum, izinler ve kullanım için yukarıdaki İngilizce bölümlere bakın. Örnek uygulama İngilizce ve Türkçe arayüzlüdür.
Arka planda servis durduruluyorsa (Xiaomi, Huawei, Samsung gibi üreticilerde sık görülür)
background_doctor arka plan işinin neden durduğunu teşhis eder.
Diğer paketler #
Aynı yayıncının diğer paketleri:
google_maps_polyline: Google Directions rotası ve polyline kodlama/çözme (saf Dart)marker_crafter: Canvas ile çizilen özel Google Maps işaretçilerianimated_route_marker: Rota ya da canlı GPS üzerinde akıcı hareket eden harita işaretçisiadvanced_geofence: Saf Dart geofence motoru: giriş, çıkış ve bekleme olaylarıroute_simulator: Test ve demo için gerçekçi sahte GPS akışıbackground_doctor: Android'de arka plan işinin neden durduğunu ve uygulamanın neden kapandığını teşhis ederscan_tally: Stok sayımı için sürekli barkod okutma: tekrar ayıklama, sayım, geri bildirim, GS1scan_tally_mobile_scanner: scan_tally için mobile_scanner kamera adaptörüturkish_kit: Türkçe doğrulayıcılar, tutarı yazıyla yazma, harf dönüşümü, il/ilçe, tatiller (saf Dart)turkish_kit_flutter: turkish_kit için Flutter bileşenleri: Türk biçimli para alanı ve girdi biçimleyicileriflutter_toastify: Animasyonlu toast bildirimleri
