StrictMode: cos'è, modalità regole rigide e debug in Android

Autore: IT Sectr Pubblicato: 2026-03-31 Tempo di lettura: 8 min

StrictMode è uno strumento per sviluppatori integrato nell'Android SDK che rileva e segnala in tempo reale operazioni di I/O accidentali e chiamate di rete sul thread principale dell'applicazione. Non corregge errori ma funge da rilevatore — lancia eccezioni o scrive in LogCat quando le politiche configurate vengono violate. Secondo Google, 2024, una corretta configurazione di StrictMode può rilevare fino all'80% dei problemi di performance prima del rilascio dell'app.

Punti chiave

  • StrictMode — un rilevatore di violazioni delle performance sul thread principale Android
  • Politiche del disco (disk_read, disk_write) e rete (network) costituiscono il set di base dei controlli
  • Lo strumento non risolve i problemi ma li notifica tramite LogCat, finestra di dialogo o crash
  • La configurazione viene eseguita in Application.onCreate utilizzando setThreadPolicy + setVmPolicy
  • Modalità di penalità: lancio eccezione (death), registrazione, notifica in dropbox

Cos'è StrictMode

StrictMode è un'API inclusa nell'Android SDK dal livello API 9 (Android 2.3 Gingerbread). Il suo compito è rilevare a runtime l'esecuzione accidentale di operazioni pesanti sul thread principale (UI) che potrebbero bloccare il rendering dell'interfaccia. Il thread principale gestisce l'elaborazione dell'input utente, il calcolo del layout e il rendering — qualsiasi blocco superiore a 16 ms provoca un frame drop.

Filosofia dello strumento

StrictMode segue il principio “fallisci rapidamente” — rilevare il problema il prima possibile, idealmente nel momento della sua prima apparizione. Invece di aspettare le lamentele degli utenti sui rallentamenti, lo sviluppatore riceve un segnale (log, finestra di dialogo o crash) direttamente nella fase di sviluppo. Lo strumento non richiede librerie aggiuntive o configurazione di Gradle — bastano poche righe di codice in Application.onCreate e funziona automaticamente su tutti i dispositivi.

Pubblico target

StrictMode è progettato per tutti gli sviluppatori Android, indipendentemente dall'esperienza. Per i principianti, aiuta a formare buone abitudini (non fare richieste di rete nel thread UI); per gli sviluppatori esperti, automatizza il controllo qualità nel pipeline CI/CD. I grandi progetti (Google, Uber, Spotify) includono StrictMode nei build di debug con penaltyDeath e lo disabilitano nei build di rilascio tramite il controllo BuildConfig.DEBUG.

Come funziona StrictMode

StrictMode intercetta le chiamate di sistema che potrebbero bloccare il thread e le confronta con l'insieme delle politiche attive. Se una chiamata corrisponde a una politica e viene eseguita sul thread principale, StrictMode applica la penalità specificata. Il meccanismo di intercettazione è implementato tramite un hook intra-processo — non utilizza la reflection e opera con un overhead minimo.

Meccanismo di rilevamento

Quando la politica StrictMode viene attivata, inietta il suo gestore nei punti di ingresso delle chiamate di sistema (FileInputStream, FileOutputStream, Socket, URLConnection). Quando l'applicazione chiama, ad esempio, URLConnection.openStream sul thread principale, StrictMode controlla il thread corrente — se è il thread principale, lo strumento si attiva. In Android 6.0+, il meccanismo è potenziato: le chiamate di rete sul thread principale generano NetworkOnMainThreadException anche senza StrictMode, ma StrictMode consente anche di controllare l'I/O del disco.

Penalità

Ogni politica può avere il proprio tipo di penalità o combinazione: penaltyLog — scrive in LogCat con stack trace, penaltyDialog — mostra una finestra di dialogo all'utente (solo debug), penaltyDeath — lancia un'eccezione e causa il crash dell'app, penaltyDropBox — salva i dati in DropBoxManager per analisi successive. Per i pipeline CI/CD, si raccomanda penaltyDeath — garantisce che nessun merge con violazioni passi inosservato.

kotlin
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        if (BuildConfig.DEBUG) {
            StrictMode.setThreadPolicy(
                StrictMode.ThreadPolicy.Builder()
                    .detectDiskReads()
                    .detectDiskWrites()
                    .detectNetwork()
                    .penaltyLog()
                    .penaltyDeath()
                    .build()
            )
        }
    }
}

