StrictMode : qu'est-ce que c'est, mode de règles strictes et débogage dans Android

Auteur : IT Sectr Publié le : 2026-03-31 Temps de lecture : 8 min

StrictMode est un outil de développement intégré au SDK Android qui détecte et signale en temps réel les opérations d'E/S accidentelles et les appels réseau sur le thread principal de l'application. Il ne corrige pas les erreurs mais agit comme un détecteur — lève des exceptions ou écrit dans LogCat lorsque les politiques configurées sont violées. Selon Google, 2024, une configuration appropriée de StrictMode permet de détecter jusqu'à 80 % des problèmes de performance avant la publication de l'application.

Points clés

  • StrictMode — un détecteur de violations de performance sur le thread principal Android
  • Les politiques de disque (disk_read, disk_write) et réseau (network) constituent l'ensemble de base des vérifications
  • L'outil ne corrige pas les problèmes mais en informe via LogCat, une boîte de dialogue ou un crash
  • La configuration s'effectue dans Application.onCreate en utilisant setThreadPolicy + setVmPolicy
  • Modes de pénalité : levée d'exception (death), journalisation, notification dans dropbox

Qu'est-ce que StrictMode

StrictMode est une API incluse dans le SDK Android depuis le niveau d'API 9 (Android 2.3 Gingerbread). Sa tâche est de détecter à l'exécution l'exécution accidentelle d'opérations lourdes sur le thread principal (UI) qui pourraient bloquer le rendu de l'interface. Le thread principal gère le traitement des entrées utilisateur, le calcul de la mise en page et le rendu — tout blocage de plus de 16 ms entraîne une perte d'image.

Philosophie de l'outil

StrictMode suit le principe « d'échec rapide » — détecter le problème le plus tôt possible, idéalement au moment de sa première apparition. Au lieu d'attendre les plaintes des utilisateurs concernant les ralentissements, le développeur reçoit un signal (journaux, boîte de dialogue ou crash) directement au stade du développement. L'outil ne nécessite pas de bibliothèques supplémentaires ni de configuration Gradle — seulement quelques lignes de code dans Application.onCreate, et il fonctionne automatiquement sur tous les appareils.

Public cible

StrictMode est conçu pour tous les développeurs Android, quelle que soit leur expérience. Pour les débutants, il aide à former de bonnes habitudes (ne pas faire de requêtes réseau dans le thread UI) ; pour les développeurs expérimentés, il automatise le contrôle qualité dans le pipeline CI/CD. Les grands projets (Google, Uber, Spotify) incluent StrictMode dans les builds de débogage avec penaltyDeath, et le désactivent dans les builds de version via la vérification BuildConfig.DEBUG.

Comment fonctionne StrictMode

StrictMode intercepte les appels système qui pourraient bloquer le thread et les compare à l'ensemble des politiques actives. Si un appel correspond à une politique et est exécuté sur le thread principal, StrictMode applique la pénalité spécifiée. Le mécanisme d'interception est implémenté via un hook intra-processus — il n'utilise pas la réflexion et fonctionne avec une surcharge minimale.

Mécanisme de détection

Lorsque la politique StrictMode est activée, elle injecte son gestionnaire dans les points d'entrée des appels système (FileInputStream, FileOutputStream, Socket, URLConnection). Lorsque l'application appelle, par exemple, URLConnection.openStream sur le thread principal, StrictMode vérifie le thread actuel — s'il s'agit du thread principal, l'outil se déclenche. Dans Android 6.0+, le mécanisme est renforcé : les appels réseau sur le thread principal génèrent NetworkOnMainThreadException même sans StrictMode, mais StrictMode permet également de contrôler les E/S disque.

Pénalité

Chaque politique peut avoir son propre type de pénalité ou combinaison : penaltyLog — écrit dans LogCat avec une trace de pile, penaltyDialog — affiche une boîte de dialogue à l'utilisateur (débogage uniquement), penaltyDeath — lève une exception et fait planter l'application, penaltyDropBox — enregistre les données dans DropBoxManager pour analyse ultérieure. Pour les pipelines CI/CD, penaltyDeath est recommandé — il garantit qu'aucun merge avec des violations ne passe inaperçu.

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

Politiques de StrictMode

StrictMode divise les politiques en deux niveaux : ThreadPolicy (niveau thread — ce qui ne peut pas être fait sur le thread principal) et VmPolicy (machine virtuelle — fuites mémoire et de ressources). Les deux niveaux sont configurés indépendamment et fonctionnent en parallèle.

ThreadPolicy : Disque et Réseau

Au niveau du thread, StrictMode contrôle quatre types de violations : lectures disque (detectDiskReads), écritures disque (detectDiskWrites), opérations réseau (detectNetwork) et appels lents personnalisés (detectCustomSlowCalls). disk_read se déclenche lors de toute lecture de SharedPreferences, SQLite ou fichiers sur le thread principal. network se déclenche lors de requêtes HTTP, WebSocket et connexions Socket. Dans Android 11+, detectUnbufferedIO a été ajouté pour détecter les E/S non tamponnées.

VmPolicy : Fuites mémoire

VmPolicy contrôle les fuites au niveau de la machine virtuelle ART : detectActivityLeaks (activités qui n'ont pas été détruites), detectLeakedClosableObjects (Cursor, Stream, Socket non fermés), detectLeakedRegistrationObjects (BroadcastReceiver, ServiceConnection non désenregistrés). Si VmPolicy détecte qu'une Activity a été créée mais pas détruite après l'appel à onDestroy, il affiche une trace de pile complète — ce qui permet d'économiser des heures de débogage de fuites mémoire.

PolitiqueNiveauCe qu'elle détecte
detectDiskReadsThreadLecture de SharedPrefs, SQLite, fichiers dans le thread UI
detectDiskWritesThreadÉcriture dans SharedPrefs, SQLite, fichiers dans le thread UI
detectNetworkThreadToute opération réseau dans le thread UI
detectActivityLeaksVMActivités survivant à onDestroy
detectLeakedClosableObjectsVMCursor, Stream, Socket non fermés

Appels lents personnalisés

Grâce à detectCustomSlowCalls, vous pouvez marquer vos propres méthodes comme «suspectes» et recevoir un avertissement lorsqu'un seuil spécifié est dépassé. Par exemple, si votre méthode loadUserProfile() prend normalement 5 ms mais parfois 200 ms — enveloppez-la dans StrictMode.noteSlowCall(«loadUserProfile»). Si la durée dépasse le seuil (par défaut 2000 ms), StrictMode générera une pénalité. Le seuil est configuré via setSlowCallDurationThreshold.

Comment configurer StrictMode

La configuration de base de StrictMode prend 10 lignes de code et s'effectue dans la méthode onCreate d'une classe Application personnalisée. La règle principale : StrictMode est activé uniquement dans les builds de débogage — dans les builds de version, il ralentit l'application et peut créer des faux positifs.

Configuration de base

Créez une classe étendant Application, enregistrez-la dans AndroidManifest.xml via l'attribut android:name et ajoutez la configuration StrictMode. ThreadPolicy.Builder inclut tous les détecteurs et tous les types de pénalité (sauf dialog — il fonctionne uniquement lorsqu'un débogueur est attaché). VmPolicy.Builder ajoute des détecteurs pour les fuites d'Activity et les objets Closable. Pour les grands projets (100+ écrans), il est recommandé de configurer VmPolicy avec penaltyDeath sur le détecteur de fuites d'Activity — c'est strict mais efficace.

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

Intégration CI/CD

Pour un contrôle automatique dans CI/CD, utilisez penaltyDeath — si un test viole la politique, l'application plantera avec une exception. Combinez avec Android Test Orchestrator pour que chaque test s'exécute dans un processus propre. Pour les tests UI (Espresso, Compose Test), écrivez une TestRule personnalisée qui intercepte les violations StrictMode et les transforme en échecs d'assertion. Exemple : dans @Before, activez StrictMode, et dans @After, vérifiez qu'il n'y a pas eu de violations.

Configuration des seuils

Par défaut, le seuil pour customSlowCall est de 2000 ms, pour disk_read et disk_write — aucun seuil (toute opération déclenche). Via setSlowCallDurationThreshold et setSlowIoDurationThreshold, vous pouvez définir vos propres valeurs en millisecondes. Si votre application lit légitimement SharedPreferences sur le thread principal (petite configuration), augmentez le seuil à 10–20 ms — cela filtrera les lectures rapides tout en conservant les lentes.

