A real-time GPS tracking application with a Flutter mobile client and a Flask + MongoDB backend server. The app supports child–parent tracking, background location services, trip history, and QR-code-based device pairing.
Note
License: GNU General Public License v3.0 — see LICENSE.
- Architecture Overview
- Communication & Transactions
- Prerequisites
- Project Structure
- Environment Setup
- Running in Development
- Debugging
- Building for Release
- Creating a Release — ReleaseMaker.py
- API Reference (Quick)
- Useful Commands Cheat-Sheet
The system follows a client-server architecture, specifically designed to handle background location updates, offline data persistence, and real-time parent-child device synchronization.
graph TD
subgraph Mobile Client [Flutter Mobile App]
UI[UI / View Layer]
State[State Management - Provider]
BGS[flutter_background_service]
SQLite[(Local SQLite DB)]
Geolocator(Location Sensors)
end
subgraph Backend [Flask Server]
API[REST API layer]
Sockets[Socket.IO / Eventlet]
BLL(Business Logic Layer)
end
subgraph Database Layer
MongoDB[(MongoDB Atlas / Local)]
end
UI <--> State
State <--> API
State <--> Sockets
BGS --> Geolocator
BGS <--> SQLite
BGS --> API
API <--> BLL
Sockets <--> BLL
BLL <--> MongoDB
Note
The dual architecture of the client allows it to act as both a Child (transmitting location) and a Parent (monitoring location), relying heavily on background processing and robust real-time communication.
| Layer | Tech |
|---|---|
| Mobile client | Flutter 3.6+, Dart |
| State management | Provider |
| Navigation | go_router |
| Maps | flutter_map + OpenStreetMap |
| Background service | flutter_background_service |
| Backend API | Flask, Flask-CORS, Eventlet, Socket.IO |
| Database | MongoDB (via PyMongo) & SQLite (local fallback) |
| Auth | bcrypt password hashing (server-side) |
| Deployment | Render (gunicorn via render.yaml) |
| Releases | Git tags + GitHub CLI (gh) via ReleaseMaker.py |
The system uses a Bimodal Communication Protocol to optimize for battery life, reliability, and low latency.
sequenceDiagram
participant Child App
participant Flask Server
participant Parent App
Note over Child App, Parent App: 1. REST API (Batch & Sync)
Child App->>Child App: Store locations offline (SQLite)
Child App->>Flask Server: POST /send (Batch coordinates)
flask Server-->>Child App: 200 OK
Note over Child App, Parent App: 2. Real-Time WebSockets (Live Live-Tracking)
Child App->>Flask Server: emit('child_location_update')
Flask Server->>Parent App: emit('live_location')
Note over Child App, Parent App: 3. On-Demand Sync
Parent App->>Flask Server: emit('parent_request_sync')
Flask Server->>Child App: emit('sync_request')
Child App->>Flask Server: emit('child_sync_batch')
Flask Server->>Parent App: emit('sync_batch')
Used for standard requests that tolerate regular HTTP overhead and don't require streaming.
- Transactions:
POST /auth/login,POST /send(Batch Data Dump),GET /history. - Characteristics: Secure, easy to load-balance, traditional Request/Response paradigm.
Used exclusively for live interactions where polling via HTTP would dramatically drain the battery and increase latency.
- Transactions:
child_onlinepresence detection,child_location_updatereal-time pipelining, and peer-to-peer style on-demand sync flows. - Characteristics: Dedicated TCP connection, event-driven, bidirectional.
Install Flutter by following the official quick-start guide:
Minimum version required: Flutter SDK that ships with Dart SDK ≥ 3.6.0 (see pubspec.yaml).
After installation, verify:
flutter --version
flutter doctorflutter doctor will list any remaining issues (missing Android toolchain, licenses, etc.) — resolve them all before continuing.
Flutter for Android requires the Android SDK and its build tools. The easiest way to get them is through Android Studio:
After installing Android Studio:
- Open SDK Manager (
Settings → Languages & Frameworks → Android SDKorMore Actions → SDK Manageron the welcome screen). - Under the SDK Platforms tab, install at least Android 14 (API 34) or the latest available.
- Under the SDK Tools tab, make sure the following are installed:
- Android SDK Build-Tools
- Android SDK Command-line Tools
- Android SDK Platform-Tools
- Accept all SDK licenses:
flutter doctor --android-licenses
Tip: You don't need to use Android Studio as your editor — VS Code with the Flutter extension works great. Android Studio is only needed for the SDK and emulator.
For on-screen testing without a physical device:
- In Android Studio → Device Manager → Create Virtual Device.
- Pick a device profile (e.g. Pixel 7) and a system image (API 34+).
- Boot the emulator, then
flutter runwill auto-detect it.
- Enable Developer Options & USB Debugging on your Android phone.
- Connect via USB and authorize the computer.
- Verify:
flutter devicesshould list it.
The backend server requires Python 3.8+.
python3 --version # Should be 3.8 or higher
pip3 --versionThe backend connects to MongoDB. You need one of:
-
Local MongoDB — Install MongoDB Community Edition and start
mongod.# Ubuntu/Debian example sudo systemctl start mongodDefault URI:
mongodb://localhost:27017/ -
MongoDB Atlas (Cloud) — Create a free cluster at mongodb.com/atlas and get your connection string.
The release script (ReleaseMaker.py) uses gh to create GitHub releases.
# Install
# Ubuntu/Debian
sudo apt install gh
# macOS
brew install gh
# Then authenticate
gh auth loginGPSTrackerBackend/
├── lib/ # Flutter app source
│ ├── main.dart # App entry point (Firebase init, background service)
│ ├── nav.dart # go_router navigation
│ ├── theme.dart # Light & dark theme definitions
│ ├── data/ # Data models & local DB
│ ├── pages/ # UI pages (auth, dashboard, map, profile, trips)
│ ├── services/ # auth_service, background_service, location_service
│ ├── state/ # App session / state management
│ ├── ui/ # Shared UI components
│ └── utils/ # Utility helpers
├── android/ # Android native config (Gradle, manifests)
├── server.py # Flask backend server
├── wsgi.py # WSGI entry point (for gunicorn / production)
├── requirements.txt # Python dependencies
├── settings.json # Local config (gitignored — see below)
├── pubspec.yaml # Flutter dependencies
├── analysis_options.yaml # Dart linter config
├── render.yaml # Render.com deployment descriptor
├── ReleaseMaker.py # Release automation script
├── print_db.py # DB inspection utility
├── test_server.py # Backend test script
├── plan.md # UI/UX design plan
└── LICENSE # GPLv3
git clone https://github.com/<your-org>/GPSTrackerBackend.git
cd GPSTrackerBackend# 1. Fetch Flutter dependencies
flutter pub get
# 2. Verify everything is ready
flutter doctor# 1. Create a virtual environment (recommended)
python3 -m venv venv
source venv/bin/activate # Linux/macOS
# venv\Scripts\activate # Windows
# 2. Install Python dependencies
pip install -r requirements.txtThis file is gitignored (it contains credentials). Create it manually in the project root:
{
"backend_url": "http://localhost:5000",
"mongo_uri": "mongodb://localhost:27017/",
"db_name": "GPSTracker",
"debug_mode": true
}| Key | Description |
|---|---|
backend_url |
Base URL the Flutter app talks to |
mongo_uri |
MongoDB connection string (local or Atlas) |
db_name |
Database name inside MongoDB |
debug_mode |
true for verbose logging |
Note
For MongoDB Atlas, replace mongo_uri with your Atlas connection string:
mongodb+srv://<user>:<password>@<cluster>.mongodb.net/?appName=<name>
# Make sure your venv is activated and MongoDB is running
python server.pyThe API server starts on http://0.0.0.0:5000. You should see:
* Running on http://0.0.0.0:5000
Verify it's alive:
curl http://localhost:5000/serverstatus
# → {"server": true}With an emulator running or a physical device connected:
# Debug mode (hot reload enabled)
flutter run
# Or target a specific device
flutter devices # list available devices
flutter run -d <device> # run on a specific oneImportant
Make sure the Flutter app's backend URL in settings.json points to your machine's IP (not localhost) if testing on a physical device, since localhost on the phone refers to the phone itself.
| Tool | How |
|---|---|
| Hot Reload | Press r in the terminal while flutter run is active |
| Hot Restart | Press R (full state reset) |
| DevTools | Press d or run flutter run and open the DevTools URL printed in the console |
| Dart Analyzer | flutter analyze — runs the linter from analysis_options.yaml |
| Verbose logging | flutter run -v |
| VS Code | Install the Flutter and Dart extensions, set breakpoints, press F5 |
| Android Studio | Open the project, use the built-in debugger and layout inspector |
| Problem | Fix |
|---|---|
Gradle build failed |
Run cd android && ./gradlew clean && cd .. then flutter run again |
minSdkVersion error |
The app uses flutter.minSdkVersion — update it in android/app/build.gradle.kts if needed |
| Device not found | Run flutter devices, check USB debugging, or restart ADB: adb kill-server && adb start-server |
# Run with Flask's built-in debugger (auto-reload on file changes)
FLASK_DEBUG=1 python server.py- Set
"debug_mode": trueinsettings.jsonfor verbose server logs. - Use tools like Postman, Insomnia, or curl to test API endpoints.
A helper script print_db.py is included for quick database inspection:
python print_db.pyYou can also connect directly with the mongosh shell:
mongosh "mongodb://localhost:27017/GPSTracker"
# List today's location data
db.getCollection("2026_03_08").find().pretty()
# List all users
db.ourusers.find().pretty()flutter build apk --releaseThe output APK will be at:
./build/app/outputs/apk/release/app-release.apk
flutter build apk --debugOutput:
./build/app/outputs/apk/debug/app-debug.apk
flutter build appbundle --releaseOutput:
./build/app/outputs/bundle/release/app-release.aab
Note
The release build currently uses debug signing keys (see android/app/build.gradle.kts). For production Play Store releases, configure your own signing key — see Flutter deployment docs.
The ReleaseMaker.py script automates the full release workflow: version bumping, git tagging, pushing, and creating a GitHub release with the APK attached.
- Git repository with push access
- GitHub CLI (
gh) installed and authenticated - A built APK (release or debug)
python ReleaseMaker.pyThe script will prompt you interactively:
Release type (stable/canary): # "stable" or "canary"
Work type (patch/minor/major): # semver bump type
Write release notes: # freeform release notes
APK path [...]: # "release", "debug", or a custom path
- Reads the latest git tag — e.g.
v1.2.3 - Bumps the version based on your chosen work type:
patch→v1.2.4minor→v1.3.0major→v2.0.0
- Appends
-canaryif the release type is canary (e.g.v1.3.0-canary) - Creates an annotated git tag with the release notes
- Pushes the tag to origin
- Creates a GitHub release via
gh release createwith the APK attached
# 1. Make sure your code is committed and pushed
git add -A
git commit -m "feat: add trip history page"
git push origin main
# 2. Build the release APK
flutter build apk --release
# 3. Run the release maker
python ReleaseMaker.py
# → Release type: stable
# → Work type: minor
# → Release notes: Added trip history page with date filtering
# → APK path: release (uses the default release APK path)
#
# Output:
# Creating release: v1.3.0
# Release created: v1.3.0| Type | When to Use | Example |
|---|---|---|
patch |
Bug fixes, small tweaks | v1.2.3 → v1.2.4 |
minor |
New features, non-breaking changes | v1.2.3 → v1.3.0 |
major |
Breaking changes, large rewrites | v1.2.3 → v2.0.0 |
canary |
Pre-release / testing builds | v1.3.0-canary |
All endpoints are served by server.py on port 5000.
- Connection URL:
/ - Events (Child):
child_online,child_location_update,child_sync_batch - Events (Parent):
live_location,sync_batch,parent_request_sync
| Method | Endpoint | Description |
|---|---|---|
POST |
/auth/register |
Register (email, password, display_name) |
POST |
/auth/login |
Login (email, password) → user object |
GET |
/auth/profile?user_id= |
Get user profile |
PUT |
/auth/profile |
Update profile (display_name, role) |
| Method | Endpoint | Description |
|---|---|---|
POST |
/send |
Send batch of GPS coordinates |
POST |
/sync |
Sync from a given timestamp |
GET |
/sync_all?userid= |
Get all historical data for a user |
GET |
/viewtoday?userid= |
Get today's coordinates |
GET |
/history?userid= |
List dates with recorded data |
GET |
/history/view?userid=&date= |
Get coordinates for a specific date |
GET |
/serverstatus |
Health check → {"server": true} |
# ─── Flutter ──────────────────────────────────────
flutter pub get # Install dependencies
flutter run # Run in debug mode
flutter run --release # Run in release mode
flutter build apk --release # Build release APK
flutter build apk --debug # Build debug APK
flutter analyze # Run Dart linter
flutter clean # Clean build artifacts
flutter doctor # Check environment health
# ─── Backend ──────────────────────────────────────
source venv/bin/activate # Activate Python venv
pip install -r requirements.txt # Install Python deps
python server.py # Run dev server (port 5000)
FLASK_DEBUG=1 python server.py # Run with auto-reload
python print_db.py # Inspect database
python test_server.py # Run backend tests
# ─── Release ──────────────────────────────────────
python ReleaseMaker.py # Interactive release workflow
# ─── Git ──────────────────────────────────────────
git tag # List all tags
git describe --tags --abbrev=0 # Show latest tag
gh release list # List GitHub releases- Fork the repository
- Create a feature branch:
git checkout -b feat/your-feature - Commit your changes:
git commit -m "feat: describe your change" - Push to your fork:
git push origin feat/your-feature - Open a Pull Request
Please follow Conventional Commits for commit messages.
GPS Tracker — Built with Flutter & Flask
Licensed under GPLv3