Questo documento definisce l'architettura tecnica, i requisiti funzionali e le scelte implementative per SmartPump, un'applicazione Android Local-First sviluppata in Java che permette di individuare i distributori di carburante più economici nelle vicinanze sfruttando i dati Open Data ufficiali del MIMIT (Ministero delle Imprese e del Made in Italy).
- Core Business: Trovare la pompa di benzina più economica nel raggio di pochi chilometri dalla posizione GPS corrente dell'utente.
- Architettura Local-First: Zero dipendenze da server o database cloud di terze parti. L'applicazione scarica i dati grezzi direttamente dalle fonti istituzionali e li elabora interamente sul dispositivo Android tramite un database SQLite locale.
- Target Iniziale: Territorio italiano (estendibile in futuro).
- Linguaggio: Java.
- Linguaggio: Java 11+
- UI: XML Layouts / Material Design 3 (o Jetpack Compose se preferito, ma l'architettura base è ottimizzata per approcci standard robusti).
- Database Locale: Room Persistence Library (SQLite).
- Gestione Background Tasks: WorkManager (per il download e l'aggiornamento giornaliero dei file CSV).
- Geolocalizzazione:
FusedLocationProviderClient(Google Play Services). - Networking (Download CSV): OkHttp o Retrofit.
Il sistema si alimenta tramite due flussi CSV giornalieri pubblicati dal Ministero:
- Anagrafica Impianti (
anagrafica_impianti_attivi.csv):- Contiene l'ID impianto, bandiera (marchio), nome, indirizzo, comune, provincia, latitudine e longitudine.
- Prezzi Praticati (
prezzo_alle_8_di_mattina.csv):- Contiene l'ID impianto, il tipo di carburante (Benzina, Gasolio, GPL, Metano), la modalità (Self o Servito), il prezzo e la data di aggiornamento.
Il database deve essere composto da due entità relazionate:
id_impianto(LONG, Primary Key)bandiera(STRING)nome(STRING)indirizzo(STRING)comune(STRING)latitudine(DOUBLE)longitudine(DOUBLE)
id(LONG, Primary Key, AutoGenerate)id_impianto(LONG, Foreign Key ->stations.id_impianto)tipo_carburante(STRING: es. "Benzina", "Gasolio")is_self(BOOLEAN)prezzo(DOUBLE)data_aggiornamento(STRING)
Per evitare calcoli pesanti su tutti i 25.000 distributori italiani ad ogni movimento dell'utente, la ricerca spaziale deve avvenire in due step:
Prima di calcolare la distanza esatta, si estraggono solo le stazioni all'interno di un rettangolo geografico circostante la posizione GPS del telefono (
Sulle poche decine di stazioni filtrate nel bounding box, si calcola la distanza reale in metri utilizzando la formula di Haversine:
Dove
- Primo Avvio: L'app controlla se il database locale è vuoto. Se vuoto, scarica i file CSV del MIMIT in background, esegue il parsing riga per riga (gestito tramite Coroutines o AsyncTask/Executor in Java) e popola le tabelle Room.
- Aggiornamento Quotidiano: Un
Workerpianificato tramiteWorkManager(eseguito preferibilmente sotto Wi-Fi una volta al giorno) scarica l'ultimo file dei prezzi e aggiorna la tabella corrispondente. - Schermata Principale (Home):
- Richiede i permessi di localizzazione.
- Ottiene la posizione corrente tramite
FusedLocationProviderClient. - Esegue la query DAO filtrando per raggio (es. 5 km), tipo di carburante (es. Benzina) e modalità (Self).
- Mostra i risultati ordinati per prezzo crescente (dal più economico).
- Navigazione: Al click su un elemento della lista, l'app lancia un
Intentverso Google Maps o Waze passando le coordinate geografiche della pompa selezionata.
- Scrivi codice modulare, pulito e rigorosamente in Java.
- Evita memory leak associando correttamente il ciclo di vita dei LifecycleOwner ai LiveData o ai Flow/Callbacks di Room.
- Gestisci sempre i thread secondari (Background Threads) per le operazioni di I/O sul database e il parsing dei CSV, evitando blocchi della UI (ANR).