feat: implement production release configuration and signing for Play Store
This commit is contained in:
@@ -141,6 +141,11 @@ Kurz: Ziel ist eine native Android-App mit Kotlin + Jetpack Compose, die die Web
|
||||
[ ] 22. Analytics: Firebase / Matomo Integration (je nach Datenschutz)
|
||||
[x] 23. Crash-Reporting: Sentry / Crashlytics integrieren
|
||||
[ ] 24. Build/Release: App signing, Release-Notes, Play-Store-Metadaten vorbereiten
|
||||
- [x] Technische Release-Basis vorbereitet: `ANDROID_VERSION_CODE` und `ANDROID_VERSION_NAME` als Gradle-Properties eingeführt (`android-app/gradle.properties`) und im App-Gradle verdrahtet.
|
||||
- [x] Production-Release-Flavor auf Produktiv-Backend parametrisierbar gemacht (`PRODUCTION_API_BASE_URL`, Default `https://harheimertc.de/`).
|
||||
- [x] Release-Signing per sicheren Gradle-Properties vorbereitet (`RELEASE_STORE_FILE`, `RELEASE_STORE_PASSWORD`, `RELEASE_KEY_ALIAS`, `RELEASE_KEY_PASSWORD`) statt Hardcoding.
|
||||
- [x] `:app:assembleProductionRelease` erfolgreich gebaut (Stand 2026-05-29).
|
||||
- [ ] Offen: Finales Upload-Keystore + Credentials in CI/Build-Host hinterlegen, Play-Store-Release-Notes und Store-Metadaten pflegen.
|
||||
[ ] 25. Dokumentation: `README-android.md` mit Setup, Architektur und Release-Anleitung
|
||||
|
||||
5) Kurzzeit-MVP (Priorität für erste Version)
|
||||
|
||||
@@ -8,9 +8,31 @@ plugins {
|
||||
val localApiBaseUrl = providers.gradleProperty("LOCAL_API_BASE_URL")
|
||||
.orElse("https://harheimertc.tsschulz.de/")
|
||||
.get()
|
||||
val productionApiBaseUrl = providers.gradleProperty("PRODUCTION_API_BASE_URL")
|
||||
.orElse("https://harheimertc.de/")
|
||||
.get()
|
||||
val sentryDsn = providers.gradleProperty("SENTRY_DSN")
|
||||
.orElse("")
|
||||
.get()
|
||||
val androidVersionCode = providers.gradleProperty("ANDROID_VERSION_CODE")
|
||||
.orElse("2")
|
||||
.get()
|
||||
.toInt()
|
||||
val androidVersionName = providers.gradleProperty("ANDROID_VERSION_NAME")
|
||||
.orElse("1.0.0")
|
||||
.get()
|
||||
val releaseMinifyEnabled = providers.gradleProperty("RELEASE_MINIFY_ENABLED")
|
||||
.orElse("true")
|
||||
.get()
|
||||
.toBoolean()
|
||||
val releaseStoreFile = providers.gradleProperty("RELEASE_STORE_FILE").orNull
|
||||
val releaseStorePassword = providers.gradleProperty("RELEASE_STORE_PASSWORD").orNull
|
||||
val releaseKeyAlias = providers.gradleProperty("RELEASE_KEY_ALIAS").orNull
|
||||
val releaseKeyPassword = providers.gradleProperty("RELEASE_KEY_PASSWORD").orNull
|
||||
val hasReleaseSigning = !releaseStoreFile.isNullOrBlank() &&
|
||||
!releaseStorePassword.isNullOrBlank() &&
|
||||
!releaseKeyAlias.isNullOrBlank() &&
|
||||
!releaseKeyPassword.isNullOrBlank()
|
||||
|
||||
android {
|
||||
namespace = "de.harheimertc"
|
||||
@@ -19,9 +41,38 @@ android {
|
||||
defaultConfig {
|
||||
applicationId = "de.harheimertc"
|
||||
minSdk = 24
|
||||
targetSdk = 34
|
||||
versionCode = 1
|
||||
versionName = "0.1.0"
|
||||
targetSdk = 35
|
||||
versionCode = androidVersionCode
|
||||
versionName = androidVersionName
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
create("release") {
|
||||
if (hasReleaseSigning) {
|
||||
storeFile = file(releaseStoreFile!!)
|
||||
storePassword = releaseStorePassword
|
||||
keyAlias = releaseKeyAlias
|
||||
keyPassword = releaseKeyPassword
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
getByName("release") {
|
||||
isMinifyEnabled = releaseMinifyEnabled
|
||||
isShrinkResources = false
|
||||
ndk {
|
||||
// Generate a native debug symbols archive for Play Console uploads.
|
||||
debugSymbolLevel = "SYMBOL_TABLE"
|
||||
}
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro",
|
||||
)
|
||||
if (hasReleaseSigning) {
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flavorDimensions += "environment"
|
||||
@@ -46,7 +97,7 @@ android {
|
||||
}
|
||||
create("production") {
|
||||
dimension = "environment"
|
||||
buildConfigField("String", "API_BASE_URL", "\"https://harheimertc.tsschulz.de/\"")
|
||||
buildConfigField("String", "API_BASE_URL", "\"$productionApiBaseUrl\"")
|
||||
buildConfigField("String", "SENTRY_DSN", "\"$sentryDsn\"")
|
||||
buildConfigField("String", "ENVIRONMENT_NAME", "\"\"")
|
||||
manifestPlaceholders["usesCleartextTraffic"] = "false"
|
||||
@@ -72,6 +123,44 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
val packageNativeDebugSymbolsForProductionRelease = tasks.register<Zip>("packageNativeDebugSymbolsForProductionRelease") {
|
||||
group = "distribution"
|
||||
description = "Packages production release native libraries into a Play Console debug symbols zip."
|
||||
dependsOn(":app:mergeProductionReleaseNativeLibs")
|
||||
from(layout.buildDirectory.dir("intermediates/merged_native_libs/productionRelease/mergeProductionReleaseNativeLibs/out/lib"))
|
||||
destinationDirectory.set(layout.buildDirectory.dir("outputs/native-debug-symbols/productionRelease"))
|
||||
archiveFileName.set("native-debug-symbols.zip")
|
||||
}
|
||||
|
||||
val collectPlayStoreArtifacts = tasks.register("collectPlayStoreArtifacts") {
|
||||
group = "distribution"
|
||||
description = "Builds production release artifacts and collects AAB, mapping, and native symbols for Play Console upload."
|
||||
dependsOn(":app:bundleProductionRelease")
|
||||
dependsOn(packageNativeDebugSymbolsForProductionRelease)
|
||||
|
||||
doLast {
|
||||
val outputDir = layout.buildDirectory.dir("outputs/playstore/productionRelease").get().asFile
|
||||
outputDir.mkdirs()
|
||||
|
||||
val bundleFile = layout.buildDirectory.file("outputs/bundle/productionRelease/app-production-release.aab").get().asFile
|
||||
if (bundleFile.exists()) {
|
||||
bundleFile.copyTo(outputDir.resolve(bundleFile.name), overwrite = true)
|
||||
}
|
||||
|
||||
val mappingFile = layout.buildDirectory.file("outputs/mapping/productionRelease/mapping.txt").get().asFile
|
||||
if (mappingFile.exists()) {
|
||||
mappingFile.copyTo(outputDir.resolve("mapping.txt"), overwrite = true)
|
||||
}
|
||||
|
||||
val nativeSymbolsZip = layout.buildDirectory.file("outputs/native-debug-symbols/productionRelease/native-debug-symbols.zip").get().asFile
|
||||
if (nativeSymbolsZip.exists()) {
|
||||
nativeSymbolsZip.copyTo(outputDir.resolve("native-debug-symbols.zip"), overwrite = true)
|
||||
}
|
||||
|
||||
println("Play Store artifacts prepared in: ${outputDir.absolutePath}")
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
|
||||
|
||||
BIN
android-app/app/instantTest/release/app-instantTest-release.aab
Normal file
BIN
android-app/app/instantTest/release/app-instantTest-release.aab
Normal file
Binary file not shown.
BIN
android-app/app/local/release/app-local-release.aab
Normal file
BIN
android-app/app/local/release/app-local-release.aab
Normal file
Binary file not shown.
BIN
android-app/app/production/release/app-production-release.aab
Normal file
BIN
android-app/app/production/release/app-production-release.aab
Normal file
Binary file not shown.
2
android-app/app/proguard-rules.pro
vendored
Normal file
2
android-app/app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Project-specific R8/ProGuard rules for release builds.
|
||||
# Keep this file intentionally minimal and add rules only when needed.
|
||||
@@ -3,3 +3,22 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m -Dfile.encoding=UTF-8
|
||||
org.gradle.workers.max=2
|
||||
# Local API base URL for running the app from Android Studio / Gradle
|
||||
LOCAL_API_BASE_URL=https://harheimertc.tsschulz.de/
|
||||
|
||||
# Production backend for Play Store build variant
|
||||
PRODUCTION_API_BASE_URL=https://harheimertc.de/
|
||||
|
||||
# Android app versioning for Play Store uploads
|
||||
ANDROID_VERSION_CODE=3
|
||||
ANDROID_VERSION_NAME=1.0.0
|
||||
|
||||
# Enable R8 for release by default so mapping.txt is generated for Play Console.
|
||||
RELEASE_MINIFY_ENABLED=true
|
||||
|
||||
# Release signing (set in local, untracked gradle.properties or via CI secrets)
|
||||
# RELEASE_STORE_FILE=/absolute/path/to/keystore.jks
|
||||
# RELEASE_STORE_PASSWORD=***
|
||||
# RELEASE_KEY_ALIAS=***
|
||||
# RELEASE_KEY_PASSWORD=***
|
||||
|
||||
# Build and collect Play Store upload artifacts:
|
||||
# ./gradlew :app:collectPlayStoreArtifacts
|
||||
|
||||
Reference in New Issue
Block a user