# Agents — Traccar Client ## Verify before claiming - Run `flutter analyze` before every commit — this project had 22 deprecated API violations (`.withOpacity()` → `.withValues(alpha:)`, `value` → `initialValue` on `DropdownButtonFormField`, `activeColor` → `activeThumbColor` on `Switch`) - Always run `flutter build apk --debug` to confirm the APK builds after any Dart or Kotlin change ## Commands ```bash flutter analyze # lint + typecheck (run before commit) flutter build apk --debug # build Android APK dart format . # format all Dart files ``` ## Architecture - **Flutter** Android app with a **MethodChannel** (`com.traccar.client/tracking`) bridging to native Kotlin services - **4 screens**: `PermissionScreen` → `MainScreen` → `SettingsScreen` / `StatusScreen` - **LocationBridge** (`lib/bridge/location_bridge.dart`) — the only Dart→Native bridge; all tracking starts here - **Native**: Kotlin services in `android/app/src/main/kotlin/com/traccar/traccar_client/` - `BridgeModule.kt` — method channel handler - `service/LocationTrackingService.kt` — foreground service - `location/HeartbeatScheduler.kt` — AlarmManager-based heartbeat (not WorkManager — WorkManager runs in separate process and static callbacks are lost) ## Key patterns & gotchas - **Permission flow**: `locationAlways` (background) requires `locationWhenInUse` to be granted first. Always request WhenInUse → then Always. Check `isPermanentlyDenied` and call `openAppSettings()` to direct user to app settings. - **Battery optimization**: Use `PowerManager.isIgnoringBatteryOptimizations(packageName)` via `BridgeModule` to detect if app is excluded from Doze. Open settings with `ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS` intent. - **Dark theme**: Set globally on `MaterialApp` (`scaffoldBackgroundColor`, `brightness: Brightness.dark`, `ColorScheme.dark`). Use `ZoomPageTransitionsBuilder` to avoid white flash on page transitions (not `FadeUpwardsPageTransitionsBuilder`). - **Tracking config**: Config dict must be passed to `startTracking()` and also sent via `updateConfig()` separately. Both calls are needed. - **`permission_screen.dart` state**: Permissions are checked at init via `_checkPermissions()`. State must be re-checked after each request call, not assumed from the request result. - **`preferences.dart`**: Uses static `SharedPreferences` instance. `Preferences.init()` must be called before `runApp()`. ## Style conventions - Monospace fonts, dark `#0d0d0d` background, teal `#00bcd4` accent, green `#00e676` for active/granted states - All UI text uses `fontFamily: 'monospace'` - Replace `Color.withOpacity(x)` → `Color.withValues(alpha: x)` (deprecated in recent Flutter) - Remove unused imports before committing ## Monorepo context The sibling `traccar-client-android` directory is the **original Java app** — reference it for expected server request format: POST to `serverUrl?id=deviceId&lat=...&lon=...×tamp=...&is_moving=0`. The `is_moving` threshold is `speed > 1.0 m/s`.