À quoi sert ProGuard (aujourd’hui R8) ?
ProGuard et R8 sont des outils utilisés pour le développement d’applications Android qui vont vous aider à optimiser et à sécuriser votre code lors de la compilation. Ils jouent trois rôles importants :
- Minification : Ils suppriment les classes, méthodes et champs inutilisés dans votre code (processus appelé tree shaking), ce qui va ainsi réduire la taille de votre application. Proguard va ainsi améliorer les performances de votre application sur Android et accélérer son téléchargement pour les utilisateurs.
- Obfuscation : Ils renomment les classes, méthodes et variables avec des noms courts et illisibles (par exemple, MyMainClass devient a.b). Cela rend donc votre code beaucoup plus difficile à lire, pour quelqu’un qui ferait de la rétro-ingénierie.
- Optimisation : Ils réorganisent le bytecode pour améliorer les performances, par exemple en supprimant des instructions redondantes ou en simplifiant les calculs.
Une partie de ce travail (notamment la minification) est déjà fait naturellement par Flutter, mais Proguard va intervenir spécifiquement pour les parties natives à Android.
R8 quant à lui, est le successeur de ProGuard et est intégré par défaut dans les versions récentes de Flutter (depuis Flutter 2.0). Il offre des optimisations plus avancées et une meilleure compatibilité avec les outils Android modernes, tout en suivant les mêmes règles que ProGuard.
Mettre en place ProGuard et R8 dans une application Flutter
Configurer ProGuard et R8 dans un projet Flutter est relativement simple, mais nécessite de bien mettre en place vos règles afin de ne pas supprimer par erreur des classes nécessaires à votre application. Je vous détaille donc ici les étapes à suivre pour un mise en place sans accrocs.
Étape 1 : Activer la minification dans build.gradle
Pour activer ProGuard et R8, vous devez commencer par modifier le fichier de configuration Gradle de votre application Android.
- Accédez à votre fichier
android/app/build.gradledans votre projet Flutter. - Dans la section
buildTypes, activez la minification et la suppression des ressources inutilisées pour le build release. Ajoutez ou modifiez comme suit :
android {
...
buildTypes {
release {
signingConfig signingConfigs.release
//Ajoutez cette partie
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
- minifyEnabled true : Active la minification et l’obfuscation.
- shrinkResources true : Supprime les ressources inutilisées.
- proguardFiles : Référence le fichier par défaut d’Android (proguard-android-optimize.txt) et un fichier personnalisé (proguard-rules.pro) où vous définirez vos règles.
R8 est normalement activé par défaut, mais pour en être sûr, rendez-vous dans votre fichier android/gradle.properties et ajoutez cette ligne :
android.enableR8=true
Étape 2 : Créer et configurer le fichier proguard-rules.pro
Cette partie est la plus délicate, car Proguard va supprimer les packages qui ne sont pas protégés, lors de la compilation. On va donc créer une liste de règles pour lui expliquer ce qui est important de préserver.
- Pour commencez, dans le dossier
android/app/, créez un fichier nomméproguard-rules.prosi vous n’en avez pas déjà un. - Ajoutez ensuite ces quelques règles de base :
# Règles de base pour Flutter
-keep class io.flutter.app.** { *; }
-keep class io.flutter.plugin.** { *; }
-keep class io.flutter.util.** { *; }
-keep class io.flutter.view.** { *; }
-keep class io.flutter.** { *; }
-keep class io.flutter.plugins.** { *; }
# Préserver les numéros de ligne pour le débogage
-keepattributes SourceFile,LineNumberTable
# Préserver les annotations et signatures
-keepattributes *Annotation*
-keepattributes Signature
Protéger ses packages
Pour préserver vos packages, vous devrez ajouter des règles spécifiques à chacun d’entre eux. Chaque projet Flutter utilisant des ressources différentes, il m’est impossible de fournir une liste exhaustive de règles pour tous les cas. Cependant, voici quelques règles que vous pouvez suivre :
- -keep : Préserve une classe, méthode ou champ pour qu’il ne soit ni supprimé ni obfusqué.
- Exemple : -keep class com.google.firebase.** { *; } préserve toutes les classes du package com.google.firebase et leurs méthodes/champs.
- -dontwarn : Ignore les avertissements pour les classes référencées mais absentes, évitant des logs inutiles.
- Exemple : -dontwarn com.google.firebase.** supprime les avertissements pour Firebase.
- -keepattributes : Conserve des métadonnées, comme les numéros de ligne pour le débogage ou les annotations pour la compatibilité.
- Exemple : -keepattributes SourceFile,LineNumberTable facilite le débogage des stack traces.
-
Wildcards :
- ** : Correspond à n’importe quelle classe ou sous-package.
- * : Correspond à n’importe quelle méthode ou champ.
Voici un exemple de règles pour les packages Firebases les plus courant (firebase_core, firebase_auth, cloud_firestore) :
# Firebase
-keep class com.google.firebase.** { *; }
-dontwarn com.google.firebase.**
-keep class com.google.android.gms.** { *; }
-dontwarn com.google.android.gms.**
Étape 3 : Nettoyer et générer l’APK release
Avant de tester si votre application fonctionne avec Proguard, nettoyez votre projet pour éviter les problèmes de cache :
flutter clean
cd android
./gradlew clean
cd ..
Générez ensuite l’APK en mode release :
flutter build apk --release
Si tout se déroule correctement, c’est qu’à priori Proguard fonctionne et vos règles sont correctes. Toutefois, n’hésitez pas à tester votre application sur votre appareil, ou bien sur un émulateur en lançant la commande :
flutter install --release

