# GPS2Audio v2.5.18 — GPX Additive Import (Bugfix Release) **Base**: v2.5.17 (`GPS2Audio_v2_5_17_license_pro_about_source.zip`) **Type**: Internal bugfix release (no Gitea upload, no Gitea release) **Version**: `versionName = 2.5.18`, `versionCode = 72` (v2.5.17 hatte 71) **Signing**: Release-Keystore v2 (`gps2audio_release_v2`), APK v2-Scheme verifiziert **Build**: `BUILD SUCCESSFUL`, Gradle 8.7, `:app:assembleRelease` --- ## 1. Was war kaputt Beim Import einer GPX-Datei wurden **alle bestehenden Wegpunkte in allen Touren gelöscht**. Ursache war ein versehentlich destruktiver Pfad in der `WaypointViewModel`: ```kotlin // v2.5.17 — fehlerhaft fun importGpx(uri: Uri, merge: Boolean = false) { val (imported, error) = ImportExportManager.importGpx(...) ... if (merge) { ... } else { repository.saveAll(imported) // <-- ERSETZT alle Waypoints global } } ``` `merge` wurde von der UI nie gesetzt, also wurde immer der destruktive Pfad genommen. Auch der `importJson`-Pfad hatte denselben Bug. ## 2. Was ist neu in v2.5.18 ### 2.1 GPX-Import ist strikt additiv und dialoggesteuert Beim Auswählen einer GPX-Datei öffnet sich jetzt der neue `GpxImportDialog`. Vorher passiert **nichts** an den Daten. Im Dialog stehen zwei Optionen zur Auswahl: * **A. „Als neue Tour importieren“** — Textfeld mit editierbarem Tournamen. Default kommt aus dem Dateinamen der GPX-Datei (ohne Endung). Liegt bereits eine gleichnamige Tour vor, wird der Name automatisch um eine laufende Nummer ergänzt (`Foo`, `Foo (2)`, `Foo (3)`, …), damit nichts überschrieben werden kann. * **B. „Zu bestehender Tour hinzufügen“** — RadioButton-Liste mit allen bestehenden Touren. Importierte Wegpunkte werden ans **Ende** der Tour angehängt. Die Reihenfolge bestehender Wegpunkte bleibt unverändert, bestehende Wegpunkte werden nicht ersetzt. * **Abbrechen** verändert nichts (keine I/O, keine Persistenz). ### 2.2 Datenverlust-Schutzlogik im Detail Die Schreiblogik ist in zwei neuen ViewModel-Funktionen gekapselt: * `importGpxAsNewTour(uri, requestedTourName)` * `importGpxIntoExistingTour(uri, targetTourName)` Beide: 1. lesen das GPX über den unveränderten `ImportExportManager.importGpx`, 2. prüfen IDs gegen die bestehenden Wegpunkt-IDs und vergeben bei Konflikt eine neue `UUID`, damit kein bestehender Wegpunkt überschrieben wird, 3. setzen `tourName` auf die finale Ziel-Tour, 4. schreiben **die Vereinigung** `existing + imported` via `repository.saveAll(...)`. `saveAll` ist von der Repository-API her weiterhin „ersetze alle“, wird aber jetzt nie mehr mit nur den importierten Punkten aufgerufen. 5. Tourliste wird ergänzt, falls die Ziel-Tour neu ist; bestehende Touren bleiben in ihrer Reihenfolge. Die alte Signatur `importGpx(uri, merge)` ist entfernt. Wer von außen GPX importieren will, muss explizit eine der beiden additiven Funktionen aufrufen. ### 2.3 JSON-Import/-Export aus der UI entfernt Im `DataSafetySheet` (Datensicherung) sind die Sektionen „Als JSON exportieren“ und „JSON importieren“ entfernt. Sichtbar bleiben: * Komplett-Backup (ZIP) erstellen / importieren — bevorzugter Weg. * GPX exportieren / importieren — mit neuem Dialog. **Bewusst NICHT entfernt** (damit alte Backups weiterhin lesbar sind): * `ImportExportManager.toJson` / `importJson` (Parser/Modell). * Die interne Gson-Serialisierung der Waypoint-Datenklasse. * Der `BackupImportManager`/`BackupExportManager` — diese nutzen JSON intern für Touren/Waypoints im ZIP. Alte Backups (auch aus v2.5.x ≤17) bleiben damit voll kompatibel. Die `viewModel.importJson(uri)`-Funktion existiert weiter, ruft aber nur noch den additiven Append-Pfad an (`appendWaypointsAdditively`). Damit kann auch ein hypothetischer interner Aufruf nicht mehr versehentlich Daten ersetzen. Die `exportJson(uri)`-Funktion bleibt unverändert, ist aber aus der UI nicht mehr erreichbar. ### 2.4 GPX-Inhalt: was wird importiert? Wie in v2.5.17 importiert `ImportExportManager.importGpx` ausschließlich ``-Wegpunkte (mit allen `wpa:`-Extensions: Radius, isActive, soundName, tourName, Abspielmodus, Schedule etc.). Reine ``-Tracks ohne Wegpunkte wurden in v2.5.17 nicht eingelesen. v2.5.18 ändert daran **bewusst nichts** — der Auftrag verlangt, vorhandenen Support sicher additiv zu machen statt eine neue Großfunktion zu bauen. Wer ``-Wegpunkte in einer GPX hat, importiert wie bisher; reine Track-only-GPX führt zur klaren Fehlermeldung „GPX enthält keine gültigen Wegpunkte ( mit lat/lon)“ und schreibt nichts. ## 3. Geänderte Dateien | Datei | Änderung | |---|---| | `app/build.gradle.kts` | `versionCode 71→72`, `versionName 2.5.17→2.5.18`, Header-Kommentar aktualisiert. | | `app/src/main/kotlin/de/waypointaudio/viewmodel/WaypointViewModel.kt` | `importJson` jetzt strikt additiv (Append + ID-Dedup). `importGpx(merge)` ersetzt durch neue Funktionen `importGpxAsNewTour` und `importGpxIntoExistingTour`. Neue Helfer `suggestTourNameForGpx`, `appendWaypointsAdditively`, `uniqueTourName`. Neuer Import `java.util.UUID`. | | `app/src/main/kotlin/de/waypointaudio/ui/WaypointListScreen.kt` | `exportJsonLauncher`, `importJsonLauncher` entfernt. `importGpxLauncher` öffnet jetzt nur noch den neuen `GpxImportDialog` (URI + Default-Name werden in State gehalten). `DataSafetySheet` ohne JSON-Sektion. Neuer Composable `GpxImportDialog` mit Mode-Auswahl + Tourliste. Neue Datenklasse `GpxImportMode` (NEW_TOUR/EXISTING). | Andere Dateien wurden nicht angefasst — kein Eingriff in Audio, Service, Routing, Map, License, Backup, PTT, Atmo, Background-Reliability, Tourcover, Track-Drafts. ## 4. Neue UX im Überblick 1. Datensicherung öffnen → Sektion „GPX (Geräte-/Tool-Austausch)“ → „GPX importieren“. 2. SAF-Dateiauswahl: GPX-Datei wählen. 3. Dialog „GPX importieren“ erscheint. 4. Option **Neue Tour**: Tourname ist mit Dateiname vorbelegt, editierbar. 5. Option **Bestehende Tour**: aus Radio-Liste wählen. 6. „Importieren“ schreibt **additiv**. „Abbrechen“ verändert nichts. 7. Snackbar bestätigt z. B. „GPX importiert: 17 Wegpunkte in Tour ‚Wanderung Schwarzwald‘“. ## 5. Erhaltene Funktionen (Regressionsschutz) Keine der folgenden Funktionen wurde berührt: * Lizenzseite v2.5.17 (Pro-Hinweis, Public Key Resource, Status-Karte). * GPS2Audio Pro Bereich, PayPal-Anfrage-Button. * Multi-Clip pro Waypoint (v2.5.12), manueller Sequenzplayer, Multi-Clip-Navigation (v2.5.14). * Countdown / Tour-Zähler. * Maximierbarer Player (v2.5.15), Tour duplizieren (v2.5.15), Waypoint kopieren im Edit-Modus (v2.5.16). * Explorer, MapLibre, Routing, Tourcover. * Backup-Export/-Import (ZIP) inkl. Tour-Cover/Medien. * PTT, Atmo, Hintergrundwiedergabe, Xiaomi-Hintergrundhilfe. * GPX-Export — Format unverändert, voll round-trip-fähig. ## 6. Build-Ergebnis * `:app:assembleRelease` → `BUILD SUCCESSFUL in 2m 5s`. * Nur Kotlin-/Compose-Deprecation-Warnings (vorhanden auch in v2.5.17). * Signiert mit `GPS2Audio_release_keystore_v2.jks`, Alias `gps2audio_release_v2`, APK Signature Scheme v2 verifiziert (`apksigner verify --verbose`). * `aapt dump badging` bestätigt: `package=de.waypointaudio versionCode=72 versionName=2.5.18 targetSdkVersion=35 minSdkVersion=26`. ## 7. Artefakte im Workspace * `/home/user/workspace/GPS2Audio_v2_5_18_gpx_additive_import_signed.apk` — signierte Release-APK, ~57 MB. * `/home/user/workspace/GPS2Audio_v2_5_18_gpx_additive_import_source.zip` — Source ohne `app/build/`, ohne `keystore.properties`, ohne `local.properties` (Keystore-Credentials bleiben außerhalb des Source-Pakets). * `/home/user/workspace/GPS2Audio_v2_5_18_gpx_additive_import_handoff.md` — dieses Dokument. ## 8. Bekannte Einschränkungen * GPX-Track-Punkte (`//`) werden weiterhin nicht importiert; nur `` (siehe 2.4). Bewusste Entscheidung, um keine Großänderung in einen Bugfix-Release zu mischen. * Beim Import-Dialog wird die Zieltour als Liste mit RadioButtons gerendert. Bei sehr vielen Touren wird das Dialog-Layout lang — funktional ok, aber optisch unspektakulär. * Der Import-Dialog ruft `ImportExportManager.importGpx` erst beim „Importieren“ auf — wenn die GPX-Datei zwischen Auswahl und Bestätigung vom Provider widerrufen wird, schlägt der Import mit der bestehenden Fehlermeldung fehl; Daten werden in diesem Fall nicht angefasst. * Update auf v2.5.x-Builds mit altem (verlorenem) Keystore ist weiterhin kein In-Place-Update, weil die Signaturlinie seit v2 abweicht (bekannt aus Keystore-Credentials). * Es wurden keine Instrumented-Tests ausgeführt (keine im Projekt enthalten). Verifikation erfolgte über Build + Code-Review der Schreibpfade: jeder Pfad, der `repository.saveAll(...)` aufruft, übergibt entweder die unveränderte bestehende Liste oder die bestehende Liste plus neue Einträge.