Skip to main content

Overview

MiTensión uses Gradle as its build system with Kotlin DSL for build scripts. The project supports multiple build variants and configurations for development and production releases.

Build System

Project Structure

MiTensión/
├── build.gradle.kts          # Root build configuration
├── settings.gradle.kts        # Project settings and modules
├── gradle.properties          # Gradle configuration
├── gradle/
│   ├── libs.versions.toml    # Version catalog for dependencies
│   └── wrapper/              # Gradle wrapper files
└── app/
    ├── build.gradle.kts      # App module build configuration
    └── proguard-rules.pro    # ProGuard rules for release builds

Build Configuration

Key build settings from app/build.gradle.kts:
android {
    namespace = "com.fxn.mitension"
    compileSdk = 36

    defaultConfig {
        applicationId = "com.fxn.mitension"
        minSdk = 31
        targetSdk = 35
        versionCode = 1
        versionName = "1.0"

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

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }
    
    kotlinOptions {
        jvmTarget = "11"
    }

    buildFeatures {
        compose = true
    }

    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.11"
    }
}
Android Version Requirements:
  • Minimum SDK: 31 (Android 12)
  • Target SDK: 35 (Android 15)
  • Compile SDK: 36

Build Variants

Debug Build

The debug build is optimized for development with additional debugging tools:
  • No code obfuscation
  • Debug symbols included
  • Faster build times
  • Compose UI tooling enabled

Release Build

From app/build.gradle.kts:
buildTypes {
    release {
        isMinifyEnabled = false
        proguardFiles(
            getDefaultProguardFile("proguard-android-optimize.txt"),
            "proguard-rules.pro"
        )
    }
}
Currently, minification is disabled. For production releases, consider enabling isMinifyEnabled = true to reduce APK size and add code obfuscation.

Gradle Commands

Building the App

# Build debug APK
./gradlew assembleDebug

# Output: app/build/outputs/apk/debug/app-debug.apk

Installing on Device

# Install debug build on connected device/emulator
./gradlew installDebug

Cleaning Build Artifacts

# Remove all build directories
./gradlew clean

# Clean and rebuild
./gradlew clean assembleDebug

Dependency Management

MiTensión uses Gradle Version Catalogs (gradle/libs.versions.toml) for centralized dependency management:
[versions]
agp = "8.13.1"
kotlin = "1.9.23"
ksp = "1.9.23-1.0.19"
composeB om = "2024.09.00"
room = "2.6.1"
lifecycle = "2.10.0"

[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }

Updating Dependencies

1

Edit Version Catalog

Update versions in gradle/libs.versions.toml
2

Sync Project

./gradlew --refresh-dependencies
3

Verify Build

./gradlew clean assembleDebug

Room Database Schema

Room database schemas are exported during build:
ksp {
    arg("room.schemaLocation", "$projectDir/schemas")
}
Schemas are saved to app/schemas/ for version control and migration tracking.
Room schema files help track database changes across versions. Commit these files to version control.

Code Generation with KSP

The project uses Kotlin Symbol Processing (KSP) for code generation:
plugins {
    id("com.google.devtools.ksp") version "1.9.23-1.0.19"
}

dependencies {
    ksp(libs.androidx.room.compiler)
}
KSP generates Room DAO implementations and database classes during compilation.

Signing Configuration

Debug Signing

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

Release Signing

For production releases, create a release keystore:
1

Generate Keystore

keytool -genkey -v -keystore mitension-release.keystore \
  -alias mitension -keyalg RSA -keysize 2048 -validity 10000
2

Create keystore.properties

Create keystore.properties in the project root (add to .gitignore):
storeFile=/path/to/mitension-release.keystore
storePassword=YOUR_STORE_PASSWORD
keyAlias=mitension
keyPassword=YOUR_KEY_PASSWORD
3

Update build.gradle.kts

Add signing configuration to app/build.gradle.kts:
val keystorePropertiesFile = rootProject.file("keystore.properties")
val keystoreProperties = Properties()
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}

