# GPS2Audio v2.5.14 — Handoff **Release-Typ:** intern (kein Gitea, keine Netz-Veröffentlichung) **Build-Datum:** 2026-05-27 **versionCode / versionName:** 68 / 2.5.14 **Basis:** `GPS2Audio_v2_5_13_xiaomi_background_reliability_source.zip` ## Artefakte | Datei | Pfad | Größe | |------|------|------| | Signiertes APK | `/home/user/workspace/GPS2Audio_v2_5_14_multiclip_playback_navigation_signed.apk` | ~56 MB | | Source-Zip (ohne Secrets) | `/home/user/workspace/GPS2Audio_v2_5_14_multiclip_playback_navigation_source.zip` | ~1,5 MB / 122 Dateien | | Handoff | `/home/user/workspace/GPS2Audio_v2_5_14_multiclip_playback_navigation_handoff.md` | dieses Dokument | ## Signatur Identische v2-Signaturlinie wie v2.5.13 — **kein neuer Keystore erzeugt**. - Keystore: `/home/user/workspace/GPS2Audio_release_keystore_v2.jks` - Credentials: `/home/user/workspace/GPS2Audio_release_keystore_v2_credentials.txt` - Alias: `gps2audio_release_v2` - Signer DN: `CN=GPS2Audio, OU=NesoHub, O=GPS2Audio, L=Germany, C=DE` - Cert SHA-256: `490511f350557083808cdf9e39fdb0a2d4d76d2224726b56018d1ac0dd9ed4e5` - Scheme: v2 (APK Signature Scheme v2) Damit ist v2.5.14 ein In-Place-Update über jede installierte v2.5.x. ## Was wurde geändert ### 1. Multi-Clip-Playback-Fix **Problem (v2.5.13):** Ein zweiter eingespeicherter Clip eines Wegpunkts wurde nicht abgespielt. `manualPlaySingle(waypoint)` und der Play-Button im ClipDetailSheet riefen ausschließlich `waypoint.primarySoundUri()` auf — alle weiteren aktiven Clips blieben stumm. **Fix:** Neues flaches Playback-Modell `PlayableItem` (siehe `data/PlayableItem.kt`) flacht die `Waypoints × activeClips()` zu einer linearen Sequenz aus. Die ViewModel-Funktion `playableSequence()` ist die einzige Quelle der Wahrheit für: - Tour-Wiedergabe (`manualPlayPause`) - Karten-/Listen-Play eines Wegpunkts (`manualPlaySingle`) — startet jetzt **die volle aktive Clip-Sequenz** dieses Wegpunkts - Detail-Player Vor/Zurück - Auto-Advance bei Clip-Ende (`MediaPlayer.OnCompletion` → nächste `PlayableItem`) Der direkte Single-Clip-Play (`manualPlaySingleClip`, aus dem Clip-Edit-Dialog) bleibt unverändert — dort soll bewusst nur dieser eine Clip laufen. GPS-getriggerte Wiedergabe (`WaypointLocationService.playClipSequence`) war bereits multi-clip-fähig und wurde nicht angefasst. ### 2. Clip-Navigation (Prev/Next) Im `ClipDetailSheet` traversieren die Skip-Buttons jetzt entlang der flachen `PlayableItem`-Sequenz: - Innerhalb eines Wegpunkts: Clip → Clip - Über Wegpunkt-Grenzen hinweg: letzter Clip von WP-N → erster Clip von WP-(N+1) - UI zeigt **„Clip 2 von 3"** wenn der Wegpunkt mehr als einen Clip hat. - Der gerade geladene Clip wird in der Track-Liste mit Primärfarbe markiert. - Der Sheet folgt automatisch dem Wegpunktwechsel (per `LaunchedEffect(currentPlayable?.waypointId)`). ### 3. Countdown / Verbleibende Zeit - Neuer ViewModel-Job (`progressJob`) pollt alle 500 ms `MediaPlayer.currentPosition` / `.duration` und füttert `_playbackProgress: StateFlow`. - Anzeige „Verbleibend m:ss" im Detail-Sheet und kompakt in der manuellen Player-Bar. - Fallback „--:--" wenn `duration` (noch) unbekannt ist. - Job stoppt sich selbst, sobald nichts mehr läuft, und wird beim Tour-Wechsel / `onCleared()` sauber gecancelt. Format-Helper: `formatRemaining(remainingMs: Long): String` in `data/PlaybackProgress.kt`. ## Geänderte Dateien (Kurzliste) | Datei | Änderung | |------|----------| | `data/PlayableItem.kt` | NEU — flaches Playback-Modell + `List.toPlayableSequence()` | | `data/PlaybackProgress.kt` | NEU — Fortschritts-Snapshot + `formatRemaining(...)` | | `service/ManualAudioPlayer.kt` | `getCurrentPositionMs()` + `getDurationMs()` exponiert | | `viewmodel/WaypointViewModel.kt` | `_currentPlayable`, `_playbackProgress`, `playableSequence()`, neue Skip-Logik, Progress-Ticker, `manualPlaySingle()` jetzt Sequenz-basiert | | `ui/ClipDetailSheet.kt` | `WaypointDetailUiState` um `currentClipIndex`/`totalClips`/`progress` erweitert, „Clip N von M"-Badge, Restzeit-Zeile, Track-Highlight | | `ui/WaypointListScreen.kt` | Sammelt `currentPlayable` + `playbackProgress`, ManualPlayerBar zeigt `remainingLabel`, Sheet ruft `playableSequence()`/`manualPrevious()`/`manualNext()` auf | | `app/build.gradle.kts` | `versionCode=68`, `versionName="2.5.14"`, Header-Kommentar aktualisiert | ## Erhaltene Features (Smoke-Liste) - v2.5.13 Xiaomi Background-Reliability (WakeLock, Foreground-Service, Hinweis-Dialog) - v2.5.12 Multi-Clip-Storage (`AudioClip`, `activeClips()`, `primarySoundUri()`) - v2.5.11 Foreground-Service, Terms-Dialog, animiertes ClipDetailSheet/Waveform - PTT-Koordinator (pause/resume), Atmo (BackgroundMusicManager) - Explorer + MapLibre-Build-Abhängigkeit (Rendering weiterhin osmdroid) - Routing, Tourcover, Splash-Screen (API 26+) ## Manueller Test-Plan 1. **3-Clip-Wegpunkt anlegen**, alle drei aktiv → in Karte „Play" auf den Wegpunkt → es sollten nacheinander alle drei Clips laufen, mit Auto-Advance. 2. **Mittleren Clip deaktivieren** → Karten-Play überspringt ihn lautlos. 3. **Detail-Sheet öffnen → „Next"** → springt Clip 1 → Clip 2 → Clip 3 → erster Clip des nächsten Wegpunkts. „Previous" rückwärts. 4. **„Clip 2 von 3"-Anzeige** und Track-Highlight auf dem gerade laufenden Clip prüfen. 5. **Countdown** im Detail-Sheet **und** in der manuellen Player-Bar — sollte sekundengenau runterzählen. 6. **Tour-Play** (Hauptbutton) — komplette flache Sequenz aller aktiven Clips aller Wegpunkte. 7. **PTT-Trigger** während Tour-Play → Audio pausiert, nach PTT-Ende resume. 8. **Atmo-Hintergrundmusik** → fadet vor Clip aus, danach wieder ein. 9. **Xiaomi-Hinweis** auf passenden Geräten beim ersten Start prüfen. 10. **Auf v2.5.13 installierter Build → APK über `adb install -r` einspielen** → kein Re-Install, Daten bleiben. ## Build-Reproduktion ```bash unzip GPS2Audio_v2_5_14_multiclip_playback_navigation_source.zip -d v2_5_14 cd v2_5_14 # local.properties / keystore.properties bewusst NICHT im Zip — anlegen: echo "sdk.dir=$ANDROID_HOME" > local.properties cat > keystore.properties <<'EOF' storeFile=/home/user/workspace/GPS2Audio_release_keystore_v2.jks storePassword= keyAlias=gps2audio_release_v2 keyPassword= EOF gradle --no-daemon :app:assembleRelease # Ergebnis: app/build/outputs/apk/release/app-release.apk ``` Gebaut wurde dieser Release mit System-Gradle 8.7 (Wrapper-Jar nicht im Zip). Toolchain: AGP wie in v2.5.13, compileSdk 35, buildTools 35.0.0, JVM 17, Kotlin via Plugin-Alias. ## Sicherheit / Operatives - **Keine** Secrets im Source-Zip (`keystore.properties`, `local.properties`, `*.jks` ausgeschlossen — verifiziert via `unzip -l`). - **Kein** neuer Keystore erzeugt. - **Keine** Gitea-Veröffentlichung, kein Netz-Push. - Artefakte liegen ausschließlich unter `/home/user/workspace/`.