|
|
|
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code when working with code in this reposi
|
|
|
|
|
|
|
|
|
|
## 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, DataStore for local persistence, and Koin for dependency injection.
|
|
|
|
|
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, Androidx DataStore for local persistence, and Koin for dependency injection.
|
|
|
|
|
|
|
|
|
|
## Build Commands
|
|
|
|
|
|
|
|
|
@@ -12,14 +12,15 @@ This is an Android navigation app built with Jetpack Compose that supports multi
|
|
|
|
|
# Build the app (from repository root)
|
|
|
|
|
./gradlew :app:assembleDebug
|
|
|
|
|
|
|
|
|
|
# Build specific flavor
|
|
|
|
|
# Build a specific flavor
|
|
|
|
|
./gradlew :app:assemblePlayDebug
|
|
|
|
|
./gradlew :app:assembleDemoDebug
|
|
|
|
|
./gradlew :app:assembleFullDebug
|
|
|
|
|
|
|
|
|
|
# Run tests
|
|
|
|
|
# Run unit tests
|
|
|
|
|
./gradlew test
|
|
|
|
|
|
|
|
|
|
# Run tests for specific module
|
|
|
|
|
# Run tests for a specific module
|
|
|
|
|
./gradlew :common:data:test
|
|
|
|
|
./gradlew :common:car:test
|
|
|
|
|
|
|
|
|
@@ -32,12 +33,12 @@ This is an Android navigation app built with Jetpack Compose that supports multi
|
|
|
|
|
|
|
|
|
|
## Module Structure
|
|
|
|
|
|
|
|
|
|
The project uses a multi-module architecture:
|
|
|
|
|
The project uses a multi-module architecture (see `settings.gradle.kts`):
|
|
|
|
|
|
|
|
|
|
- **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)
|
|
|
|
|
- **app/** - Main Android app with Jetpack Compose UI for phone (`com.kouros.navigation`)
|
|
|
|
|
- **common/data/** - Core data layer with routing logic, repositories, view models, persistence (`com.kouros.data`)
|
|
|
|
|
- **common/car/** - Android Auto/Automotive OS UI implementation
|
|
|
|
|
- **automotive/** - Placeholder for future native Automotive OS app
|
|
|
|
|
- **automotive/** - Placeholder for future native Automotive OS app (no Kotlin sources yet)
|
|
|
|
|
|
|
|
|
|
Dependencies flow: `app` → `common:car` → `common:data`
|
|
|
|
|
|
|
|
|
@@ -45,156 +46,212 @@ Dependencies flow: `app` → `common:car` → `common:data`
|
|
|
|
|
|
|
|
|
|
### Routing Providers (Pluggable System)
|
|
|
|
|
|
|
|
|
|
The app supports three routing engines that implement the `NavigationRepository` abstract class:
|
|
|
|
|
The app supports three routing engines that extend the `NavigationRepository` abstract class (`common/data/.../data/NavigationRepository.kt`):
|
|
|
|
|
|
|
|
|
|
1. **OsrmRepository** - OSRM routing engine
|
|
|
|
|
2. **ValhallaRepository** - Valhalla routing engine
|
|
|
|
|
3. **TomTomRepository** - TomTom routing engine
|
|
|
|
|
1. **ValhallaRepository** - Valhalla routing engine (ordinal 0)
|
|
|
|
|
2. **OsrmRepository** - OSRM routing engine (ordinal 1)
|
|
|
|
|
3. **TomTomRepository** - TomTom routing engine (ordinal 2, default)
|
|
|
|
|
|
|
|
|
|
Each provider has a corresponding mapper class (`OsrmRoute`, `ValhallaRoute`, `TomTomRoute`) that converts provider-specific JSON responses to the universal `Route` data model.
|
|
|
|
|
Selection is driven by `RouteEngine` enum order (see `Data.kt`). `NavigationRepository` also exposes shared HTTP helpers (`fetchUrl`, `searchPlaces`, `reverseAddress`) that use Nominatim for geocoding and `ApplicationConfig`-backed HTTP basic auth for protected endpoints.
|
|
|
|
|
|
|
|
|
|
Each provider has a corresponding mapper (`OsrmRoute`, `ValhallaRoute`, `TomTomRoute`) that converts provider-specific JSON into the universal `Route` model. The universal model is decomposed into a dedicated `data/route/` package: `Routes`, `Leg`, `Step`, `Maneuver`, `Intersection`, `Lane`, `Summary`.
|
|
|
|
|
|
|
|
|
|
**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
|
|
|
|
|
1. Create `NewProviderRepository` extending `NavigationRepository` under `common/data/src/main/java/com/kouros/navigation/data/<provider>/`
|
|
|
|
|
2. Implement `getRoute()` and `getTraffic()`
|
|
|
|
|
3. Create `NewProviderRoute.kt` with a `mapToRoute(response, builder)` function that populates a `Route.Builder`
|
|
|
|
|
4. Add a `RouteEngine` enum entry and provider branch in `Route.Builder.route()` (`data/Route.kt`)
|
|
|
|
|
5. Update `NavigationUtils.getViewModel()` (`utils/NavigationUtils.kt`) to return a `NavigationViewModel` wired to the new repository
|
|
|
|
|
|
|
|
|
|
### Data Flow
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
User Action (search/select destination)
|
|
|
|
|
User action (search / select destination)
|
|
|
|
|
↓
|
|
|
|
|
ViewModel.loadRoute() [LiveData]
|
|
|
|
|
NavigationViewModel.loadRoute() [LiveData / Flow]
|
|
|
|
|
↓
|
|
|
|
|
NavigationRepository.getRoute() [Selected provider]
|
|
|
|
|
NavigationRepository.getRoute() [selected provider]
|
|
|
|
|
↓
|
|
|
|
|
*Route.mapToRoute() [Convert to universal Route model]
|
|
|
|
|
*Route.mapToRoute() [convert to universal Route]
|
|
|
|
|
↓
|
|
|
|
|
RouteModel.startNavigation()
|
|
|
|
|
↓
|
|
|
|
|
RouteModel.updateLocation() [On each location update]
|
|
|
|
|
RouteCalculator.findStep() [on each location update]
|
|
|
|
|
↓
|
|
|
|
|
UI observes LiveData and displays current step
|
|
|
|
|
NavigationState updated → UI observes and renders 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.
|
|
|
|
|
**Navigation logic** (`common/data/.../model/`):
|
|
|
|
|
- `RouteModel.kt` - Core navigation engine; tracks position, manages step progression, owns `NavigationState`
|
|
|
|
|
- `RouteCalculator.kt` - Step-finding algorithm: snaps current location to the nearest waypoint, computes leftover distance, handles snap correction and reroute thresholds
|
|
|
|
|
- `RouteCarModel.kt` (`common/car/.../navigation/`) - Extends RouteModel with Android Auto-specific formatting
|
|
|
|
|
- `NavigationViewModel.kt` - androidx ViewModel exposing route, traffic, places (Nominatim), amenities (Overpass), and fuel prices (Tankerkönig) as LiveData
|
|
|
|
|
- `SettingsViewModel.kt` - State holder for DataStore-backed settings (dark mode, 3D, routing engine, avoid preferences, etc.)
|
|
|
|
|
- `BaseStyleModel.kt` - Map style state
|
|
|
|
|
|
|
|
|
|
**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
|
|
|
|
|
**Data models** (`common/data/.../data/`):
|
|
|
|
|
- `Route.kt` - Universal route wrapper with `Route.Builder` and provider dispatch
|
|
|
|
|
- `data/route/*` - Decomposed route components (`Routes`, `Leg`, `Step`, `Maneuver`, `Intersection`, `Lane`, `Summary`)
|
|
|
|
|
- `NavigationState.kt` - Immutable navigation state (route, flags, location, bearing, maneuver, destination)
|
|
|
|
|
- `Data.kt` - Shared types (`Place`, `StepData`, `SearchFilter`, `Locations`, `ValhallaLocation`) plus `object Constants` and the `RouteEngine`, `DarkMode`, `EngineType`, `ViewStyle`, `NavigationThemeColor` enums
|
|
|
|
|
- `ApplicationConfig.kt` - Loads `USER` / `PASSWORD` from `BuildConfig` for HTTP basic auth on protected endpoints
|
|
|
|
|
|
|
|
|
|
**Repositories:**
|
|
|
|
|
- `NavigationRepository.kt` - Abstract base class for all routing providers
|
|
|
|
|
- Also handles Nominatim geocoding search and TomTom traffic incidents
|
|
|
|
|
**Persistence** (`common/data/.../data/datastore/` and `common/data/.../repository/`):
|
|
|
|
|
- `DataStoreManager.kt` - Single source of truth for preference keys; exposes `Flow<T>` reads and `suspend` writes for each setting
|
|
|
|
|
- `SettingsRepository.kt` - Higher-level wrapper over `DataStoreManager`
|
|
|
|
|
|
|
|
|
|
**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
|
|
|
|
|
**Repositories** (`common/data/.../data/`):
|
|
|
|
|
- `NavigationRepository.kt` - Abstract base class for routing providers; also handles Nominatim geocoding (search and reverse)
|
|
|
|
|
- `osrm/`, `valhalla/`, `tomtom/` - Provider implementations and JSON DTOs
|
|
|
|
|
- `fuel/FuelPrices.kt` - Tankerkönig fuel-price client (returns `List<Station>`)
|
|
|
|
|
- `overpass/` - Overpass API client for POIs and speed limits
|
|
|
|
|
|
|
|
|
|
**Android Auto / Automotive** (`common/car/`):
|
|
|
|
|
- `NavigationCarAppService.kt` - CarAppService entry point
|
|
|
|
|
- `CarSession.kt` (abstract) and concrete `NavigationSession.kt`, `ClusterSession.kt`
|
|
|
|
|
- `screen/NavigationScreen.kt` - Main navigation template; `NavigationType` enum drives template selection (VIEW, NAVIGATION, REROUTE, RECENT, ARRIVAL)
|
|
|
|
|
- `screen/SearchScreen.kt`, `RoutePreviewScreen.kt`, `PlaceListScreen.kt`, `CategoriesScreen.kt`, `CategoryScreen.kt`, `StopOverScreen.kt`, `RequestPermissionScreen.kt`
|
|
|
|
|
- `screen/settings/*` - Per-setting screens (RoutingSettings, NavigationSettings, DisplaySettings, DarkModeSettings, DistanceSettings, AudioSettings, CarSettings, PasswordSettings)
|
|
|
|
|
- `screen/observers/*` - Observer pattern that bridges LiveData to car screens. `NavigationObserverManager` orchestrates `RouteObserver`, `TrafficObserver`, `TrafficMessageObserver`, `PlaceSearchObserver`, `CategoryObserver`, `MaxSpeedObserver`, `SpeedCameraObserver`
|
|
|
|
|
- Supporting managers: `SurfaceRenderer.kt` (virtual display + map), `DeviceLocationManager.kt`, `CarSensorManager.kt`, `NavigationNotificationManager.kt` + `NavigationNotificationService.kt`, `TextToSpeechManager.kt`, `CustomLifecycleOwner.kt`
|
|
|
|
|
- `map/MapView.kt`, `map/LocationPuck.kt` - MapLibre rendering for the car surface
|
|
|
|
|
|
|
|
|
|
### 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 |
|
|
|
|
|
| Service | Purpose | URL |
|
|
|
|
|
|---------------|--------------------------|------------------------------------------------------------------------------|
|
|
|
|
|
| OSRM | Routing | `https://router.project-osrm.org/route/v1/driving/` |
|
|
|
|
|
| Valhalla | Routing | `https://kouros-online.de/valhalla/route?json=` (HTTP basic auth) |
|
|
|
|
|
| TomTom | Routing | `https://api.tomtom.com/routing/1/calculateRoute/` |
|
|
|
|
|
| TomTom | Traffic incidents | `https://api.tomtom.com/traffic/services/5/incidentDetails` |
|
|
|
|
|
| Nominatim | Geocoding (search/reverse) | `https://nominatim.openstreetmap.org/` |
|
|
|
|
|
| Overpass | POIs & speed limits | OpenStreetMap Overpass API (DEBUG builds use `https://kouros-online.de/api/interpreter`) |
|
|
|
|
|
| Tankerkönig | Fuel prices | `https://creativecommons.tankerkoenig.de/json/list.php?` (API key in `fuel/FuelPrices.kt`) |
|
|
|
|
|
|
|
|
|
|
In DEBUG builds, `TomTomRepository` and `FuelPrices` can be pointed at a local fixture (see `useLocal` flags) — TomTom can fall back to `R.raw.tomom_routing`, fuel falls back to a local JSON URL.
|
|
|
|
|
|
|
|
|
|
## Important Constants
|
|
|
|
|
|
|
|
|
|
Located in `Constants.kt` (`common/data`):
|
|
|
|
|
Defined in `object Constants` inside `common/data/.../data/Data.kt`:
|
|
|
|
|
|
|
|
|
|
```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
|
|
|
|
|
NEXT_STEP_THRESHOLD = 500.0 // Distance (m) to show next maneuver
|
|
|
|
|
DESTINATION_ARRIVAL_DISTANCE = 10.0 // Distance (m) to trigger arrival
|
|
|
|
|
MAXIMAL_SNAP_CORRECTION = 50.0 // Max distance (m) to snap to route
|
|
|
|
|
MAXIMAL_ROUTE_DEVIATION = 100.0 // Max deviation (m) before reroute
|
|
|
|
|
NEAREST_LOCATION_DISTANCE = 10F
|
|
|
|
|
SPEED_UPDATE_DISTANCE = 600F
|
|
|
|
|
INSTRUCTION_DISTANCE = 50
|
|
|
|
|
SPEED_BEARING_DEVIATION = 60
|
|
|
|
|
TILT = 60.0 // Map tilt in degrees during navigation
|
|
|
|
|
TANKER_KOENIG_DELAY = 300_000 // ms between fuel price refreshes
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
SharedPreferences keys:
|
|
|
|
|
- `ROUTING_ENGINE` - Selected provider (0=Valhalla, 1=OSRM, 2=TomTom)
|
|
|
|
|
- `DARK_MODE_SETTINGS` - Theme preference
|
|
|
|
|
- `AVOID_MOTORWAY`, `AVOID_TOLLWAY` - Route preferences
|
|
|
|
|
DataStore keys (see `DataStoreManager.PreferencesKeys`):
|
|
|
|
|
- `RoutingEngine` (Int) — `0=Valhalla`, `1=OSRM`, `2=TomTom` (default 2)
|
|
|
|
|
- `DarkMode` (Int), `Show3D` (Bool), `CarLocation` (Bool)
|
|
|
|
|
- `AvoidMotorway`, `AvoidTollway`, `AvoidFerry` (Bool)
|
|
|
|
|
- `LastRoute`, `RecentPlaces`, `FuelPrices`, `LastFuelPrices`
|
|
|
|
|
- `TomTomApiKey`, `DistanceMode`, `GuidanceAudio`, `Traffic`, `TripSuggestion`, `EngineType`, `AlternativeRoutes`
|
|
|
|
|
|
|
|
|
|
## 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
|
|
|
|
|
1. **Route loading** — User searches via Nominatim → selects place → `NavigationViewModel.loadRoute()` calls the selected repository
|
|
|
|
|
2. **Route parsing** — Provider JSON → `*Route.mapToRoute()` populates `Route.Builder` → universal `Route` → `RouteModel.startNavigation()`
|
|
|
|
|
3. **Location tracking** — `FusedLocationProviderClient` updates → `RouteModel.updateLocation()`
|
|
|
|
|
4. **Step calculation** — `RouteCalculator.findStep()` snaps location to the nearest waypoint, returns `StepMatch`, and updates the current step index
|
|
|
|
|
5. **UI updates** — `NavigationState` flows out via LiveData/Compose state; phone and car UIs render the current/next step (instruction, distance, icon, lanes)
|
|
|
|
|
6. **Arrival** — When distance < `DESTINATION_ARRIVAL_DISTANCE`, navigation ends
|
|
|
|
|
|
|
|
|
|
## Testing Navigation
|
|
|
|
|
|
|
|
|
|
The app includes mock location support for testing:
|
|
|
|
|
The phone app supports mock locations for testing:
|
|
|
|
|
|
|
|
|
|
- Set `useMock = true` in MainActivity
|
|
|
|
|
- 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
|
|
|
|
|
- Choose mode in `model/Simulation.kt` / `model/MockLocation.kt`:
|
|
|
|
|
- `type = 1` — Simulate movement along the entire route
|
|
|
|
|
- `type = 2` — Test a specific step range
|
|
|
|
|
- `type = 3` — Replay a GPX track file
|
|
|
|
|
|
|
|
|
|
## ObjectBox Database
|
|
|
|
|
The car module has its own `navigation/Simulation.kt` for car-side simulation.
|
|
|
|
|
|
|
|
|
|
ObjectBox is configured in `common/data/build.gradle.kts` with the kapt plugin. The database stores:
|
|
|
|
|
### Unit tests
|
|
|
|
|
|
|
|
|
|
- Recent destinations (category: "Recent")
|
|
|
|
|
- Favorite places (category: "Favorites")
|
|
|
|
|
- Imported contacts (category: "Contacts")
|
|
|
|
|
- `common/data/src/test/.../model/RouteCalculatorTest.kt`
|
|
|
|
|
- `common/data/src/test/.../model/RouteModelTest.kt`
|
|
|
|
|
- `common/data/src/test/.../model/IconMapperTest.kt`
|
|
|
|
|
- `common/data/src/test/.../model/OverpassTest.kt`
|
|
|
|
|
- `common/data/src/test/.../utils/GeoUtilsTest.kt`
|
|
|
|
|
- `common/car/src/test/.../screen/NavigationScreenTest.kt`
|
|
|
|
|
- `common/car/src/test/.../screen/observers/CategoryObserverTest.kt`, `ObserversTest.kt`
|
|
|
|
|
|
|
|
|
|
Queries use ObjectBox query builder pattern with generated `Place_` property accessors.
|
|
|
|
|
## Persistence
|
|
|
|
|
|
|
|
|
|
All app preferences are stored via Androidx **DataStore Preferences** (`navigation_settings` data store). There is no Room/ObjectBox/SQL database — the only persisted entities are settings and serialized lists (recent places, last route, last fuel prices) kept as strings.
|
|
|
|
|
|
|
|
|
|
`DataStoreManager` exposes a `Flow<T>` per setting plus a matching `suspend set*` writer. `SettingsRepository` wraps it for higher-level access. `SettingsViewModel` and `AppViewModel` consume those flows for UI state.
|
|
|
|
|
|
|
|
|
|
## 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
|
|
|
|
|
**Phone app** (`app/src/main/java/com/kouros/navigation/`):
|
|
|
|
|
- `ui/MainActivity.kt` - Entry point with permission handling and Navigation Compose host
|
|
|
|
|
- `ui/MapView.kt` - MapLibre rendering with camera state management
|
|
|
|
|
- `ui/SheetLayout.kt` - Bottom sheet scaffold
|
|
|
|
|
- `ui/PermissionScreen.kt`
|
|
|
|
|
- `ui/navigation/AppNavGraph.kt` - Compose navigation graph
|
|
|
|
|
- `ui/navigation/NavigationScreen.kt`, `NavigationSheet.kt` - Turn-by-turn UI
|
|
|
|
|
- `ui/search/SearchScreen.kt`, `SearchSheet.kt`
|
|
|
|
|
- `ui/settings/SettingsScreen.kt`, `SettingsRoute.kt`, `DisplayScreen.kt`, `NavigationScreen.kt`, `CarScreen.kt`, `Settings.kt`
|
|
|
|
|
- `ui/components/SettingItem.kt`, `SettingSwitch.kt`, `RadioButtonSingleSelection.kt`, `SectionTitle.kt`
|
|
|
|
|
- `ui/app/AppViewModel.kt`, `AppViewModelProvider.kt`
|
|
|
|
|
- `ui/theme/{Color,Type,Shapes,Theme}.kt`
|
|
|
|
|
- `model/Simulation.kt`, `model/MockLocation.kt` - Mock location for testing
|
|
|
|
|
- `di/appModule.kt` - Koin module
|
|
|
|
|
- `MainApplication.kt` - Application class
|
|
|
|
|
|
|
|
|
|
**Android Auto:**
|
|
|
|
|
- Uses CarAppService Screen templates (NavigationTemplate, MessageTemplate, MapWithContentTemplate)
|
|
|
|
|
- NavigationType enum controls which template to display (VIEW, NAVIGATION, REROUTE, RECENT, ARRIVAL)
|
|
|
|
|
**Android Auto** uses CarAppService templates (NavigationTemplate, MessageTemplate, MapWithContentTemplate). `NavigationType` (in `screen/NavigationScreen.kt`) controls which template to render. UI state is synchronized with `NavigationViewModel` through the observers in `screen/observers/`.
|
|
|
|
|
|
|
|
|
|
## Build Flavors
|
|
|
|
|
|
|
|
|
|
Two product flavors with dimension "version":
|
|
|
|
|
- **demo** - applicationId: `com.kouros.navigation.demo`
|
|
|
|
|
- **full** - applicationId: `com.kouros.navigation.full`
|
|
|
|
|
`app/build.gradle.kts` defines three product flavors under the `store` dimension:
|
|
|
|
|
- **play** - applicationIdSuffix `.play`
|
|
|
|
|
- **demo** - applicationIdSuffix `.demo`
|
|
|
|
|
- **full** - applicationIdSuffix `.full`
|
|
|
|
|
|
|
|
|
|
Base namespace is `com.kouros.navigation`; current versionName is `0.3.0.109`. Java/Kotlin target is 21 for the app module, 11 for `common:data`. compileSdk/targetSdk = 37, minSdk = 33.
|
|
|
|
|
|
|
|
|
|
`signing.properties` (root, gitignored) provides the keystore credentials for both debug and release builds. `local.properties` provides `USER` / `PASSWORD` build config fields consumed by `ApplicationConfig`.
|
|
|
|
|
|
|
|
|
|
## Common Patterns
|
|
|
|
|
|
|
|
|
|
**Dependency Injection (Koin):**
|
|
|
|
|
**Dependency injection (Koin):**
|
|
|
|
|
```kotlin
|
|
|
|
|
single { OsrmRepository() }
|
|
|
|
|
viewModel { ViewModel(get()) }
|
|
|
|
|
viewModel { NavigationViewModel(get()) }
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**LiveData Observation:**
|
|
|
|
|
**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.
|
|
|
|
|
**Step-finding algorithm:**
|
|
|
|
|
`RouteCalculator` iterates the current step's waypoints, calculates distance from the current location to each, and snaps to the nearest waypoint. Snap is rejected if the closest point exceeds `MAXIMAL_SNAP_CORRECTION`; deviation greater than `MAXIMAL_ROUTE_DEVIATION` triggers a reroute.
|
|
|
|
|
|
|
|
|
|
**Settings flow:**
|
|
|
|
|
```kotlin
|
|
|
|
|
val darkMode by viewModel.darkMode.collectAsStateWithLifecycle()
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Known Limitations
|
|
|
|
|
|
|
|
|
|
- Valhalla route mapping is incomplete (search for TODO comments in ValhallaRoute.kt)
|
|
|
|
|
- Valhalla route mapping is incomplete in places (search for TODO comments in `data/valhalla/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
|
|
|
|
|
- Speed-limit queries via Overpass API could be optimized for performance
|
|
|
|
|
- TomTom and Tankerkönig clients have DEBUG-only `useLocal` shortcuts that hit fixture URLs (`http://192.168.1.37/...` and `R.raw.tomom_routing`) — these need to be off for any real-network testing
|
|
|
|
|
- The `automotive` module is wired into Gradle but has no Kotlin source yet
|
|
|
|
|