adaptive_location_tracker 0.0.7
adaptive_location_tracker: ^0.0.7 copied to clipboard
A battery-efficient adaptive location tracker with offline sync, Kalman filtering, and foreground service support.
Adaptive Location Tracker 📍 #
A "Gold Standard" location tracking plugin for Flutter, designed for battery efficiency, high accuracy, and offline resilience. It creates a foreground service on Android to track location reliably in the background, making it perfect for field force, delivery, and logistics applications.
✨ Features #
- 🔋 Battery Efficient: Uses Google's
FusedLocationProviderClientto minimize battery drain. - 🧠 Intelligent Filtering:
- Activity Recognition: Automatically detects if the user is
STILL,WALKING, orIN_VEHICLEto adjust tracking logic dynamically. - State Machine: Uses a robust logic engine to "Lock" location when stationary (preventing spiderwebbing) and "Breakout" only when verified movement occurs.
- Outlier Detection: Rejects impossible jumps in location (e.g., GPS drift) and filters low-accuracy signals.
- Activity Recognition: Automatically detects if the user is
- 📡 Offline Support:
- Local Buffer: Automatically saves coordinates to a local SQLite database when the network is unavailable.
- Auto-Sync: data is automatically retried and uploaded in the correct chronological order when connectivity returns.
- 🛠️ Customizable:
- Configurable HTTP endpoint, headers, and update intervals.
- Customizable Notification title and text.
- Ability to send custom extra data (User ID, Task ID, etc.) with every payload.
- 🔌 Plug & Play: Handles permission checks, foreground services, and wake locks internally.
- 🌐 Dual Mode: Supports both HTTP/REST and WebSockets for real-time tracking.
🚀 Installation #
Add the package to your pubspec.yaml. Since this is a private plugin, you might use a path or git dependency:
dependencies:
adaptive_location_tracker:
path: ../path/to/adaptive_location_tracker
# OR
# git:
# url: git@github.com:yourusername/adaptive_location_tracker.git
Android Setup #
The plugin handles most permissions, but you should ensure your android/app/src/main/AndroidManifest.xml does not conflict. The plugin automatically adds:
FOREGROUND_SERVICEACCESS_FINE_LOCATIONACCESS_COARSE_LOCATIONINTERNETACTIVITY_RECOGNITION(for Motion Detection)
📖 Usage #
1. Import the package #
import 'package:adaptive_location_tracker/adaptive_location_tracker.dart';
2. Start Tracking #
Call start() with your API endpoint and configuration. The service will spin up and start posting JSON data to your URL.
HTTP Mode (Default):
await AdaptiveLocationTracker.start(
url: 'https://your-api.com/v1/trace',
headers: {'Authorization': 'Bearer YOUR_JWT_TOKEN'},
extraData: {
'driver_id': 12345,
'route_id': 'RT-9988',
},
notificationTitle: "Active Delivery",
notificationText: "Tracking location for safety",
intervalSeconds: 15,
);
WebSocket Mode:
Enable isWebSocket: true to stream real-time locations over a socket connection. If the socket fails, data falls back to the local database and is synced via HTTP later.
await AdaptiveLocationTracker.start(
url: 'wss://your-api.com/ws/locations', // Use wss://
isWebSocket: true, // <--- Enable Socket Mode
headers: {'Authorization': 'Bearer ...'},
extraData: {'user_id': 101},
);
3. Stop Tracking #
To stop the background service and release resources:
await AdaptiveLocationTracker.stop();
⚠️ Important: Android Background Restrictions #
🔋 strict Battery Optimizations #
Android OS becomes very aggressive when the device battery is low (usually < 15%) or "Battery Saver" mode is enabled. In these states, the OS may:
- Throttle GPS updates.
- Kill background services (even Foreground Services) to save power.
- Suspend network activity.
Recommendation: Advise your users to keep "Battery Saver" OFF during active tracking sessions for guaranteed reliability.
📱 OEM Specific Issues (Xiaomi, OnePlus, Samsung) #
Some manufacturers (notably Xiaomi/MIUI, OnePlus/OxygenOS) have aggressive custom battery killers that ignore standard Android rules.
- Xiaomi (MIUI): By default, MIUI prevents background auto-start. Users must manually enable "Autostart" for your app in Settings, otherwise the service may be killed ~20 minutes after the screen goes off.
- OnePlus: "Battery Optimization" must be set to "Don't Optimize".
Mitigation: You should detect these devices and prompt the user to whitelist your app in their battery settings if critical tracking is required.
📡 API Payload Format #
The plugin sends a POST request (or Socket Message) with the following JSON:
{
"latitude": 37.774929,
"longitude": -122.419418,
"accuracy": 12.5, // in meters
"timestamp": 1679812345678, // Unix epoch milliseconds (GPS time)
// ... Plus any fields you passed in 'extraData'
"driver_id": 12345,
"route_id": "RT-9988",
"mode": "bike"
}
⚙️ How it works internally #
- Garbage Gate: Incoming GPS points with poor accuracy (> 60m) or impossible speeds (> 150km/h) are immediately rejected.
- State Machine: The service tracks if the user is
MOVINGorSTATIONARY.- Moving: Points are buffered and passed if they show significant distance from the last point.
- Stationary: If the user stops (detected by Motion Sensor + GPS Cluster), the location "locks" to a single high-quality point. No more updates are sent until a "Breakout" (verified sustained movement) occurs.
- Local DB & Sync (Store-and-Forward):
- Robustness: All locations are routed through a local SQLite database or queue.
- FIFO Queue: Data is sent in strict First-In-First-Out order. If a send fails, the system blocks and retries that specific point indefinitely using a linear backoff.
- Hybrid WebSocket: If WebSocket is enabled, the plugin attempts a "Direct Send" (Zero Latency). If successful, the DB is skipped. If it fails, the data falls back to the reliable DB queue.
- lifecycle: The local DB is automatically cleared when the service is stopped by the user, ensuring clean sessions.
💡 Best Practices for Backend Integration #
🕷️ Avoiding "Spiderweb" Polylines #
When drawing the route on a map, DO NOT sort by the device timestamp included in the JSON payload.
- Issue: If the device clock is slightly off, or if the user has bad connectivity, legacy points might arrive "late" but with an old timestamp. Sorting by this old timestamp can cause the polyline to zig-zag back and forth (spiderwebbing).
- Solution: Always sort your points by the Server-Side Request Time (
created_atin your DB). The plugin guarantees that points are uploaded in the correct chronological order of occurrence (FIFO), so the time you receive them is the correct order to draw them.
❤️ Credits #
Built for high-reliability field operations.