-
GPS2Audio v2.0.0 Phase 1 Stable
released this
2026-05-15 14:29:52 +02:00 | 7 commits to main since this releaseGPS2Audio v2.0.0 — Phase 1 Fixes — Handoff
Build date: 2026-05-14
versionCode: 28
versionName: 2.0.0
applicationId: de.waypointaudio
Signed: yes, withGPS2Audio_release_keystore.jks(same identity as the first release)Artifacts
File Purpose /home/user/workspace/GPS2Audio_v2_0_0_phase1_signed.apkSigned release APK (≈ 14.4 MB) /home/user/workspace/GPS2Audio_v2_0_0_phase1_source.zipFull source tree ( work/root) without keystore, credentials, or realkeystore.properties/home/user/workspace/GPS2Audio_v2_0_0_phase1_handoff.mdThis document Build / signing verification
package: name='de.waypointaudio' versionCode='28' versionName='2.0.0' Signer #1 certificate DN: CN=GPS2Audio, OU=NesoHub, O=GPS2Audio, L=Germany, C=DE Signer #1 certificate SHA-256 digest: 7b0ea4d5528605173d299d7b268e7ab8768dd504ec15b66a52d47b4257b3bb46The SHA-256 matches the fingerprint recorded in
GPS2Audio_release_keystore_credentials.txtexactly — the APK is signed
with the same release identity asGPS2Audio_first_release_signed.apk.
apksigner verifyreports the certificate without errors. The build was
produced viagradle :app:assembleRelease; no debug build is shipped for
this milestone.Install / update notes
- This APK updates the installed first release (versionCode 27) because
the package name (de.waypointaudio), keystore identity, and signature
scheme are identical. No uninstall needed. - Users keep their tours, waypoints, audio files, drafts and tour-music
settings — only new DataStore stores (wake_lock_settings,
map_provider_settings) are added with safe defaults
(mode = Nie,provider = OpenStreetMap).
Phase 1 feature checklist
1.1 Wake Lock / Display aktiv halten
WAKE_LOCKpermission was already inAndroidManifest.xml(for audio
service); confirmed present and unchanged.- German UI with three radio-button options:
- Nie (default)
- Nur bei aktiver Tour/GPS — only while the GPS service is running
- Immer wenn App im Vordergrund — whenever the app window is visible - Implementation uses
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
on the Activity window (recommended pattern, see
https://developer.android.com/training/scheduling/wakelock). This is
preferred overPowerManager.SCREEN_DIM_WAKE_LOCK(deprecated) because
Android automatically clears the flag when the activity pauses, so the
"release when app goes to background" requirement is satisfied by the
framework itself and cannot leak. - Wake lock cleared explicitly in
MainActivity.onPause()and re-applied
inonResume()(in addition to the framework's automatic handling). - One-time Akku-Hinweis dialog appears the first time the user
switches from Nie to an active mode. Tracked in DataStore
(battery_hint_shown), so it never re-appears. - Setting persisted via DataStore (
wake_lock_settings) — new file
data/WakeLockSettings.kt. - Auto-dim after X min: not implemented in Phase 1 — would require a
custom timer + screen-brightness reset path that fights the Android
system display timeout. Limitation documented here; will revisit in
Phase 2 if requested.
Files touched:
app/src/main/kotlin/de/waypointaudio/data/WakeLockSettings.kt(new)app/src/main/kotlin/de/waypointaudio/service/WakeLockController.kt(new)app/src/main/kotlin/de/waypointaudio/ui/WakeLockSettingsDialog.kt(new)app/src/main/kotlin/de/waypointaudio/MainActivity.kt(wires controller, observes service state)app/src/main/kotlin/de/waypointaudio/ui/WaypointListScreen.kt(menu entry, dialog launch)app/src/main/res/values/strings.xml(new wake-lock strings)
1.2 Atmo-Bereich nach oben verschieben
- New scroll-region order on the main page:
Tour-Zähler → Live/PTT → Atmo (Begleitmusik) → Manueller Player → Wegpunkt-Tracks. - Existing fixed
ScrollableTabRowfor tours stays pinned at top, untouched. - Page remains scrollable; bottom FAB padding (
Spacer 160 dp) preserved. - No duplicate cards — old positions of the Atmo player and manual player
bar (below the waypoint list) were removed.
Files touched:
app/src/main/kotlin/de/waypointaudio/ui/WaypointListScreen.kt
1.3 Atmo Resume vollständig absichern
- AtmoResumeManager introduced as a single source of truth for
interrupt-start / interrupt-end across all three interruption
sources (WAYPOINT,MANUAL_PLAYER,PTT). It usespause()on the
sharedBackgroundMusicPlayer, which preserves the ExoPlayer's
current position — neverstop()(which releases the player and
loses the position). - PTT path now delegates to
AtmoResumeManager.notifyInterruptStart/End
viaLivePttManager.pauseAtmo / restoreAtmo. The previous inline logic
(which already usedpauseMusic()and a remembered "was playing"
flag) was replaced — behavior is identical from the user's perspective,
but it now runs through the central manager. - Waypoint path continues to use the existing
BackgroundMusicPlayer.before/afterWaypointAudiohooks. Those hooks
already callpause()internally for the PAUSE_RESUME behavior and
preserve position via the live ExoPlayer instance. They are explicitly
documented in the newAtmoResumeManagerso future contributors know
that the waypoint route is the canonical pause/resume contract. - Manual Player path wraps every manual play with the same
musicManager.beforeWaypointAudio()/afterWaypointAudio()pair
(unchanged) — that means manual-player interruptions use the same
pause-with-position semantics as GPS-triggered waypoint audio. - Resume only fires if Atmo was active immediately before the first
interruption and no other interruption is still active and the
Atmo player still holds content (i.e. the user has not manually
stopped it during the interruption). - Loop / natural-end edge case:
BackgroundMusicPlayeralready uses
Player.REPEAT_MODE_ALL, so an Atmo track that finishes naturally
mid-interruption simply transitions to the next item; on resume the
next-item start position is correct.
Files touched:
app/src/main/kotlin/de/waypointaudio/service/AtmoResumeManager.kt(new)app/src/main/kotlin/de/waypointaudio/service/LivePttManager.kt(delegates to AtmoResumeManager)
1.4 TopBar — Variante C (Icon + kompakter Titel)
- Title row in
WaypointListScreenis nowRow { Image(24dp) + Text(titleMedium / SemiBold) }. R.drawable.ic_launcheris reused (the launcher icon already encodes
the MapPin + sound-wave concept; there is no separate
ic_launcher_foregroundresource — single-source icon in this repo).- Line break in GPS2Audio fixed via
maxLines = 1+softWrap = false
+overflow = TextOverflow.Ellipsis.
Files touched:
app/src/main/kotlin/de/waypointaudio/ui/WaypointListScreen.kt
1.5 Versionsnummer bereinigen
app/build.gradle.kts:versionCode = 28,versionName = "2.0.0".- No suffix; Über diese App (
AboutDialog) reads viaAppVersion.get()
(existing util) and therefore now displays Version 2.0.0 (28) with
no code changes.
1.6 Karten-Provider Auswahl
- New enum
MapProviderwith eight OSMDroid-based tile sources:
OSM (default / fallback), CartoDB Positron, CartoDB Dark Matter,
OpenTopoMap, ESRI Satellite, ESRI Hybrid, Stadia Alidade, Stadia
Outdoors. All are wired throughXYTileSource— no library swap. - German selection dialog (
MapProviderDialog) reached from a
new layers-icon button in the Map TopBar actions row. - Selection persisted app-wide via DataStore
(map_provider_settings). Per-tour persistence not implemented:
tours currently store only audio settings (TourAudioSettings),
not map settings — adding a per-tour map provider would require a new
per-tour store and migration of existing tour data, which is out of
scope for Phase 1. The app-wide setting is reachable from the map at
any time, so it is one tap to switch. - Live tile-source switch:
LaunchedEffect(selectedProvider)in both
MapScreenandTrackDraftEditorScreenupdates the activeMapView
and callsinvalidate()so the new tiles load immediately. - OSM-Attribution remains the persistent
OsmAttributionBadgeoverlay
onMapScreen— visible for all providers. The provider-specific
copyright (CartoDB, Esri, Stadia, OpenTopoMap) is encoded in each
XYTileSourceand surfaced when osmdroid prints copyright info.
Files touched:
app/src/main/kotlin/de/waypointaudio/data/MapProvider.kt(new)app/src/main/kotlin/de/waypointaudio/ui/MapProviderDialog.kt(new)app/src/main/kotlin/de/waypointaudio/ui/MapScreen.ktapp/src/main/kotlin/de/waypointaudio/ui/TrackDraftEditorScreen.ktapp/src/main/res/values/strings.xml(new provider strings)
First-release regression checklist
Each of these features from the first release was inspected and is not
modified by this milestone:applicationIdde.waypointaudiounchanged.- Track-Editor / draft archive, thick route line + handles, marking,
"import marked points" flow — code paths inTrackDraftListScreen,
TrackDraftEditorScreen,WaypointRepositoryuntouched apart from
a single map-tile-source line. - Backup export / import unchanged (
io/BackupExportManager.kt,
io/BackupImportManager.kt). - Sort mode for tours and waypoint tracks unchanged (SortModeBar +
TourReorderList still in WaypointListScreen). - Scrollable main page preserved (the outer
verticalScrollcolumn
still wraps everything below the tab row). - Map search in normal map and editor unchanged (
PlaceSearchDialog
still wired into bothMapScreenandTrackDraftEditorScreen). - Audio library playlist selection unchanged (
BegleitmusikDialog). - PTT / Atmo collapsible unchanged (
LivePttCard). - PTT pauses / resumes Atmo correctly — same behavior, now routed
throughAtmoResumeManager. Manually traced:pauseAtmo→
notifyInterruptStart(PTT)→ snapshotswasAtmoPlayingAtFirstInterruption
and pauses if playing;restoreAtmo→notifyInterruptEnd(PTT)→
resumes only if it was playing and the player still has content. - OSM attribution layout (
OsmAttributionBadge) still rendered for
every provider — verified by inspectingMapScreen.ktlines 819–824. - About: PayPal support link, automatic version display
(AppVersion.get()), per-version startup notice
(VersionNoticeStore,VersionNoticeDialogHost) — all unchanged.
BecauseversionCode = 28is new, the one-time version notice will
fire once on first launch of v2.0.0. - JSON / GPX I/O (
ImportExportManager), GPS behaviors
(WaypointLocationService,TrackRecordingService) untouched.
Build details
gradle :app:assembleRelease BUILD SUCCESSFUL in 1m 51s 43 actionable tasks: 43 executedCompiler warnings (non-fatal, all pre-existing):
launchWhenStarteddeprecation in MainActivity (could be migrated to
repeatOnLifecyclein a later cleanup pass).- A handful of osmdroid + Material3 deprecations carried over from the
first release.
Implementation notes worth remembering
- WAKE_LOCK manifest permission is genuinely needed by the audio
service (MediaPlayer keeps CPU alive in foreground service). The new
display-on logic does not need an additional manifest permission —
FLAG_KEEP_SCREEN_ONrequires none. - Per-tour map provider was considered and explicitly deferred because
the existingTourAudioSettingsstore is audio-only; adding a parallel
per-tour map store would have created two parallel persistence schemas
in one milestone. The single app-wide setting is one tap away on the map. PowerManagerwake lock is not held in addition to
FLAG_KEEP_SCREEN_ONfor the display use case. Two mechanisms competing
for the same outcome makes future maintenance harder and provides no
user-visible benefit on modern Android.- AtmoResumeManager.activeInterruptions is a
Set: if a PTT press
overlaps with a waypoint trigger, both must end before the Atmo resumes.
This prevents the Atmo from briefly re-starting between two adjacent
interruptions. - keystore.properties is excluded from the source zip (only the
.exampletemplate is included). The keystore.jksfile and
credentials are never bundled. Build from this zip with the
signing-config environment variables or by writing a local
keystore.propertiesoutside source control.
Downloads
- This APK updates the installed first release (versionCode 27) because