Files
GPS2Audio/app/build.gradle.kts
T
2026-05-30 05:42:44 +00:00

245 lines
13 KiB
Kotlin
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import java.util.Properties
import java.io.FileInputStream
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
}
val keystorePropertiesFile = rootProject.file("keystore.properties")
val keystoreProperties = Properties().apply {
if (keystorePropertiesFile.exists()) {
load(FileInputStream(keystorePropertiesFile))
}
}
fun resolveSigningValue(propsKey: String, envKey: String): String? {
val fromProps = keystoreProperties.getProperty(propsKey)
if (!fromProps.isNullOrBlank()) return fromProps
val fromEnv = System.getenv(envKey)
if (!fromEnv.isNullOrBlank()) return fromEnv
return null
}
android {
namespace = "de.waypointaudio"
compileSdk = 35
buildToolsVersion = "35.0.0"
defaultConfig {
applicationId = "de.waypointaudio"
minSdk = 26
targetSdk = 35
// v2.5.18 — Bugfix: GPX-Import ist jetzt strikt additiv.
// - Datenverlust-Schutz: Der GPX-Import in v2.5.17 hat über
// `repository.saveAll(imported)` versehentlich alle bestehenden
// Wegpunkte in sämtlichen Touren ersetzt. Ab v2.5.18 löscht ein
// GPX-Import nie bestehende Daten.
// - Neuer Import-Dialog mit zwei Optionen:
// (A) Als neue Tour importieren (editierbarer Name, Default aus
// GPX-Dateiname).
// (B) Zu bestehender Tour hinzufügen (Auswahl der Tour).
// Abbrechen verändert nichts.
// - JSON-Import/-Export in der sichtbaren UI entfernt; das ZIP-Backup
// übernimmt diese Rolle. Interne JSON-Parser/-Modelle bleiben für
// Backup-Kompatibilität erhalten.
// - v2.5.17 Lizenz/Pro/About bleibt unverändert.
// - Alle weiteren Funktionen (Multi-Clip, Sequenzplayer, Countdown,
// maximierbarer Player, Tour duplizieren, Waypoint kopieren,
// Explorer/MapLibre/Routing, Backup ZIP, PTT/Atmo, Hintergrund,
// Tourcover) bleiben unverändert.
//
// v2.5.19 — Menü- und UX-Politur:
// • „Track Editor" aus dem Hauptmenü entfernt (über Explorer
// erreichbar). Funktionalität (TrackDraftListScreen/-Editor)
// bleibt vollständig im Code.
// • „Klassische Ansicht" umbenannt zu „Bearbeitungsmodus" — bessere
// UX-Begriffswahl auf Deutsch.
// • „Touren ordnen" aus der einzelnen Touransicht in das Menü der
// Audio-Bibliothek (HomeScreen) verschoben. Sortier-Funktion
// (TourReorderDialog + WaypointViewModel.moveTour) unverändert.
// • Backup: Tour-Cover (Icon + Palette + Bild) sind ab v2.5.7
// bereits Teil des ZIP-Backups (media/covers/<tour>.jpg) und
// werden beim Import wiederhergestellt. v2.5.19 ist hierbei
// inhaltlich unverändert; dieser Eintrag dient der Klarstellung
// in der Versionshistorie.
//
// v2.5.20 — Phase 2 des Lizenzsystems:
// • Echter Import einer .gps2audio-license-Datei über das Android
// Storage Access Framework (ACTION_OPEN_DOCUMENT).
// • Offline-Signaturprüfung (ECDSA P-256 SHA-256) gegen den bereits
// in res/raw eingebetteten Public Key, kanonisches JSON wie im
// Python-Tool (sortierte Keys, kein Whitespace).
// • Lokale Ablage der validierten Lizenz in filesDir/license/
// inkl. Backup-Ausschluss (data_extraction_rules + backup_rules).
// • Anzeige im About-Dialog: Status (Keine/Gültig/Ungültig/Abgelaufen),
// Lizenztyp, Lizenznehmer, Gültigkeit, Lizenz-ID, Bindung,
// Permissions (deutsch beschriftet).
// • Buttons „Lizenz importieren / exportieren / entfernen" inkl.
// Bestätigungsdialog. Keine Feature-Sperren, alle bestehenden
// Funktionen bleiben unverändert nutzbar.
// v2.5.21 — Re-Import-Bugfix + Geräte-ID:
// • Behebt: Lizenzdatei konnte nach Entfernen + Re-Import nicht mehr
// gelesen werden. Ursache: LicenseStatusProvider.initialized-Flag
// wurde nach remove() nicht zurückgesetzt; kombiniert mit
// transienten SAF-URI-Permissions führte das zu "Lizenzdatei konnte
// nicht gelesen werden" beim zweiten Import-Versuch.
// • Fix: initialized wird in remove() auf false gesetzt. import()
// liest Bytes immer frisch, ohne gecachte URIs.
// • Geräte-ID: app-spezifische UUID (SharedPreferences, kein Backup),
// SHA-256-Hash "GPS2AudioDevice:"+uuid für Lizenz-Tool-Kompatibilität.
// Anzeige + Kopier-Button im Über-Dialog. Keine harte Bindung aktiv.
// v2.5.23 — Lizenzimport-Regression-Fix:
// • v2.5.22 wechselte zu GetContent(), was auf manchen OEM-Geräten
// (Huawei/EMUI, MIUI-Galerie-Modus) nur Medien anzeigt — .gps2audio-
// license-Dateien unsichtbar, Erstimport unmöglich.
// • Fix: Zurück zu OpenDocument() mit breiten MIME-Typen (json/text/
// octet-stream/*). Echter SAF-Datei-Browser zeigt alle Dateien.
// • importNonce-Mechanismus: Key-basierter Launcher-Slot-Reset erzwingt
// frischen SAF-Picker auch bei Wiederwahl derselben URI.
// • Robustes Lesen (copyTo statt readBytes), differenzierte
// Fehlermeldungen und reloadTrigger aus v2.5.22 beibehalten.
// v2.5.24 — Lizenzimport-Fallbacks:
// • readLicenseBytes(): drei Lesestrategien (openInputStream, openFileDescriptor,
// File-Fallback) mit separater Fehlersammlung.
// • Diagnose-Dialog bei Totalausfall: technische Fehlermeldungen statt generisches Toast.
// • Textimport-Fallback: Button "Lizenz aus Zwischenablage / Text einfügen" öffnet
// AlertDialog mit großem Textfeld + Zwischenablage-Schaltfläche.
// • OpenDocument() mit nur "*/*" (keine MIME-Liste, verhindert Galerie-Modus auf MIUI).
// • importNonce-Mechanismus aus v2.5.23 unverändert beibehalten.
// v2.5.25 — License-Import-Thread-Fix:
// • Alle blockierenden I/O-Operationen (contentResolver.openInputStream,
// openFileDescriptor, FileInputStream, ByteArrayOutputStream.copyTo,
// LicenseStatusProvider.import inkl. JSON/Signaturvalidierung) auf
// Dispatchers.IO verschoben. Root Cause: NetworkOnMainThreadException
// auf Android 9+ (StrictMode blockiert Netzwerk-/Disk-I/O auf Main-Thread).
// • ActivityResult-Callback startet Coroutine (rememberCoroutineScope);
// withContext(Dispatchers.IO) für readLicenseBytes + import();
// danach UI-State/Toast/reloadTrigger auf Main-Thread.
// • isImporting-Flag verhindert Doppelauslösung des Import-Buttons.
// • Export-Callback (openOutputStream) ebenfalls auf IO.
// • Textimport: import() ebenfalls auf IO.
// • Alle v2.5.24-Fallbacks (drei Lesestrategien, Diagnose-Dialog,
// Textimport, OpenDocument */*, importNonce) unverändert.
// v2.5.29 — Lizenz-Persistenz-Fix: Update-sichere Lizenzablage.
// v2.5.30 — Home Atmo-Modul entfernt; Playback-Persistenz beim Tour-Wechsel.
// • Atmo-Modul/-Toggle auf der Startseite (HomeScreen) entfernt.
// Atmo bleibt vollständig in der Tour-Ansicht (WaypointListScreen) verfügbar.
// • selectTour() stoppt keine laufende Wiedergabe mehr beim Tour-Wechsel.
// Stop nur noch bei expliziten Nutzeraktionen: Play in anderer Tour,
// Stop-Button, GPS-Dienst bewusst stoppen.
//
// v2.5.31 — Tourcover-Backup-Fix: frei gewählte Bilder werden jetzt
// zuverlässig gesichert und beim Import wiederhergestellt.
// • BackupExportManager: ZIP-Entry-Pfade für Cover-Bilder erhalten
// einen eindeutigen Index-Präfix ("media/covers/001_tourname.jpg"),
// damit Touren mit gleichem sanitisierten Namen nicht kollidieren.
// • BackupExportManager: Fallback-Lesestrategie für Cover-Bilder:
// absoluter Dateipfad → ContentResolver → file://-URI.
// • BackupImportManager: Verbesserte Fehlerprotokollierung beim
// Cover-Bild-Import; Rückwärtskompatibel mit v2.5.7v2.5.30-Backups.
// • Kein Änderungen am Lizenzsystem, Feature-Gates, Touren/Waypoints.
// v2.5.34 — Explorer-Kontext-Fix: selectDefaultTour() beim Einstieg aus
// der Audio-Bibliothek/Home verhindert das Übernehmen des zuletzt aktiven
// Tour-Kontexts. Einstieg aus konkreter Tour behält Tour-Karte.
// v2.5.38 — Kartenattribution, POI-Layer, Kartenstil-Persistenz.
// • Kartenattribution rechtlich sauber: kompaktes Badge bottom-left
// (anklickbar → openstreetmap.org/copyright), vollständiger Karteninfo-
// Dialog aus dem Ebenen-Sheet (OpenFreeMap, OpenMapTiles, OSM, ODbL).
// • POI-Layer-Kategorien im Ebenen-Sheet: Sehenswürdigkeiten (default an),
// Infrastruktur, Gastronomie, Mobilität (default aus). Symbol-Layer des
// geladenen MapLibre-Styles werden per Layer-ID-Heuristik ein-/ausgeblendet.
// Auswahl wird persistent gespeichert (DataStore). Kein Crash wenn Layer fehlt.
// • Kartenstil-Persistenz: baseStyle zuverlässig beim Neustart wiederhergestellt.
// POI-Auswahl ebenfalls persistent. Alle MapStyleStore-Keys unverändert.
// • Stylewechsel stellt Overlays, Attribution und POI-Sichtbarkeit wieder her.
// • Keine Regressionen: Phantom-Layer-Fix, Lizenzsystem, Multi-Clip,
// PTT, Tour-Zähler, Backup/Cover, GPX-Import, Explorer/Routing,
// Tour-/Waypoint-Kopien, Hintergrundwiedergabe.
versionCode = 98
versionName = "2.5.44"
}
val storeFilePath = resolveSigningValue("storeFile", "GPS2AUDIO_RELEASE_STORE_FILE")
val storePassword = resolveSigningValue("storePassword", "GPS2AUDIO_RELEASE_STORE_PASSWORD")
val keyAliasValue = resolveSigningValue("keyAlias", "GPS2AUDIO_RELEASE_KEY_ALIAS")
val keyPasswordValue = resolveSigningValue("keyPassword", "GPS2AUDIO_RELEASE_KEY_PASSWORD")
val hasReleaseSigning = storeFilePath != null && storePassword != null &&
keyAliasValue != null && keyPasswordValue != null
signingConfigs {
if (hasReleaseSigning) {
create("release") {
storeFile = file(storeFilePath!!)
this.storePassword = storePassword
keyAlias = keyAliasValue
keyPassword = keyPasswordValue
}
}
}
buildTypes {
release {
if (hasReleaseSigning) {
signingConfig = signingConfigs.getByName("release")
}
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
buildFeatures {
compose = true
}
lint {
abortOnError = false
checkReleaseBuilds = false
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.lifecycle.viewmodel.compose)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
implementation(libs.androidx.material.icons.extended)
implementation(libs.androidx.navigation.compose)
implementation(libs.androidx.datastore.preferences)
implementation(libs.gson)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.coroutines.play.services)
implementation(libs.play.services.location)
implementation(libs.osmdroid)
// v2.2.2 — MapLibre Native Android SDK als Build-Abhängigkeit eingezogen.
// Das eigentliche Rendering nutzt weiterhin osmdroid (siehe ExplorerScreen),
// damit Stabilität/Größe nicht regressieren. MapLibre dient als Grundlage
// für künftige Vektor-/3D-Layer-Schritte (siehe Handoff).
implementation(libs.maplibre.android.sdk)
implementation(libs.media3.exoplayer)
implementation(libs.media3.common)
// v2.5.8 — Android Splash Screen API (Backport für API 26+). Wir nutzen
// den stabilen Weg via androidx.core.splashscreen, damit Pre-31 dieselbe
// Intro-Optik bekommt wie API 31+.
implementation(libs.androidx.core.splashscreen)
debugImplementation(libs.androidx.ui.tooling)
}