A daily weather-insight app for Android. Each morning, at a time you set, ClothesCast posts a one-sentence comparative summary — “4°C warmer than yesterday, leave the jumper at home” or “50% chance of rain at 3pm — take an umbrella” — derived on-device from yesterday’s actual weather, today’s forecast, and the clothes thresholds you’ve configured.
It can also speak the insight aloud — through the platform TTS engine, or through an online voice (Gemini) if you’d rather a more natural read.
See PRIVACY.md for what data leaves the device and when.
Working v1: full daily-insight pipeline (Open-Meteo → on-device rendering → notification +/- TTS), Compose Settings UI for everything (location, schedule, delivery mode, units, clothes rules, voice engine, API keys, calendar tie-in), runtime permission UX, boot/timezone/locale alarm re-arm, and a debug “Fire insight now” button for testing without waiting until the scheduled time.
Distribution: every push to main ships a signed AAB to the Play Store
internal track for testers, and a debug APK is also available from the CI
artifact (see below) for sideload installs.
commonMain later
without a rewrite.USE_EXACT_ALARM) → BroadcastReceiver → WorkManager
for daily scheduling that survives Doze, reboot, timezone and locale
changes.TextToSpeech engine
(default, fully on-device), or an online voice via the Gemini API.
Online engines are BYOK; keys are encrypted on-device via Tink +
Android Keystore + DataStore Preferences.READ_CALENDAR granted, the daily
sentence can name the event the clothes advice is for —
“Bring an umbrella for your 3pm meeting.”ACCESS_COARSE_LOCATION granted, the
worker uses the phone’s coarse location at notify-time instead of the
city you picked.| Module | Status |
|---|---|
:core:domain |
Pure-Kotlin models, use cases (insight rendering, clothes rules), repository interfaces |
:core:data |
Open-Meteo forecast + geocoding clients, Gemini TTS client, parser tests |
:app |
Compose UI, manifest, receivers, worker, alarm scheduler, DI, platform TTS, calendar reader, encrypted key store |
Three options, in roughly increasing order of friction:
main build automatically. Every push to main ships a
signed AAB to this track.testers group in
the FAD console, you get the debug APK from every push to main with a
one-tap install link.main.
.github/workflows/ci.yml).app-debug-apk artifact.app-debug.apk to the phone (Drive, USB, etc.).POST_NOTIFICATIONS. Without it the daily insight has nowhere
to go.jumper, jacket,
shorts, umbrella) are a sensible starting set. Add your own — e.g.
gloves when temperature drops below 5°C.READ_CALENDAR to let the daily
sentence reference an overlapping event by name.Requires JDK 21. Pure-Kotlin modules build without an Android SDK:
./gradlew :core:domain:test :core:data:test
The :app module needs the standard Android SDK (compileSdk 35,
build-tools;35.0.0) on the local Android Studio install path. The CI
workflow shows the exact setup.
Some Android OEMs (Xiaomi, Oppo, OnePlus, aggressive Samsung profiles) kill
backgrounded apps and prevent the alarm from firing on schedule. See
dontkillmyapp.com for per-OEM workarounds —
typically “exclude from battery optimisations” and “allow autostart”. The
underlying scheduling primitive (setExactAndAllowWhileIdle with
USE_EXACT_ALARM) is the strictest the platform offers; anything that
suppresses it is a vendor-side override.