1. Controlli Preliminari
Obiettivo:
Assicurarsi che l’ambiente di sviluppo e il codice siano in uno stato ideale per una build affidabile, priva di errori e pronta per il rilascio.
1.1 Aggiornamento delle dipendenze
- Verifica outdated:
flutter pub outdated # Elenca i pacchetti non aggiornati
flutter pub upgrade # Aggiorna all’ultima versione consentita
- Pulizia cache:
flutter clean
flutter pub get
- Lockfile coerente:
- Controlla il file
pubspec.lock
per garantire che tutte le versioni siano bloccate correttamente.
1.2 Analisi del codice e testing
- Static code analysis:
flutter analyze # Rileva errori, warning e problemi di stile
- Unit & widget test:
flutter test # Esegue tutti i test definiti
Tip: integra analisi e test nella CI per fail-fast su PR.
1.3 Rimozione del debug e logging
- Rimuovi tutti i
print()
e logger di debug non configurabili a runtime. - Disabilita banner di debug in
MaterialApp
:
MaterialApp(
debugShowCheckedModeBanner: false,
…
)
1.4 Configurazione dei metadati dell’app Flutter
-
pubspec.yaml
-
name
: identificatore univoco del package (in minuscolo, senza spazi) -
description
: breve descrizione dell’app -
version
:<major>.<minor>.<patch>+<buildNumber>
(es.1.0.0+1
) -
Android (in
android/app/src/main/AndroidManifest.xml
o tramite Gradle) -
applicationId
: nel fileandroid/app/build.gradle
sottodefaultConfig
-
versionName
eversionCode
: gestiti automaticamente da Flutter in base apubspec.yaml
, ma possono essere sovrascritti inbuild.gradle
-
Permessi: dichiara solo quelli strettamente necessari (camera, geolocalizzazione, microfono, ecc.)
-
iOS (in
ios/Runner/Info.plist
) -
CFBundleIdentifier
: definito in Xcode → Runner → General → Identity -
CFBundleShortVersionString
eCFBundleVersion
: sincronizzati conpubspec.yaml
, ma modificabili in Xcode -
Didascalie per permessi (Privacy – Camera Usage Description, Privacy – Location When In Use Usage Description, ecc.)
Verifica sempre che nome, icona e permessi corrispondano alle linee guida di Play Store e App Store.
2. Gestione Assets
Obiettivo:
Organizzare, ottimizzare e configurare tutti gli asset dell’app (icone, splash screen, immagini e font) per garantire coerenza visiva e performance ottimali.
2.1 Icona e Splash Screen
- Icona dell’app
- Aggiungi il pacchetto
flutter_launcher_icons
neldev_dependencies
dipubspec.yaml
:
dev_dependencies:
flutter_launcher_icons: ^0.9.2
flutter_icons:
android: true
ios: true
image_path: "assets/icons/app_icon.png"
- Esegui:
flutter pub get
flutter pub run flutter_launcher_icons:main
- Splash screen nativo
- Aggiungi
flutter_native_splash
indev_dependencies
:
dev_dependencies:
flutter_native_splash: ^2.2.16
flutter_native_splash:
color: "#FFFFFF"
image: "assets/images/splash.png"
android: true
ios: true
- Esegui:
flutter pub get
flutter pub run flutter_native_splash:create
Mantieni le immagini in alta risoluzione (almeno 1080×1080 px) per icone e splash, così da evitare aliasing su dispositivi con schermi ad alta densità.
2.2 Immagini e Font
- Cartelle e struttura
- Crea la struttura:
assets/
images/
fonts/
- Dichiara gli asset in
pubspec.yaml
:
flutter:
assets:
- assets/images/
fonts:
- family: MyFont
fonts:
- asset: assets/fonts/MyFont-Regular.ttf
- asset: assets/fonts/MyFont-Bold.ttf
-
Ottimizzazione
-
Comprimi immagini con strumenti come TinyPNG
-
Usa formati moderni (WebP per Android, PNG per trasparenza)
-
Accesso in codice
Image.asset('assets/images/example.png');
Text(
'Titolo',
style: TextStyle(fontFamily: 'MyFont'),
);
Considera l’uso di GIF o Lottie per animazioni leggere e di qualità.
3. Sicurezza e Privacy
Obiettivo:
Garantire protezione dei dati sensibili, rispetto della privacy degli utenti e conformità alle policy di store e normative.
3.1 Gestione dei Dati Sensibili
- Archiviazione sicura
- Utilizza
flutter_secure_storage
per salvare token, credenziali e dati critici.
final storage = FlutterSecureStorage();
await storage.write(key: 'token', value: token);
- Chiavi API e segreti
- Non hardcodare mai nel codice sorgente.
- Carica tramite variabili d’ambiente o servizi di secret management (es. GitHub Actions Secrets, Firebase Remote Config).
Usa file .env
esclusi dal controllo versione (.gitignore) e librerie come flutter_dotenv
per semplicità in sviluppo.
3.2 Permessi dell’App
- Richiedi solo i permessi strettamente necessari:
- Internet (per network)
- Fotocamera/Storage (se necessario)
- Configura le motivation captions:
- Android (
AndroidManifest.xml
-><uses-permission>
e<application android:requestLegacyExternalStorage>
) - iOS (
Info.plist
->NSCameraUsageDescription
,NSPhotoLibraryUsageDescription
, ecc.)
Mantieni le descrizioni concise e chiare: “L’app utilizza la fotocamera per scansionare codici QR”.
3.3 Privacy Policy e Conformità
- Redigi una privacy policy che spieghi:
- Tipologia di dati raccolti
- Scopo del trattamento
- Terze parti coinvolte (analytics, crash reporting)
- Pubblica il documento su un dominio accessibile:
- GitHub Pages, Notion, sito dedicato
- Inserisci il link nel pannello di configurazione di Google Play Console e App Store Connect.
Controlla le linee guida GDPR e CCPA se distribuisci in UE o California.
4. Testing & QA
Obiettivo:
Verificare la stabilità, la qualità e le performance dell’app su diversi dispositivi e scenari, garantendo un’esperienza utente fluida.
4.1 Test su Dispositivi Reali
- Android:
- Testa su almeno un dispositivo con Android 8.0+.
- Controlla comportamenti su schermi di diverse dimensioni e DPI.
- iOS:
- Testa su un iPhone con iOS 13+ e se possibile un iPad.
- Verifica conformità alle linee guida Apple (UI, performance).
Esegui test su dispositivi entry-level e high-end per coprire casi di performance critiche.
4.2 Emulatori e Simulatori
- Configura AVD in Android Studio con:
- CPU: x86_64 e ARM
- Risoluzioni comuni (720p, 1080p, 1440p)
- Usa iOS Simulator per test rapidi su differenti versioni di iOS.
Integra emulatori nel CI per test automatici su più configurazioni.
4.3 Performance e Profiling
- Flutter DevTools:
- Timeline: identifica frame skippati (>16ms).
- Memory: monitora crescita della memoria nel tempo.
flutter pub global activate devtools
flutter pub global run devtools
- CPU Profiler:
- Trova funzioni costose in build/repaint.
4.4 Test Automatizzati
-
Unit Test Isolano e verificano singole funzioni, classi o metodi della logica di business senza dipendenze esterne. Ideali per:
-
Validare algoritmi e calcoli (es. funzioni di formattazione, conversione)
-
Mockare servizi esterni (API, repository) con pacchetti come
mockito
omocktail
-
Assicurare una copertura di codice elevata (obiettivo ≥ 80%)
-
Widget Test Eseguono test su widget individuali in un ambiente simulato, controllando:
-
Rendering corretto del layout e dei componenti UI
-
Interazioni dell’utente (tap, scroll, inserimento testo)
-
Stato interno del widget e aggiornamenti del widget tree
-
Utilizzo di
pumpWidget
,pumpAndSettle
eFinder
per selezionare widget -
Integration Test Simulano flussi utente completi dall’avvio dell’app alla chiusura, su emulatori o dispositivi reali:
-
Automazione di tap, scroll e input di testo
-
Verifica di navigazione, autenticazione, salvataggio dati e chiamate di rete reali
-
Possibili approcci:
-
flutter_driver
(legacy) contest_driver/app.dart
-
integration_test
(consigliato) con test scritti accanto al codice (integration_test/app_test.dart
)
Esempi di comandi
# Esegui Unit & Widget Test
flutter test
# Integration Test con flutter_driver
flutter drive \
--target=test_driver/app.dart
# Integration Test con package:integration_test
flutter test integration_test
Organizza test in cartelle test/unit
, test/widget
, test/integration
per chiarezza.
5. Build Split (Android)
Obiettivo:
Generare pacchetti ottimizzati per ciascuna architettura, riducendo le dimensioni dell’app e migliorando il tempo di installazione.
5.1 Comando di Build Split
Esegui:
flutter build apk --split-per-abi
Questo comando produce più APK distinti in build/app/outputs/flutter-apk/
:
app-armeabi-v7a-release.apk
app-arm64-v8a-release.apk
app-x86_64-release.apk
Ogni APK contiene soli i binari necessari all’architettura specificata.
5.2 Vantaggi
- Dimensione ridotta: l’utente scarica solo il codice binario per il proprio device.
- Installazione più veloce: pacchetto più leggero.
- Navigazione semplificata: Play Store distribuisce automaticamente il file giusto.
5.3 Build App Bundle
Per il Play Store, Google consiglia l’App Bundle:
flutter build appbundle --target-platform android-arm,android-arm64,android-x64
Questo genera un file .aab
che il Play Store usa per creare APK ottimizzati per gli utenti.
L’App Bundle semplifica la gestione delle versioni e include il supporto di Play Feature Delivery e Play Asset Delivery.
5.4 Archiviazione e firma
- Signing
- Configura
key.properties
ebuild.gradle
con le tue chiavi. - Esegui:
flutter build appbundle --build-name=1.0.0 --build-number=100
- Verifica
jarsigner -verify -verbose -certs build/app/outputs/bundle/release/app-release.aab
6. Build Flavors in Flutter
Obiettivo: Creare varianti dell’app (dev
, staging
, prod
) usando solo strumenti accessibili via Flutter.
6.1 Entrypoint & Dart-Define
Crea tre file Dart separati:
lib/main_dev.dart
lib/main_staging.dart
lib/main_prod.dart
Avvia il flavor via CLI:
flutter run --flavor dev -t lib/main_dev.dart
--dart-define=API_URL=https://api-dev.example.com
--dart-define=FIREBASE_PROJECT=myapp-dev
--dart-define=SENTRY_DSN=https://dev-sentry.io/123
--dart-define=LOG_LEVEL=DEBUG
6.2 Configurazione EnvConfig
In ciascun entrypoint (main_dev.dart
, etc.) importa e avvia l’app:
import 'package:flutter/material.dart';
import 'app.dart'; // il widget root della tua app
void main() {
runApp(MyApp());
}
Definisci la classe di configurazione:
class EnvConfig {
static const apiUrl = String.fromEnvironment('API_URL');
static const firebaseProj = String.fromEnvironment('FIREBASE_PROJECT');
static const sentryDsn = String.fromEnvironment('SENTRY_DSN');
static const logLevel = String.fromEnvironment('LOG_LEVEL');
}
6.3 Esempio di utilizzo nel codice
Un semplice esempio di chiamata HTTP che usa EnvConfig
:
import 'package:http/http.dart' as http;
import 'env_config.dart';
class ApiService {
Future<String> fetchData() async {
final uri = Uri.parse('${EnvConfig.apiUrl}/items');
final resp = await http.get(uri);
if (resp.statusCode == 200) {
return resp.body;
} else {
throw Exception('Errore: ${resp.statusCode}');
}
}
}
Oppure mostra la configurazione sulla UI:
import 'package:flutter/material.dart';
import 'env_config.dart';
class SettingsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Settings (${EnvConfig.logLevel})')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('API URL: ${EnvConfig.apiUrl}'),
Text('Firebase: ${EnvConfig.firebaseProj}'),
Text('Sentry DSN: ${EnvConfig.sentryDsn}'),
],
),
),
);
}
}
Organizza assets in cartelle dedicate (assets/dev
, assets/prod
), mantieni naming coerente e integra i flavor nella pipeline CI/CD per build automatiche.
6.4 Vantaggi e Best Practice
- Isolamento completo di endpoint, chiavi e asset
- Rideploy sicuro su CI/CD con pipeline dedicate
- Monitoring e Logging segmentati per ambiente
- Feature Toggles per gestione graduale di nuove funzionalità
7. Build di Release
Obiettivo:
Costruire pacchetti finali pronti per la distribuzione su store ufficiali o canali alternativi, garantendo firma, versioning e conformità alle linee guida.
7.1 Android
- APK di debug/testing
flutter build apk
- App Bundle per Play Store
flutter build appbundle
- Per specificare più architetture:
flutter build appbundle --target-platform android-arm,android-arm64,android-x64
- Firma della release
- Crea
key.properties
con path del keystore, alias e password. - Configura
android/app/build.gradle
per leggerekey.properties
. - Esegui la build con versioning:
flutter build appbundle --build-name=1.0.0 --build-number=100
- Verifica firma
jarsigner -verify -verbose -certs build/app/outputs/bundle/release/app-release.aab
Controlla nella Play Console lo split per ABI e le dimensioni di download.
7.2 iOS
-
Prerequisiti
-
Mac con macOS e Xcode (versione ≥ 12).
-
Apple Developer account configurato in Xcode.
-
Build e Archiviazione
flutter build ios --release
-
Apre il workspace pronto per Archive.
-
In Xcode: Product → Archive → Upload to App Store Connect.
-
Firma e Provisioning
-
Seleziona il provisioning profile e certificate corretti.
-
Verifica che
CFBundleIdentifier
,CFBundleShortVersionString
eCFBundleVersion
siano corretti inInfo.plist
.
Automatizza il caricamento su App Store Connect con xcrun altool
o fastlane deliver
.