tracpulse/AGENTS.md
2026-04-30 16:46:27 +07:00

3 KiB

Agents — Traccar Client

Verify before claiming

  • Run flutter analyze before every commit — this project had 22 deprecated API violations (.withOpacity().withValues(alpha:), valueinitialValue on DropdownButtonFormField, activeColoractiveThumbColor on Switch)
  • Always run flutter build apk --debug to confirm the APK builds after any Dart or Kotlin change

Commands

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: PermissionScreenMainScreenSettingsScreen / 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=...&timestamp=...&is_moving=0. The is_moving threshold is speed > 1.0 m/s.