Mettre en place ProGuard (R8) dans une application Flutter


Avatar de Pierre Courtois

Optimiser et sécuriser son application Flutter est quelque chose de crucial. L’un des outils les plus puissants pour y parvenir est ProGuard ou son successeur, R8. Dans cet article, nous allons explorer ce que sont ces outils, pourquoi ils sont essentiels, et comment les intégrer dans votre projet Flutter, étape par étape.


Proguard dans Flutter

À 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.

  1. Accédez à votre fichier android/app/build.gradle dans votre projet Flutter.
  2. 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.

  1. Pour commencez, dans le dossier android/app/, créez un fichier nommé proguard-rules.pro si vous n’en avez pas déjà un.
  2. 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.**

Sur cette partie, n’hésitez pas à faire appel à une AI comme ChatGPT ou Grok, en lui fournissant la liste de packages et en lui demande de générer les règles pour vous.

Notez également que tous les packages n’ont pas besoin de règles. Par exemple, les packages purement Dart (comme provider ou google_fonts) n’en nécessitent pas, car ils sont gérés par le tree shaking de Flutter. Consultez donc la documentation des ressources que vous utilisez pour savoir lesquelles ont besoin de règles.

É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
Avatar de Pierre Courtois