Lorsque vous activez l'optimisation des applications avec les paramètres par défaut, R8 effectue des optimisations approfondies afin de maximiser les avantages en termes de performances. R8 apporte des modifications substantielles au code, y compris en renommant, en déplaçant et en supprimant des champs et des méthodes de classe. Si cela entraîne des erreurs, vous devez spécifier les parties du code à laisser intactes en écrivant des règles de conservation.
R8 peut supprimer ou modifier de manière incorrecte du code dans les situations suivantes:
- Réflexion: code accessible à l'aide de la réflexion, par exemple à l'aide de
Class.forName()
ouMethod.invoke()
. R8 ne peut généralement pas déterminer les classes ou méthodes auxquelles on accède de cette manière. - Sérialisation: les classes ou les champs nécessaires à la sérialisation et à la désérialisation peuvent sembler inutilisés par R8 (il s'agit d'une autre forme de réflexion).
- Java Native Interface (JNI): méthodes Java appelées à partir de code natif. R8 n'analyse pas le code natif pour voir ce qu'il pourrait appeler dans Java.
Cette page explique comment limiter l'étendue des optimisations de R8. Pour savoir comment personnaliser les ressources conservées, consultez la section Ajouter des règles de conservation pour les ressources.
Où ajouter des règles de conservation
Vous devez ajouter vos règles à un fichier proguard-rules.pro
situé dans le répertoire racine du module (le fichier peut déjà être présent, mais si ce n'est pas le cas, créez-le). Pour appliquer les règles du fichier, vous devez le déclarer dans votre fichier build.gradle.kts
(ou build.gradle
) au niveau du module, comme indiqué dans le code suivant:
Kotlin
android { buildTypes { release { isMinifyEnabled = true isShrinkResources = true proguardFiles( // Default file with default optimization rules. getDefaultProguardFile("proguard-android-optimize.txt"), // File with your custom rules. "proguard-rules.pro" ) ... } } ... }
Groovy
android { buildTypes { release { minifyEnabled true shrinkResources true proguardFiles( // Default file with default optimization rules. getDefaultProguardFile('proguard-android-optimize.txt'), // File with your custom rules. 'proguard-rules.pro' ) } } // ... }
Par défaut, votre script de compilation inclut également le fichier proguard-android-optimize.txt
. Ce fichier inclut des règles requises pour la plupart des projets Android. Vous devez donc le conserver dans le script de compilation.
Écrire des règles de conservation
Lors de la compilation de l'application, R8 détecte le code qui doit être conservé dans une application en analysant le graphique des appels de votre application, qui commence par les entrées du fichier manifeste (telles que vos activités ou services) et suit chaque appel de fonction d'application et de bibliothèque. R8 supprime le code qui n'est pas directement référencé de cette manière, ce qui peut entraîner des problèmes si le code exécuté ne fait pas partie de ce graphique, par exemple le code appelé par réflexion. En écrivant vos propres règles de conservation, vous pouvez indiquer à R8 le code qui doit rester dans l'application.
Pour ajouter une règle de conservation, ajoutez une ligne -keep
dans le fichier proguard-rules.pro
.
Conserver la syntaxe des règles
Les règles de conservation suivent généralement le format suivant:
-<KeepOption> [OptionalModifier,...] <ClassSpecification> [{ OptionalMemberSpecification }]
Par exemple, pour conserver une classe spécifique et tous ses membres, utilisez la commande suivante:
-keep class com.myapp.MyClass { *; }
Pour en savoir plus, consultez la section des exemples.
Voici ce que font les composants de la règle de conservation:
<KeepOption>
vous permet de spécifier les aspects d'une classe à conserver:Option "Conserver" Description -keep
Conservez la classe et les membres listés dans
[{ OptionalMemberSpecification }]
.-keepclassmembers
Autorisez l'optimisation de la classe. Si la classe est conservée, conservez les membres listés dans
[{ OptionalMemberSpecification }]
.-keepnames
Autorisez la suppression de la classe et des membres, mais n'obscurcissez ni ne modifiez pas la classe d'une autre manière.
-keepclassmembernames
Autorisez la suppression de la classe et des membres, mais ne masquez ni ne modifiez les membres d'une autre manière.
-keepclasseswithmembers
Aucune suppression ni obscurcissement des classes si les membres correspondent au modèle spécifié.
Nous vous recommandons d'utiliser principalement
-keepclassmembers
, car il permet les optimisations les plus nombreuses, puis-keepnames
si nécessaire.-keep
n'autorise aucune optimisation. Essayez donc de l'utiliser avec parcimonie.[OptionalModifier],...]
vous permet de lister zéro ou plusieurs modificateurs de langage Java d'une classe, par exemplepublic
oufinal
.<ClassSpecification>
vous permet de spécifier la classe (ou la superclasse ou l'interface implémentée) à laquelle la règle de conservation doit s'appliquer. Dans le cas le plus simple, il s'agit d'une classe complète.[{ OptionalMemberSpecification }]
vous permet de filtrer le comportement de conservation pour n'inclure que les classes et les méthodes correspondant à certains schémas. En règle générale, cette option est recommandée dans la plupart des règles de conservation pour éviter de conserver plus que prévu.
Exemples de règles Keep
Voici quelques exemples de règles de conservation bien conçues.
Créer une sous-classe
Cette règle de conservation est empaquetée dans androidx.room:room-runtime
pour que les constructeurs de base de données soient instanciés par réflexion.
-keep class * extends androidx.room.RoomDatabase { void <init>(); }
Réflexion du framework Android ObjectAnimator
Cette règle de conservation est empaquetée dans androidx.vectordrawable:vectordrawable-animated
pour permettre à ObjectAnimator
d'appeler des getters ou des setteurs à partir du code natif avec JNI. Notez que les systèmes d'animation plus récents de Compose ne nécessitent pas de règles de conservation comme celle-ci. Il ne s'agit que d'un exemple de structure de règle.
-keepclassmembers class androidx.vectordrawable.graphics.drawable.VectorDrawableCompat$* {
void set*(***);
*** get*();
}
Enregistrement JNI
Cette règle de conservation est empaquetée dans androidx.graphics:graphics-path
, qui permet de conserver les méthodes natives. Cela peut être nécessaire si votre bibliothèque enregistre manuellement des méthodes natives avec env->RegisterNatives()
.
-keepclasseswithmembers class androidx.graphics.path.** {
native <methods>;
}