Politiche di StrictMode

StrictMode divide le politiche in due livelli: ThreadPolicy (livello thread — cosa non può essere fatto sul thread principale) e VmPolicy (macchina virtuale — perdite di memoria e risorse). Entrambi i livelli vengono configurati indipendentemente e funzionano in parallelo.

ThreadPolicy: Disco e Rete

A livello di thread, StrictMode controlla quattro tipi di violazioni: letture disco (detectDiskReads), scritture disco (detectDiskWrites), operazioni di rete (detectNetwork) e chiamate lente personalizzate (detectCustomSlowCalls). disk_read si attiva su qualsiasi lettura di SharedPreferences, SQLite o file sul thread principale. network si attiva su richieste HTTP, WebSocket e connessioni Socket. In Android 11+, è stato aggiunto detectUnbufferedIO per rilevare I/O non bufferizzato.

VmPolicy: Perdite di Memoria

VmPolicy controlla le perdite a livello della macchina virtuale ART: detectActivityLeaks (attività che non sono state distrutte), detectLeakedClosableObjects (Cursor, Stream, Socket non chiusi), detectLeakedRegistrationObjects (BroadcastReceiver, ServiceConnection non deregistrati). Se VmPolicy rileva che un'Activity è stata creata ma non distrutta dopo la chiamata a onDestroy, emette uno stack trace completo — risparmiando ore di debug delle perdite di memoria.

PoliticaLivelloCosa rileva
detectDiskReadsThreadLettura di SharedPrefs, SQLite, file nel thread UI
detectDiskWritesThreadScrittura in SharedPrefs, SQLite, file nel thread UI
detectNetworkThreadQualsiasi operazione di rete nel thread UI
detectActivityLeaksVMAttività che sopravvivono a onDestroy
detectLeakedClosableObjectsVMCursor, Stream, Socket non chiusi

Chiamate lente personalizzate

Tramite detectCustomSlowCalls, puoi marcare i tuoi metodi come “sospetti” e ricevere un avviso quando viene superata una soglia specificata. Ad esempio, se il tuo metodo loadUserProfile() richiede normalmente 5 ms ma a volte 200 ms — avvolgilo in StrictMode.noteSlowCall(“loadUserProfile”). Se la durata supera la soglia (default 2000 ms), StrictMode genererà una penalità. La soglia viene configurata tramite setSlowCallDurationThreshold.

Come configurare StrictMode

La configurazione di base di StrictMode richiede 10 righe di codice e viene eseguita nel metodo onCreate di una classe Application personalizzata. La regola principale: StrictMode viene attivato solo nei build di debug — nei build di rilascio rallenta l'app e può creare falsi positivi.

Configurazione di base

Crea una classe che estende Application, registrala in AndroidManifest.xml tramite l'attributo android:name e aggiungi la configurazione di StrictMode. ThreadPolicy.Builder include tutti i rilevatori e tutti i tipi di penalità (tranne dialog — funziona solo quando un debugger è collegato). VmPolicy.Builder aggiunge rilevatori per perdite di Activity e oggetti Closable. Per i grandi progetti (100+ schermate), si consiglia di configurare VmPolicy con penaltyDeath sul rilevatore di perdite di Activity — è severo ma efficace.

kotlin
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        if (BuildConfig.DEBUG) {
            StrictMode.setVmPolicy(
                StrictMode.VmPolicy.Builder()
                    .detectActivityLeaks()
                    .detectLeakedClosableObjects()
                    .detectLeakedRegistrationObjects()
                    .penaltyLog()
                    .penaltyDeath()
                    .build()
            )
        }
    }
}

Integrazione CI/CD

Per il controllo automatico in CI/CD, utilizza penaltyDeath — se un test viola la politica, l'app si bloccherà con un'eccezione. Combina con Android Test Orchestrator in modo che ogni test venga eseguito in un processo pulito. Per i test UI (Espresso, Compose Test), scrivi una TestRule personalizzata che intercetti le violazioni di StrictMode e le trasformi in errori di asserzione. Esempio: in @Before, attiva StrictMode e in @After, verifica che non ci siano state violazioni.

Configurazione delle soglie

Per impostazione predefinita, la soglia per customSlowCall è 2000 ms, per disk_read e disk_write — nessuna soglia (qualsiasi operazione attiva). Tramite setSlowCallDurationThreshold e setSlowIoDurationThreshold, puoi impostare i tuoi valori in millisecondi. Se la tua app legge legittimamente SharedPreferences sul thread principale (piccola configurazione), aumenta la soglia a 10–20 ms — questo filtrerà le letture veloci mantenendo quelle lente.

Best practice di StrictMode

StrictMode è uno strumento potente ma delicato. Una configurazione errata porta a milioni di falsi positivi, facendo sì che gli sviluppatori smettano di prestarvi attenzione. Di seguito le pratiche comprovate raccolte dall'esperienza di grandi team Android.

Attivare solo nei build di debug

Questa è una regola ferrea: StrictMode NON deve mai essere attivo nei build di rilascio. Utilizza il flag BuildConfig.DEBUG o un buildConfigField personalizzato. Nei build di rilascio, molte librerie di terze parti eseguono legittimamente operazioni sul thread principale (inizializzazione SDK, scrittura cache) e StrictMode creerà falsi positivi. Inoltre, penaltyDialog in un build di rilascio mostrerà una finestra di dialogo all'utente finale — il che è inaccettabile.

Utilizzare tre livelli di severità

Per i progetti piccoli (1–10 schermate), configura penaltyLog — i log sono sufficienti per l'analisi manuale. Per i progetti medi (10–50 schermate), aggiungi penaltyDeath su rete e customSlowCalls. Per i grandi progetti (50+ schermate), attiva il set completo di politiche con penaltyDeath in CI/CD e penaltyLog per lo sviluppo locale. Questa gradazione evita di sovraccaricare gli sviluppatori con falsi crash mentre controlla rigorosamente la qualità nel pipeline.

Gestione dei falsi positivi

Alcune librerie (Firebase, Crashlytics, Adjust) eseguono legittimamente operazioni in background che StrictMode potrebbe rilevare erroneamente. Soluzioni: aggiungi la libreria a una whitelist tramite penaltyListener, aggiorna la libreria a una versione con commutazione esplicita al thread in background, o utilizza StrictMode.vmPolicy. In Android 11+, è stato introdotto StrictMode.OnVmViolationListener per il filtraggio programmatico delle violazioni tramite stack trace.

kotlin
// Filtraggio dei falsi positivi tramite penaltyListener
StrictMode.setThreadPolicy(
    StrictMode.ThreadPolicy.Builder()
        .detectAll()
        .penaltyListener { violation ->
            val stack = violation.stackTraceToString()
            if ("com.google.firebase" !in stack) {
                logViolation(violation)
            }
        }
        .build()
)

StrictMode vs Android Lint vs Profiler

StrictMode non è l'unico strumento di controllo qualità nell'ecosistema Android. Per capire il suo posto, confrontiamolo con Android Lint, Android Profiler e Perfetto secondo criteri chiave: tempo di verifica, profondità di analisi e automazione.

CriterioStrictModeAndroid LintProfiler / Perfetto
Tempo di verificaRuntime (mentre l'app è in esecuzione)Tempo di compilazione (prima del lancio)Runtime (post-mortem)
Cosa verificaDisco, rete, perditeXML, codice, risorseCPU, memoria, rete, energia
AutomazioneCI/CD tramite penaltyDeathAttività Gradle + lint-baselineRichiede analisi manuale
ProfonditàSolo thread UI e perditeAnalisi statica del codiceQuadro completo delle performance
Falsi positiviMedi (dipendono dalle librerie)Bassi (regole configurate)Nessuno (misurazioni effettive)

La strategia migliore è combinare tutti e tre gli approcci: Android Lint cattura errori evidenti in fase di compilazione (ad esempio, un IdleHandler dimenticato), StrictMode rileva i problemi a runtime e Android Profiler / Perfetto viene utilizzato per analisi approfondite quando i primi due strumenti non forniscono risposte. Nei progetti reali (Google Maps, Instagram), StrictMode viene introdotto nella seconda settimana di sviluppo — subito dopo aver impostato l'architettura di base.

Esempi di codice con StrictMode

Esaminiamo due scenari reali in cui StrictMode aiuta a rilevare e correggere problemi di performance: lettura di SharedPreferences sul thread principale e perdita di Activity tramite un callback non deregistrato.

Rilevamento di SharedPreferences lenti

All'avvio dell'app, StrictMode con la politica detectDiskReads rileverà la lettura di SharedPreferences sul thread principale. Soluzione: caricare la configurazione in modo asincrono tramite CoroutineScope o memorizzarla nella cache all'avvio. SharedPreferences legge in modo sincrono un file XML dal disco — anche con un file piccolo (1–2 KB), l'operazione richiede 1–5 ms e fino a 20 ms su dispositivi economici, il che può causare frame drop.

kotlin
// ❌ Codice problematico — lettura di SharedPrefs nel thread UI
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // StrictMode detectDiskReads → VIOLAZIONE!
        prefs = getSharedPreferences("config", MODE_PRIVATE)
    }
}

// ✅ Codice corretto — lettura tramite Coroutine
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        loadConfigAsync()
    }
}

Rilevamento di perdite di Activity

StrictMode con VmPolicy.detectActivityLeaks rileverà un'Activity che è uscita dallo stack (finish è stato chiamato) ma l'oggetto Activity rimane in memoria a causa di un riferimento statico o di un callback non deregistrato. Scenario tipico: registrazione di EventBus o LocationListener in onResume senza chiamare unregister in onPause. VmPolicy emetterà uno stack trace indicando la riga in cui è stato creato il riferimento.

kotlin
// ❌ Perdita — callback non cancellato
private var locationCallback: LocationCallback? = null

override fun onResume() {
    super.onResume()
    locationCallback = LocationCallback(this::onLocationUpdated)
    locationManager.register(locationCallback) // StrictMode → PERDITA!
}

override fun onPause() {
    super.onPause()
    // Dimenticato: locationManager.unregister(locationCallback)
}

Domande frequenti

StrictMode rallenta l'app?

StrictMode aggiunge effettivamente un piccolo overhead — ogni chiamata di sistema viene verificata rispetto alle politiche. L'impatto sulle performance è dell'1–3% nei build di debug ed è assente nei build di rilascio (dove StrictMode è disabilitato). Attivando detectAll su dispositivi vecchi (Android 6–8), l'overhead può raggiungere il 5%, quindi si consiglia di configurare solo le politiche necessarie.

StrictMode può essere utilizzato con Jetpack Compose?

Sì, StrictMode è completamente compatibile con Jetpack Compose. Le politiche di disco e rete funzionano a livello del framework, indipendentemente dal framework UI. Inoltre, in Compose la criticità dei blocchi UI è maggiore — Compose ridisegna i frame a 120 FPS su dispositivi con alto refresh rate, quindi 5 ms aggiuntivi nella lettura del file diventano più evidenti.

Perché StrictMode non si attiva alla lettura di SharedPreferences?

A partire da Android 8.1 (API 27), SharedPreferences può utilizzare la cache in memoria — se il file è già stato letto, una rilettura non attiverà StrictMode. Assicurati di chiamare getSharedPreferences per la prima volta (lettura a freddo) e che la politica detectDiskReads sia attiva. Verifica anche che StrictMode non sia stato sovrascritto in un fragment senza genitore.

Come disabilitare StrictMode per test individuali?

Nei test JUnit, utilizza StrictMode.allowThreadDiskReads() e StrictMode.allowThreadDiskWrites() in @Before e ripristina le impostazioni in @After tramite StrictMode.enableDefaults(). Per i test di strumentazione, utilizza un TestRunner personalizzato con conservazione temporanea della politica originale. Nei test Espresso, è conveniente avvolgere il codice sensibile a StrictMode in un IdlingResource.

StrictMode è necessario in Kotlin Multiplatform?

StrictMode funziona solo sulla piattaforma Android tramite Android SDK. In Kotlin Multiplatform (KMP), il codice commonMain non può utilizzare StrictMode, ma per androidMain puoi aggiungerlo come al solito. Per la parte iOS, utilizza un analogo — l'asserzione DispatchQueue.main.async per il thread principale.

Riepilogo

  • StrictMode — un rilevatore a runtime di problemi di performance sul thread principale Android
  • Le politiche sono divise in ThreadPolicy (disco, rete) e VmPolicy (perdite di memoria)
  • La configurazione richiede 10 righe di codice in Application.onCreate con un controllo BuildConfig.DEBUG
  • Per CI/CD, utilizza penaltyDeath — una violazione della politica causa il crash dell'app
  • StrictMode non sostituisce ma completa Android Lint e Perfetto
  • Un corretto filtraggio dei falsi positivi è la chiave per un uso efficace dello strumento
  • Si consiglia di introdurre StrictMode nella seconda settimana di sviluppo del progetto

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche