Acerca de las reglas de conservación

Cuando habilitas la optimización de la app con la configuración predeterminada, R8 realiza optimizaciones extensas para maximizar los beneficios de rendimiento. R8 realiza modificaciones importantes 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 debe 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 cause 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 muestran 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 que se busca por su nombre con Class.getDeclaredMethod() ni una anotación recuperada con Class.getAnnotation(). En estos casos, R8 podría cambiar el nombre de estos métodos y anotaciones o quitarlos por completo, lo que generaría una ClassNotFoundException o una NoSuchMethodException en el tiempo 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 basada en cadenas dinámicas, por lo que sus optimizaciones podrían interrumpir tu código.

Esta no es una lista exhaustiva de situaciones que requieren reglas de conservación, pero abarca la mayoría de los casos en los que podrías necesitarlas.

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 crucial 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 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 src/<variant>/keepRules directorio. 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.
            }
        }
    }
}

Omite las reglas de conservación predeterminadas de la plataforma de Android (avanzado)

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 de AGP inferiores a 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 en el archivo, debes declararlo en el archivo de nivel de módulo build.gradle.kts (o build.gradle).

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: Las 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: Las reglas de conservación deben diseñarse con cuidado para asegurarte de obtener el equilibrio adecuado entre maximizar la optimización del código sin interrumpir la app de forma involuntaria. Para obtener información sobre cómo escribir reglas de conservación, consulta Agrega reglas de conservación.

Reglas de conservación para autores de bibliotecas

Después de obtener información sobre las opciones globales y la sintaxis de las reglas de conservación, consulta Optimización para autores de bibliotecas para obtener más detalles.