No Description

Krasimir Kazakov eb243b119a feat: download and install updates in app 1 week ago
android eb243b119a feat: download and install updates in app 1 week ago
assets 035d933fb7 feat: use stylized icon choices for pinned shortcuts 1 week ago
docs eb243b119a feat: download and install updates in app 1 week ago
lib eb243b119a feat: download and install updates in app 1 week ago
releases eb243b119a feat: download and install updates in app 1 week ago
test eb243b119a feat: download and install updates in app 1 week ago
tool 0cf321ad40 docs: align emulator setup with the verified host GPU 1 week ago
.gitignore 7c3ef2090d feat: build the single-screen CarDash launcher 1 week ago
.metadata 7c3ef2090d feat: build the single-screen CarDash launcher 1 week ago
AGENTS.md eb243b119a feat: download and install updates in app 1 week ago
README.md eb243b119a feat: download and install updates in app 1 week ago
analysis_options.yaml 7c3ef2090d feat: build the single-screen CarDash launcher 1 week ago
pubspec.lock 7c3ef2090d feat: build the single-screen CarDash launcher 1 week ago
pubspec.yaml 0bfd245a59 feat: add Gogs update check and 1.0.1 update test 1 week ago

README.md

CarDash

A calm, configurable Android car dashboard launcher, built with Flutter.

CarDash replaces the tablet home screen with one landscape page: a large clock, battery and Wi-Fi status, a now-playing media card, and up to 16 buttons — Navigation, Music, Radio, All apps, plus any apps you pin from All Apps. The first three can be shown, hidden and assigned to installed apps; Settings opens from the gear next to Wi-Fi. External apps open full-screen using the normal Android launcher mechanism. No overlays, no root, no kiosk setup.

Verified on Android 15 and Android 10 tablet emulators at 1280×800, 1280×720 and 1024×600. Runs on a physical Android 17 HyperOS tablet. OBD-II UI/parser is implemented; the ELM327 socket path still needs a real-car test. Landscape only.

Download

Gogs limits release attachments to 32 MB, so the 54 MB universal APK is linked directly from the repository.

Screenshots

Light Dark
CarDash light home CarDash dark home

Also: Home with top-right Settings · Home at 1024×600 · All apps · app picker · Settings · accent & buttons · Settings · Car data · Settings · Media access · Now playing · 1280×720 · GPS speed · Mocked OBD · 1280×720 · Mocked OBD · 1280×800 · Night mode · Blue accent · user-app icon on Home · pinned-app menu · change-icon grid · PIN lock · 1024×600 layout

The two Mocked OBD images are documentation renders with a simulated adapter state (82 km/h, 34% throttle, 7.4 L/100 km, Outside 17°C). They are not live vehicle data.

Features

  • One home screen — no pages, no top bar, no bottom dock; information and controls live on the home page.
  • Large clock and date with the device's 12/24-hour preference.
  • Battery, charging and Wi-Fi status, with one switch to hide the battery level and charging bolt.
  • OBD-II car data — optional Bluetooth Classic ELM327 adapter. Shows digital speed, a throttle bar and rolling 5 km MAF economy, plus ambient temperature when the adapter provides it.
  • GPS speed fallback — when no OBD adapter is connected and precise location is already allowed, show speed from GPS; it reads 0 km/h when stationary. CarDash never prompts for this; GPS must be enabled and location previously allowed (for example through the weather toggle).
  • Location temperature fallback — if OBD has no ambient value, an optional Settings toggle fetches the current temperature from Open-Meteo using the device location. The row reads Outside, 7°C for OBD or Sofia, 7°C for weather, and turns red below 3°C. No network/selection means no row.
  • Now-playing media card — the circular ring shows song progress around a play/pause button. The song title and artist scroll along the bottom; paused audio stops the scroll and holds its position. When nothing is playing it reads Nothing playing. The volume slider, −/+, and Mute pill remain.
  • Update check — on startup, CarDash queries the public Gogs release list without blocking the dashboard. Settings → Updates shows the current version, a Check button, and an Update action that downloads the APK and opens Android’s installer. Android still requires confirmation and a one-time “install unknown apps” allowance; silent installation is not attempted.
  • Now-playing access — Settings → Media grants Android notification access, used only to read the active media session’s title, duration and position. CarDash never reads or stores notification content.
  • Configurable home buttons — switches in Settings show or hide Navigation, Music and Radio. All apps is always the last button; Settings now sits next to Wi-Fi in the top-right status area and is no longer a grid tile.
  • Pin any app from All Apps — long-press an app to add it to Home. The home page holds up to 16 buttons including All apps, and the grid shrinks as it fills.
  • Edit a pinned app — long-press it on Home for Rename, Change icon and Remove. Pinned apps show their own icon by default. Rename changes only the Home label; Change icon offers Default plus 29 monochrome line icons (white on dark, black on light); Remove takes effect without confirmation. Re-add the app from All Apps.
  • One-time launcher tip — the first run shows a short notification that the default-launcher setting lives in Settings. It is not shown again.
  • All apps — searchable grid of every launchable app, launched full-screen.
  • Media-aware Music tile — while media audio is active and the Music shortcut is assigned, the stylized music icon shows a small animated equalizer. Android exposes media-active state, not the playing package, to a normal launcher; see the limitation below.
  • Six accent colors — Green, Blue, Amber, Rose, Violet or Teal, applied across the whole interface.
  • Prevent CarDash from sleeping — a Settings switch, on by default. Turn it off to use the system display timeout.
  • Night mode — long-press an empty part of the Home background to go black with a very dim centered clock; tap anywhere to return. Long-presses on buttons and cards are unaffected.
  • A short onboarding hint — the long-press hint fades away two minutes after app start, then stays gone.
  • Light / Dark / Automatic theme. Automatic uses a fixed local-time window (default 19:00–07:00), editable in Settings.
  • Optional PIN — four digits, stored as a salted PBKDF2 hash in Keystore-backed storage. It is requested only when the launcher process cold-starts, never when returning from an app.
  • Standard Android home role — no overlay, kiosk or root.
  • Android 10+, landscape-only, tablet-first (verified at 1280×800).
  • No accounts, no telemetry, no T&C screen. Network access is used only for the optional Open-Meteo temperature fallback.

