Skip to content

ZeusWatch

VersionLicensePlatformKotlinComposeAPI

A free, open-source Android weather app with a premium dark UI, 37 customizable cards, animated Lottie icons, Gemini Nano AI summaries, multi-source forecasts, route weather planning, custom alert rules, and smart alerts. No API keys required for core forecasts. Powered by Open-Meteo, FMI, LibreWXR, RainViewer, Blitzortung, NWS, MeteoAlarm, JMA, MET Norway, Environment Canada, Hong Kong Observatory, BMKG, WMO SWIC, and optional WeatherFlow Tempest PWS observations.

design

Screenshots

TodaySettingsRadar
ZeusWatch Today screen with current conditions and forecast cardsZeusWatch Settings screen with refined category cardsZeusWatch Radar screen with live map controls

Quick Start

git clone https://github.com/SysAdminDoc/zeuswatch.git
cd zeuswatch
./gradlew assembleStandardDebug

Install the APK from app/build/outputs/apk/standard/debug/ or open in Android Studio and run directly.

Requirements: Android Studio with AGP 9.2 support, JDK 17+, Android SDK 37.0

Download

Releases publish per-ABI APKs to reduce download size:

APKSizeUse when
ZeusWatch-standard-arm64-v8a~20 MBMost modern phones (2017+)
ZeusWatch-standard-armeabi-v7a~17 MBOlder 32-bit devices
ZeusWatch-standard-universal~49 MBUnsure which ABI you need
ZeusWatch-freenet-*Same variantsF-Droid compatible (no Google Play Services)
ZeusWatch-wear~5 MBWear OS companion watch app

Download from GitHub Releases.

Verify Downloads

Release APK signing certificate SHA-256:

FB:03:10:AA:52:0F:6C:C6:EB:DA:04:61:71:9E:A9:22:40:EA:2B:4A:A1:D0:15:79:A9:D1:8A:F5:A9:5F:A7:CD

For every release, verify the checksum file and APK signatures locally:

cat ZeusWatch-vX.Y.Z-provenance.json
sha256sum -c SHA256SUMS.txt
apksigner verify --verbose --print-certs ZeusWatch-standard-arm64-v8a-vX.Y.Z.apk
apksigner verify --verbose --print-certs ZeusWatch-freenet-arm64-v8a-vX.Y.Z.apk
apksigner verify --verbose --print-certs ZeusWatch-wear-vX.Y.Z.apk

The provenance JSON records the source commit, clean-tree state, toolchain versions, APK hashes, signing certificate SHA-256, and local verification commands used for the release.


Features

Core Weather

FeatureDescription
Current ConditionsLarge temp display, feels-like with wind chill/heat index explanation, condition, high/low, sky gradients
Yesterday Comparison"5° warmer than yesterday" label in hero header with color-coded warm/cool indicator
Weather SummaryTime-aware natural language forecast ("Clear skies this morning") via Gemini Nano through ML Kit GenAI Prompt API (default) or template engine, with UV/humidity warnings
Hourly Forecast72h scrollable strip with temp, animated Lottie icons, wind direction arrows, precip probability, smart rain timeline ("Rain likely within 3h"), feels-like when significantly different
16-Day ForecastExpandable daily rows with temperature range bars, rain hours, sunshine, snowfall, wind gusts, UV max. "Warmest" day highlighted
Temperature GraphInteractive Canvas graph with drag-to-inspect, precipitation bars, forecast average normals band, optional confidence bands, and detail-sheet uncertainty explanations
Rain Next Hour60-minute precipitation nowcasting bar chart from Open-Meteo minutely_15 data
Temperature NormalsShaded band on temperature graph showing forecast average range with dashed boundary lines

Data & Visualization

FeatureDescription
Today's Details10+ cell grid: humidity, wind (with gusts), UV, pressure (with trend indicator), visibility, dew point (with comfort descriptor), sunrise/sunset, cloud cover, snowfall/snow depth
Wind CompassAnimated Canvas compass with direction needle, Beaufort scale coloring, gust display
UV Index BarColor gradient bar with level markers, descriptions, "UV peaks at 2 PM" annotation, and safe sun exposure time
Air QualityPM2.5, PM10, O3, NO2, SO2, CO with EPA/European AQI scales, circular gauge, dominant pollutant highlighting, and 5-day daily AQI forecast bars
Pollen DataPer-species animated bars: alder, birch, grass, mugwort, olive, ragweed (hourly fallback)
Moon PhaseCanvas moon illumination with Conway's algorithm, moonrise/moonset, day length, sunrise/sunset countdown
Sun ArcSemicircular sun position visualization with "Sunset in 2h 15m" countdown
Snowfall CardCurrent snowfall rate + snow depth + daily total, auto-hidden when no snow
Sunshine DurationToday's sunshine hours with circular progress ring
Severe Weather PotentialCAPE-based thunderstorm indicator with instability levels
Outdoor Activity ScoreWeighted 0-100 composite score from temp, wind, UV, humidity, precipitation, AQI with factor breakdown bars
Golden HourMorning and evening golden hour times for photographers
Humidity & ComfortHumidity gauge with comfort level indicator, dew point, and zone markers
Precipitation Forecast24-hour precipitation probability bars with peak callout and accumulation total
Pressure Trend24-hour barometric pressure line graph with trend direction and delta
Wind Forecast24-hour wind speed line graph with gust overlay bars and peak callout
Forecast EvolutionOptional Open-Meteo Single Runs card compares recent model runs for temp/rain-risk deltas
Provider AgreementOptional card compares next-24h temperature and precipitation across 2-3 forecast providers with agreement/divergence badges
Tempest PWSOptional WeatherFlow Tempest card listens for one-minute observations from the user's own station
Clothing SuggestionsRule-based outfit recommendations from feels-like temp, rain, snow, UV, wind
Pet SafetyPavement temperature estimates, heat stress, cold exposure, storm anxiety alerts

Smart Alerts & Safety

FeatureDescription
Severe Weather AlertsMulti-source: NWS (US), MeteoAlarm (31 EU countries), JMA (Japan), Environment Canada, Hong Kong Observatory (selectable for HK), BMKG (Indonesia), WMO SWIC (130+ countries global fallback), Pirate Weather (with API key)
Alert Source PreferenceConfigurable country routing: Auto-detect, NWS only, MeteoAlarm, JMA, Environment Canada, All sources; Data Sources can also select Hong Kong Observatory and BMKG
4 Notification ChannelsExtreme (alarm sound, bypass DND), Severe (high), Moderate (default), Minor (low)
Alert DeduplicationTracks seen alert IDs so the same warning is never re-notified
Multi-Location AlertsMonitors all saved locations by default, not just current GPS
Progress Nowcast NotificationsAndroid 16+ nowcast alerts use ProgressStyle segments for dry/light/steady/heavy rain timelines, with BigText fallback on older devices
Driving Condition AlertsBlack ice, fog, low visibility, hydroplaning, high wind, snow/ice — derived from forecast data
Route Weather PlannerEnter/share endpoints or import a bounded GPX 1.1 route/track through Android's document picker; samples follow cumulative geometry, preserve partial results, and clearly label assumed-speed estimates as non-navigation guidance
Health AlertsMigraine triggers (pressure/temp swings, configurable threshold), respiratory (humidity extremes), arthritis (temp swing)
Haptic FeedbackSeverity-appropriate vibration patterns when alerts display
Expired Alert FilteringSkips alerts past their expiration timestamp
Custom Alert RulesUser-defined thresholds: today's high/low, wind gusts, 24h rain, UV peak. Hourly background evaluation with per-rule dedupe. Separate notification channel
Pressure TrendRising/Falling/Steady indicator computed from hourly surface pressure data

Radar & Maps

FeatureDescription
Radar ProvidersUser-selectable: Windy Radar WebView, LibreWXR Native MapLibre playback with nowcast tiles (max zoom 12, Viper HD), RainViewer Native MapLibre playback with past-radar tiles (max zoom 7, Universal Blue), NWS Radar (US), or NWS Radar Lite (US)
Animated Radar PlaybackPlay/pause, frame slider, recent-past labels, timestamp overlay, cached frame metadata fallback (native mode)
Radar Preview CardRecent selected native radar tile + CartoDB dark basemap on the Today tab
Radar TabFull-screen radar in the bottom nav with provider-aware rendering
Route Weather OverlayRadar includes a foreground route-weather estimator for straight-line corridors or imported GPX geometry, with sampled weather and risk timing
Map Layer SelectorOverlay layers: Radar, Lightning, Satellite, Clouds
Active Warning PolygonsNative radar renders NWS warning polygons with severity colors and tappable alert details
Lightning Strike OverlayReal-time global lightning data via Blitzortung WebSocket with capped GeoJSON rendering and reconnect backoff
Community Weather ReportsFirebase Firestore-backed crowd-sourced condition reporting with rate limiting

Multi-Source Forecast System

SourceData TypesRegion
Open-MeteoForecast, AQI, Pollen, Minutely, Historical, Single RunsGlobal
Open-Meteo ModelsBOM ACCESS-G, UK Met Office, DMI HARMONIE, Meteo-France forecast/AROME nowcast sourcesAustralia, UK/North Atlantic, Northern Europe, France/Central Europe
Finnish Meteorological InstituteHARMONIE WFS forecastFinland / Nordic-Baltic region
NWSAlertsUnited States
MeteoAlarmAlerts31 EU countries
JMAAlertsJapan
MET NorwayForecastGlobal
Environment CanadaForecast, AlertsCanada
Hong Kong ObservatoryForecast, AlertsHong Kong
BMKGAlertsIndonesia
GeoSphere AustriaINCA 15-minute nowcast, AlertsAustria / Alpine region
WMO SWICAlertsGlobal fallback by country
OpenWeatherMapForecast (fallback)Global (API key)
Pirate WeatherForecast (fallback)Global (API key)
Bright SkyForecast (fallback)Germany

The WeatherSourceManager supports primary + fallback source per data type with automatic failover. Sources are configurable globally in Settings, saved locations can override forecast and alert providers from the Locations screen, and Settings > Data Sources shows local provider health with a redacted diagnostics export for support.

Forecasts are cached as normalized WeatherData per location and provider, so saved-location switches can render cached conditions immediately while the selected source refreshes in the background. Open-Meteo's older response cache is retained only as a migration fallback for Open-Meteo reads.

Settings > Data Sources includes an opt-in Open-Meteo FlatBuffers mode. When enabled, the main Open-Meteo forecast and historical On This Day archive calls request format=flatbuffers, decode through com.open-meteo:sdk, and automatically fall back to the existing JSON path if the binary response cannot be fetched or decoded.

Settings > Data Sources also includes an opt-in read-only ecosystem ContentProvider at content://com.sysadmindoc.nimbus.provider.weather/ with Breezy-compatible version, locations, and weather paths for Tasker, KWGT, and similar tools. External queries require the com.sysadmindoc.nimbus.READ_PROVIDER permission and read cached data only; they never trigger live network refreshes.

When providers publish localized condition or alert text, matching user-locale source wording is preferred before falling back to app WMO labels.

Widgets (Jetpack Glance)

WidgetSizeContent
Current3x1Icon + temp + location + high/low
3-Day3x2Current conditions + 3-day forecast columns + staleness indicator
Forecast4x3Current + 6hr hourly strip + 5-day rows + staleness indicator
Hourly Strip4x1Current temp + next 5 hourly temps with icons and precip%
Saved Cities4x3/4x4Up to 5 saved locations with cached temperature and condition
Temperature1x1/2x1Compact icon + current temperature
Compact2x1Icon, temperature, location, and updated state
Daily4x2Five-day outlook rows with high/low and condition icons
  • Per-widget location configuration via config activity
  • Tap-to-refresh from freshness badges and empty states; tap widget body to open the app when loaded
  • Proactive background caching for all saved locations
  • Material You theming with GlanceTheme

Customization

SettingOptions
Radar ProviderWindy Radar / LibreWXR Native / RainViewer Native / NWS Radar (US) / NWS Radar Lite (US)
Icon StyleMeteocons Animated (Lottie, default) / Material Icons / Custom Icon Packs
Theme ModeStatic Dark / Weather Adaptive (accent colors shift: amber for sun, blue for rain, purple for storms)
Weather SummaryAI-Generated (Gemini Nano, default) / Standard template
Card VisibilityToggle each of the 37 card types on/off
Card OrderingReorderable card list in Settings with move up/down arrows
TemperatureFahrenheit / Celsius
Wind Speedmph / km/h / m/s / knots
PressureinHg / hPa / mbar
Precipitationinches / mm
Visibilitymiles / km
Time Format12-hour / 24-hour
Hourly Range72 hours (default) / 48 hours
NotificationsAlert notifications, persistent weather notification (default on), nowcasting alerts with Android 16 progress timelines, driving alerts, health alerts
Alert SeverityExtreme only / Severe+ / Moderate+ / All
Alert SourceAuto-detect / NWS / MeteoAlarm / JMA / Environment Canada / All, plus Hong Kong Observatory and BMKG through Data Sources
Data TogglesSnowfall, CAPE, sunshine duration, golden hour, Beaufort colors, outdoor score, yesterday comparison
HealthMigraine alerts with configurable pressure threshold (3.0/5.0/7.0/10.0 hPa/3h)
HapticsVibration feedback for weather alerts
Weather ParticlesRain, snow, and sun ray animations on/off
Cache TTLConfigurable: 15 / 30 / 60 / 120 minutes
Source DiagnosticsLocal provider success/failure history, cache age, active fallback state, and redacted support export

More

FeatureDescription
Compare WeatherSide-by-side comparison with weather icons, visibility, cloud cover, value highlighting, and a provider chart overlay for hourly temperature/rain divergence
Location SearchOpen-Meteo geocoding with debounced search and error feedback
Multi-LocationRoom database with add/remove/auto-GPS saved locations
Drag-to-Reorder LocationsLong-press drag handles to reorder saved locations with batch persistence
Location Temperature PreviewSaved location list shows cached temperatures with weather condition icons
Per-Location SourcesSaved locations can override forecast and alert providers while falling back to the app defaults when unset
Provider-Aware Offline CacheSaved locations keep source-specific cached forecasts for immediate offline-first rendering before background refresh
Share as TextFormatted weather summary via system share sheet
Share as ImageRendered dark-themed weather card as PNG
Persistent NotificationAlways-on notification showing current conditions (toggleable)
Proactive CachingBackground worker pre-fetches weather for all saved locations
Offline ModeRoom-cached weather data survives network failures with "Cached" indicator
Adaptive LayoutPhone and tablet layouts via LazyColumn. Tablets get two-pane weather + radar (840dp+)
Live Weather WallpaperRain, snow, thunderstorm, sun rays, cloud wisps, fog particle effects over existing wallpaper
Wear OS CompanionWatch app, Material3 animated weather tile, and complications for temperature, condition/high-low, UV, and icon slots
Smartspacer PluginOptional Smartspacer target and temperature complication read the ZeusWatch cache for Pixel At a Glance-style current conditions
Ecosystem ContentProviderOptional Breezy-compatible read-only provider exposes saved locations and cached forecasts to Tasker, KWGT, and similar tools with an Android permission gate
Premium State PolishFocused, pressed, disabled, loading, empty, and recovery states use consistent dark glass chrome across phone, widgets, and Wear OS
AccessibilityTalkBack descriptions on all Canvas components, alert icons, non-color risk cues on color-coded weather surfaces, and merged card semantics with liveRegion alerts
Localization FoundationCore navigation, Today shell states/card headers/card microcopy/alert dialogs/report sheet, Settings controls/enums, Home Card labels, Custom Alerts, Locations, Compare, widgets, and Wear OS state copy use Android string resources with Spanish plus Arabic/Hebrew RTL resources; provider-native condition and alert text is preferred when upstream language matches the user's locale
App ShortcutsLong-press launcher: Search, Radar, Settings, Compare
Deep Linkszeuswatch:// URI scheme for locations, radar, settings, compare
F-Droid Readyfreenet build flavor with no proprietary dependencies
Custom Icon PacksDiscover bundled + external APK icon packs via intent
Alert Expiry CountdownAlert banners show "3h 15m left" / "Expired"
Sunrise/Sunset CountdownAstronomy card shows "Sunset in 2h 15m" with auto-switch
Smart Rain TimelineHourly strip shows "Rain likely within 3h" or "Rain ending soon"
Data Staleness Indicator"Updated" text turns amber when data is 1+ hours old
Wind Direction ArrowsHourly forecast items show wind direction when > 10 km/h
Dew Point Comfort ColorsColor-coded comfort level (blue=dry, green=comfortable, orange=muggy, red=oppressive)
Time-Aware Summary"Clear skies this morning" / "Overcast this afternoon" / "tonight"
Collapsible SettingsAll sections collapsible with tap-to-toggle, Data Sources + Advanced start collapsed

Architecture

┌──────────────────────────────────────────────────────────────────────────┐
│ UI Layer (Jetpack Compose) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │MainScreen│ │RadarScreen│ │ Settings │ │Locations │ │CompareScreen │ │
│ │+ViewModel│ │+ViewModel │ │ + VM │ │+ VM │ │+ ViewModel │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └──────┬───────┘ │
│ │ │ │ │ │ │
│ 37 Card Types via LazyColumn items() │
│ WeatherSummary | NowcastCard | RadarPreview | HourlyStrip | TempGraph │
│ DailyForecast | UvIndexBar | WindCompass | AqiCard | PollenCard | ... │
│ ClothingSuggestion | PetSafety | DrivingAlert | HealthAlert | ... │
│ │
├──────────────────────────────────────────────────────────────────────────┤
│ Domain Layer (Repositories + Evaluators + Source Manager) │
│ ┌────────────────┐ ┌──────────────────┐ ┌───────────────────────────┐ │
│ │WeatherRepo │ │WeatherSource │ │AlertRepo + AlertSource │ │
│ │(fetch+cache+ │ │Manager (primary/ │ │Adapters (NWS, MeteoAlarm,│ │
│ │ direct+history)│ │fallback adapters)│ │JMA, ECCC) │ │
│ └────────────────┘ └──────────────────┘ └───────────────────────────┘ │
│ ┌────────────┐ ┌───────────┐ ┌────────────┐ ┌────────────────┐ │
│ │AirQuality │ │LocationRepo│ │RadarRepo │ │Community │ │
│ │Repo(AQ+ │ │(geocode+ │ │(LibreWXR/ │ │ReportRepo │ │
│ │pollen) │ │Room+sort) │ │RainViewer) │ │(Firestore) │ │
│ └───────────┘ └────────────┘ └────────────┘ └────────────────┘ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────────┐ │
│ │WeatherSummary │ │ClothingSuggestion│ │DrivingCondition │ │
│ │Engine (NLG/AI) │ │Evaluator │ │Evaluator + HealthEval│ │
│ └──────────────────┘ └──────────────────┘ │+ PetSafetyEvaluator │ │
│ └──────────────────────┘ │
│ │
├──────────────────────────────────────────────────────────────────────────┤
│ Data Layer │
│ ┌───────────────────────────────┐ ┌───────────────────────────────┐ │
│ │ Retrofit APIs │ │ Room Database (v5) │ │
│ │ Open-Meteo Forecast │ │ weather_cache │ │
│ │ Open-Meteo Geocoding │ │ saved_locations (+sources) │ │
│ │ Open-Meteo Air Quality │ │ │ │
│ │ Open-Meteo minutely_15 │ │ DataStore + encrypted keys │ │
│ │ Open-Meteo Historical │ │ Units, display, cards, │ │
│ │ Open-Meteo Single Runs │ │ notifications, health, │ │
│ │ LibreWXR / RainViewer Radar │ │ source defaults, haptics, │ │
│ │ NWS / MeteoAlarm / JMA / ECCC │ │ seen alert IDs, widgets │ │
│ │ Blitzortung WebSocket │ │ widget location prefs │ │
│ │ Firebase Firestore │ │ │ │
│ └───────────────────────────────┘ └───────────────────────────────┘ │
│ │
│ DI: Hilt (NetworkModule + DatabaseModule) │
│ Background: AlertCheckWorker + WidgetRefreshWorker (WorkManager) │
│ Notifications: 4 alert channels + 1 persistent weather channel │
└──────────────────────────────────────────────────────────────────────────┘

Stack: Gradle 9.4.1, AGP 9.2.0, Kotlin 2.3.21, Jetpack Compose (BOM 2026.06.01), Hilt 2.60, Retrofit 3.0.0, OkHttp 5.4.0, Room 2.8.4, DataStore 1.2.1 with Tink-encrypted API keys, Open-Meteo SDK 1.10.0 FlatBuffers decoder, Smartspacer SDK 1.1.2, ML Kit GenAI Prompt 1.0.0-beta2, MapLibre 13.3.1, Glance 1.1.1, Wear Tiles 1.6.1, ProtoLayout 1.4.1, WorkManager 2.11.2, Lottie 6.7.1, Coil 3.1.0, Firebase Firestore (BOM 34.12.0)


APIs

All core APIs are free with no keys required:

APIPurposeRate Limit
Open-Meteo ForecastCurrent, hourly (48-72h), daily (16d), optional FlatBuffers payloads, minutely_15 nowcasting10,000/day
Open-Meteo model forecastsNo-key regional model forecast sources: BOM ACCESS-G, UK Met Office, DMI HARMONIENo key required
Open-Meteo HistoricalYesterday's weather for comparison and On This Day archive data, with optional FlatBuffers payloads10,000/day
Open-Meteo Single RunsOptional forecast-evolution model-run comparisonNo key required
Open-Meteo GeocodingLocation search + reverse geocode10,000/day
Open-Meteo Air QualityAQI, pollutants, pollen (6 species), 5-day daily forecast10,000/day
LibreWXRFOSS radar tile source with RainViewer-compatible metadata, Viper HD color scheme, max zoom 12, and nowcast framesCC-BY-4.0 data
RainViewerPast radar tile images only (past 2h, max zoom 7, Universal Blue PNG; no nowcast/satellite)Fair use
Windy.comEmbedded interactive radar (WebView option)Fair use
NWS AlertsUS severe weather alertsFair use
MeteoAlarmEU severe weather alerts (31 countries)Fair use
JMAJapan severe weather alertsFair use
Environment CanadaCanadian severe weather alertsFair use
Hong Kong ObservatoryHong Kong current conditions, 9-day forecast, and weather warningsFree open data
BMKGIndonesian CAP nowcast weather alertsNo key required
WMO SWICGlobal severe weather alert fallbackFair use
FMI Open DataNordic/Baltic HARMONIE WFS forecastNo key required
MET NorwayForecast fallbackFair use
Bright SkyGermany forecast fallbackFair use
BlitzortungReal-time lightning strike data (WebSocket)Fair use
Firebase FirestoreCommunity weather reportsFree tier

Optional fallback sources (require API keys configured in Settings):

APIPurpose
OpenWeatherMapForecast fallback
Pirate WeatherForecast fallback
WeatherFlow TempestPersonal station observations

OpenWeatherMap and Pirate Weather keys plus WeatherFlow Tempest access tokens are stored in an encrypted DataStore backed by Tink and Android Keystore. Existing plaintext keys migrate automatically on first launch.

Community reports use an anonymous append-only Firestore model: users can read reports and submit new condition reports, but reports cannot be updated or deleted after submission. Reports are stored without an owner id so readers cannot correlate one account's reports into a movement history; coordinates are rounded to two decimal degrees before upload, reports disappear from app results after two hours, and Firestore TTL removes expired documents asynchronously. The server-side per-account 5-minute write-rate limit is enforced entirely through a separate per-uid throttle ledger. Collection reads are capped server-side to a bounded page size (no whole-collection firehose), and nearby report lookups use geohash ranges plus exact-distance filtering so dense reports on the same latitude cannot hide truly nearby reports. firestore.rules validates coarsened coordinates, geohash shape, condition enum values, timestamp freshness, two-hour expiry, note length, and the query page-size bound. The standard flavor installs Firebase App Check before Firestore/Auth access: debug builds use the Firebase debug provider and release builds use Play Integrity. Firebase enforcement is still a console-side switch; enable Firestore App Check enforcement only after registering the app, reviewing request metrics, and configuring Play Integrity settings for non-Play distribution if needed. The freenet flavor is unaffected and uses a no-op community report repository with no Firebase dependency.

Open-Meteo Parameters Used

Current: temperature, humidity, feels-like, weather code, wind (speed/direction/gusts), pressure, UV, visibility, dew point, cloud cover, precipitation, snowfall, snow depth, CAPE

Hourly: All current params + precipitation probability, sunshine duration, surface pressure (48-72h configurable)

Daily: Weather code, temp high/low, sunrise/sunset, UV max, wind speed max/gusts max/direction dominant, precipitation sum/probability/hours, snowfall sum, sunshine duration (16d)

Minutely_15: Precipitation (24 intervals = 6 hours of 15-min resolution)


Build Flavors

FlavorDescription
standardIncludes Google Play Services for FusedLocationProvider + Gemini Nano through ML Kit GenAI Prompt
freenetF-Droid compatible — no proprietary dependencies (uses Android LocationManager)
# Standard (Google Play)
./gradlew assembleStandardRelease
# F-Droid
./gradlew assembleFreenetRelease

Project Structure

app/src/main/java/com/sysadmindoc/nimbus/
├── MainActivity.kt # Deep links, WindowSizeClass, theme wiring
├── NimbusApplication.kt # Hilt, WorkManager, notification channels
├── data/
│ ├── api/ # Retrofit services (8), Room DAOs, database
│ ├── model/ # Domain models, Room entities, API DTOs
│ ├── repository/ # Repositories, UserPreferences, CardConfig
│ │ ├── WeatherRepository # Direct fetch + cache + history + minutely
│ │ ├── WeatherSourceManager # Multi-source primary/fallback adapter system
│ │ ├── AlertRepository # Country-auto-detecting multi-source alerts
│ │ ├── AirQualityRepository # AQI + pollen + 5-day daily forecast
│ │ ├── LocationRepository # Geocoding + Room + reordering
│ │ ├── RadarRepository # LibreWXR/RainViewer tile URLs + frame list
│ │ ├── DrivingRouteWeatherPlan # Route waypoint weather/risk model
│ │ └── CommunityReportRepo # Firestore crowd-sourced reports
│ └── location/ # GPS location provider, reverse geocoder
├── di/ # Hilt modules (Network, Database)
├── ui/
│ ├── component/ # 30+ reusable Compose components
│ │ ├── WeatherSummaryCard # NLG / AI-generated summary
│ │ ├── NowcastCard # 60-min precipitation chart
│ │ ├── RadarPreviewCard # Live radar tile
│ │ ├── TemperatureGraph # Interactive drag-to-inspect graph + normals band
│ │ ├── OutdoorScoreCard # Activity score gauge
│ │ ├── DrivingAlertCard # Driving hazard alerts
│ │ ├── HealthAlertCard # Health trigger alerts
│ │ ├── ClothingSuggestionCard # Outfit recommendations
│ │ ├── PetSafetyCard # Pet weather safety alerts
│ │ ├── GoldenHourCard # Photography times
│ │ ├── SunMoonArc # Sun position visualization
│ │ ├── AqiGauge # Circular AQI gauge + daily forecast
│ │ ├── AnimatedWeatherIcon # Material/Lottie/Custom switcher
│ │ ├── HumidityCard # Humidity gauge with comfort
│ │ ├── RadarLayerSelector # Map overlay layer chips
│ │ ├── AlertBanner # Pulsing severity-colored alert bar
│ │ └── ... # 14 more components
│ ├── screen/
│ │ ├── main/ # Today/Hourly/Daily tabs + tablet two-pane
│ │ ├── radar/ # Dual-provider radar + playback + layers + route weather planner
│ │ ├── settings/ # Entry shell + extracted section/control composables
│ │ ├── locations/ # Search + drag-to-reorder saved locations
│ │ └── compare/ # Side-by-side weather comparison
│ ├── navigation/ # NavHost with typed routes
│ └── theme/ # Colors, typography, weather-adaptive themes
├── util/ # 12 utility classes
│ ├── WeatherSummaryEngine # Template-based NLG
│ ├── GeminiNanoSummaryEngine # On-device AI summaries (standard flavor)
│ ├── WeatherFormatter # 30+ unit-aware format methods
│ ├── DrivingConditionEvaluator# Ice, fog, hydroplaning, wind detection
│ ├── HealthAlertEvaluator # Migraine, respiratory, arthritis triggers
│ ├── ClothingSuggestionEvaluator # Outfit recommendation engine
│ ├── PetSafetyEvaluator # Pet weather hazard detection
│ ├── MeteoconMapper # WMO code to Lottie filename mapping
│ ├── HapticHelper # Severity-based vibration patterns
│ ├── AlertNotificationHelper # Alert + nowcast progress notifications
│ ├── WeatherNotificationHelper# Persistent current-weather notification
│ ├── AlertCheckWorker # Background alert monitoring
│ ├── AccessibilityHelper # TalkBack descriptions
│ ├── ShareWeatherHelper # Text + image sharing
│ ├── IconPackManager # Bundled + external icon pack discovery
│ └── BlitzortungService # Real-time lightning WebSocket
├── wallpaper/
│ └── WeatherWallpaperService # Live weather wallpaper with particle effects
├── widget/ # 8 Glance home screen widgets
│ ├── NimbusSmallWidget # 3x1: temp + icon
│ ├── NimbusMediumWidget # 3x2: current + 3-day
│ ├── NimbusLargeWidget # 4x3: hourly + 5-day
│ ├── NimbusForecastStripWidget# 4x1: hourly temp strip
│ ├── NimbusSavedCitiesWidget # 4x3/4x4: saved-city overview
│ ├── NimbusTempWidget # compact temp-only surface
│ ├── NimbusCompactWidget # 2x1 compact current conditions
│ ├── NimbusDailyWidget # 4x2 daily outlook
│ ├── WidgetRefreshWorker # Periodic refresh + proactive caching
│ ├── WidgetRefreshAction # Tap-to-refresh Glance callback
│ ├── WidgetConfigActivity # Per-widget location picker
│ └── WidgetLocationPrefs # Widget-to-location DataStore mapping
└── smartspacer/ # Smartspacer target/complication cache bridge

Configuration

Settings Sections (all collapsible)

SectionOptions
DisplayRadar provider, icon style (Meteocons/Material/Custom), theme mode, summary style (AI/template)
CardsToggle + reorder each of 37 card types with move up/down arrows
UnitsTemperature, wind, pressure, precipitation, visibility, time format
NotificationsAlert notifications (severity threshold, multi-location, source preference), persistent weather, nowcasting timelines, driving, health
Data DisplayHourly range (48/72h), snowfall, CAPE, sunshine, golden hour, Beaufort colors, outdoor score, yesterday comparison
HealthMigraine alerts with pressure threshold (3.0/5.0/7.0/10.0 hPa/3h)
AccessibilityHaptic feedback for alerts
Visual EffectsWeather particle animations
Data SourcesApp-wide primary + fallback defaults per data type, Open-Meteo FlatBuffers opt-in, Gadgetbridge broadcast, ecosystem ContentProvider, API keys (collapsed by default)
AdvancedCache TTL (15/30/60/120 min) (collapsed by default)
AboutVersion, data source, license

Card Types (37)

All cards can be independently shown/hidden and reordered:

Weather Summary, Radar Preview, Rain Next Hour, Hourly Forecast, Temperature Graph, Forecast Evolution, Provider Agreement, Tempest PWS, Daily Forecast, UV Index, Wind Compass, Air Quality, Pollen, Outdoor Activity Score, Snowfall, Severe Weather Potential, Golden Hour, Sunshine Duration, Driving Conditions, Health Alerts, What to Wear, Pet Safety, Moon Phase, Humidity & Comfort, Precipitation Forecast, Pressure Trend, Wind Forecast, Today's Details, Cloud Cover, Visibility, On This Day, Aurora / Kp Index, Activity Index, Solar Irradiance, Marine, Flood Risk, Climate Outlook


Animated Icons (Default)

ZeusWatch uses Meteocons animated Lottie weather icons by default (MIT license).

  1. Download the "fill" style Lottie JSON files from the Meteocons repository
  2. Place them in app/src/main/assets/meteocons/

See app/src/main/assets/meteocons/README.md for the full file list. The app gracefully falls back to Material Icons when Lottie files are missing. You can switch to static Material Icons in Settings > Display > Icon Style.

Custom Icon Packs

Third-party icon packs are discoverable via:

  • Bundled packs in app/src/main/assets/iconpacks/ with manifest.json
  • External APKs exposing the com.sysadmindoc.nimbus.ICON_PACK intent

Testing

# Unit tests — formatters, models, repositories, ViewModels
./gradlew testStandardDebugUnitTest
# Public provider contract checks — live or cached schema/availability smoke
py -3 tools/check_provider_contracts.py
# Release provenance manifest — after signed APKs and SHA256SUMS.txt exist
py -3 tools/generate_release_provenance.py
# Instrumented Compose UI tests — screen rendering, interactions
./gradlew connectedStandardDebugAndroidTest
# Accessibility release gate - WCAG contrast, touch targets, Compose checks
./gradlew accessibilityGate
# Startup performance gate - release startup Macrobenchmark p95 <1200 ms# Use a stable physical target for release acceptance; emulator results are advisory
./gradlew startupGate
# Baseline profile collection - use a stable physical benchmark target
./gradlew :app:generateStandardReleaseBaselineProfile
# Firestore community-report rules tests
npm install
npm run test:firestore-rules
SuiteFrameworkCoverage
UnitJUnit 4 + MockK + Turbine + coroutines-testWeatherFormatter (20), WeatherCode (12), Accessibility contrast, AirQuality (14), Alerts (9), MainViewModel (10), LocationsViewModel (7)
UICompose UI Test + JUnit4 + Hilt TestingMainScreen, SettingsScreen, LocationsScreen, accessibility audit gate
PerformanceAndroidX Macrobenchmark 1.5.0-alpha07 + Baseline Profile Gradle pluginCold-start release p95 gate and standard release baseline-profile collection
Firestore rulesFirebase Emulator + rules-unit-testingCommunity report create/read validation, malformed/stale rejection, append-only delete/update denial

1,100+ phone unit tests and 74 wear unit tests across 110+ test suites.


Contributing

Issues and PRs welcome. Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-feature)
  3. Commit changes (git commit -m 'Add my feature')
  4. Push to the branch (git push origin feature/my-feature)
  5. Open a Pull Request

Development Notes

  • All raw API values are metric (Celsius, km/h, mm, hPa, meters). Unit conversion happens in WeatherFormatter.
  • Unit settings flow via CompositionLocalProvider(LocalUnitSettings provides ...). Standalone screens (Radar, Compare) read from their ViewModel's prefs.settings flow.
  • Card rendering is driven by CardType enum + LazyColumn items() in the main-screen content renderer. Add new cards by extending CardType and adding a render branch.
  • Weather-adaptive theming reads from LocalWeatherThemeState CompositionLocal.
  • Multi-source forecasts use WeatherSourceManager with Hilt WeatherSourceAdapter map bindings — add new sources by implementing an adapter and registry binding.
  • Alert sources use AlertSourceAdapter interface — auto-detected by country via Geocoder.
  • Current roadmap and research notes are maintained locally in ROADMAP.md and RESEARCH.md. Historical research lives in docs/research-archive.md.

Roadmap

Current planning is maintained locally in ROADMAP.md; research synthesis is maintained locally in RESEARCH.md. Historical phase-1 research remains in docs/research-archive.md.

Implemented through v1.5.0 (historical snapshot; superseded by the current documentation above):

  • 29 dynamic card types with user-configurable order and visibility
  • Gemini Nano AI weather summaries enabled by default (with template fallback)
  • Animated Meteocons Lottie icons enabled by default
  • Sequential permission flow: Location -> Notifications -> Background Location
  • 72h hourly forecast, persistent notifications, nowcasting alerts on by default
  • 4 new data cards: Humidity, Precipitation Chart, Pressure Trend, Wind Forecast
  • Smart context: rain timeline, sunrise/sunset countdown, time-aware greetings
  • Feels-like overlay on temperature graph
  • Temperature range bars in daily forecast with color-coded gradients
  • Alert expiry countdown on banners
  • Card reorder in Settings with move up/down arrows
  • Collapsible settings sections
  • Pull-to-refresh on all tabs
  • Compare screen with weather icons and value highlighting
  • Outdoor score with factor breakdown bars
  • Wind direction arrows and dew point comfort colors
  • Data staleness indicator (amber when stale)
  • Native MapLibre animated radar with layer selector
  • Real-time lightning strike overlay (Blitzortung WebSocket)
  • Live weather wallpaper with particle effects
  • Multi-source forecast fallback (10 selectable forecast sources)
  • International alert sources (NWS, MeteoAlarm, JMA, Environment Canada, Hong Kong Observatory, BMKG)
  • Community weather reports (Firebase Firestore)
  • Tablet two-pane layout
  • 22 crash/bug fixes, Crashlytics removed

Privacy

ZeusWatch collects zero user data. No analytics, no tracking, no telemetry, no location history, no advertising identifiers, no data shared with third parties.

  • No accounts required. The app works fully offline after the first forecast fetch.
  • Foreground-only location. The manifest declares fine/coarse location only; ZeusWatch never requests background location, and widgets/workers reuse the last foreground fix.
  • No network requests except weather data. All API calls go directly to the configured weather services (Open-Meteo, RainViewer, etc.) — no intermediary servers.
  • Community reports (standard flavor only) use anonymous Firebase Auth with no personal identifiers, round coordinates to two decimal degrees, disappear after two hours, and use asynchronous Firestore TTL deletion. The freenet flavor has zero Firebase or Google dependency.
  • API keys/tokens (optional, user-provided) are encrypted on-device via Android Keystore + Tink AEAD and never leave the device.
  • Cloud backup excluded. Preferences, widget data, encrypted keys, and databases are excluded from Android cloud backup and device-to-device transfer via data_extraction_rules.xml.
  • Crash reports (ACRA) are opt-in, sent via email, and PII-redacted before dispatch.

The freenet flavor contains no proprietary code and is suitable for F-Droid distribution.


License

This project is licensed under the GNU Lesser General Public License v3.0.

Weather data provided by Open-Meteo.com under CC BY 4.0. Nordic/Baltic forecast data by Finnish Meteorological Institute. Radar tiles by LibreWXR or RainViewer. Interactive radar by Windy.com. Lightning data by Blitzortung.org. Alert data by National Weather Service, MeteoAlarm, JMA, Environment Canada, Hong Kong Observatory, BMKG, and WMO SWIC. Animated icons by Meteocons (MIT).

About

A free, open-source Android weather app with a premium dark UI. No API keys required. Powered by Open-Meteo, Windy.com, and NWS.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

7 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages