git clone <repo-url> cd PAE # Crear local.properties (si no existe) echo "sdk.dir=/path/to/Android/sdk" > local.properties
./gradlew build --dry-run # o ./gradlew downloadDependencies
# Debug (desarrollo) ./gradlew :Machine:assembleDebug # Release (producción) ./gradlew :Machine:assembleRelease
# Debug ./gradlew :RutaPAE:assembleDebug # Release ./gradlew :RutaPAE:assembleRelease
./gradlew :MachineDomain:build ./gradlew :MachineData:build ./gradlew :Contract:build # etc.
# Build de todo el proyecto ./gradlew build # Build con test ./gradlew build connectedCheck # Clean + build ./gradlew clean build
plugins { id 'com.android.application' version '...' kotlin 'org.jetbrains.kotlin.android' version '...' } allprojects { repositories { google() mavenCentral() jitpack { url "https://jitpack.io" } } }
android { compileSdk 36 defaultConfig { applicationId "co.ada.paemachine" minSdk 27 targetSdk 36 versionCode 9 versionName "0.9.0" javaCompileOptions { annotationProcessorOptions { includeCompileClasspath true } } } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } kotlinOptions { jvmTarget = '17' } buildFeatures { compose = true buildConfig = true } packagingOptions { resources { excludes += '/META-INF/{AL2.0,LGPL2.1}' } } } dependencies { implementation project(':MachineDomain') implementation project(':MachineData') implementation project(':Contract') implementation project(':Core') // ... más dependencias }
cd keystore/ # Machine keytool -genkey -v -keystore machine-release.jks \ -keyalg RSA -keysize 2048 -validity 10000 \ -alias machine-key \ -dname "CN=Ada,O=Ada,L=Bogota,ST=DC,C=CO" # RutaPAE keytool -genkey -v -keystore rutapae-release.jks \ -keyalg RSA -keysize 2048 -validity 10000 \ -alias rutapae-key \ -dname "CN=Ada,O=Ada,L=Bogota,ST=DC,C=CO"
android { signingConfigs { release { storeFile file("../keystore/machine-release.jks") storePassword System.getenv("KEYSTORE_PASS") ?: "" keyAlias "machine-key" keyPassword System.getenv("KEY_PASS") ?: "" } } buildTypes { release { signingConfig signingConfigs.release minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } }
export KEYSTORE_PASS="tu_keystore_password" export KEY_PASS="tu_key_password" ./gradlew :Machine:assembleRelease
# Listar contenido de keystore keytool -list -v -keystore keystore/machine-release.jks # Verificar firma de APK jarsigner -verify -verbose build/outputs/apk/release/Machine-release.apk # Inspeccionar certificado zipinfo -1 build/outputs/apk/release/Machine-release.apk | grep META-INF/
ProGuard optimiza y protege el código:
# machine/proguard-rules.pro
# Serialización Kotlin
-keepclassmembers class co.ada.contract.models.** {
public <init>(...);
public <methods>;
}
-keepclasshierarchynames class co.ada.contract.models.**
# Enums
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# Room (si se usara)
-keep class **.BuildConfig { *; }
# Composable
-keep @androidx.compose.runtime.Composable class ** { *; }
android.enableR8 = true android.enableR8.fullMode = true # modo agresivo
#!/bin/bash set -e echo "=== Build PAE Release ===" # Limpiar ./gradlew clean # Compilar Machine echo "Building Machine..." ./gradlew :Machine:assembleRelease # Compilar RutaPAE echo "Building RutaPAE..." ./gradlew :RutaPAE:assembleRelease # Generar APKs con alineación ./gradlew :Machine:alignRelease ./gradlew :RutaPAE:alignRelease echo "=== Build completado ===" echo "Machine: build/outputs/apk/release/Machine-release.apk" echo "RutaPAE: build/outputs/apk/release/RutaPAE-release.apk"
Write-Host "=== Build PAE Release ===" # Limpiar & .\gradlew.bat clean # Machine Write-Host "Building Machine..." & .\gradlew.bat :Machine:assembleRelease # RutaPAE Write-Host "Building RutaPAE..." & .\gradlew.bat :RutaPAE:assembleRelease Write-Host "=== Build completado ==="
adb install build/outputs/apk/debug/Machine-debug.apk adb install build/outputs/apk/debug/RutaPAE-debug.apk
adb install build/outputs/apk/release/Machine-release.apk adb install build/outputs/apk/release/RutaPAE-release.apk
adb install -r build/outputs/apk/release/Machine-release.apk
adb uninstall co.ada.paemachine adb uninstall co.ada.rutapae
adb logcat -s PackageManager
# .github/workflows/build.yml name: Build PAE on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up JDK 17 uses: actions/setup-java@v3 with: java-version: '17' distribution: 'temurin' - name: Build Machine run: ./gradlew :Machine:assembleRelease - name: Build RutaPAE run: ./gradlew :RutaPAE:assembleRelease - name: Upload artifacts uses: actions/upload-artifact@v3 with: name: apks path: build/outputs/apk/release/
# Unit tests ./gradlew test # Android tests (requiere emulador) ./gradlew connectedAndroidTest # Lint ./gradlew lint # Lint + tests + build ./gradlew build connectedCheck
MAJOR.MINOR.PATCH (e.g., 0.9.0)MAJOR.MINOR.PATCH (e.g., 0.4.0)// Machine/build.gradle.kts android { defaultConfig { versionCode 10 versionName "0.10.0" } }
Solución:
./gradlew clean --build-cache ./gradlew build
Solución: eliminar dependencias duplicadas de Kotlin
configurations {
all*.exclude module: 'kotlin-stdlib'
}
Solución: actualizar repositorios
./gradlew :dependencies ./gradlew clean build --refresh-dependencies
Solución: versión de JDK incorrecta
java -version # debe ser 17+
# Gradle cache rm -rf ~/.gradle/caches # Build cache ./gradlew cleanBuildCache # Android Studio cache rm -rf ~/.android/cache
# build.gradle org.gradle.parallel=true org.gradle.workers.max=8
# Habilitar daemon org.gradle.daemon=true # Desabilitar si hay problemas ./gradlew --no-daemon build
./gradlew build --profile # Genera HTML en build/reports/profile/
./gradlew lint # Report en build/reports/lint-results.html
./gradlew dependencies # Genera árbol de dependencias