Skip to main content

Overview

TechSales uses Gradle build types to create different versions of the app for development and production. Build types control code optimization, debugging capabilities, and security features.

Build Configuration

Build types are defined in app/build.gradle.kts:
app/build.gradle.kts
android {
    namespace = "com.teamtech.techsales"
    compileSdk {
        version = release(36) {
            minorApiLevel = 1
        }
    }

    defaultConfig {
        applicationId = "com.teamtech.techsales"
        minSdk = 29
        targetSdk = 36
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }
}

Default Configuration

Application Identity

namespace
String
required
The app’s package namespace used for R class generation and AndroidManifest merging.Value: com.teamtech.techsales
applicationId
String
required
Unique identifier for the app on the device and in the Play Store.Value: com.teamtech.techsales
namespace and applicationId can be different, but they typically match. The namespace is for code organization, while applicationId identifies the app at runtime.

SDK Versions

compileSdk
Int
required
Android SDK version used for compilation. Uses SDK 36 with minor API level 1.Value: release(36) { minorApiLevel = 1 }
minSdk
Int
required
Minimum Android version required to run the app.Value: 29 (Android 10)
targetSdk
Int
required
Android version the app is designed to run on. Determines which platform behaviors apply.Value: 36
Devices running Android versions below minSdk = 29 (Android 10) cannot install TechSales. This excludes approximately 30% of Android devices as of 2024.

Version Information

versionCode
Int
required
Internal version number. Must increase with each release for Play Store updates.Value: 1
versionName
String
required
User-facing version string displayed to users.Value: "1.0"
Increment versionCode for every release (even internal builds). Use semantic versioning for versionName (e.g., “1.0.0”, “1.1.0”, “2.0.0”).

Test Configuration

testInstrumentationRunner
String
Test runner for instrumented tests.Value: androidx.test.runner.AndroidJUnitRunner

Build Types

Debug Build (Default)

The debug build type is automatically created by Android Gradle Plugin with these defaults:
debug {
    isDebuggable = true
    isMinifyEnabled = false
    isShrinkResources = false
    applicationIdSuffix = ".debug"
    versionNameSuffix = "-debug"
}
Characteristics:
  • Debugging enabled
  • No code obfuscation
  • Faster build times
  • Signed with debug keystore
  • Can be installed alongside release builds
Use Cases:
  • Local development
  • Testing on devices
  • Debugging with Android Studio
  • CI/CD test builds

Release Build

The release build type is explicitly configured:
app/build.gradle.kts
release {
    isMinifyEnabled = false
    proguardFiles(
        getDefaultProguardFile("proguard-android-optimize.txt"),
        "proguard-rules.pro"
    )
}
isMinifyEnabled
Boolean
default:"false"
Controls code shrinking and obfuscation using R8/ProGuard.Current Value: false
Recommended for Production: true
proguardFiles
List<File>
ProGuard/R8 configuration files for code optimization and obfuscation.
isMinifyEnabled = false means the release build is NOT optimized. For production releases, set this to true to reduce APK size and improve security.

ProGuard Configuration

Default ProGuard File

getDefaultProguardFile("proguard-android-optimize.txt")
Provides Android-specific ProGuard rules with optimizations. Located in the Android SDK. Alternative:
  • proguard-android.txt - Basic rules without aggressive optimizations
  • proguard-android-optimize.txt - Includes optimization rules (recommended)

Custom ProGuard Rules

Create app/proguard-rules.pro for custom rules:
proguard-rules.pro
# Keep model classes for JSON serialization
-keep class com.teamtech.techsales.models.** { *; }

# Keep custom views
-keep class com.teamtech.techsales.views.** { *; }

# Preserve line numbers for crash reports
-keepattributes SourceFile,LineNumberTable

# Remove logging in release builds
-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
    public static *** i(...);
}
ProGuard rules are only applied when isMinifyEnabled = true. They have no effect in the current configuration.

Enabling Code Optimization

For production releases, enable minification:
buildTypes {
    release {
        isMinifyEnabled = true
        isShrinkResources = true
        proguardFiles(
            getDefaultProguardFile("proguard-android-optimize.txt"),
            "proguard-rules.pro"
        )
    }
}
isShrinkResources
Boolean
default:"false"
Removes unused resources from the APK when enabled. Requires isMinifyEnabled = true.
Benefits of Enabling Minification:
  • Smaller APK Size - Reduces download size by 30-50%
  • Faster Performance - Optimized bytecode runs more efficiently
  • Better Security - Obfuscated code is harder to reverse engineer
  • Reduced Method Count - Removes unused methods and classes

Compile Options

