7.7 KiB
Traccar Client Fork - Agent Specification
This spec describes how to transform a fresh fork of traccar/traccar-client (Flutter) into a simplified, hardcoded tracking client. Apply all changes to the main branch.
Goal
Create a minimal Traccar Client that:
- Hard-codes all server/tracking settings (no user configuration)
- Shows only a device ID and a tracking toggle in the UI
- Removes access to settings, status, manual send, QR scanning, and password protection
Upstream Repository
https://github.com/traccar/traccar-client
The app is a Flutter project targeting iOS and Android from a single Dart codebase.
1. Configuration File: lib/config.dart
Create a new file lib/config.dart with compile-time constants. This is the single source of truth for all hardcoded settings. A developer forking this project only needs to edit this file to reconfigure the app.
class AppConfig {
AppConfig._();
/// Traccar server URL
static const String serverUrl = 'https://c.track.rs';
/// Location accuracy: 'highest', 'high', 'medium', or 'low'
static const String accuracy = 'highest';
/// Location update interval in seconds
static const int intervalSeconds = 60;
/// Distance filter in meters (0 = disabled)
static const int distanceFilter = 0;
/// Whether to enable stop detection
static const bool stopDetection = false;
/// Whether to buffer locations when offline
static const bool buffer = true;
/// Fastest location update interval in seconds (Android)
static const int fastestIntervalSeconds = 30;
}
All other modified files must read from AppConfig instead of using inline literals.
2. Hardcoded Settings (via AppConfig)
These values are set in lib/config.dart and enforced at runtime:
| Setting | Constant | Default Value |
|---|---|---|
| Server URL | AppConfig.serverUrl |
https://c.track.rs |
| Location Accuracy | AppConfig.accuracy |
highest |
| Interval | AppConfig.intervalSeconds |
60 |
| Distance Filter | AppConfig.distanceFilter |
0 (disabled) |
| Stop Detection | AppConfig.stopDetection |
false (disabled) |
| Buffer | AppConfig.buffer |
true |
| Fastest Interval | AppConfig.fastestIntervalSeconds |
30 |
3. File Changes
3.1 lib/preferences.dart
Add import 'config.dart'; at the top.
migrate() method
After the existing migration logic and device ID generation, force-set values from AppConfig:
// After device ID generation
await instance.setString(url, AppConfig.serverUrl);
await instance.setString(accuracy, AppConfig.accuracy);
await instance.setInt(interval, AppConfig.intervalSeconds);
await instance.setInt(distance, AppConfig.distanceFilter);
await instance.setBool(buffer, instance.getBool(buffer) ?? AppConfig.buffer);
await instance.setBool(stopDetection, AppConfig.stopDetection);
await instance.setInt(fastestInterval, instance.getInt(fastestInterval) ?? AppConfig.fastestIntervalSeconds);
geolocationConfig() method
Replace dynamic preference reads with AppConfig references:
isHighestAccuracy=AppConfig.accuracy == 'highest'locationUpdateInterval=AppConfig.intervalSeconds * 1000(but set to0in the config when highest accuracy)desiredAccuracy: UseDESIRED_ACCURACY_NAVIGATIONon iOS,DESIRED_ACCURACY_HIGHon Android (when highest)url:AppConfig.serverUrl(passed through_formatUrl)distanceFilter:AppConfig.distanceFilter.toDouble()locationUpdateInterval(in config):0(when highest accuracy, for continuous tracking)disableElasticity:truedisableStopDetection:!AppConfig.stopDetectionpausesLocationUpdatesAutomatically:falseon iOS,nullon AndroidfastestLocationUpdateInterval:0when highest accuracy, elseAppConfig.fastestIntervalSeconds * 1000
3.2 lib/main_screen.dart
Complete rewrite. Replace the entire file with a minimal screen containing:
- AppBar with title
'Traccar Client' - Centered body with two cards:
- Device ID card: Shows label "Device ID" and a
SelectableTextdisplaying the device ID in monospace bold (headlineSmall) - Tracking toggle card: A
SwitchListTilelabeled "Continuous Tracking" with subtitle showing state ("Sending location updates" / "Location tracking disabled")
- Device ID card: Shows label "Device ID" and a
- Tracking toggle behavior:
- On: calls
bg.BackgroundGeolocation.start()then checks battery optimizations - Off: calls
bg.BackgroundGeolocation.stop() - Track
isMovingstate; setactiveTrackColorto error color whenisMoving == false(stationary warning)
- On: calls
- State listeners: Listen to
onEnabledChangeandonMotionChangefrom BackgroundGeolocation - Battery optimization dialog: Keep the
_checkBatteryOptimizationsmethod that shows a dialog usingbg.DeviceSettings
Remove entirely:
- Settings button/navigation
- Status screen button/navigation
- "Send Location" button
- Password service import and usage
- Any reference to
SettingsScreenorStatusScreennavigation
Imports needed: flutter/material.dart, flutter/services.dart, traccar_client/main.dart (for messengerKey), traccar_client/preferences.dart, flutter_background_geolocation, l10n/app_localizations.dart
3.3 lib/settings_screen.dart
Complete rewrite. Replace with a minimal read-only screen (not navigable from main UI, but kept for completeness):
Add import 'config.dart'; at the top.
- Device ID display (read-only
ListTile) - Continuous Tracking
SwitchListTile(functional) - Read-only disabled
ListTileentries displaying values fromAppConfig:- Server:
AppConfig.serverUrl - Location Accuracy:
AppConfig.accuracy - Distance:
AppConfig.distanceFilter(show "Disabled" when 0) - Interval:
'${AppConfig.intervalSeconds} seconds' - Stop Detection:
AppConfig.stopDetection(show "Disabled"/"Enabled")
- Server:
3.4 ios/Runner.xcodeproj/project.pbxproj
Find the build phase named FlutterFire: "flutterfire upload-crashlytics-symbols" and prepend exit 0 to the shell script to skip it. This prevents flutterfire: command not found build failures.
The shellScript value should start with:
\n#!/bin/bash\n# Skip Firebase Crashlytics for now\nexit 0\n
followed by the original script content (which will never execute).
4. Files NOT Modified
These files remain unchanged from upstream:
lib/main.dart- App entry point, Firebase init, app links, rate dialoglib/geolocation_service.dartlib/configuration_service.dartlib/push_service.dartlib/quick_actions.dartlib/location_cache.dartlib/status_screen.dart- Kept in codebase but not navigablelib/password_service.dart- Kept in codebase but unusedlib/qr_code_screen.dart- Kept in codebase but not navigablepubspec.yaml- All localization files (
lib/l10n/) - Android platform files
5. Verification Checklist
After applying changes:
flutter pub getsucceedsflutter build iossucceeds (no flutterfire errors)flutter build apk --releasesucceeds- App launches showing only device ID and tracking toggle
- No settings, status, or send location buttons visible
- Toggling tracking on starts background location reporting to
https://c.track.rs - Device ID is auto-generated (8-digit random number) and persists across launches
- Location updates use highest accuracy with 0 distance filter
- Stop detection is disabled (tracking never auto-pauses)