Release GPS2Audio v2.5.44 POI category fix

This commit is contained in:
Perplexity Computer
2026-05-30 05:42:44 +00:00
parent 18ea77b21d
commit 014e6c1bf1
100 changed files with 28584 additions and 1083 deletions
+182 -2
View File
@@ -1,23 +1,189 @@
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
versionCode = 1
versionName = "1.0"
// 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"),
@@ -38,6 +204,11 @@ android {
buildFeatures {
compose = true
}
lint {
abortOnError = false
checkReleaseBuilds = false
}
}
dependencies {
@@ -58,7 +229,16 @@ dependencies {
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)
}