~/heizoelradar.md

HeizölRadar

HeizölRadar ist eine Android-App, die den günstigsten Heizölpreis für die eigene Postleitzahl und Liefermenge im Blick behält. Sie prüft alle 15 Minuten im Hintergrund die Angebote einer Heizölpreisvergleichsseite, meldet sich nur dann, wenn sich der beste Preis geändert hat, und führt mit einem Tipp direkt zur Bestellseite des günstigsten Händlers.

Bald im Google Play Store: Die finale Version von HeizölRadar wird demnächst im Google Play Store verfügbar sein.

  • Android
  • Kotlin
  • WorkManager
  • Coroutines
  • Eigenes Diagramm (Canvas)
  • Ohne Backend

Screenshots

So sieht die App aus: der Startbildschirm mit dem besten Preis und dem Preisverlauf, die Einstellungen und die Dialoge für Liefermenge und Postleitzahl.

HeizölRadar Startbildschirm mit bestem Preis pro 100 Liter, Preisänderung seit 24 Stunden und Preisverlauf als Diagramm
Startbildschirm: bester Preis und Preisverlauf
HeizölRadar mit Kennzahlen Tief, Hoch und Messwerte sowie den Einstellungen für Postleitzahl, Liefermenge und Benachrichtigungen
Kennzahlen und Einstellungen
Dialog zur Liefermenge mit Eingabefeld und Schnellwahl von 1.000 bis 5.000 Litern
Dialog: Liefermenge mit Schnellwahl
Dialog zur Eingabe der Postleitzahl, für die HeizölRadar den günstigsten Preis sucht
Dialog: Postleitzahl eingeben

Auf einen Blick

MerkmalWert
PlattformAndroid 8.0 oder neuer (minSdk 26, targetSdk 34)
SpracheKotlin
OberflächeKlassische Views mit XML-Layouts, ohne UI-Bibliothek
HintergrundprüfungWorkManager, alle 15 Minuten
DiagrammSelbst gezeichneter Canvas-View
DatenLokal auf dem Gerät, kein eigener Server
Version1.0
VerfügbarkeitFinale Version demnächst im Google Play Store

Funktionen

  • Postleitzahl: Wird beim ersten Start abgefragt und lässt sich jederzeit ändern. Ein Wechsel startet sofort eine neue Prüfung, der Verlauf wird pro Postleitzahl getrennt geführt.
  • Liefermenge: Wählbar von 500 bis 32.000 Litern (Standard 3.500 Liter, mit Schnellwahl). Der Verlauf wird pro Postleitzahl und Menge geführt, weil der Preis pro 100 Liter von der Menge abhängt.
  • Benachrichtigung bei Preisänderung: Die App meldet sich nur, wenn sich der günstigste Preis gegenüber der letzten Prüfung geändert hat. Die Meldung lässt sich in den Einstellungen abschalten.
  • Direkt bestellen: „Jetzt bestellen“ in der App und in der Benachrichtigung öffnet die Bestellseite des aktuell günstigsten Angebots.
  • Preisverlauf: Liniendiagramm für 24 Stunden, 7 Tage, 30 Tage oder alle Daten, mit Tooltip beim Antippen und Ziehen sowie Tief, Hoch und Trend gegenüber dem Stand vor 24 Stunden.

Technische Hintergründe

Architektur auf einen Blick

Die App besteht aus wenigen, klar getrennten Teilen. Eine Hintergrundaufgabe holt die Preise, speichert sie und entscheidet, ob eine Meldung nötig ist. Die Oberfläche zeigt nur den gespeicherten Stand und das Diagramm.

WorkManager (alle 15 Minuten)
  ?? PriceCheckWorker (CoroutineWorker)
       ?? Angebote für PLZ und Liefermenge abrufen
       ?? günstigstes Angebot bestimmen (Preis pro 100 l)
       ?? Messwert im Verlauf speichern (CSV)
       ?? Preis geändert?
            ?? ja  ? Benachrichtigung mit Direktlink zur Bestellung
            ?? nein ? keine Meldung
BausteinAufgabe
MainActivityOberfläche mit Preiskarte, Diagramm und Einstellungen. Plant die Prüfung und fragt Berechtigungen an.
PriceCheckWorkerPrüfung im Hintergrund: Angebote abrufen, günstigstes bestimmen, Verlauf speichern, bei Preisänderung benachrichtigen.
PriceHistorySpeichert die Messwerte als CSV-Datei und verwirft Einträge nach zwei Jahren.
NotificationHelperBenachrichtigungskanal und Aktionen „Jetzt bestellen“ und „Preisverlauf“.
PriceChartViewEigenes Liniendiagramm mit Fläche, leuchtendem Endpunkt und Touch-Tooltip.

Hintergrundprüfung mit WorkManager

