Build Type — co to jest, konfiguracja debug i release w Gradle

Autor: IT Sectr Opublikowano: 2026-05-30 Czas czytania: 9 min

Build Type w Android to konfiguracja Gradle, która określa, jak aplikacja jest budowana: z debugowaniem lub bez, z optymalizacją kodu lub bez, z jakim certyfikatem podpisu. Android Gradle Plugin udostępnia dwa standardowe Build Type — debug i release, a programista może dodawać własne, na przykład staging lub benchmark. Według Google Android Developers, 2025, prawidłowa konfiguracja Build Type zmniejsza rozmiar APK do 60% dzięki minification i resource shrinking. Każdy Build Type łączy się z Product Flavors w Build Variant.

Najważniejsze

  • Build Type — konfiguracja budowania z parametrami debuggable, minification, signing.
  • Debug — wersja deweloperska z debuggable=true, minification=false, debug.keystore.
  • Release — wersja końcowa z debuggable=false, minification=true, production signing.
  • ProGuard i R8 wykonują obfuskację, optymalizację i kompresję kodu w wersjach release.
  • BuildConfigField umożliwia definiowanie zmiennych dostępnych w kodzie oddzielnie dla każdego typu.

Co to jest Build Type?

Build Type — to element konfiguracji Gradle w projekcie Android, który opisuje parametry kompilacji i pakowania aplikacji. Każdy Build Type to nazwany zestaw opcji: debuggable (włączyć debugowanie), minificationEnabled (włączyć kompresję kodu), shrinkResources (włączyć kompresję zasobów), proguardFiles (pliki reguł ProGuard), signingConfig (certyfikat podpisu) i inne. Build Types są deklarowane w bloku android.buildTypes pliku build.gradle modułu app.

Głównym zadaniem Build Type jest rozdzielenie development workflow (szybkie budowanie, szczegółowe logi, debugowanie) i production release (zoptymalizowany kod, minimalny rozmiar, bezpieczeństwo). Debug powinien budować się w sekundach i dostarczać maksimum informacji programiście. Release powinien być maksymalnie szybki i kompaktowy dla użytkowników. Build Type to konfiguracja infrastrukturalna, niezwiązana z funkcjonalnością aplikacji.

Android Gradle Plugin automatycznie tworzy source set dla każdego Build Type — katalog src/<buildType>/ (na przykład src/debug/, src/release/). W tym source set można umieszczać zasoby, kod i manifest, które będą stosowane tylko dla danego typu budowania. Na przykład w src/debug/ można umieścić AndroidManifest.xml z uprawnieniem do instalacji z ADB, a w src/release/ — bez niego. Source set Build Type ma priorytet nad source set Product Flavor.

Build Type vs Product Flavor

Kluczowa różnica: Build Type odpowiada na pytanie „jak budować?", a Product Flavor — na pytanie „co budować?". Build Type może być debug, release, staging. Product Flavor może być free, paid, enterprise. Build Type nie zmienia funkcjonalności aplikacji (nie dodaje ani nie usuwa ekranów), Product Flavor — zmienia. Build Type może wyłączyć debuger i włączyć obfuskację, Product Flavor — zmienić applicationId i zasoby. Oba działają w parze: każdy Build Type łączy się z każdym Product Flavor, tworząc Build Variant.

Standardowe Build Types: debug i release

Debug — to Build Type tworzony przez AGP domyślnie. Zawiera debuggable=true, co umożliwia podłączenie debugera, przeglądanie logów Log.d i używanie profilera Android Studio. Minification jest wyłączone, więc budowanie jest szybkie. W wersji debug applicationId otrzymuje sufiks ".debug" (jeśli nie został nadpisany), co pozwala zainstalować wersję debug równolegle z wersją release na jednym urządzeniu. Debug jest podpisywany certyfikatem z debug.keystore, który jest tworzony automatycznie przez Android SDK.

Release — to Build Type do publikacji aplikacji. debuggable=false, minificationEnabled=true (domyślnie), shrinkResources=true. Programista musi określić signingConfig z certyfikatem produkcyjnym — w przeciwnym razie wersja nie będzie uznana za release. Release używa ProGuard lub R8 do obfuskacji, optymalizacji i kompresji kodu. Android Studio nie może podłączyć debugera do wersji release (jeśli debuggable=false). Wszystkie wywołania Log.d i Log.v są usuwane z kodu na etapie minification, jeśli skonfigurowano odpowiednie reguły ProGuard.

Ważne: wersje debug nie testują zachowania release. Minification może zmienić zachowanie kodu — reflection, serializacja, Gson/SQLite i inne biblioteki często wymagają reguł ProGuard. Dlatego przed publikacją należy zbudować wersję release i przetestować ją. Google Play Console i Firebase Test Lab umożliwiają przesyłanie wersji release do automatycznego testowania na rzeczywistych urządzeniach przed publikacją.

groovy
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" }
        }
    }
}

