Build Type in der Android-Entwicklung ist eine Gradle-Konfiguration, die festlegt, wie die Anwendung erstellt wird: mit oder ohne Debugging, mit oder ohne Code-Optimierung und mit welchem Signaturzertifikat. Das Android Gradle Plugin bietet zwei standardmäßige Build Types — debug und release, und Entwickler können eigene benutzerdefinierte Typen wie staging oder benchmark hinzufügen. Laut Google Android Developers, 2025 reduziert die richtige Build Type-Konfiguration die APK-Größe durch minification und resource shrinking um bis zu 60%. Jeder Build Type wird mit Product Flavors zu einem Build Variant kombiniert.
Wichtigste Erkenntnisse
Build Type ist ein Element der Gradle-Konfiguration in Android-Projekten, das die Kompilierungs- und Packungsparameter der Anwendung beschreibt. Jeder Build Type ist ein benannter Satz von Optionen: debuggable (Debugging aktivieren), minificationEnabled (Code-Kompression aktivieren), shrinkResources (Ressourcenkompression aktivieren), proguardFiles (ProGuard-Regeldateien), signingConfig (Signaturzertifikat) und andere. Build Types werden im Block android.buildTypes der build.gradle-Datei des app-Moduls deklariert.
Die Hauptaufgabe des Build Type ist es, den Development Workflow (schneller Build, detaillierte Logs, Debugging) vom Production Release (optimierter Code, minimale Größe, Sicherheit) zu trennen. Ein Debug-Build sollte in Sekunden kompilieren und dem Entwickler maximale Informationen liefern. Ein Release-Build sollte für Benutzer so schnell und kompakt wie möglich sein. Build Type ist eine Infrastruktureinstellung, die nichts mit der Funktionalität der Anwendung zu tun hat.
Das Android Gradle Plugin erstellt automatisch ein Source Set für jeden Build Type — das Verzeichnis src/<buildType>/ (z.B. src/debug/, src/release/). Ressourcen, Code und Manifestdateien, die in dieses Source Set gelegt werden, gelten nur für diesen Build-Typ. Zum Beispiel kann in src/debug/ eine AndroidManifest.xml mit ADB-Installationsberechtigung platziert werden, in src/release/ ohne. Das Source Set des Build Type hat Priorität über das Source Set des Product Flavor.
Der Hauptunterschied: Build Type beantwortet die Frage „Wie bauen?“, während Product Flavor die Frage „Was bauen?“ beantwortet. Build Type kann debug, release, staging sein. Product Flavor kann free, paid, enterprise sein. Build Type ändert nicht die Funktionalität der Anwendung (fügt keine Bildschirme hinzu oder entfernt sie), Product Flavor schon. Build Type kann den Debugger deaktivieren und die Verschleierung aktivieren, Product Flavor kann applicationId und Ressourcen ändern. Beide arbeiten zusammen: Jeder Build Type wird mit jedem Product Flavor zu einem Build Variant kombiniert.
Debug ist der von AGP standardmäßig erstellte Build Type. Er hat debuggable=true, was das Anhängen des Debuggers, das Anzeigen von Log.d-Logs und die Verwendung des Android Studio-Profilers ermöglicht. Die Minification ist deaktiviert, daher ist der Build schnell. In einem Debug-Build erhält die applicationId das Suffix „.debug“ (falls nicht überschrieben), was die Installation der Debug-Version neben der Release-Version auf demselben Gerät ermöglicht. Der Debug-Build wird mit einem Zertifikat aus debug.keystore signiert, das vom Android SDK automatisch erstellt wird.
Release ist der Build Type für die Veröffentlichung der Anwendung. debuggable=false, minificationEnabled=true (standardmäßig), shrinkResources=true. Der Entwickler muss ein signingConfig mit einem Produktionszertifikat angeben — andernfalls wird der Build nicht als Release-Build betrachtet. Der Release-Build verwendet ProGuard oder R8 zur Verschleierung, Optimierung und Code-Kompression. Android Studio kann keinen Debugger an einen Release-Build anhängen (wenn debuggable=false). Alle Log.d- und Log.v-Aufrufe werden während der Minification aus dem Code entfernt, wenn die entsprechenden ProGuard-Regeln konfiguriert sind.
Wichtig: Debug-Builds testen nicht das Release-Verhalten. Minification kann das Code-Verhalten ändern — Reflection, Serialisierung, Gson/SQLite und andere Bibliotheken erfordern oft ProGuard-Regeln. Daher sollten Sie vor der Veröffentlichung immer einen Release-Build erstellen und testen. Die Google Play Console und Firebase Test Lab ermöglichen das Hochladen von Release-Builds für automatisierte Tests auf echten Geräten vor der Veröffentlichung.
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" }
}
}
}
Zusätzlich zu debug und release können benutzerdefinierte Build Types erstellt werden — zum Beispiel staging (Zwischenumgebung) oder benchmark (für Leistungstests). Ein benutzerdefinierter Build Type wird im buildTypes-Block genauso wie debug und release deklariert. Der Name kann beliebig sein, aber es wird empfohlen, semantisch klare Namen auf Englisch zu verwenden. Für staging werden normalerweise debuggable=true (zur Diagnose von Problemen in der Staging-Umgebung) und minification=true (zum Testen der Verschleierung vor der Produktion) gesetzt.
Ein benutzerdefinierter Build Type erhält automatisch ein entsprechendes Source Set (src/staging/) und generiert Aufgaben wie assembleStaging. AGP legt keine Beschränkungen für die Anzahl benutzerdefinierter Typen fest, aber jeder neue Typ multipliziert die Anzahl der Build Variants. Die praktische Grenze liegt bei 4–5 Build Types: debug, staging, benchmark, release und möglicherweise debugMinified (debug mit aktivierter Minification zum Testen von ProGuard-Regeln).
Für einen benutzerdefinierten Build Type können Sie debuggable von debug mit initWith erben. Das Schlüsselwort initWith kopiert alle Parameter des angegebenen Build Type, die anschließend überschrieben werden können. Dies ist praktisch, um staging basierend auf debug zu erstellen: initWith debug + zusätzlich minification aktivieren. Ohne initWith müssten Sie alle Parameter des Basistyps manuell auflisten.
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 — für Bibliotheken, die keinen benchmark-Typ haben
// wenn die Bibliothek nur release hat — verwendet AGP diesen
SigningConfig legt fest, welches Zertifikat zum Signieren des APK oder AAB verwendet wird. Android verlangt, dass alle installierbaren Anwendungen signiert sind — ohne dies erlaubt das System keine Installation. Für Debug-Builds verwendet AGP debug.keystore — ein vorinstalliertes Zertifikat mit einem bekannten Passwort, das von den Android SDK Tools generiert wird. Für Release-Builds müssen Sie Ihr eigenes Zertifikat über Android Studio (Build → Generate Signed Bundle/APK) oder die keytool-Befehlszeile erstellen.
Die Speicherung von Signaturschlüsseln ist ein kritischer Sicherheitsaspekt. Es wird empfohlen, Release-Schlüssel nicht im Quellcode-Repository zu speichern. Stattdessen werden eine keystore.properties-Datei (zu .gitignore hinzugefügt), CI/CD-Umgebungsvariablen oder der verschlüsselte Speicher von Android Studio verwendet. In CI/CD (GitHub Actions, GitLab CI) werden Signaturschlüssel in secrets gespeichert und über Systemeigenschaften an build.gradle übergeben. Beispiel: storePassword = System.getenv("KEYSTORE_PASSWORD").
Jeder Build Type kann auf sein eigenes signingConfig verweisen. Für release — ein Produktionszertifikat, für debug — debug.keystore, für staging — ein separates staging-Zertifikat. Die Signaturkonfiguration wirkt sich direkt auf die Installierbarkeit der Anwendung aus: Wenn Sie debug mit debug.keystore und staging mit einem Produktionsschlüssel signieren, kann staging aufgrund nicht übereinstimmender Signaturen nicht über der Debug-Version installiert werden. Die applicationId muss sich ebenfalls unterscheiden — verwenden Sie dazu 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 ist der Prozess des Entfernens ungenutzten Codes und des Umbenennens von Klassen, Methoden und Feldern in kurze Namen. AGP führt Minification mit ProGuard (veraltet) oder R8 (empfohlen, ab AGP-Version 3.4 integriert) durch. R8 führt vier Operationen aus: shrinking (Entfernen ungenutzter Klassen), optimisation (Code-Vereinfachung), obfuscation (Umbenennung) und preverify (Hinzufügen von Kompatibilitätsinformationen). Das Ergebnis ist ein kleineres APK, das schwerer zu dekompilieren ist.
Minification-Regeln werden in ProGuard-Regeldateien definiert — Textdateien mit Syntax wie -keep, -dontwarn, -keepclassmembers. Ohne Regeln entfernt oder benennt R8 Klassen um, die über Reflection verwendet werden (Gson, Retrofit, Room, Kotlin-Serialisierung). Die Android Studio-Projektvorlage erstellt eine Datei proguard-rules.pro, in der Regeln für bestimmte Bibliotheken hinzugefügt werden. Bibliotheken können auch eingebaute Regeln enthalten — sie werden automatisch aus jar/aar eingebunden.
Shrink resources (shrinkResources=true) entfernt ungenutzte Ressourcen aus dem APK. R8 ermittelt zunächst, welche Ressourcen im Code nicht verwendet werden (prüft R.java und Manifest-Referenzen) und entfernt sie dann aus dem endgültigen Build. Für Ressourcen, die über getIdentifier() oder von Drittanbieter-Bibliotheken verwendet werden, müssen Sie tools:keep="@layout/my_layout" in den Ressourcen hinzufügen. In Kombination mit Minification kann Resource Shrinking die APK-Größe um 40–60% reduzieren.
# proguard-rules.pro — obligatorische Regeln
# Gson: Klassen für Serialisierung behalten
-keepclassmembers class com.example.** {
<fields>;
}
# Retrofit: API-Schnittstellen behalten
-keep,allowobfuscation interface com.example.api.*
# Room: DAO und Entity behalten
-keep class * extends androidx.room.RoomDatabase
-keep @interface androidx.room.** { *; }
# Kotlin Coroutines: Löschen von Continuation verhindern
-keepnames class kotlinx.coroutines.internal.*
# OkHttp: Service Loader erhalten
-keep class okhttp3.** { *; }
BuildConfig ist eine automatisch generierte Java-/Kotlin-Klasse, die in defaultConfig, productFlavors und buildTypes definierte Konstanten enthält. Über buildConfigField können benutzerdefinierte Felder hinzugefügt werden: buildConfigField "String", "API_URL", '"https://api.example.com"'. Ein in buildType deklariertes BuildConfigField ist in allen Varianten dieses Typs verfügbar. Werte in buildType überschreiben Werte aus productFlavor, die wiederum defaultConfig überschreiben.
Für Debug-Builds ist es praktisch, API_URL auf localhost oder einen Staging-Server zu setzen, für release auf Produktion. BuildConfig.FLAVOR und BuildConfig.BUILD_TYPE werden ebenfalls automatisch generiert und enthalten den Namen des aktuellen Flavors und Build-Typs. Im Code kann verwendet werden: if (BuildConfig.DEBUG) { /* Logs */ } — die Konstante DEBUG ist nur für den debug Build Type wahr. BuildConfig.DEBUG ist ein Standardfeld, das AGP zu jedem BuildConfig hinzufügt.
Ressourcen für Build Type werden über das Source Set src/<buildType>/res/ definiert. Zum Beispiel kann src/debug/res/values/strings.xml den String „Server: Dev“ enthalten, während src/release/res/ „Server: Prod“ enthalten kann. Manifest-Ressourcen werden ebenfalls über das Source Set überschrieben: src/debug/AndroidManifest.xml kann <uses-permission android:name="android.permission.INTERNET" /> nur für Debug-Builds enthalten. Dies ist sauberer als die Überprüfung von BuildConfig im Code und funktioniert sogar für Attribute, die nicht programmatisch gesetzt werden können (wie 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
}
// Verwendung: Die Hauptklasse lädt Config über Reflection
fun getConfig(): AppConfig = when (BuildConfig.BUILD_TYPE) {
"debug" -> DebugConfig
else -> ReleaseConfig
}
Häufig gestellte Fragen
Ja, erstellen Sie einen benutzerdefinierten Build Type wie debugMinified mit initWith debug und aktivieren Sie die Minification: debugMinified { initWith debug; minification true }. Dies ist nützlich zum Testen von ProGuard-Regeln, ohne eine vollständige Release-Version zu bauen.
Führen Sie apksigner aus dem Android SDK aus: apksigner verify --print-certs app-release.apk. Wenn das Zertifikat mit dem in der Google Play Console übereinstimmt, ist die Signatur korrekt. Sie können auch mit jarsigner für ältere Formate überprüfen.
matchingFallbacks gibt an, welcher Build Type einer Bibliothek verwendet werden soll, wenn sie den erforderlichen Typ nicht hat. Wenn die App beispielsweise einen „staging“-Typ hat, die Bibliothek aber nur „release“, verwendet AGP release für die Bibliothek. Es wird als Liste angegeben: matchingFallbacks = ["release", "debug"].
Verwenden Sie in den ProGuard-Regeln -keep für die Klassen der Bibliothek. Beispiel: -keep class com.some.library.** { *; }. Um die Minification für alle Bibliotheken vollständig zu deaktivieren, geben Sie -dontobfuscate und -dontoptimize in proguard-rules.pro an.
Build Type selbst ändert weder minSdk noch targetSdk. Sie können jedoch minSdk für einen bestimmten Build Type festlegen: debug { minSdk 21 }. Dies ist nützlich für Debug-Builds — Sie können nur API 21+ unterstützen, um den Build zu beschleunigen, während Release-Builds minSdk 26 verwenden.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch