Build Type en el desarrollo Android es una configuración de Gradle que determina cómo se compila la aplicación: con o sin depuración, con o sin optimización de código, y con qué certificado de firma. Android Gradle Plugin proporciona dos Build Types estándar — debug y release, y el desarrollador puede agregar los suyos propios, como staging o benchmark. Según Google Android Developers, 2025, una configuración correcta de Build Type reduce el tamaño del APK hasta un 60% gracias a la minification y resource shrinking. Cada Build Type se combina con Product Flavors para formar un Build Variant.
Puntos clave
Build Type es un elemento de la configuración de Gradle en proyectos Android que describe los parámetros de compilación y empaquetado de la aplicación. Cada Build Type es un conjunto nombrado de opciones: debuggable (habilitar depuración), minificationEnabled (habilitar compresión de código), shrinkResources (habilitar compresión de recursos), proguardFiles (archivos de reglas ProGuard), signingConfig (certificado de firma) y otros. Los Build Types se declaran en el bloque android.buildTypes del archivo build.gradle del módulo app.
La función principal de Build Type es separar el development workflow (compilación rápida, registros detallados, depuración) del production release (código optimizado, tamaño mínimo, seguridad). La compilación debug debe compilarse en segundos y proporcionar la máxima información al desarrollador. La compilación release debe ser lo más rápida y compacta posible para los usuarios. Build Type es una configuración de infraestructura, no relacionada con la funcionalidad de la aplicación.
Android Gradle Plugin crea automáticamente un source set para cada Build Type — el directorio src/<buildType>/ (por ejemplo, src/debug/, src/release/). Los recursos, código y archivos de manifiesto colocados en este source set se aplican solo a ese tipo de compilación. Por ejemplo, en src/debug/ se puede colocar un AndroidManifest.xml con permiso de instalación desde ADB, y en src/release/ sin él. El source set de Build Type tiene prioridad sobre el source set de Product Flavor.
La diferencia clave: Build Type responde a la pregunta "¿cómo compilar?", mientras que Product Flavor responde a "¿qué compilar?". Build Type puede ser debug, release, staging. Product Flavor puede ser free, paid, enterprise. Build Type no cambia la funcionalidad de la aplicación (no agrega ni elimina pantallas), Product Flavor sí lo hace. Build Type puede desactivar el depurador y activar la ofuscación, Product Flavor puede cambiar el applicationId y los recursos. Ambos funcionan juntos: cada Build Type se combina con cada Product Flavor para formar un Build Variant.
Debug es el Build Type predeterminado creado por AGP. Tiene debuggable=true, lo que permite conectar el depurador, ver registros Log.d y usar el perfilador de Android Studio. La minification está desactivada, por lo que la compilación es rápida. En una compilación debug, el applicationId recibe el sufijo ".debug" (si no se ha sobrescrito), lo que permite instalar la versión debug junto con la versión release en el mismo dispositivo. La compilación debug se firma con un certificado de debug.keystore, que Android SDK crea automáticamente.
Release es el Build Type para publicar la aplicación. debuggable=false, minificationEnabled=true (por defecto), shrinkResources=true. El desarrollador debe especificar un signingConfig con un certificado de producción; de lo contrario, la compilación no se considerará release. La compilación release utiliza ProGuard o R8 para ofuscación, optimización y compresión de código. Android Studio no puede conectar el depurador a una compilación release (si debuggable=false). Todas las llamadas Log.d y Log.v se eliminan del código durante la minification si se configuran las reglas ProGuard adecuadas.
Importante: las compilaciones debug no prueban el comportamiento de release. La minification puede cambiar el comportamiento del código — reflection, serialización, Gson/SQLite y otras bibliotecas a menudo requieren reglas ProGuard. Por lo tanto, siempre compile y pruebe una compilación release antes de publicar. Google Play Console y Firebase Test Lab permiten cargar compilaciones release para pruebas automatizadas en dispositivos reales antes de la publicación.
android {
buildTypes {
debug {
debuggable true
minification false
signingConfig signingConfigs.debug
versionNameSuffix "-debug"
}
release {
debuggable false
minification true
shrinkResources true
proguardFiles "proguard-rules.pro"
signingConfig signingConfigs.release
ndk { abiFilters "arm64-v8a", "x86_64" }
}
}
}
Además de debug y release, se pueden crear Build Types personalizados — por ejemplo staging (entorno intermedio) o benchmark (para pruebas de rendimiento). Un Build Type personalizado se declara en el bloque buildTypes de la misma manera que debug y release. El nombre puede ser cualquiera, pero se recomienda usar nombres semánticamente claros en inglés. Para staging, generalmente se establece debuggable=true (para diagnosticar problemas en el entorno de staging) y minification=true (para probar la ofuscación antes de producción).
Un Build Type personalizado obtiene automáticamente un source set correspondiente (src/staging/) y genera tareas como assembleStaging. AGP no impone límites en la cantidad de tipos personalizados, pero cada nuevo tipo multiplica la cantidad de Build Variants. El límite práctico es de 4 a 5 Build Types: debug, staging, benchmark, release y posiblemente debugMinified (debug con minification activada para probar reglas ProGuard).
Para un Build Type personalizado, se puede heredar debuggable de debug usando initWith. La palabra clave initWith copia todos los parámetros del Build Type especificado, después de lo cual se pueden sobrescribir. Esto es conveniente para crear staging basado en debug: initWith debug + activar adicionalmente minification. Sin initWith, habría que enumerar manualmente todos los parámetros del tipo base.
android {
buildTypes {
staging {
initWith debug
minification true
shrinkResources true
proguardFiles "staging-proguard-rules.pro"
versionNameSuffix "-staging"
}
benchmark {
initWith release
signingConfig signingConfigs.debug
matchingFallbacks = ["release"]
}
}
}
// matchingFallbacks — para bibliotecas que no tienen un tipo benchmark
// si la biblioteca solo tiene release — AGP lo utiliza
SigningConfig determina qué certificado se utiliza para firmar el APK o AAB. Android requiere que todas las aplicaciones instalables estén firmadas; sin ello, el sistema no permitirá la instalación. Para las compilaciones debug, AGP utiliza debug.keystore, un certificado preinstalado con una contraseña conocida que generan Android SDK Tools. Para las compilaciones release, debe crear su propio certificado a través de Android Studio (Build → Generate Signed Bundle/APK) o mediante la herramienta de línea de comandos keytool.
El almacenamiento de claves de firma es un aspecto crítico de seguridad. Se recomienda no almacenar las claves release en el repositorio de código fuente. En su lugar, se utiliza un archivo keystore.properties (agregado a .gitignore), variables de entorno de CI/CD o el almacenamiento cifrado de Android Studio. En CI/CD (GitHub Actions, GitLab CI), las claves de firma se almacenan en secrets y se pasan a build.gradle a través de propiedades del sistema. Ejemplo: storePassword = System.getenv("KEYSTORE_PASSWORD").
Cada Build Type puede hacer referencia a su propio signingConfig. Para release — un certificado de producción, para debug — debug.keystore, para staging — un certificado de staging independiente. La configuración de firma afecta directamente la posibilidad de instalar la aplicación: si firma debug con debug.keystore y staging con una clave de producción, staging no se puede instalar sobre la versión debug debido a la discrepancia de firmas. El applicationId también debe diferir; para ello se utiliza applicationIdSuffix.
android {
signingConfigs {
debug {
storeFile file("debug.keystore")
storePassword "android"
keyAlias "androiddebugkey"
keyPassword "android"
}
release {
storeFile file("release-key.jks")
storePassword System.getenv("KEYSTORE_PASS")
keyAlias "my-key"
keyPassword System.getenv("KEY_PASS")
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
Minification es el proceso de eliminar código no utilizado y renombrar clases, métodos y campos a nombres cortos. AGP realiza la minification con ProGuard (heredado) o R8 (recomendado, integrado en AGP desde la versión 3.4). R8 realiza cuatro operaciones: shrinking (eliminación de clases no utilizadas), optimization (simplificación de código), obfuscation (cambio de nombre) y preverify (adición de información de compatibilidad). El resultado es un APK más pequeño y más difícil de descompilar.
Las reglas de minification se definen en archivos de reglas ProGuard, archivos de texto con sintaxis como -keep, -dontwarn, -keepclassmembers. Sin reglas, R8 eliminará o renombrará clases utilizadas mediante reflection (Gson, Retrofit, Room, serialización de Kotlin). La plantilla de proyecto de Android Studio crea un archivo proguard-rules.pro donde se agregan reglas para bibliotecas específicas. Las bibliotecas también pueden contener reglas integradas; se incluyen automáticamente desde jar/aar.
Shrink resources (shrinkResources=true) elimina los recursos no utilizados del APK. R8 primero determina qué recursos no se utilizan en el código (verifica R.java y las referencias del manifiesto) y luego los elimina de la compilación final. Para los recursos utilizados a través de getIdentifier() o por bibliotecas de terceros, debe agregar tools:keep="@layout/my_layout" en los recursos. Combinado con minification, resource shrinking puede reducir el tamaño del APK entre un 40 y un 60%.
# proguard-rules.pro — reglas obligatorias
# Gson: conservar clases para serialización
-keepclassmembers class com.example.** {
<fields>;
}
# Retrofit: conservar interfaces API
-keep,allowobfuscation interface com.example.api.*
# Room: conservar DAO y Entity
-keep class * extends androidx.room.RoomDatabase
-keep @interface androidx.room.** { *; }
# Kotlin Coroutines: evitar la eliminación de Continuation
-keepnames class kotlinx.coroutines.internal.*
# OkHttp: conservar el service loader
-keep class okhttp3.** { *; }
BuildConfig es una clase Java/Kotlin generada automáticamente que contiene constantes definidas en defaultConfig, productFlavors y buildTypes. Mediante buildConfigField se pueden agregar campos personalizados: buildConfigField "String", "API_URL", '"https://api.example.com"'. Un BuildConfigField declarado en buildType está disponible en todas las variantes de ese tipo. Los valores en buildType sobrescriben los valores de productFlavor, que a su vez sobrescriben defaultConfig.
Para las compilaciones debug, es conveniente establecer API_URL en localhost o un servidor de staging, y para release en producción. BuildConfig.FLAVOR y BuildConfig.BUILD_TYPE también se generan automáticamente y contienen el nombre del flavor y el build type actuales. En el código se puede usar: if (BuildConfig.DEBUG) { /* logs */ } — la constante DEBUG es verdadera solo para el build type debug. BuildConfig.DEBUG es un campo estándar que AGP agrega a cada BuildConfig.
Los recursos para Build Type se definen mediante el source set src/<buildType>/res/. Por ejemplo, src/debug/res/values/strings.xml puede contener la cadena "Server: Dev", mientras que src/release/res/ puede contener "Server: Prod". Los recursos del manifiesto también se sobrescriben mediante el source set: src/debug/AndroidManifest.xml puede incluir <uses-permission android:name="android.permission.INTERNET" /> solo para compilaciones debug. Esto es más limpio que verificar BuildConfig en el código y funciona incluso para atributos que no se pueden establecer mediante programación (como networkSecurityConfig).
// src/debug/kotlin/.../DebugConfig.kt
object DebugConfig {
val apiUrl = "http://localhost:8080/api"
val enableLogging = true
val enableCrashReporting = false
}
// src/release/kotlin/.../ReleaseConfig.kt
object ReleaseConfig {
val apiUrl = "https://api.production.com/v2"
val enableLogging = false
val enableCrashReporting = true
}
// Uso: la clase principal carga Config mediante reflection
fun getConfig(): AppConfig = when (BuildConfig.BUILD_TYPE) {
"debug" -> DebugConfig
else -> ReleaseConfig
}
Preguntas frecuentes
Sí, cree un Build Type personalizado como debugMinified con initWith debug y active la minification: debugMinified { initWith debug; minification true }. Esto es útil para probar reglas ProGuard sin compilar una versión release completa.
Ejecute apksigner de Android SDK: apksigner verify --print-certs app-release.apk. Si el certificado coincide con el cargado en Google Play Console, la firma es correcta. También se puede verificar con jarsigner para formatos antiguos.
matchingFallbacks especifica qué Build Type de una biblioteca usar si esta no tiene el tipo requerido. Por ejemplo, si la aplicación tiene un tipo "staging" pero la biblioteca solo tiene "release", AGP usa release para la biblioteca. Se especifica como una lista: matchingFallbacks = ["release", "debug"].
En las reglas ProGuard, use -keep para las clases de la biblioteca. Por ejemplo: -keep class com.some.library.** { *; }. Para desactivar completamente la minification para todas las bibliotecas, especifique -dontobfuscate y -dontoptimize en proguard-rules.pro.
Build Type por sí mismo no cambia minSdk ni targetSdk. Sin embargo, se puede establecer minSdk para un Build Type específico: debug { minSdk 21 }. Esto es útil para compilaciones debug: puede soportar solo API 21+ para acelerar la compilación, mientras que las compilaciones release usan minSdk 26.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también