Files
navigation/CLAUDE.md
2026-02-07 12:56:45 +01:00

7.1 KiB

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

# 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: appcommon:carcommon: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):

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):

single { OsrmRepository() }
viewModel { ViewModel(get()) }

LiveData Observation:

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