Skip to content

Repository files navigation

HudNav

Android navigator for the Changan Deepal S09 EV that mirrors a Yandex MapKit-powered route to the car's built-in windshield HUD projector.

The main screen runs on the central touchscreen (search address, tap a point on the map, build a route). When you press the Go button, the route is projected onto the windshield as a compact overlay: maneuver icon, distance, street name and ETA on a pure-black background that becomes transparent on the glass.

For deeper architecture notes see CLAUDE.md.


Prerequisites

  • Android Studio Hedgehog (2023.1) or newer.
  • JDK 17. Android Studio ships its own JBR; using it is the easiest path (see commands below).
  • Android SDK with platforms 34 and 35 installed via the SDK Manager. compileSdk = 35, minSdk = 26.
  • A device or emulator running Android 8.0+ for testing.
  • A Yandex MapKit API key (see step 2 below).

Setup

1. Clone the repository

git clone <your-fork-url> car-apps
cd car-apps

2. Get a Yandex MapKit API key

  1. Open https://developer.tech.yandex.ru/.
  2. Sign in with a Yandex account and start the connect-API flow.
  3. Pick the MapKit Mobile SDK product. This single key covers map rendering, address search, the driving router and turn-by-turn data; no other API needs to be enabled.
  4. Once approved, copy the key.

3. Create local.properties

This file is gitignored on purpose: it holds your machine's SDK path and the secret API key. It is not created automatically when you clone, you need to add it yourself.

Create local.properties in the project root (next to build.gradle.kts):

# Path to your Android SDK installation:
#   macOS:   /Users/<you>/Library/Android/sdk
#   Linux:   /home/<you>/Android/Sdk
#   Windows: C:\\Users\\<you>\\AppData\\Local\\Android\\Sdk
sdk.dir=/Users/<you>/Library/Android/sdk

# Yandex MapKit key from step 2
MAPKIT_API_KEY=00000000-0000-0000-0000-000000000000

The Gradle build script reads MAPKIT_API_KEY from this file and exposes it as BuildConfig.MAPKIT_API_KEY, which is then handed to MapKit at startup (HudNavApp.onCreate). If the value is missing, the map tiles will fail to load.

Make sure the key is on its own line. It is easy to accidentally paste it at the end of sdk.dir= and break the SDK path.

4. Open the project

  • Android Studio: File > Open and select the car-apps directory. Gradle will sync automatically.
  • Command line: you can build and install without ever opening the IDE.

Build and run

The project uses the Gradle wrapper. Set JAVA_HOME to the JDK that ships with Android Studio so Gradle finds a recent enough Java:

# macOS, Android Studio bundled JBR
export JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home"

# Linux, typical paths
# export JAVA_HOME="/snap/android-studio/current/android-studio/jbr"

Install a debug build on a connected device

./gradlew :app:installDebug

Build a signed release APK

./gradlew :app:assembleRelease
# Output: app/build/outputs/apk/release/app-release.apk

The release config currently signs with the standard debug keystore, which is good enough for personal use. Replace it with your own keystore in app/build.gradle.kts (buildTypes.release.signingConfig) before publishing.


Testing without driving

Driving to the car for every change is impractical. Two tools help.

Virtual second display (simulates the HUD on a phone or emulator)

# Create a 1280x480 overlay window on the device. It appears as displayId 3.
adb shell settings put global overlay_display_devices "1280x480/160"

# Inspect available displays (the HUD will be FLAG_PRESENTATION).
adb shell dumpsys display | grep -E "displayId|FLAG_PRESENTATION"

# Turn it off when done.
adb shell settings put global overlay_display_devices null

Demo mode for the HUD activity

In the app, open the HUD calibration screen and tap the Test on HUD button. The HUD activity opens on the detected secondary display with a fake maneuver populated, so you can adjust the projection insets and scale visually without needing GPS or a real route.

Route simulation along a real polyline

After building a route on the main screen, tap the Simulate button. The foreground service interpolates position along the polyline at about 50 km/h and publishes location updates to the HUD activity, so you can see the route move without driving.


Project layout (quick reference)

app/src/main/
├── AndroidManifest.xml
├── java/com/example/hudnav/
│   ├── HudNavApp.kt              MapKit init
│   ├── MainActivity.kt           map, search, tap-to-pin, Go button
│   ├── HudActivity.kt            HUD overlay on the projector
│   ├── SettingsActivity.kt       HUD calibration sliders
│   ├── NavigationService.kt      ForegroundService: GPS + simulation
│   ├── state/                    NavigationState + StateFlow repository
│   └── util/                     display locator, density, geo helpers
└── res/
    ├── layout/                   3 activities + reusable slider include
    ├── drawable/                 maneuver glyphs, position arrow, backgrounds
    ├── raw/hud_map_style.json    minimal Yandex map style for the HUD
    └── values/                   colors / themes / strings

Troubleshooting

Symptom Likely cause / fix
SDK location not found sdk.dir line in local.properties is missing or got concatenated with the next line. Fix the newline.
App launches, map area is blank or grey Wrong or missing MAPKIT_API_KEY in local.properties. Re-check the value and rebuild.
bad base-64 crash on launch Old font_certs.xml left over from downloadable fonts. Should not happen on main; if it does, wipe .gradle/ and rebuild.
Unable to locate a Java Runtime from ./gradlew JAVA_HOME not exported. See Build and run above.
HUD activity does not start on the projector The system blocks launchDisplayId for unsigned apps on stock Android. The Deepal S09 head unit allows it; on a regular phone use the virtual overlay above and pick that display id in the picker.
wm density 72 -d <id> exits non-zero Requires root or a system-signed APK. Safe to ignore on a regular phone, only relevant on the actual car.

License

Personal project, no license declared. Yandex MapKit usage is governed by the Yandex Developer Terms (https://yandex.com/legal/mapkit_sdk_agreement/).

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages