Open-source Android weather widget that puts a detailed forecast directly on your home screen — no ads, no tracking, no account. Choose a 48-hour or 7-day meteogram with temperature, precipitation, and daylight on a single glanceable chart. Powered by the free Open-Meteo API.
- Two home-screen widgets: 48-hour chart (46h forecast + 6h past) and 7-day chart, both rendered natively via AndroidSVG
- Meteogram chart with:
- Temperature line with gradient fill
- Precipitation bars
- Daylight intensity (computed from cloud cover and sun position)
- Current time marker
- Weekday labels (weekly) / hour labels (48h)
- Smart refresh:
- Foreground timer checks every minute for stale data (>15 min) and redraws at half-hour boundaries
- AlarmManager (~15 min inexact) catches up on device wake
- WorkManager periodic task (~30 min) with network-connected constraint
- BOOT_COMPLETED refresh on device restart
- Event-driven updates (screen unlock, network change, locale/timezone change)
- Flexible location:
- GPS with reverse geocoding (native platform geocoder)
- City search via Open-Meteo geocoding API
- Recent cities remembered
- Berlin default when GPS unavailable
- Material You dynamic color support (Android 12+)
- Light/dark theme following system preference
- 36 languages supported
- Locale-aware units (°F for US/Liberia/Myanmar, °C elsewhere; 12/24h time)
- Offline support with smart caching:
- Automatic cache fallback when offline
- Fibonacci retry backoff (1, 2, 3, 5, 8 min) for background refresh
- Visual "OFFLINE" watermark on stale data (>1 hour old)
- Cached location and city name preserved
- No API key required — uses free Open-Meteo API
- No ads, no tracking, no account
- Flutter 3.x
- Android SDK
- Android device or emulator
# Get dependencies
flutter pub get
# Generate localizations
flutter gen-l10n
# Build options (via Makefile)
make debug # x86_64 only (68MB) - for emulator
make release # arm64 only (19MB) - for phones
make install # Build release + install on device
make install-debug # Build debug + install on emulator- Install the app on your device
- Open the app and let it load weather data
- Long-press on home screen → Widgets
- Find "Meteograph" and drag to home screen
- Tap widget to refresh data
lib/
├── main.dart # App entry point, edge-to-edge setup
├── generated/version.dart # Generated git version info (gitignored)
├── l10n/ # Localization files (36 languages)
│ ├── app_en.arb # English (template)
│ └── app_*.arb # ar, be, bg, bn, bs, cs, da, de, el, es,
│ # fi, fr, hi, hr, is, it, ja, jv, ka, ko,
│ # mk, nl, no, pa, pl, pt, ro, sk, sq, sv,
│ # ta, tr, uk, vi, zh
├── screens/
│ └── home_screen.dart # Main app screen (both chart panels)
├── services/
│ ├── location_service.dart # GPS + city search + reverse geocoding
│ ├── widget_service.dart # Home widget updates via home_widget
│ ├── native_svg_service.dart # Method channel to Kotlin (SVG / weather / cache)
│ ├── units_service.dart # Temperature unit and 12/24h logic
│ └── material_you_service.dart # Material You color pass-through
├── theme/
│ └── app_theme.dart # Colors, themes, Material You mapping
└── widgets/
└── native_svg_chart_view.dart # PlatformView wrapper for native SVG
android/app/src/main/kotlin/.../
├── MainActivity.kt # Flutter activity + method channel
├── MeteogramApplication.kt # Receiver registration, alarm schedule
├── MeteogramWidgetProvider.kt # Base widget (48h) — shared logic
├── MeteogramWeeklyWidgetProvider.kt # 7-day variant (extends base)
├── WidgetEventReceiver.kt # Locale / timezone / network receiver
├── WidgetAlarmScheduler.kt # 15-min inexact AlarmManager
├── WidgetAlarmReceiver.kt # Alarm broadcast handler
├── BootCompletedReceiver.kt # Refresh on device boot
├── WidgetUtils.kt # Shared widget helpers
├── WidgetChartColors.kt # Material You color resolver
├── WeatherUpdateWorker.kt # WorkManager periodic refresh (~30 min)
├── WeatherFetcher.kt # Native HTTP client for Open-Meteo
├── WeatherDataParser.kt # Cached-weather parser + chart views
├── SvgChartGenerator.kt # Native SVG generator (single source of truth)
├── MaterialYouColorExtractor.kt # Dynamic color extraction
├── MaterialYouColorWorker.kt # Background color updates
├── SvgChartPlatformView.kt # In-app native SVG rendering
└── SvgChartViewFactory.kt # PlatformView factory
android/app/src/main/res/
├── layout/meteogram_widget.xml # 48h widget layout
├── layout/meteogram_widget_weekly.xml # 7-day widget layout
├── xml/meteogram_widget_info.xml
├── xml/meteogram_widget_weekly_info.xml
└── drawable/widget_background.xml
Uses Open-Meteo free APIs (no API key required):
GET https://api.open-meteo.com/v1/forecast
?latitude={lat}
&longitude={lon}
&hourly=temperature_2m,precipitation,cloud_cover
&timezone=UTC
&past_hours=32
&forecast_days=7
The 32-hour past window keeps the weekly chart's "now" line at the same fraction of width as the 48-hour chart. The 48-hour chart slices a smaller window (6h past + 46h future) from the same cache.
Returns hourly data for:
temperature_2m— temperature in Celsiusprecipitation— rain/snow in mmcloud_cover— cloud coverage percentage (0-100)
Daylight intensity is computed locally from cloud cover and solar position.
GET https://geocoding-api.open-meteo.com/v1/search
?name={query}
&count=8
&language={locale}
The language parameter uses the user's current locale so results come
back in their preferred language.
The home screen widgets use:
HomeWidgetProviderfrom the home_widget packageRemoteViewsfor native Android widget rendering- SVG chart generated in Kotlin (
SvgChartGenerator.kt) and rasterised via AndroidSVG - AlarmManager (~15 min inexact), WorkManager (~30 min with network constraint), and BOOT_COMPLETED for reliable background refresh
- Event receivers for unlock / network / locale / timezone changes
RemoteViews Limitations:
- Only supports: TextView, ImageView, LinearLayout, RelativeLayout, FrameLayout
- Does NOT support: View, Space, custom views
- Foreground:
home_screen.dart→NativeSvgService.fetchWeather()→ KotlinWeatherFetcherpulls from Open-Meteo → caches to SharedPreferences - SVG generation:
SvgChartGenerator.ktreads the cache and produces an SVG string — single source of truth used by both the in-app chart and both widgets - In-app: SVG rendered via native PlatformView (AndroidSVG)
- Widget: SVG rasterised to a bitmap and shown in an ImageView
- Background: AlarmManager / WorkManager / BOOT_COMPLETED / event receivers trigger a native refresh + widget re-render, Flutter engine stays off
Edit lib/theme/app_theme.dart for the in-app UI and
android/app/src/main/kotlin/.../SvgChartGenerator.kt for the chart itself
(SvgChartColors.light / SvgChartColors.dark). Example from the Dart side:
static const light = MeteogramColors(
temperatureLine: Color(0xFFFF6B6B), // Coral red
precipitationBar: Color(0xFF1A9D92), // Deeper teal (legibility on white)
daylightBar: Color(0xFFFF8F00), // Dark amber
nowIndicator: Color(0xFFFFE66D), // Golden yellow
// ...
);Edit android/app/src/main/res/drawable/widget_background.xml:
<gradient
android:startColor="#BA1B2838"
android:endColor="#BA0D1B2A"
android:angle="135" />
<corners android:radius="24dp" />- Create
lib/l10n/app_XX.arb(copy from app_en.arb) - Translate all strings
- Run
flutter gen-l10n
Supported locales are auto-detected from ARB files.
| Package | Purpose |
|---|---|
| home_widget | Android/iOS widget support |
| geolocator | GPS location |
| geocoding | Reverse geocoding (city names) |
| http | API requests |
| path_provider | File storage |
| shared_preferences | Settings storage |
| intl | Locale-aware formatting |
Material You theming uses native Android color extraction (MaterialYouColorExtractor.kt).
Business Source License 1.1 - see LICENSE
- Free for non-commercial and personal use
- Commercial use requires a license
- Converts to MIT on 2029-01-01
Contributions welcome! Please read the existing code style and test your changes.
- Weather data: Open-Meteo
- Widget support: home_widget
- SVG rendering: AndroidSVG