app/build.gradle.kts
compileOptions {
    sourceCompatibility = JavaVersion.VERSION_11
    targetCompatibility = JavaVersion.VERSION_11
}
sourceCompatibility
JavaVersion
required
Java language version for source code.Value: Java 11
targetCompatibility
JavaVersion
required
Java bytecode version for compiled classes.Value: Java 11
Java 11 is the minimum version required for Android Gradle Plugin 8.0+. It enables modern Java features like var, lambda improvements, and HTTP client.

Building the App

Debug Build

# Build debug APK
./gradlew assembleDebug

# Install debug build on connected device
./gradlew installDebug

# Build and install
./gradlew assembleDebug installDebug
Output Location: app/build/outputs/apk/debug/app-debug.apk

Release Build

# Build release APK
./gradlew assembleRelease

# Build Android App Bundle (for Play Store)
./gradlew bundleRelease
Output Locations:
  • APK: app/build/outputs/apk/release/app-release.apk
  • AAB: app/build/outputs/bundle/release/app-release.aab
Google Play requires Android App Bundles (.aab) for new apps. AAB files are smaller and enable dynamic delivery features.

Signing Configuration

Debug Signing

Debug builds are automatically signed with the debug keystore:
  • Location: ~/.android/debug.keystore
  • Password: android
  • Alias: androiddebugkey
  • Alias Password: android

Release Signing

For production releases, configure a release keystore:
app/build.gradle.kts
android {
    signingConfigs {
        create("release") {
            storeFile = file("../keystore/release.keystore")
            storePassword = providers.gradleProperty("RELEASE_STORE_PASSWORD").orNull
            keyAlias = providers.gradleProperty("RELEASE_KEY_ALIAS").orNull
            keyPassword = providers.gradleProperty("RELEASE_KEY_PASSWORD").orNull
        }
    }
    
    buildTypes {
        release {
            signingConfig = signingConfigs.getByName("release")
            isMinifyEnabled = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
}
Store credentials in ~/.gradle/gradle.properties:
RELEASE_STORE_PASSWORD=your_store_password
RELEASE_KEY_ALIAS=your_key_alias
RELEASE_KEY_PASSWORD=your_key_password
Never commit keystores or passwords to version control. Add them to .gitignore and store securely in CI/CD secrets.

Build Variants

Build variants combine build types with product flavors. TechSales currently has:
  • debug - Debug build type
  • release - Release build type

Adding Product Flavors

Create multiple app versions (e.g., free/paid, dev/staging/prod):
android {
    flavorDimensions += "environment"
    
    productFlavors {
        create("dev") {
            dimension = "environment"
            applicationIdSuffix = ".dev"
            versionNameSuffix = "-dev"
        }
        
        create("staging") {
            dimension = "environment"
            applicationIdSuffix = ".staging"
            versionNameSuffix = "-staging"
        }
        
        create("production") {
            dimension = "environment"
        }
    }
}
This creates variants:
  • devDebug, devRelease
  • stagingDebug, stagingRelease
  • productionDebug, productionRelease

Build Performance

Optimization Tips

  1. Enable Build Cache
gradle.properties
org.gradle.caching=true
  1. Enable Parallel Execution
gradle.properties
org.gradle.parallel=true
  1. Increase Memory
gradle.properties
org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=512m
  1. Use Configuration Cache
gradle.properties
org.gradle.configuration-cache=true

Build Time Comparison

Build TypeMinificationTypical Time
DebugDisabled10-30s
ReleaseDisabled15-40s
ReleaseEnabled30-90s
The first build after clean is slower. Subsequent builds use cached outputs and are significantly faster.
For production releases, use this configuration:
app/build.gradle.kts
android {
    buildTypes {
        release {
            // Enable code optimization
            isMinifyEnabled = true
            isShrinkResources = true
            
            // ProGuard configuration
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
            
            // Signing configuration
            signingConfig = signingConfigs.getByName("release")
            
            // Disable debugging
            isDebuggable = false
            
            // Enable ProGuard mapping file upload to Play Console
            // for crash stack trace deobfuscation
        }
    }
}

Analyzing Build Output

APK Size Analysis

# Analyze APK contents
./gradlew analyzeReleaseBundle

# Or use Android Studio
# Build > Analyze APK...

Dependency Tree

# View all dependencies
./gradlew :app:dependencies

Build Scan

# Generate build scan with performance metrics
./gradlew assembleRelease --scan

Common Issues

ProGuard/R8 Errors

Problem: App crashes in release build but works in debug. Solution: Add ProGuard keep rules for classes causing issues:
-keep class com.your.problematic.Class { *; }

Signing Errors

Problem: “Could not find signing config ‘release’” Solution: Ensure signing config is defined before build types reference it.

Duplicate Classes

Problem: “Duplicate class found in modules…” Solution: Exclude conflicting dependencies:
implementation(libs.some.library) {
    exclude(group = "com.duplicate", module = "module")
}

Build docs developers (and LLMs) love