android {
    signingConfigs {
        create("release") {
            storeFile = file(keystoreProperties["storeFile"] ?: "")
            storePassword = keystoreProperties["storePassword"] as? String
            keyAlias = keystoreProperties["keyAlias"] as? String
            keyPassword = keystoreProperties["keyPassword"] as? String
        }
    }
    
    buildTypes {
        release {
            signingConfig = signingConfigs.getByName("release")
            isMinifyEnabled = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
}
4

Build Signed APK

./gradlew assembleRelease
Output: app/build/outputs/apk/release/app-release.apk (signed)
Never commit keystore.properties or the keystore file to version control! Add them to .gitignore.

ProGuard Configuration

ProGuard rules are defined in app/proguard-rules.pro. Common rules for MiTensión:
# Keep Room entities
-keep class com.fxn.mitension.data.** { *; }

# Keep Compose runtime
-keep class androidx.compose.** { *; }
-dontwarn androidx.compose.**

# Keep Kotlin metadata
-keep class kotlin.Metadata { *; }

# Keep WorkManager
-keep class androidx.work.** { *; }
-dontwarn androidx.work.**

Build Outputs

After building, artifacts are located in:

APK Files

app/build/outputs/apk/[variant]/
  • app-debug.apk
  • app-release.apk

App Bundles

app/build/outputs/bundle/[variant]/
  • app-release.aab

Build Logs

app/build/outputs/logs/
  • Compilation logs
  • Lint reports

Test Results

app/build/reports/tests/
  • Unit test reports
  • Instrumentation test reports

Version Management

Update app version in app/build.gradle.kts:
defaultConfig {
    versionCode = 2        // Increment for each release
    versionName = "1.1.0"  // User-visible version
}
Version Code: Integer incremented with each release (1, 2, 3…)Version Name: Semantic version string (1.0.0, 1.1.0, 2.0.0)

Gradle Wrapper

The project includes a Gradle wrapper for consistent builds:
# Use wrapper (recommended)
./gradlew assembleDebug

# Update wrapper version
./gradlew wrapper --gradle-version=8.13
Always use ./gradlew instead of system-installed gradle to ensure consistent build environment across machines.

Common Build Tasks

# List all available tasks
./gradlew tasks

# Show project dependencies
./gradlew dependencies

# Check for dependency updates
./gradlew dependencyUpdates

# Analyze APK size
./gradlew analyzeReleaseBundle

# Generate build scan
./gradlew build --scan

Android Studio Build

1

Select Build Variant

Open Build Variants panel (View → Tool Windows → Build Variants)Select:
  • debug for development
  • release for production
2

Build APK

Build → Build Bundle(s) / APK(s) → Build APK(s)
3

Generate Signed Bundle

Build → Generate Signed Bundle / APKFollow the wizard to select keystore and create signed release

Continuous Integration

Example GitHub Actions workflow for building MiTensión:
name: Build APK

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up JDK 11
      uses: actions/setup-java@v3
      with:
        java-version: '11'
        distribution: 'temurin'
    
    - name: Cache Gradle packages
      uses: actions/cache@v3
      with:
        path: |
          ~/.gradle/caches
          ~/.gradle/wrapper
        key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
    
    - name: Grant execute permission for gradlew
      run: chmod +x gradlew
    
    - name: Build with Gradle
      run: ./gradlew assembleDebug
    
    - name: Run tests
      run: ./gradlew test
    
    - name: Upload APK
      uses: actions/upload-artifact@v3
      with:
        name: app-debug
        path: app/build/outputs/apk/debug/app-debug.apk

Troubleshooting

Build Failures

# Clean KSP generated code
./gradlew clean
rm -rf app/build/generated/ksp
./gradlew assembleDebug
# Clear dependency cache
./gradlew clean --refresh-dependencies
rm -rf ~/.gradle/caches
Add to gradle.properties:
org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=512m
Ensure Kotlin and Compose compiler versions are compatible:
  • Kotlin 1.9.23 → Compose Compiler 1.5.11
Update in app/build.gradle.kts:
composeOptions {
    kotlinCompilerExtensionVersion = "1.5.11"
}

Performance Optimization

Enable Build Cache

Add to gradle.properties:
org.gradle.caching=true

Parallel Builds

org.gradle.parallel=true

Configuration Cache

org.gradle.configuration-cache=true

Incremental Compilation

Already enabled by default in Kotlin 1.9.23
For faster builds during development, use ./gradlew assembleDebug --offline when dependencies haven’t changed.

Build docs developers (and LLMs) love