Tworzenie niestandardowych Build Types

Dziedziczenie przez initWith

Oprócz debug i release można tworzyć własne Build Types — na przykład staging (środowisko przejściowe) lub benchmark (do testów wydajności). Niestandardowy Build Type jest deklarowany w bloku buildTypes tak samo jak debug i release. Nazwa może być dowolna, ale zaleca się używanie semantycznie zrozumiałych nazw w języku angielskim. Dla staging zwykle ustawia się debuggable=true (do diagnozowania problemów w środowisku staging) i minification=true (aby testować obfuskację przed produkcją).

Niestandardowy Build Type automatycznie otrzymuje odpowiadający source set (src/staging/) i generuje zadania typu assembleStaging. AGP nie nakłada ograniczeń na liczbę niestandardowych typów, ale każdy nowy typ mnoży liczbę Build Variants. Praktyczny limit to 4-5 Build Types: debug, staging, benchmark, release i ewentualnie debugMinified (debug z włączoną minification do testowania reguł ProGuard).

Dla niestandardowego Build Type można dziedziczyć debuggable z debug za pomocą initWith. Słowo kluczowe initWith kopiuje wszystkie parametry wskazanego Build Type, a następnie można je nadpisać. Jest to wygodne do tworzenia staging na podstawie debug: initWith debug + dodatkowo włączyć minification. Bez initWith trzeba by ręcznie wymieniać wszystkie parametry typu bazowego.

groovy
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 — dla bibliotek, które nie mają typu benchmark
// jeśli biblioteka ma tylko release — AGP go używa

Konfiguracja podpisu dla różnych typów budowania

SigningConfig określa, jakim certyfikatem podpisywany jest APK lub AAB. Android wymaga podpisu wszystkich instalowanych aplikacji — bez niego system nie pozwoli na instalację APK. Dla wersji debug AGP używa debug.keystore — preinstalowanego certyfikatu ze znanym hasłem, generowanego przez Android SDK Tools. Dla wersji release należy utworzyć własny certyfikat przez Android Studio (Build → Generate Signed Bundle/APK) lub za pomocą polecenia keytool.

Przechowywanie kluczy podpisu to krytyczny aspekt bezpieczeństwa. Zaleca się nie przechowywać kluczy release w repozytorium kodu źródłowego. Zamiast tego używa się: pliku keystore.properties (dodanego do .gitignore), zmiennych środowiskowych CI/CD lub zaszyfrowanego magazynu Android Studio. W CI/CD (GitHub Actions, GitLab CI) klucze podpisu są przechowywane w sekretach i przekazywane do build.gradle przez właściwości systemowe. Przykład: storePassword = System.getenv("KEYSTORE_PASSWORD").

Każdy Build Type może odwoływać się do własnego signingConfig. Dla release — certyfikat produkcyjny, dla debug — debug.keystore, dla staging — oddzielny certyfikat staging. Konfiguracja podpisu bezpośrednio wpływa na możliwość instalacji aplikacji: jeśli debug jest podpisany debug.keystore, a staging kluczem produkcyjnym, staging nie będzie można zainstalować na wersji debug z powodu niezgodności podpisów. ApplicationId również musi się różnić — w tym celu używa się applicationIdSuffix.

groovy
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, ProGuard i R8

Resource Shrinking

Minification — to proces usuwania nieużywanego kodu i zmiany nazw klas, metod i pól na krótkie nazwy. AGP wykonuje minification za pomocą ProGuard (przestarzały) lub R8 (zalecany, wbudowany w AGP od wersji 3.4). R8 wykonuje cztery operacje: shrinking (usuwanie nieużywanych klas), optimisation (upraszczanie kodu), obfuscation (zmiana nazw) i preverify (dodawanie informacji o zgodności). Rezultat — APK o mniejszym rozmiarze, który trudniej dekompilować.

Reguły minification są definiowane w ProGuard rules files — plikach tekstowych ze składnią -keep, -dontwarn, -keepclassmembers. Bez reguł R8 usunie lub zmieni nazwy klas używanych przez reflection (Gson, Retrofit, Room, Kotlin serialization). Szablon projektu Android Studio tworzy proguard-rules.pro, do którego dodaje się reguły dla konkretnych bibliotek. Biblioteki mogą również zawierać wbudowane reguły — są one automatycznie dołączane z jar/aar.

Shrink resources (shrinkResources=true) usuwa nieużywane zasoby z APK. R8 najpierw określa, które zasoby nie są używane w kodzie (sprawdza R.java i odwołania w manifeście), a następnie usuwa je z końcowej wersji. Dla zasobów używanych przez getIdentifier() lub biblioteki zewnętrzne należy dodać tools:keep="@layout/my_layout" w zasobach. W połączeniu z minification, resource shrinking może zmniejszyć rozmiar APK o 40-60%.

text
# proguard-rules.pro — obowiązkowe reguły
# Gson: zachowaj klasy do serializacji
-keepclassmembers class com.example.** {
    <fields>;
}

# Retrofit: zachowaj interfejsy API
-keep,allowobfuscation interface com.example.api.*

# Room: zachowaj DAO i Entity
-keep class * extends androidx.room.RoomDatabase
-keep @interface androidx.room.** { *; }

# Kotlin Coroutines: zapobiegaj usunięciu Continuation
-keepnames class kotlinx.coroutines.internal.*

# OkHttp: zachowaj service loader
-keep class okhttp3.** { *; }

BuildConfigField i zasoby dla Build Type

BuildConfig — to automatycznie generowana klasa Java/Kotlin, która zawiera stałe zdefiniowane w defaultConfig, productFlavors i buildTypes. Przez buildConfigField można dodać niestandardowe pola: buildConfigField "String", "API_URL", '"https://api.example.com"'. BuildConfigField zadeklarowany w buildType jest dostępny we wszystkich wariantach tego typu. Wartości w buildType nadpisują wartości z productFlavor, które z kolei nadpisują defaultConfig.

Dla wersji debug wygodnie jest ustawić API_URL na localhost lub serwer staging, a dla release — na produkcyjny. BuildConfig.FLAVOR i BuildConfig.BUILD_TYPE również są generowane automatycznie i zawierają nazwę bieżącego flavor i build type. W kodzie można użyć: if (BuildConfig.DEBUG) { /* logi */ } — stała DEBUG jest równa true tylko dla build type debug. BuildConfig.DEBUG to standardowe pole, które AGP dodaje do każdego BuildConfig.

Zasoby dla Build Type są definiowane przez source set src/<buildType>/res/. Na przykład src/debug/res/values/strings.xml może zawierać tekst „Server: Dev", a src/release/res/ — „Server: Prod". Zasoby manifestu są również nadpisywane przez source set: src/debug/AndroidManifest.xml może zawierać <uses-permission android:name="android.permission.INTERNET" /> tylko dla wersji debug. Jest to czystsze niż sprawdzanie BuildConfig w kodzie i działa nawet dla atrybutów, których nie można ustawić programowo (na przykład networkSecurityConfig).

kotlin
// 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
}

// Użycie: główna klasa ładuje Config przez reflection
fun getConfig(): AppConfig = when (BuildConfig.BUILD_TYPE) {
    "debug" -> DebugConfig
    else -> ReleaseConfig
}

Często zadawane pytania

Czy można mieć wersję debug z minification?

Tak, utwórz niestandardowy Build Type, np. debugMinified, z initWith debug i włącz minification: debugMinified { initWith debug; minification true }. Jest to przydatne do testowania reguł ProGuard bez budowania pełnej wersji release.

Jak sprawdzić, czy wersja release jest poprawnie podpisana?

Uruchom apksigner z Android SDK: apksigner verify --print-certs app-release.apk. Jeśli certyfikat zgadza się z tym przesłanym do Google Play Console — podpis jest prawidłowy. Można również sprawdzić przez jarsigner dla starszych formatów.

Co to jest matchingFallbacks w Build Type?

matchingFallbacks określa, który Build Type biblioteki użyć, jeśli nie ma ona wymaganego typu. Na przykład, jeśli aplikacja ma typ „staging", a biblioteka tylko „release", AGP użyje release dla biblioteki. Jest podawany jako lista: matchingFallbacks = ["release", "debug"].

Jak wyłączyć minification dla konkretnej biblioteki?

W regułach ProGuard użyj -keep dla klas biblioteki. Na przykład: -keep class com.some.library.** { *; }. Aby całkowicie wyłączyć minification dla wszystkich bibliotek, ustaw -dontobfuscate i -dontoptimize w proguard-rules.pro.

Czy Build Type wpływa na wersję API Android?

Build Type sam w sobie nie zmienia minSdk ani targetSdk. Można jednak ustawić minSdk dla konkretnego Build Type: debug { minSdk 21 }. Jest to przydatne dla wersji debug — można obsługiwać tylko API 21+ dla przyspieszenia budowania, a release budować na minSdk 26.

Podsumowanie

  • Build Type — infrastrukturalna konfiguracja budowania, określająca debugowanie, kompresję i podpis.
  • Debug — szybkie budowanie do rozwoju, release — zoptymalizowane do publikacji.
  • Niestandardowe Build Types (staging, benchmark) są tworzone przez initWith do dziedziczenia parametrów.
  • R8 wykonuje minification, obfuscation i resource shrinking, zmniejszając APK do 60%.
  • BuildConfigField i source sets umożliwiają definiowanie zmiennych i zasobów dla każdego typu.
  • Klucze podpisu dla release powinny być przechowywane poza repozytorium — w secrets CI/CD lub zaszyfrowanym magazynie.
  • Zalecenie: zawsze testuj wersję release przed publikacją — debug nie pokazuje zachowania z minification.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również