Tracelet
Production-grade background geolocation for Flutter — fully open-source.
Battery-conscious motion-detection intelligence, geofencing, SQLite persistence, HTTP sync, and headless Dart execution for iOS & Android.
Features
- Background location tracking — continuous GPS with configurable
distanceFilteranddesiredAccuracy - Motion-detection intelligence — accelerometer + activity recognition automatically toggle GPS to save battery
- Geofencing — circular and polygon geofences with enter/exit/dwell events. Unlimited geofences via proximity-based auto-load/unload
- SQLite persistence — all locations stored locally, queryable, with configurable retention limits
- HTTP auto-sync — batch upload with retry, exponential backoff, offline queue, Wi-Fi-only option
- Headless execution — run Dart code in response to background events
- Scheduling — time-based tracking windows (e.g., "Mon–Fri 9am–5pm") with optional AlarmManager (Android)
- Start on boot — resume after device reboot
- Dart-controlled permissions — no native dialogs, full Dart-side customization
- Foreground service toggle — run with or without a persistent notification (Android)
- Debug sounds — audible feedback during development
- Elasticity control — speed-based distance filter scaling with disable/multiplier overrides
- Location filtering — reject GPS spikes, low-accuracy readings, and speed jumps via
LocationFilter - Kalman filter — optional GPS coordinate smoothing via Extended Kalman Filter (
useKalmanFilter: true) - Trip detection — automatic trip start/stop events with distance, duration, and waypoints
- Polygon geofences — define geofences with arbitrary polygon vertices for non-circular regions
- Auto-stop — automatically stop tracking after N minutes via
stopAfterElapsedMinutes - Activity recognition tuning — confidence thresholds, stop-detection delays, stationary behavior
- Timestamp metadata — optional extra timing fields on each location record
- Geofence high-accuracy mode — full GPS pipeline in geofence-only mode (Android)
- Prevent suspend (iOS) — silent audio keep-alive for continuous background execution
- Unlimited geofences — monitor thousands of geofences despite platform limits (100 Android / 20 iOS). Only the closest geofences within
geofenceProximityRadiusare registered with the OS. As the device moves, geofences are automatically swapped in/out, withonGeofencesChangeevents for each activation/deactivation. - Shared Dart algorithms — location filtering, geofence proximity, schedule parsing, and persistence logic run in shared Dart for cross-platform consistency
- Battery budget engine — adaptive feedback control adjusts
distanceFilter,desiredAccuracy, and periodic interval to maintain a configurablebatteryBudgetPerHourtarget (1.0–5.0 %/hr). Subscribe viaonBudgetAdjustment(). - Carbon footprint estimator — per-trip and cumulative CO₂ calculator using EU EEA 2024 emission factors (gCO₂/km) per transport mode. Returns
TripCarbonSummarywith breakdown by mode. - Delta encoding — 60–80% HTTP batch payload reduction via delta compression. Dart + Kotlin + Swift implementations for native encoding during sync.
- R-tree spatial index — O(log n) geofence queries supporting 10,000+ geofences with sub-ms lookup.
queryCircle()andqueryBBox()APIs. - GDPR/CCPA compliance reports —
generateComplianceReport()returns structured data processing inventory (JSON & Markdown export). - Sparse updates — app-level deduplication drops locations within
sparseDistanceThresholdof last recorded position. - Dead reckoning — inertial navigation (accel + gyro + compass) when GPS lost, with configurable activation delay and max duration.
- Wi-Fi-only sync —
disableAutoSyncOnCellulardefers HTTP sync to Wi-Fi connections. - Periodic mode — configurable one-shot fixes (60 sec–12 hrs), with Android foreground service and exact alarm support.
- Mock location detection — detect and reject spoofed GPS with configurable detection levels (basic platform flags + advanced heuristics). Learn more →
- OEM compatibility — automatic mitigations for aggressive OEM power management (Huawei, Xiaomi, OnePlus, Samsung, Oppo, Vivo) with Settings Health API. Learn more →
- iOS background hardening — all critical native operations wrapped in
beginBackgroundTask, with iOS 17+CLBackgroundActivitySessionand iOS 18+CLServiceSessionfor extended background runtime. Learn more → - Adaptive sampling — auto-adjusts
distanceFilterbased on detected activity, battery level, and speed for optimal battery/accuracy trade-off. Learn more → - Health check API —
getHealth()returns a comprehensive diagnostic snapshot covering permissions, battery, sensors, database, and geofence state with actionable warnings. Learn more → - HTTP sync retry engine — configurable retry with exponential backoff for transient server failures (5xx, 429, timeout). Learn more →
- Configurable motion sensitivity — tune accelerometer thresholds (
shakeThreshold,stillThreshold,stillSampleCount) for Low/Medium/High preset profiles or custom values
Quick Start
import 'package:tracelet/tracelet.dart' as tl;
// 1. Subscribe to events
tl.Tracelet.onLocation((tl.Location location) {
print('${location.coords.latitude}, ${location.coords.longitude}');
});
tl.Tracelet.onMotionChange((tl.Location location) {
print('Moving: ${location.isMoving}');
});
// 2. Initialize
final state = await tl.Tracelet.ready(tl.Config(
geo: tl.GeoConfig(
desiredAccuracy: tl.DesiredAccuracy.high,
distanceFilter: 10.0,
filter: tl.LocationFilter(
trackingAccuracyThreshold: 100,
maxImpliedSpeed: 80,
useKalmanFilter: true, // smooth GPS coordinates
),
),
app: tl.AppConfig(
stopOnTerminate: false,
startOnBoot: true,
),
persistence: tl.PersistenceConfig(
maxDaysToPersist: 7,
maxRecordsToPersist: 5000,
),
logger: tl.LoggerConfig(
debug: true,
logLevel: tl.LogLevel.verbose,
),
));
// 3. Start tracking
await tl.Tracelet.start();
Documentation
Kalman Filter GPS Smoothing
Enable the Extended Kalman Filter to smooth GPS coordinates, eliminate jitter, and produce cleaner tracks:
final state = await tl.Tracelet.ready(tl.Config(
geo: tl.GeoConfig(
filter: tl.LocationFilter(
useKalmanFilter: true, // Enable Kalman smoothing
),
),
));
The filter uses a constant-velocity model with GPS accuracy as measurement noise. It runs natively on both Android and iOS for zero-overhead smoothing. See the Kalman Filter Guide for details.
Trip Detection
Subscribe to trip events that fire automatically when the device transitions from moving to stationary. See the Trip Detection Guide for full details.
tl.Tracelet.onTrip((tl.TripEvent trip) {
print('Trip ended: ${trip.distance}m in ${trip.duration}s');
print('From: ${trip.startLocation}');
print('To: ${trip.stopLocation}');
print('Avg speed: ${trip.averageSpeed} m/s');
print('Waypoints: ${trip.waypoints.length}');
});
Polygon Geofences
Define geofences with arbitrary polygon vertices instead of circular regions:
await tl.Tracelet.addGeofence(tl.Geofence(
identifier: 'campus',
latitude: 37.422, // centroid for proximity sorting
longitude: -122.084,
radius: 0, // ignored for polygon geofences
vertices: [
[37.423, -122.086],
[37.424, -122.082],
[37.421, -122.081],
[37.420, -122.085],
],
));
Polygon containment uses the ray-casting algorithm for efficient point-in-polygon checks. Requires geofenceModeHighAccuracy: true. See the Polygon Geofences Guide for full details.
| Guide | Description |
|---|---|
| Android Setup | Gradle, permissions, and manifest configuration |
| iOS Setup | Info.plist, capabilities, and entitlements |
| Permissions | Permission flow, status codes, Dart dialog examples |
| Background Tracking | Foreground service, silent mode, runtime switching |
| API Reference | All methods, events, and return types |
| Configuration | All config groups with property tables |
| Kalman Filter | GPS smoothing — how it works, when to use it |
| Trip Detection | Automatic trip events — setup, API, edge cases |
| Polygon Geofences | Polygon geofences — vertices, ray-casting, examples |
| Web Support | Web platform capabilities, limitations, and browser APIs |
| Mock Detection | Detect & reject spoofed GPS — detection levels, heuristics, platform details |
| OEM Compatibility | Huawei/Xiaomi/OnePlus/Samsung/Oppo/Vivo mitigations, Settings Health API |
| Adaptive Sampling | Auto-adjust distanceFilter by activity, battery, and speed |
| Health Check | Diagnostic API — permissions, battery, sensors, database |
| HTTP Sync | Retry engine, exponential backoff, offline queue |
| iOS Background Hardening | Background task protection, session APIs, prevent suspend |
| Privacy Zones | Location exclusion zones for sensitive areas |
| Audit Trail | Cryptographic hash-chain audit trail for compliance |
| Battery Budget | Feedback loop — auto-tune tracking to stay within battery drain target |
| Delta Encoding | 60–80% HTTP payload compression via differential location encoding |
| Carbon Estimator | Real-time CO₂ estimation by transport mode (EU EEA 2024 factors) |
| Compliance Report | Auto-generated GDPR Article 30 / CCPA compliance reports |
| Dead Reckoning | IMU-based inertial navigation during GPS signal loss |
| Sparse Updates | App-level location deduplication — reduce DB writes and sync volume |
| Periodic Mode | Timed one-shot GPS fixes — WorkManager, foreground service, exact alarms |
Architecture
This is the app-facing package in a federated plugin:
| Package | Description |
|---|---|
tracelet (this package) |
Dart API — the only package apps depend on |
tracelet_platform_interface |
Abstract platform interface |
tracelet_android |
Kotlin Android implementation |
tracelet_ios |
Swift iOS implementation |
tracelet_web |
Web implementation (experimental) |
Support
If you find Tracelet useful, consider buying me a coffee:
License
Apache 2.0 — see LICENSE for details.
Libraries
- tracelet
- Tracelet — Production-grade background geolocation for Flutter.