Meilleures pratiques de StrictMode

StrictMode est un outil puissant mais capricieux. Une configuration incorrecte entraîne des millions de faux positifs, ce qui fait que les développeurs cessent d'y prêter attention. Voici des pratiques éprouvées recueillies auprès de l'expérience de grandes équipes Android.

Activer uniquement dans les builds de débogage

C'est une règle absolue : StrictMode ne doit JAMAIS être actif dans les builds de version. Utilisez le flag BuildConfig.DEBUG ou un buildConfigField personnalisé. Dans les builds de version, de nombreuses bibliothèques tierces effectuent légitimement des opérations sur le thread principal (initialisation SDK, écriture de cache), et StrictMode créera des faux positifs. De plus, penaltyDialog dans un build de version affichera une boîte de dialogue à l'utilisateur final — ce qui est inacceptable.

Utiliser trois niveaux de sévérité

Pour les petits projets (1–10 écrans), configurez penaltyLog — les journaux suffisent pour une analyse manuelle. Pour les projets moyens (10–50 écrans), ajoutez penaltyDeath sur le réseau et customSlowCalls. Pour les grands projets (50+ écrans), activez l'ensemble complet des politiques avec penaltyDeath dans CI/CD, et penaltyLog pour le développement local. Cette gradation évite de surcharger les développeurs avec de faux crashes tout en contrôlant strictement la qualité dans le pipeline.

Gestion des faux positifs

Certaines bibliothèques (Firebase, Crashlytics, Adjust) effectuent légitimement des opérations en arrière-plan que StrictMode pourrait détecter incorrectement. Solutions : ajoutez la bibliothèque à une liste blanche via penaltyListener, mettez à jour la bibliothèque vers une version avec commutation explicite vers un thread d'arrière-plan, ou utilisez StrictMode.vmPolicy. Dans Android 11+, StrictMode.OnVmViolationListener a été introduit pour le filtrage programmatique des violations par trace de pile.

kotlin
// Filtrage des faux positifs via 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 Profileurs

StrictMode n'est pas le seul outil de contrôle qualité dans l'écosystème Android. Pour comprendre sa place, comparons-le avec Android Lint, Android Profiler et Perfetto selon des critères clés : temps de vérification, profondeur d'analyse et automatisation.

CritèreStrictModeAndroid LintProfiler / Perfetto
Temps de vérificationRuntime (pendant l'exécution de l'application)Temps de compilation (avant le lancement)Runtime (post-mortem)
Ce qu'il vérifieDisque, réseau, fuitesXML, code, ressourcesCPU, mémoire, réseau, énergie
AutomatisationCI/CD via penaltyDeathTâche Gradle + lint-baselineNécessite une analyse manuelle
ProfondeurThread UI et fuites uniquementAnalyse statique de codeImage complète des performances
Faux positifsMoyens (dépendent des bibliothèques)Faibles (règles configurées)Aucun (mesures réelles)

La meilleure stratégie consiste à combiner les trois approches : Android Lint détecte les erreurs évidentes au moment de la compilation (par exemple, un IdleHandler oublié), StrictMode détecte les problèmes à l'exécution, et Android Profiler / Perfetto est utilisé pour une analyse approfondie lorsque les deux premiers outils ne fournissent pas de réponses. Dans les projets réels (Google Maps, Instagram), StrictMode est introduit à la deuxième semaine de développement — juste après la mise en place de l'architecture de base.

Exemples de code avec StrictMode

Examinons deux scénarios réels où StrictMode aide à détecter et corriger les problèmes de performance : la lecture de SharedPreferences sur le thread principal et la fuite d'Activity via un callback non désenregistré.

Détection des SharedPreferences lents

Au démarrage de l'application, StrictMode avec la politique detectDiskReads détectera la lecture de SharedPreferences sur le thread principal. Solution : charger la configuration de manière asynchrone via CoroutineScope ou la mettre en cache en mémoire au démarrage. SharedPreferences lit de manière synchrone un fichier XML depuis le disque — même avec un petit fichier (1–2 Ko), l'opération prend 1–5 ms, et jusqu'à 20 ms sur les appareils bon marché, ce qui peut entraîner une perte d'image.

kotlin
// ❌ Code problématique — lecture de SharedPrefs dans le thread UI
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // StrictMode detectDiskReads → VIOLATION !
        prefs = getSharedPreferences("config", MODE_PRIVATE)
    }
}

// ✅ Code corrigé — lecture via Coroutine
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        loadConfigAsync()
    }
}

Détection des fuites d'Activity

StrictMode avec VmPolicy.detectActivityLeaks détectera une Activity qui a quitté la pile (finish a été appelé) mais dont l'objet Activity reste en mémoire en raison d'une référence statique ou d'un callback non désenregistré. Scénario typique : enregistrement d'EventBus ou de LocationListener dans onResume sans appeler unregister dans onPause. VmPolicy affichera une trace de pile indiquant la ligne où la référence a été créée.

kotlin
// ❌ Fuite — callback non annulé
private var locationCallback: LocationCallback? = null

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

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

Foire aux questions

StrictMode ralentit-il l'application ?

StrictMode ajoute effectivement une petite surcharge — chaque appel système est vérifié par rapport aux politiques. L'impact sur les performances est de 1–3 % dans les builds de débogage et est absent dans les builds de version (où StrictMode est désactivé). Lors de l'activation de detectAll sur les anciens appareils (Android 6–8), la surcharge peut atteindre 5 %, il est donc recommandé de configurer uniquement les politiques nécessaires.

Peut-on utiliser StrictMode avec Jetpack Compose ?

Oui, StrictMode est entièrement compatible avec Jetpack Compose. Les politiques de disque et de réseau fonctionnent au niveau du framework, indépendamment du framework UI. De plus, dans Compose, la criticité des blocages UI est plus élevée — Compose redessine les images à 120 FPS sur les appareils à taux de rafraîchissement élevé, donc 5 ms supplémentaires sur la lecture de fichier deviennent plus perceptibles.

Pourquoi StrictMode ne se déclenche-t-il pas à la lecture de SharedPreferences ?

À partir d'Android 8.1 (API 27), SharedPreferences peut utiliser la mise en cache en mémoire — si le fichier a déjà été lu, une relecture ne déclenchera pas StrictMode. Assurez-vous d'appeler getSharedPreferences pour la première fois (lecture à froid) et que la politique detectDiskReads est active. Vérifiez également que StrictMode n'a pas été remplacé dans un fragment sans parent.

Comment désactiver StrictMode pour des tests individuels ?

Dans les tests JUnit, utilisez StrictMode.allowThreadDiskReads() et StrictMode.allowThreadDiskWrites() dans @Before, et restaurez les paramètres dans @After via StrictMode.enableDefaults(). Pour les tests d'instrumentation, utilisez un TestRunner personnalisé avec préservation temporaire de la politique d'origine. Dans les tests Espresso, il est pratique d'envelopper le code sensible à StrictMode dans une IdlingResource.

StrictMode est-il nécessaire dans Kotlin Multiplatform ?

StrictMode fonctionne uniquement sur la plateforme Android via le SDK Android. Dans Kotlin Multiplatform (KMP), le code commonMain ne peut pas utiliser StrictMode, mais pour androidMain, vous pouvez l'ajouter comme d'habitude. Pour la partie iOS, utilisez un équivalent — l'assertion DispatchQueue.main.async pour le thread principal.

Résumé

  • StrictMode — un détecteur à l'exécution des problèmes de performance sur le thread principal Android
  • Les politiques sont divisées en ThreadPolicy (disque, réseau) et VmPolicy (fuites mémoire)
  • La configuration prend 10 lignes de code dans Application.onCreate avec une vérification BuildConfig.DEBUG
  • Pour CI/CD, utilisez penaltyDeath — une violation de politique fait planter l'application
  • StrictMode ne remplace pas mais complète Android Lint et Perfetto
  • Un filtrage approprié des faux positifs est la clé d'une utilisation efficace de l'outil
  • Il est recommandé d'introduire StrictMode à la deuxième semaine de développement du projet

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi