# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is an Android navigation app built with Jetpack Compose that supports multiple routing providers (OSRM, Valhalla, TomTom) and includes Android Auto/Automotive OS integration. The app uses MapLibre for rendering, ObjectBox for local persistence, and Koin for dependency injection. ## Build Commands ```bash # Build the app (from repository root) ./gradlew :app:assembleDebug # Build specific flavor ./gradlew :app:assembleDemoDebug ./gradlew :app:assembleFullDebug # Run tests ./gradlew test # Run tests for specific module ./gradlew :common:data:test ./gradlew :common:car:test # Install on device ./gradlew :app:installDebug # Clean build ./gradlew clean ``` ## Module Structure The project uses a multi-module architecture: - **app/** - Main Android app with Jetpack Compose UI for phone - **common/data/** - Core data layer with routing logic, repositories, and data models (shared by all modules) - **common/car/** - Android Auto/Automotive OS UI implementation - **automotive/** - Placeholder for future native Automotive OS app Dependencies flow: `app` → `common:car` → `common:data` ## Architecture ### Routing Providers (Pluggable System) The app supports three routing engines that implement the `NavigationRepository` abstract class: 1. **OsrmRepository** - OSRM routing engine 2. **ValhallaRepository** - Valhalla routing engine 3. **TomTomRepository** - TomTom routing engine Each provider has a corresponding mapper class (`OsrmRoute`, `ValhallaRoute`, `TomTomRoute`) that converts provider-specific JSON responses to the universal `Route` data model. **Adding a new routing provider:** 1. Create `NewProviderRepository` extending `NavigationRepository` in `common/data/src/main/java/com/kouros/navigation/data/` 2. Implement `getRoute()` method 3. Create `NewProviderRoute.kt` with `mapToRoute()` function 4. Add provider detection logic in `Route.Builder.route()` 5. Update `NavigationUtils.getViewModel()` to return appropriate ViewModel ### Data Flow ``` User Action (search/select destination) ↓ ViewModel.loadRoute() [LiveData] ↓ NavigationRepository.getRoute() [Selected provider] ↓ *Route.mapToRoute() [Convert to universal Route model] ↓ RouteModel.startNavigation() ↓ RouteModel.updateLocation() [On each location update] ↓ UI observes LiveData and displays current step ``` ### Key Classes **Navigation Logic:** - `RouteModel.kt` - Core navigation engine (tracks position, calculates distances, manages steps) - `RouteCarModel.kt` - Extends RouteModel with Android Auto-specific formatting - `ViewModel.kt` - androidx.ViewModel with LiveData for route, traffic, places, etc. **Data Models:** - `Route.kt` - Universal route structure used by all providers - `Place.kt` - ObjectBox entity for favorites/recent locations - `StepData.kt` - Display data for current navigation instruction **Repositories:** - `NavigationRepository.kt` - Abstract base class for all routing providers - Also handles Nominatim geocoding search and TomTom traffic incidents **Android Auto:** - `NavigationCarAppService.kt` - Entry point for Android Auto/Automotive OS - `NavigationSession.kt` - Session management - `NavigationScreen.kt` - Car screen templates with NavigationType state machine - `SurfaceRenderer.kt` - Handles virtual display and map rendering ### External APIs | Service | Purpose | Base URL | |---------|---------|----------| | OSRM | Routing | `https://kouros-online.de/osrm/route/v1/driving/` | | Valhalla | Routing | `https://kouros-online.de/valhalla/route` | | TomTom | Traffic incidents | `https://api.tomtom.com/traffic/services/5/incidentDetails` | | Nominatim | Geocoding search | `https://kouros-online.de/nominatim/` | | Overpass | POI & speed limits | OpenStreetMap Overpass API | ## Important Constants Located in `Constants.kt` (`common/data`): ```kotlin NEXT_STEP_THRESHOLD = 120.0 m // Distance to show next maneuver DESTINATION_ARRIVAL_DISTANCE = 40.0 m // Distance to trigger arrival MAXIMAL_SNAP_CORRECTION = 50.0 m // Max distance to snap to route MAXIMAL_ROUTE_DEVIATION = 80.0 m // Max deviation before reroute ``` SharedPreferences keys: - `ROUTING_ENGINE` - Selected provider (0=Valhalla, 1=OSRM, 2=TomTom) - `DARK_MODE_SETTINGS` - Theme preference - `AVOID_MOTORWAY`, `AVOID_TOLLWAY` - Route preferences ## Navigation Flow 1. **Route Loading**: User searches via Nominatim → selects place → ViewModel.loadRoute() calls selected repository 2. **Route Parsing**: Provider JSON → mapper converts to universal Route → RouteModel.startNavigation() 3. **Location Tracking**: FusedLocationProviderClient provides updates → RouteModel.updateLocation() 4. **Step Calculation**: findStep() snaps location to nearest waypoint → updates current step 5. **UI Updates**: currentStep() and nextStep() provide display data (instruction, distance, icon, lanes) 6. **Arrival**: When distance < DESTINATION_ARRIVAL_DISTANCE, navigation ends ## Testing Navigation The app includes mock location support for testing: - Set `useMock = true` in MainActivity - Enable "Mock location app" in Android Developer Options - Choose test mode: - `type = 1` - Simulate movement along entire route - `type = 2` - Test specific step range - `type = 3` - Replay GPX track file ## ObjectBox Database ObjectBox is configured in `common/data/build.gradle.kts` with the kapt plugin. The database stores: - Recent destinations (category: "Recent") - Favorite places (category: "Favorites") - Imported contacts (category: "Contacts") Queries use ObjectBox query builder pattern with generated `Place_` property accessors. ## Compose UI Structure **Phone App:** - `MainActivity.kt` - Main entry with permission handling and Navigation Compose - `NavigationScreen.kt` - Turn-by-turn navigation display - `SearchSheet.kt` / `NavigationSheet.kt` - Bottom sheet content - `MapView.kt` - MapLibre rendering with camera state management **Android Auto:** - Uses CarAppService Screen templates (NavigationTemplate, MessageTemplate, MapWithContentTemplate) - NavigationType enum controls which template to display (VIEW, NAVIGATION, REROUTE, RECENT, ARRIVAL) ## Build Flavors Two product flavors with dimension "version": - **demo** - applicationId: `com.kouros.navigation.demo` - **full** - applicationId: `com.kouros.navigation.full` ## Common Patterns **Dependency Injection (Koin):** ```kotlin single { OsrmRepository() } viewModel { ViewModel(get()) } ``` **LiveData Observation:** ```kotlin viewModel.route.observe(this) { routeJson -> routeModel.startNavigation(routeJson, context) } ``` **Step Finding Algorithm:** RouteModel iterates through all step waypoints, calculates distance to current location, and snaps to the nearest waypoint to determine current step index. ## Known Limitations - Valhalla route mapping is incomplete (search for TODO comments in ValhallaRoute.kt) - Rerouting logic exists but needs more testing - Speed limit queries via Overpass API could be optimized for performance - TomTom implementation uses local JSON file (R.raw.tomom_routing) instead of live API