Die Prüfung läuft als periodische Aufgabe (PeriodicWorkRequest) im 15-Minuten-Takt, das ist die kürzeste Wiederholungsrate, die WorkManager erlaubt. Der Worker ist ein CoroutineWorker, die Netzwerkabfrage läuft also nicht auf dem Hauptthread. Beim Start der App wird die Aufgabe mit der Richtlinie „UPDATE“ eingeplant, damit es nie doppelte Aufgaben gibt. Zusätzlich gibt es eine manuelle Prüfung, die sofort ausgelöst werden kann.

Damit der Takt zuverlässig eingehalten wird, bittet die App beim ersten Start um eine Ausnahme von der Akku-Optimierung.

Datenquelle

Die Angebote kommen über eine Schnittstelle einer Heizölpreisvergleichsseite. Die App übergibt Postleitzahl und Liefermenge und erhält pro Händler unter anderem den Preis pro 100 Liter, den Gesamtpreis und die Lieferzeit zurück. Der Liefermengenbereich der App reicht von 500 bis 32.000 Litern, dem Bereich, für den zuverlässig Angebote geliefert werden.

Preisvergleich und Benachrichtigung

Aus der Angebotsliste bestimmt der Worker das günstigste Angebot anhand des Preises pro 100 Liter. Verglichen wird auf den Cent gerundet, damit Rundungsrauschen keine Meldungen auslöst. Nur wenn sich der Preis gegenüber der letzten Prüfung geändert hat, entsteht eine Benachrichtigung. Sie zeigt Preis und Händler im deutschen Zahlenformat, ein Tipp öffnet die Bestellseite, und zwei Aktionen führen zum Bestellen oder zum Preisverlauf. Der Direktlink wird aus der Konfiguration und dem Angebot zusammengebaut, genauso wie ihn die Angebotsliste selbst erzeugt.

Preisverlauf und eigenes Diagramm

Jeder Messwert landet als Zeile in einer CSV-Datei im privaten App-Speicher: Zeitstempel, Preis, Händlerkennung, Postleitzahl, Menge und Händlername. Einträge werden nach zwei Jahren verworfen, und der Verlauf wird pro Postleitzahl und Menge gefiltert. Das Diagramm zeichnet ein eigener View direkt auf den Canvas: Verlaufslinie, Fläche, leuchtender Endpunkt und ein Tooltip, der beim Antippen und Ziehen folgt. Solange weniger als zwei Messwerte vorliegen, zeigt er einen Radar-Platzhalter. Eine Diagramm-Bibliothek ist dafür nicht nötig.

Zustand und Einstellungen

Postleitzahl, Liefermenge, der Schalter für Benachrichtigungen und der letzte Stand der Prüfung liegen in den SharedPreferences. Ändert sich Postleitzahl oder Menge, löscht die App den letzten Stand, entfernt die offene Benachrichtigung und startet sofort eine neue Prüfung. Die Oberfläche aktualisiert sich über einen OnSharedPreferenceChangeListener von selbst.

Bewusst wenige Abhängigkeiten

Das Projekt kommt mit vier Bibliotheken aus: core-ktx, appcompat, work-runtime-ktx und die Kotlin-Coroutines. Es gibt weder Material-Komponenten noch Compose noch Firebase. Benachrichtigungen kommen lokal aus der App und brauchen kein Backend.

Berechtigungen

  • Internet und Netzwerkstatus für die Abfrage
  • Benachrichtigungen (ab Android 13 zur Laufzeit abgefragt)
  • Ausnahme von der Akku-Optimierung für einen zuverlässigeren 15-Minuten-Takt

Design

Die App ist durchgehend dunkel gehalten, mit einem Akzentverlauf von Mint über Blau zu Violett. Mint steht für „günstiger“ und „Tief“, Pink für „teurer“ und „Hoch“. Farbige Linien gehören zum Look: Verlaufsrahmen an Karten und Eingabefeldern, ein Akzentstrich unter den Überschriften und ein Verlaufstrenner. Das Logo zeigt einen Öltropfen im Zentrum eines Radars und liegt als Vektor vor, auch als monochrome Variante für das Android-Themed-Icon und die Statusleiste.

  • Hintergrund #0B0F14
  • Karte #131A22
  • Mint (günstiger, Tief) #00E5A8
  • Blau #00B3FF
  • Violett #7C4DFF
  • Pink (teurer, Hoch) #FF4D8D

Datenschutz und Datenhaltung

Alle Daten bleiben auf dem Gerät: Einstellungen, letzter Stand und Preisverlauf liegen im privaten App-Speicher. Es gibt kein eigenes Backend, keine Nutzerkonten und kein Tracking. An die Vergleichsseite werden nur Postleitzahl und Liefermenge übermittelt, die für die Preisabfrage nötig sind.

Zurück zur Übersicht: Projekte und Referenzen