Processors

Proguard

Proguard configurations allow libraries to specify how post-processing tools like optimizers and shrinkers should operate on library bytecode. Note that while Proguard is the name of a specific tool, a Proguard configuration may be read by R8 or any number of other post-processing tools.

NOTE Jetpack libraries must not run Proguard on their release artifacts. Do not specify minifyEnabled, shrinkResources, or proguardFiles in your build configuration.

Bundling with a library

Android libraries (AARs) can bundle consumer-facing Proguard rules using the consumerProguardFiles (not proguardFiles) field in their build.gradle file's defaultConfig:

android {
    defaultConfig {
        consumerProguardFiles 'proguard-rules.pro'
    }
}

Libraries do not need to specify this field on buildTypes.all.

Java-only libraries (JARs) can bundle consumer-facing Proguard rules by placing the file under the META-INF resources directory. The file must be named using the library's unique Maven coordinate to avoid build-time merging issues:

<project>/src/main/resources/META-INF/proguard/androidx.core_core.pro

Conditional Proguard Rules

Libraries are strongly encouraged to minimize the number of classes that are kept as part of keep rules. More specifically, library authors are expected to identify the entry points of their library that call into code paths that may require classes to be exempt from proguard rules. This may be due to internal reflection usages or JNI code. In the case of JNI code, java/kotlin classes and methods that are implemented in native must be exempt in order to avoid JNI linking errors in libraries that are consumed by applications built with proguard enabled.

A common pattern is to create an annotation class that is used to annotate all classes and methods that are to be excluded from proguard obfuscation.

For example:

/// in MyProguardExceptionAnnotation.kt
internal annotation class MyProguardExemptionAnnotation

Then reference this annotation within your proguard config conditionally whenever the public API is consumed that leverages facilities that need to be excluded from proguard optimization.

# in proguard-rules.pro
# The following keeps classes annotated with MyProguardExemptionAnnotation
# defined above
-if class androidx.mylibrary.MyPublicApi
-keep @androidx.mylibrary.MyProguardExemptionAnnotation public class *

# The following keeps methods annotated with MyProguardExcemptionAnnotation
-if class androidx.mylibrary.MyPublicApi
-keepclasseswithmembers class * {
    @androidx.mylibrary.MyProguardExcemptionAnnotation *;
}

Note that for each public API entry point an additional proguard rule would need to be introduced in the corresponding proguard-rules.pro. This is because as of writing there is no “or” operator within proguard that can be used to include the keep rules for multiple conditions. So each rule would need to be copy/pasted for each public API entrypoint.