Cuando habilitas la optimización de la app con la configuración predeterminada, R8 realiza optimizaciones exhaustivas para maximizar los beneficios de rendimiento. R8 realiza modificaciones sustanciales en el código, como cambiar el nombre, mover y quitar clases, campos y métodos. Si observas que estas modificaciones causan errores, debes especificar qué partes del código R8 no debería modificar declarándolas en las reglas de conservación.
Situaciones comunes que requieren reglas de conservación
R8 identifica y conserva todas las llamadas directas en tu código. Sin embargo, R8 no puede ver los usos indirectos del código, lo que puede hacer que quite el código que necesita tu app y que se produzcan fallas. Usa reglas de conservación para indicarle a R8 que conserve ese código que se usa de forma indirecta. A continuación, se indican algunas situaciones comunes en las que es probable que necesites reglas de conservación:
- Código al que se accede por reflexión: R8 no puede identificar cuándo se accede a clases, campos o métodos con reflexión. Por ejemplo, R8 no puede identificar un método buscado por su nombre con
Class.getDeclaredMethod()ni una anotación recuperada conClass.getAnnotation(). En estos casos, es posible que R8 cambie el nombre de estos métodos y anotaciones, o bien que los quite por completo, lo que generará unaClassNotFoundExceptiono unaNoSuchMethodExceptionen el entorno de ejecución. - Código llamado desde la interfaz nativa de Java (JNI): Cuando el código nativo (C o C++) llama a un método de Java o Kotlin, o el código de Java o Kotlin llama al código C++ con JNI, la llamada se basa en una búsqueda de cadena dinámica del nombre del método. R8 no puede ver la llamada de método dinámica basada en cadenas, por lo que sus optimizaciones podrían dañar tu código.
Esta no es una lista exhaustiva de situaciones que requieren reglas de conservación, pero estas situaciones abarcan la mayoría de los casos en los que podrías necesitar reglas de conservación.
Si tu propio código usa la reflexión o se llama desde JNI, puedes anotarlo con anotaciones de Jetpack Keep en lugar de escribir reglas de conservación de forma manual. Su complemento de Gradle genera las reglas de conservación a partir de las anotaciones en el momento de la compilación.
Comprende cómo las reglas de conservación afectan la optimización
R8 es un optimizador de todo el programa que analiza el código de tu app para quitar el código no utilizado, intercalar métodos, combinar clases y ofuscar identificadores. Sin embargo, R8 solo puede optimizar dentro de la configuración que definas.
Las reglas de conservación representan una instrucción explícita para limitar la optimización. Cada regla de conservación que declares restringe la capacidad de R8 para transformar esa parte de tu base de código. El valor de una regla de conservación bien diseñada radica en su especificidad:
Las reglas de conservación limitadas permiten una optimización máxima: Si solo se orientan a los puntos de entrada exactos a los que se accede de forma dinámica (como un constructor reflexivo o un campo serializado), permites que R8 optimice el resto del código.
Las reglas de conservación amplias impiden la optimización: Declarar reglas para todo el paquete o comodines amplios impide que R8 optimice clases enteras y todos sus miembros. R8 no puede quitar, intercalar, combinar ni ofuscar ese código.
Las reglas de conservación demasiado amplias generan directamente objetos binarios DEX inflados, un mayor espacio en memoria de la app, tiempos de inicio más lentos (TTID y TTFD) y tasas de ANR más altas. Tu objetivo no debe ser conservar las clases "por si acaso", sino definir el contrato mínimo necesario para la ejecución dinámica.
Para encontrar reglas de conservación amplias o innecesarias, incluidas las de bibliotecas de terceros, usa el analizador de configuración de R8. Informa las puntuaciones de reducción, optimización y ofuscación que muestran qué parte de tu código puede optimizar R8.
Cómo agregar reglas de conservación a tu app
La configuración de las reglas de conservación depende de la versión del AGP que uses.
Las apps más grandes suelen tener código en varios módulos de biblioteca. En esos casos, suele ser mejor colocar las reglas de conservación junto con el código al que se aplican dentro del módulo de biblioteca específico. La diferencia fundamental en el mantenimiento de las reglas de conservación para las bibliotecas radica en cómo declaras estas reglas dentro del archivo build.gradle.kts (o build.gradle) del módulo de tu biblioteca. Consulta Optimización para autores de bibliotecas para obtener más información.
Para AGP 9.3 y versiones posteriores
Agrega tus reglas a un archivo con el sufijo .keep en el directorio src/<variant>/keepRules. Por ejemplo, src/main/keepRules/custom-rules.keep. Ten en cuenta que el uso del DSL actualizado para AGP 9.3 y versiones posteriores habilita la optimización de código y recursos, y no requiere que definas de forma explícita el archivo de reglas de conservación predeterminado de Android (proguard-android-optimize.txt), ya que se incluye de forma predeterminada, a menos que se omita de forma explícita.
Kotlin
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
}
Groovy
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
}
Omitir las reglas de conservación predeterminadas de la plataforma de Android (avanzado)
El AGP proporciona un conjunto de reglas predeterminadas de la plataforma de Android. Para omitir estas reglas de
la configuración de tu proyecto y administrar todas las reglas de conservación por tu cuenta, establece
optimization.keepRules.includeDefault en false.
Kotlin
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
keepRules {
includeDefault = false // The file with optimization
// rules for the Android platform is included by
// default. To omit this file, set this option to false.
}
}
}
}
}
Groovy
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
keepRules {
includeDefault = false // The file with optimization
// rules for the Android platform is included by
// default. To omit this file, set this option to false.
}
}
}
}
}
DSL heredado para versiones del AGP anteriores a la 9.3
Agrega tus reglas a un archivo proguard-rules.pro ubicado en el directorio raíz del módulo de la app. Es posible que el archivo ya esté allí, pero, si no es así, créalo. Para aplicar
las reglas del archivo, debes declararlo en el archivo build.gradle.kts (o build.gradle)
a nivel del módulo.
De forma predeterminada, tu archivo de compilación también incluye el archivo
proguard-android-optimize.txt. Este archivo incluye reglas que son necesarias para la mayoría de los proyectos de Android, por lo que debes dejarlo en el archivo de compilación. Este archivo se basa en el archivo proguard-common.txt y comparte contenido con él.
DSL heredado (Kotlin)
android {
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
// Default file with default optimization rules.
getDefaultProguardFile("proguard-android-optimize.txt"),
...
)
}
}
}
DSL heredado (Groovy)
android {
buildTypes {
release {
minifyEnabled = true
shrinkResources = true
// Default file with default optimization rules.
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
...
}
}
}
Agrega una regla de conservación
Cuando agregas reglas de conservación, puedes incluir opciones globales y definir tus propias reglas de conservación.
Opciones globales: Son directivas generales que afectan la forma en que R8 opera en toda tu base de código. Para obtener más información, consulta Opciones globales.
Reglas de conservación: Estas reglas deben diseñarse con cuidado para garantizar que obtengas el equilibrio adecuado entre maximizar la optimización del código sin dañar la app de forma involuntaria. Para aprender a escribir reglas de conservación, consulta Cómo agregar reglas de conservación.
Reglas de conservación para autores de bibliotecas
Después de conocer las opciones globales y la sintaxis de las reglas de conservación, consulta Optimización para autores de bibliotecas para obtener más detalles.