-
released this
2026-05-15 14:32:38 +02:00 | 7 commits to main since this releaseGPS2Audio v2.1.0 – PTT Recorder – Handoff
Artifacts
Path Size Notes /home/user/workspace/GPS2Audio_v2_1_0_ptt_recorder_signed.apk14.5 MB release-signed /home/user/workspace/GPS2Audio_v2_1_0_ptt_recorder_source.zip230 KB source bundle /home/user/workspace/GPS2Audio_v2_1_0_ptt_recorder_handoff.md– this document SHA-256 (APK):
181fa1846bc384cae8b7e2ad72db8ea1943c881b8b7878cd50d40205b929705aBuild / verification
package: de.waypointaudio versionCode: 37 (was 36 in v2.0.8 – satisfies "> 36") versionName: 2.1.0 compileSdk: 35 minSdk: 26 targetSdk: 35 gradle :app:assembleRelease → BUILD SUCCESSFUL (1m 47s, 43 tasks) apksigner verify --print-certs Signer #1 DN: CN=GPS2Audio, OU=NesoHub, O=GPS2Audio, L=Germany, C=DE Signer #1 SHA-256: 7B:0E:A4:D5:52:86:05:17:3D:29:9D:7B:26:8E:7A:B8:76:8D:D5:04:EC:15:B6:6A:52:D4:7B:42:57:B3:BB:46 ← matches GPS2Audio_release_keystore.jks fingerprint (verified)What was implemented
1. PTT Settings (
AudioRoutingSettings)- New persisted fields on the existing DataStore (
audio_routing_settings):liveOutputEnabled: Boolean— defaulttrue(matches v2.0.8 PTT behaviour)recordingEnabled: Boolean— defaultfalserecordingFormat: PttRecordingFormat— defaultM4A_AAC
- Validation guard in
LivePttManager.saveRoutingSettings()and in the
Settings dialog: if the user turns both off, Live is forced back on
(toast hint shown in the dialog). - The new
PttSettingsDialog(LivePttCard.kt) replaces the v2.0.8
AudioDeviceDialogand merges both responsibilities:- Toggles for Live-Ausgabe and Aufnahme speichern (with German
helper text). - Format selector: M4A/AAC active; WAV shown but radio button
disabled, label reads "WAV (in v2.1.0 nicht verfügbar)" — see
Limitations below. - Existing input/output device dropdowns, refresh button and hints
kept exactly as in v2.0.8.
- Toggles for Live-Ausgabe and Aufnahme speichern (with German
2. Recording engine (
PttRecorder)- Wraps Android
MediaRecorder(MIC source, MPEG-4 container, AAC
encoder, mono, 44.1 kHz, 96 kbps). API ≥ 31 uses
MediaRecorder(context), below uses the deprecated default constructor. - Files saved to
<app filesDir>/recordings/PTT_<yyyyMMdd_HHmmss>.m4a. - On
stop()reads the duration viaMediaMetadataRetrieverand returns
a fully populatedPttRecordingvalue (id, displayName, filePath,
file://URI, format, createdAt, durationMs, optional lat/lon). cancel()releases the recorder and deletes the partial file.
3. Recording library (
PttRecording+PttRecordingStore)- New DataStore (
ptt_recordings) with a single JSON-encoded list of
recording metadata entries. Gson is already a project dependency. - Operations:
recordings: Flow<List<PttRecording>>(always sorted by
createdAt desc),add,delete,rename.
4. PTT lifecycle (
LivePttManager)startPtt()now reads the saved settings and:- Pauses Atmo + waypoint audio (unchanged from v2.0.8).
- Starts the
MediaRecorderfirst (ifrecordingEnabled). Sets
recordingActive=true. - Starts the existing
LivePttServiceforeground service (if
liveOutputEnabled). The service still uses
AudioSource.VOICE_COMMUNICATIONso on most devices both clients
share the mic; if either init fails the other continues and a
status message is surfaced.
stopPtt()stops the live service, finalises the recording on a
coroutine (fetchesfusedLocation.lastLocationwith a 1.5 s timeout
to attach lat/lon), persists the metadata inPttRecordingStoreand
posts the result tolastRecording: StateFlow<PttRecording?>.- New helper methods:
deleteRecording,renameRecording,
clearLastRecording. - Recording state surfaced via
recordingActive: StateFlow<Boolean>
for the UI to show a red dot/pill in the PTT card.
5. UI changes
- LivePttCard (
ui/LivePttCard.kt): adds aLibraryMusicicon
button next to the Settings icon that opens the recordings library.
Status row shows "Aufnahme läuft" + redFiberManualRecorddot when
recording. A small "Live + Aufnahme" / "Nur Aufnahme" / "Nur Live"
summary line appears under the status. Echo warning is suppressed
when Live is off. - PttSettingsDialog (same file): merged dialog described above.
- PostRecordingDialog (
ui/PttRecordingDialogs.kt): shown
automatically wheneverlastRecordingbecomes non-null. Buttons:- Als Waypoint-Audio zuweisen → opens
WaypointChooserDialog - Löschen → calls
pttManager.deleteRecordingand clears the
last-recording state - OK → dismisses without action
- Als Waypoint-Audio zuweisen → opens
- PttRecordingsLibraryDialog: full bottom-sheet style dialog with
scrollable list of all recordings; per-item "Zuweisen" and "Löschen"
buttons with confirm dialog for delete. - WaypointChooserDialog: lists every waypoint of the currently
selected tour; tapping a card setswaypoint.soundUri = recording.uri
andwaypoint.soundName = recording.displayNamevia
WaypointViewModel.upsert(). This is the existing assignment path,
so the audio is immediately played on waypoint entry like any other
sound.
6. WaypointListScreen integration
- Passes
onOpenRecordingscallback toLivePttCard. - Renders the post-recording dialog, recordings-library dialog and
waypoint-chooser dialog at the end of the screen so they overlay
the main UI.
7. Backup
- The existing
BackupExportManageralready collects every
waypoint.soundUriintomedia/waypoints/<tour>/...in the backup
ZIP. Because assigned recordings are written into that exact field
with afile://URI rooted in<filesDir>/recordings/, assigned
PTT recordings flow through the existing media backup unchanged. - Unassigned (orphan) recordings are not copied to a backup —
there is no recordings section indata/...json. This is documented
as a limitation; adding it would require touching the import path as
well. See Limitations below.
Preserved v2.0.8 features
- Stream playlist (multi-URL Atmo, shuffle, REPEAT_MODE_ALL): untouched.
- AtmoPlaybackService foreground media-playback architecture: untouched.
- PTT audio priority chain (PTT pauses Atmo and waypoint audio,
AtmoResumeManager + WaypointAudioInterruptionCoordinator) — only the
invocation site inLivePttManagerwas edited; the contract is the
same. - Backup format, GPS track drafts, tour reorder, waypoint editor,
drafts archive, map provider selector, version-notice dialog — all
untouched.
Limitations / known gaps
- WAV format is intentionally not implemented. The selector in the
PTT settings dialog shows it disabled with a German label. Reason:
keeping the PTT live path stable was the top priority; M4A/AAC is
the supported codec viaMediaRecorderand works on every device
from API 26 upwards. - Live + Aufnahme simultaneously should work on most devices —
AudioRecord(VOICE_COMMUNICATION)andMediaRecorder(MIC)are
separate clients and Android typically allows both to read from the
mic in parallel. On vendor-specific builds (some Huawei / Samsung
devices have been reported in the wild) one of the two may fail to
init. The manager logs the failure, surfaces a status message and
keeps the one that did start. If a user encounters this, the
workaround is to disable Live in the PTT settings. - Orphan recordings are not auto-backed-up. Only recordings that
the user assigned to a waypoint end up in the backup ZIP (via the
existingsoundUrienumeration). Recordings that live only in the
library remain in<filesDir>/recordings/on the device. - Recording playback inside the library list is not implemented.
Users can verify a recording by assigning it to a waypoint or by
triggering the post-recording dialog directly after capture. Adding
in-place playback would require an extra MediaPlayer instance and
was out of scope for the "stable PTT recorder" objective. - Renaming a recording is supported by the store
(renameRecording) but no UI is wired up yet — recordings carry
thePTT_<timestamp>default name.
Files added / changed
Added: app/src/main/kotlin/de/waypointaudio/data/PttRecording.kt app/src/main/kotlin/de/waypointaudio/service/PttRecorder.kt app/src/main/kotlin/de/waypointaudio/ui/PttRecordingDialogs.kt Changed: app/build.gradle.kts (versionCode 36→37, versionName 2.0.8→2.1.0) app/src/main/kotlin/de/waypointaudio/data/AudioRoutingSettings.kt app/src/main/kotlin/de/waypointaudio/service/LivePttManager.kt app/src/main/kotlin/de/waypointaudio/ui/LivePttCard.kt (PttSettingsDialog merged) app/src/main/kotlin/de/waypointaudio/ui/WaypointListScreen.kt (3 dialog hooks) app/src/main/res/values/strings.xml (~25 new strings)No manifest changes were needed:
RECORD_AUDIO,FOREGROUND_SERVICE,
FOREGROUND_SERVICE_MICROPHONEwere already declared for v2.0.8 PTT.Test plan (manual)
- Open PTT settings. Verify defaults: Live = ON, Aufnahme = OFF.
- Try turning both off → Live should snap back ON, German hint shown.
- Enable Aufnahme, leave Live on, save. Trigger PTT (start), speak a
few seconds, stop. Verify:- PTT card shows red mic + "Aufnahme läuft" while active.
- Post-recording dialog appears with file name + duration (+ GPS if
permissions granted). - "Als Waypoint-Audio zuweisen" → list shows waypoints of current
tour; tap one → confirmation. - Enter that waypoint on the map → recorded audio plays.
- Open library via the headphones icon → recording is listed → delete
it → file and metadata both gone. - Disable Live (Aufnahme only), trigger PTT → only recording happens,
no echo, status row shows red dot. Verify Atmo pauses while
recording and resumes on stop. - Trigger Atmo with stream playlist → start PTT → Atmo pauses → stop
PTT → Atmo resumes (regression check for v2.0.8 behaviour). - Backup export with "Medien/Atmo" enabled → unzip → assigned
recording appears undermedia/waypoints/<tour>/....
Build status — final
- Result:
BUILD SUCCESSFUL(gradle 8.9, AGP from project,
compileSdk 35, JDK 17). - APK signature: verified, certificate matches the v2.0.x release
keystore fingerprint7B:0E:A4:D5:…:BB:46. - APK metadata:
de.waypointaudioversionCode37versionName
2.1.0. - Tests: project contains no unit/instrumentation tests; manual
verification described above. Runtime testing on a device was not
possible from this build host.
Downloads
- New persisted fields on the existing DataStore (