Requirements

  • Flutter 3.47.8 / Dart 3.13.7 (or a compatible newer stable release)
  • Android SDK 36, build-tools 36
  • JDK 21 for Gradle (the machine default is JDK 27, which is not validated)
  • Android 10 (API 29) or newer device/emulator
  • A landscape tablet or an emulator; the app locks itself to landscape
  • The prepared tablet AVDs use the host GPU; a working GPU driver is recommended
  • Optional: a Bluetooth Classic ELM327 adapter already paired in Android
  • Optional: location access for the Open-Meteo temperature fallback

The Android application ID is com.wasp.cardash_launcher. Android package segments cannot contain hyphens, so the requested com.wasp.cardash-launcher spelling is normalized to an underscore.

export JAVA_HOME=/usr/lib/jvm/java-21-openjdk
export ANDROID_HOME=/opt/android-sdk
export PATH="$ANDROID_HOME/platform-tools:$PATH"

Quick start

flutter pub get
./tool/check.sh

# Boot the prepared 10.1" 1280×800 Android 15 tablet (headless)
./tool/emulator.sh 35

# Build, install, and make CarDash the HOME app
./tool/install.sh debug

If the emulator does not yet exist on another machine, create it with:

sdkmanager "system-images;android-35;google_apis;x86_64"
avdmanager create avd -n cardash_tablet_api35 \
  -k "system-images;android-35;google_apis;x86_64" \
  -d "10.1in WXGA (Tablet)"

The repository also has an Android 10 AVD (cardash_tablet_api29) for minimum-version checks.

Manual install

flutter build apk --release
adb install -r build/app/outputs/flutter-apk/app-release.apk
adb shell cmd role add-role-holder android.app.role.HOME com.wasp.cardash_launcher
adb shell am start -a android.intent.action.MAIN -c android.intent.category.HOME

On a real tablet, use Settings → General → Home app → Set as default and accept the system prompt. Android will not let an app force itself into the home role silently. CarDash no longer keeps a home-role banner on the dashboard; the first run shows a one-time tip pointing to this setting.

Using CarDash

Action Result
Tap Navigation / Music / Radio Open the assigned app full-screen
Long-press Navigation / Music / Radio Pick a different installed app
Tap an unassigned shortcut Open the app picker
Settings → Accent Pick Green, Blue, Amber, Rose, Violet or Teal
Settings → Battery & charging Show or hide battery level and charging bolt
Settings → Prevent CarDash from sleeping Keep the display on, or use the system timeout
Long-press an empty part of Home Enter black night mode with a dim clock
Tap the night screen Return to the dashboard
Settings → Home buttons switches Show or hide Navigation, Music, Radio
Long-press an app in All Apps Add it to Home (up to 16 buttons)
Long-press an added app on Home Rename, Change icon or Remove
Settings → Car data Pick a paired ELM327 or None
Settings → Car data → Location temperature Enable GPS weather fallback
No OBD + allowed location + GPS on Shows GPS speed above the volume card; 0 when stopped
Temperature row OBD ambient, or location weather when OBD has none
Settings Theme, accent, media access, battery, home buttons, default-home role, PIN
All apps Search every launchable app; tap to open, hold to pin
Music tile while media is active Shows the selected app icon + equalizer
Circular ring Song progress; tap the centre to play/pause
Song title at the card bottom Scrolls only while playing; holds when paused
Screen Stays awake while CarDash is in front
Mute pill Toggle media mute
Slider or − / + Set media volume
Hardware volume keys Adjust the dashboard's media volume; the slider follows

The app hides the Android status and navigation bars while CarDash is in the foreground. Swipe from an edge to reveal them temporarily; they hide again when the app resumes.

Settings

General

  • Light / Dark / Auto theme.
  • Accent: Green, Blue, Amber, Rose, Violet or Teal.
  • Battery & charging: one switch hides both the level and charging bolt.
  • Prevent CarDash from sleeping: keep the display on; on by default.
  • Auto night window (default dark from 19:00, light from 07:00).
  • Home buttons: show/hide Navigation, Music, Radio; live count out of 16.
  • Assign the app for each slot; All apps is fixed and last.
  • Settings is always available from the gear next to Wi-Fi.
  • Home role status and shortcut to the system prompt.

Media

  • Notification access for the now-playing title, duration and progress.
  • Read-only: CarDash does not read notification content.
  • Without access the ring stays empty and the card shows a generic Playing / Nothing playing state.

Car data

  • OBD-II adapter dropdown: None plus paired Bluetooth Classic devices.
  • Connection status and a Find/Allow action for Bluetooth permission.
  • Location temperature toggle: “Show temperature from current location if no OBD-II connected.” Enabling it asks for location permission.
  • Read-only note: CarDash never writes to the ECU.

Updates

  • Non-blocking check against the public Gogs releases.
  • Shows current/latest version; Update downloads the APK and opens Android’s installer.
  • Android confirms the install and, on first use, asks to allow CarDash as an unknown-app source. No silent installation.

Security

  • Set, change or remove a four-digit PIN.
  • The PIN is requested only on a cold start. It does not re-lock when switching apps, after screen-off, or after returning from Navigation. This is the agreed behavior, not an oversight.
  • The PIN protects the launcher UI. It is not the Android lock screen; set a device screen lock separately for device-level security.
  • There is no PIN recovery. Resetting app data removes it.

Architecture

lib/
  core/        design tokens, theme controller, icons, shared widgets
  data/        models, platform services, SettingsRepository (single source of truth)
  features/
    home/      home page, shortcut grid, volume card, OBD/weather controllers
    apps/      All Apps, app-picker sheet
    settings/  General, Car data + Security
    lock/      PIN pad, cold-start lock screen
android/...    MainActivity, LauncherBridge, SystemBridge, TelemetryBridge, ObdService
tool/          emulator, install, check scripts
docs/          implementation plan, design notes
  • Flutter owns all UI. Kotlin exposes package enumeration/launching, the HOME role, battery/Wi-Fi, media volume, active media metadata, Bluetooth OBD and one-shot location over method channels.
  • The OBD layer is read-only, Bluetooth Classic SPP, bonded devices only. A worker thread serializes ELM327 requests; Flutter polls the latest snapshot.
  • SettingsRepository is the only persistence path. Controllers are ChangeNotifiers injected with provider.
  • External apps are separate activities; Android has no public API to embed them inside the launcher. This app deliberately accepts full-screen launching for maximum compatibility.
  • Full OBD/weather design and hardware notes: docs/OBD_TEMPERATURE.md.

Testing

flutter analyze
flutter test
./tool/check.sh

The 50 tests cover PIN hashing/persistence, settings persistence, theme/accent, dark accent tinting, battery visibility, first-run state, slot visibility, pinned apps, custom labels/icons, the 16-button cap at 1280×800, 1280×720 and 1024×600, the dense shortcut grid, the equalizer animation, OBD economy, the OBD card, media-key playback, media metadata/progress, the marquee, the play/pause ring, the keep-awake preference, the night overlay, GPS speed fallback and the update version/availability logic. Native package enumeration, the HOME role, volume, app launching and PIN flows were verified on API 35 and API 29 emulators. Location permission, reverse geocoding and the Open-Meteo fallback were verified live on the API 35 emulator. Now-playing title, artist, progress and pause/resume were verified against a live Chrome MediaSession. The OBD hardware path compiles and is covered by the parser/economy design, but no ELM327 adapter is available on this machine; socket behavior still needs a car test. Release The 1.0.1 universal APK is built from this tree. The emulator completed a live 1.0.0 → 1.0.1 in-app update; the physical tablet has the 1.0.0 installer build ready for its own test.

Troubleshooting the emulator

The prepared AVDs use the host GPU (-gpu host), which is the verified setup on this machine. Software rendering with SwiftShader segfaulted on the API 35 image. If your machine has no usable GPU, you can try:

CARDASH_GPU=swiftshader_indirect ./tool/emulator.sh 35

The prepared AVD resolution is 1280×800. If the emulator is already running, ./tool/emulator.sh stop shuts it down before starting a different one. The Android 15 AVD is left running headlessly after development; use ./tool/emulator.sh 35 window for a visible window.

Compatibility and limitations

  • minSdk 29 (Android 10); compile/targetSdk 36. Nothing in the design requires a newer Android release.
  • Landscape only (sensorLandscape). The home page is designed for 1280×800 and verified at 1280×720 and 1024×600; 16 buttons fit at all three.
  • 16-button cap includes All apps; Settings lives in the top-right status area and does not consume a slot. Only apps pinned from All Apps show an original app icon by default; the predefined slots, All apps and the Settings gear stay stylized. A pinned icon can be replaced with the Default app icon or the 29 stylized choices.
  • Accent-tinted dark theme — dark canvas, surfaces and borders blend toward the selected accent, so Blue no longer shows a green base.
  • Media equalizer reacts to system media activity. The now-playing title and progress use the active Android MediaSession, which requires the special notification-access grant in Settings → Media.
  • Notification access is used only for media metadata. CarDash does not read notification text or store track history. Revoke it in Android settings at any time; the ring and title then fall back to an empty/generic state.
  • Screen-on is controlled by Settings → Prevent CarDash from sleeping (default on). It applies only while CarDash is the foreground window; with the switch off, the normal Android display timeout applies.
  • Night mode is a display overlay only. It does not change panel brightness or keep the screen awake by itself; the screen-on preference still applies. Long-press on cards and buttons is reserved for their own actions.
  • Onboarding hint is anchored to process start and disappears after two minutes; it does not return until the next cold start.
  • No embedded third-party app UI. Navigation/Music/Radio are launched in their own full-screen windows.
  • Renaming changes the Home label only. Android does not allow a launcher to rename another app's installed label.
  • Custom icons are bundled monochrome SVGs, so they follow the light/dark theme. Default restores the pinned app's own icon.
  • Play/pause uses Android media keys. It resumes a paused session when one responds; if nothing is playing, it opens the app assigned to the Music slot (or asks you to choose one). The ring shows Play whenever audio is inactive.
  • Updates download and invoke Android’s installer. CarDash never silently installs. Android requires the user to confirm each install and, once, to allow CarDash as an unknown-app source.
  • Song progress/title require notification access. Without it, Android does not expose MediaSession metadata to a normal launcher; the card still controls playback and shows Nothing playing or Playing.
  • GPS speed fallback requires precise location already granted and the GPS provider enabled; CarDash does not request permission from this path. OBD speed wins whenever an adapter is connected, and stale/no-fix GPS values are hidden.
  • OBD-II is a subset: Bluetooth Classic SPP only, paired devices only, read-only. Speed, throttle, MAF economy and ambient temperature are implemented; RPM, coolant, voltage, MIL/DTCs, fuel level and BLE/Wi-Fi adapters are not.
  • Weather fallback uses Open-Meteo and the device location. It requires location permission and network access; if either is unavailable, the temperature row is hidden. OBD ambient wins whenever present.
  • Location data is not stored. Only the selected adapter address and the weather toggle are persisted.
  • QUERY_ALL_PACKAGES is used to list all launchable apps. It is reasonable for a launcher but requires a Play policy declaration if the app is ever distributed; this is a local/sideload build for now.
  • Network access is used for the optional Open-Meteo temperature fallback and the Gogs release check. There are no accounts, ads, telemetry or silent auto-updates.
  • The launcher cannot replace Android's lock screen. The PIN does not protect a running session, by design.

Design

The visual language is inspired by the TrailCurrent Godwit head unit (MIT): warm neutral surfaces, a selectable instrument accent, large numerals and quiet line icons. It is not a copy of that UI.

  • Typeface: Manrope (SIL Open Font License), bundled offline.
  • Icons: Lucide (ISC), bundled as SVGs.
  • Palette and tokens: lib/core/theme/app_colors.dart.

Roadmap

  • Optional compact now-playing control beside the volume card.
  • Real-car ELM327 soak test (speed/throttle/MAF/ambient).
  • Release signing configuration.
  • Real-device soak test on an Android 10 car tablet.

License

This repository is in local development and has not been pushed or published. A project license has not been chosen yet. Third-party asset licenses: Manrope (OFL) and Lucide (ISC). The design is inspired by TrailCurrent Godwit (MIT).