# Konfiguration: PreferencesManager ## Zweck Zentraler Manager für alle App-Einstellungen und persistierte Daten. Nutzt Android DataStore. ## Wichtige Dateien - `app/src/main/kotlin/de/traewelling/app/util/PreferencesManager.kt` - `app/src/main/kotlin/de/traewelling/app/util/AuthSession.kt` ## Gespeicherte Werte ### Auth-Daten | Key | Flow-Typ | Beschreibung | | --------------- | --------------- | ------------------------------------- | | `server_url` | `Flow` | Server-URL (Standard: traewelling.de) | | `access_token` | `Flow` | Manuell validierter oder über OAuth-Helfer gespeicherter Bearer-Token | | `refresh_token` | `Flow` | OAuth Refresh Token | | `client_id` | `Flow` | OAuth Client ID | | `client_secret` | `Flow` | OAuth Client Secret | | `username` | `Flow` | Aktueller Nutzername | | `isLoggedIn` | `Flow` | Login-Status (Access-Token vorhanden) | | `auth_session_revision` | intern String | Neue UUID bei Anmeldung, Abmeldung oder Tokenänderung; Altbestand ohne Feld verwendet `legacy` | `authSession: Flow` beziehungsweise `getAuthSession()` lesen Server, nicht leeren Token und Revision gemeinsam. `saveValidatedSession` ersetzt eine vollständige validierte Sitzung atomar und entfernt alte OAuth-/Nutzer-/Fahrtwerte sowie den Erkennungs-Opt-in. `clearSession()` bewahrt den Server und allgemeine Einstellungen, entfernt jedoch Token, Refresh-/Clientdaten, Nutzername, aktive Fahrt, Fahrtcache und Erkennungs-Opt-in und erneuert die Revision. `trackingConfiguration: Flow` liest Auth-Snapshot, aktive Status-ID, GPS-Einstellung und Fahrterkennungs-Opt-in gemeinsam aus derselben Preferences-Ausgabe. Activity und Service dürfen diese Werte nicht aus getrennt eintreffenden Flows zu einer scheinbar gültigen fremden Fahrt zusammensetzen. `clearSessionIfMatches`, `saveUsernameIfMatches` und `saveTokensIfMatches` schreiben nur für den unveränderten erwarteten Snapshot. `saveActiveStatusIdIfMatches` schützt entsprechend verspätete Check-in-Antworten. Diese Prüfung erfolgt im DataStore-`edit`, nicht nur vor einem suspendierenden Aufruf. Revisionen trennen auch Logout und erneuten Login mit demselben Token; sie sind keine Geheimnisse oder GPS-Daten. ### Active Status | Key | Flow-Typ | Beschreibung | | ------------------ | ------------ | ---------------------------------------------- | | `active_status_id` | `Flow` | ID der aktiven Fahrt (für TripTrackingService) | ### Stationsalarm und Trackingzustand | Key | Zugriff / Standard | Beschreibung | | --- | --- | --- | | `gps_tracking_enabled` | `Flow`, `true` | GPS-Tracking gewünscht; ersetzt keine Standortfreigabe | | `announcement_radius_meters` | `Flow`, `0` | `0` für Automatik; feste Werte `300`, `500`, `1000`, `2000` Meter | | `trip_tracking_state` | `getTrackingState(): String?` | JSON-Zustand der aktiven Fahrt; intern gespeichert | | `location_permission_requested` | `hasRequestedLocationPermission(): Boolean`, `false` | Merkt eine bereits angeforderte Standortfreigabe für den manuellen Weg zu Android-App-Berechtigungen | `setAnnouncementRadiusMeters` und der lesende Flow setzen ungültige Radien auf Automatik (`0`) zurück. `saveTrackingState(statusId, stateJson, expectedSession)` schreibt nur, wenn die Status-ID und der übergebene Auth-Snapshot weiterhin passen. Der Tracking-Service liefert diesen Snapshot auch an `clearActiveTracking`; ein abgelöster Service kann damit keine gleich nummerierte Fahrt einer anderen Zugangsgeneration überschreiben oder löschen. Der optionale Sessionparameter dient weiterhin kompatiblen internen Aufrufern; der aktive Service verwendet den Guard. Ein Wechsel beziehungsweise Löschen der aktiven Status-ID entfernt den Trackingzustand. `clearActiveTracking(statusId)` löscht ihn nur für die passende aktive Fahrt. Auch `clearSession()` entfernt aktive Fahrt und Trackingzustand. Der Tracking-Cache enthält Status-ID, Check-in, Haltfolge und `TrackingProgress`. Gespeichert werden aktueller Besuch, `gpsEstablished` zur Unterscheidung von GPS- und vorläufigem Zeitcursor sowie erfolgreich eingereihte Ansageschlüssel. Positionen, Bewegungshistorie und lokale GPS-Zeitbeobachtungen/-prognosen werden nicht persistiert. Die [GPS-Zeiterweiterung](../module/gps-zeiten.md) benötigt keine eigene Preference; die bestehende Standortfreigabe und `gps_tracking_enabled` bestimmen ihre Verfügbarkeit. Der Marker einer Standortanfrage ist keine erteilte Berechtigung: Diese wird bei jedem sichtbaren Start erneut geprüft. Ein TTS-Fehler beziehungsweise Abbruch kann den noch aktuellen Ansageschlüssel wieder freigeben; der Service speichert diesen korrigierten Fortschritt. Der für die Status-Timeline bereitgestellte `trackingLiveState` bleibt dagegen ausschließlich im Prozessspeicher und führt keinen zusätzlichen DataStore-Key ein. Das Tracking-Cacheformat bleibt Version 1. Die [SEV-Ergänzung](../module/sev-haltestellen.md) erweitert das vorhandene Fahrtcache-JSON optional um `fullStopovers` (vollständige API-Fahrt als Richtungskontext) und `sevMaps` (öffentliche Bahnhofskarten mit Abrufzeit). Es wird kein eigener Preference-Key eingeführt. Alte Version-1-Einträge ohne diese Felder werden mit vorhandener Haltfolge beziehungsweise leerer SEV-Quelle gelesen. Wiederhergestellte Quellen werden gegen Alter, Datum und Richtung erneut aufgelöst; die persistierten Karten enthalten öffentliche Bahnhof-/Ersatzhaltpunkte, keine GPS-Gerätepositionen oder Bewegungshistorie. Native Bahn-/Tram-Linienzüge und OSRM-Straßen-Geometrien bleiben ausschließlich im RAM, ohne zusätzliche Preference oder Erweiterung des Fahrtcache-JSON. Nach Wiederanlauf muss die zur restaurierten Haltfolge passende Geometrie erneut geladen werden. Ein Download speichert keinen Gerätefix und verlängert keine GPS-Zeitgültigkeit. ### Reisebegleitung | Key | Flow / Standard | Beschreibung | | --- | --- | --- | | `ride_recognition_enabled` | `Flow`, `false` | Ausdrücklicher Opt-in für die sichtbare Fahrtsuche; Kandidaten und Fixes bleiben im RAM. | | `trip_change_alerts_enabled` | `Flow`, `true` | Änderungsmonitor-Hinweise zur eigenen aktiven Fahrt. | | `trip_change_speech_enabled` | `Flow`, `true` | Änderungssprache; benötigt zusätzlich aktivierte Hinweise und globale TTS. | | `live_progress_enabled` | `Flow`, `true` | Fortschrittsdarstellung und systemabhängige Live-Update-Anfrage. | | `lock_screen_details_enabled` | `Flow`, `true` | Sichtbare Reisedetails; `false` verwendet öffentliche Ersatzanzeigen und unterdrückt Promotion. | | `public_rail_realtime_enabled` | `Flow`, `true` | Anonyme zusätzliche Bahn-Livedaten über DBF/IRIS; benötigt keine Zugangsdaten. | Die zugehörigen suspend-Getter und Setter entsprechen den Flow-Namen. Ein aktiver Check-in pausiert die Erkennung, ohne einen Kandidaten als Fahrt zu speichern. Der Trackingcache enthält zusätzlich `TripChangeMonitorState` mit letzten Ereigniswerten zur Deduplizierung. Die frische Vergleichsbasis, Verspätungsreferenzen und Gerätepositionen werden weiterhin nicht persistiert. `getPublicRailRealtimeEnabled()` und `setPublicRailRealtimeEnabled(Boolean)` steuern die [DBF-Ergänzung](../api/live-datenquellen.md). Ein laufender Zusatzabruf wird vor der Veröffentlichung erneut gegen diese Einstellung geprüft. Erfolgreich gelesene Zeiten/Gleise behalten im bestehenden Fahrtcache ihre Quell- und Abrufmetadaten; alte Einträge ohne Metadaten werden als unbekannt behandelt. Cachewiederherstellung setzt keinen neuen Live-Abrufzeitpunkt. ### TTS-Einstellungen | Key | Flow-Typ | Beschreibung | | -------------- | --------------- | --------------------------------- | | `tts_enabled` | `Flow` | TTS aktiviert (Standard: false) | | `tts_engine` | `Flow` | TTS-Engine-Paketname | | `tts_language` | `Flow` | BCP47 Language Tag (z.B. "de-DE") | | `tts_voice` | `Flow` | Voice-Name | ## Konstanten ```kotlin DEFAULT_SERVER_URL = "https://traewelling.de" REDIRECT_URI = "traewelling://oauth-callback" OAUTH_SCOPES = "read-statuses write-statuses read-notifications read-settings write-settings" ``` ## Offline-Zugriff Für nicht-reaktive Kontexte gibt es suspend-Funktionen: - `getAccessToken(): String?` - `getServerUrl(): String` - `getUsername(): String?` - `getTtsEnabled(): Boolean` - `getGpsTrackingEnabled(): Boolean` - `getAnnouncementRadiusMeters(): Int` - `getTrackingState(): String?` - etc. ## Offene Fragen - Keine spezifischen aktuell. ## Verwandte Seiten - [Auth](../module/auth.md) - [Config-Dateien](./config-dateien.md) - [TripTracking](../module/trip-tracking.md) - [GPS-Zeiten](../module/gps-zeiten.md) - [SEV-Ersatzhaltestellen](../module/sev-haltestellen.md) - [StatusDetail](../module/status-detail.md) - [Settings](../module/settings.md) - [Fahrterkennung](../module/ride-recognition.md) - [Fahrtänderungen](../module/trip-changes.md) - [Reisefortschritt](../module/trip-progress.md)