# GPS2Audio v2.5.37 — Explorer Map Styles — Handoff **Build date**: 2026-05-29 **versionName**: 2.5.37 **versionCode**: 91 **applicationId**: de.waypointaudio **Base**: GPS2Audio v2.5.36 (Phantom-Layer-Fix) --- ## Deliverables | File | Description | |------|-------------| | `GPS2Audio_v2_5_37_explorer_map_styles_universal_signed.apk` | Universelle signierte Release-APK (57 MB) | | `GPS2Audio_v2_5_37_explorer_map_styles_source.zip` | Vollständiger Quellcode ohne Build-Artefakte | | `GPS2Audio_v2_5_37_explorer_map_styles_handoff.md` | Dieses Dokument | --- ## APK-Verifikation - **Signatur**: APK Signature Scheme v2 ✓ - **Signierer**: CN=GPS2Audio, OU=NesoHub, O=GPS2Audio, L=Germany, C=DE - **SHA-256 Zertifikat**: `490511f350557083808cdf9e39fdb0a2d4d76d2224726b56018d1ac0dd9ed4e5` - **SHA-1 Zertifikat**: `21a1c97867e4448f9be8bad2fe6d6fb3974e2020` - **ABI-Abdeckung**: arm64-v8a, armeabi-v7a, x86, x86_64 (universal APK) ✓ - **Keystore**: `/home/user/workspace/GPS2Audio_release_keystore_v2.jks` - **Alias**: `gps2audio_release_v2` --- ## Was wurde geändert ### Neue Kartenstile (Explorer Map Styles) Alle 5 Stile sind kostenlos, benötigen keinen API-Key und keinen eigenen Server. Stile werden via `Style.Builder().fromUri(url)` geladen (MapLibre Android 11.x API). | Enum-Wert | Anzeigename | URL / Methode | |-----------|-------------|---------------| | `MODERN_2D` | Modern | `https://tiles.openfreemap.org/styles/positron` | | `DARK` | Dunkel | `https://tiles.openfreemap.org/styles/dark` | | `OUTDOOR` | Outdoor | `https://tiles.openfreemap.org/styles/liberty` | | `CITY_3D` | 3D Stadt | `https://tiles.openfreemap.org/styles/positron` + FillExtrusionLayer | | `CLASSIC` | Klassisch | OSM-Raster-JSON (tile.openstreetmap.org) via `fromJson()` | **SATELLITE ist entfernt** aus dem UI und der aktiven Auswahl. Alte gespeicherte Werte (`"satellite"`) werden automatisch auf `MODERN_2D` migriert. ### 3D-Stadtansicht (CITY_3D) - Basis: OpenFreeMap Positron (heller Vektorstil) - Nach Style-Load: `addBuildingExtrusionIfAvailable(style)` wird aufgerufen - Source: `"openmaptiles"`, Source-Layer: `"building"` - Höhe: `render_height`, Basis: `render_min_height` (OpenMapTiles-Schema) - Farbverlauf: #EAEEF2 (niedrig) → #C8D4E0 (200 m+) - Einfügen: `addLayerBelow(extrusionLayer, firstSymbolLayerId)` — Labels bleiben sichtbar - **Robustheit**: Vollständiges try/catch — wenn Building-Layer/Source fehlt, 2D-Fallback ohne Crash - Kamera-Pitch: 45° bei CITY_3D ### Style-Wechsel / Overlay-Rehydration Der Style-Wechsel läuft über einen `LaunchedEffect(layerState.baseStyle, mapLibreMap)`: 1. Annotation-Caches leeren (verhindert Phantom-Layer aus v2.5.36-Fix) 2. `ml.setStyle(Style.Builder().fromUri(...), onStyleReady)` oder `fromJson()` für CLASSIC 3. `onStyleReady`-Callback: 3D-Extrusion einfügen (CITY_3D), Kamera-Pitch setzen, `styleReady = true` 4. Alle abhängigen `LaunchedEffect`s (Routen, Wegpunkte, Tracks, Clip-Linien) reagieren auf `styleReady` und werden nach Style-Load korrekt neu gezeichnet ### Phantom-Layer-Fix (aus v2.5.36 übernommen) Der bestehende Phantom-Layer-Fix aus v2.5.36 bleibt vollständig erhalten. Annotation-Caches werden vor jedem Style-Wechsel explizit geleert, sodass keine verwaisten Layer aus dem vorherigen Style zurückbleiben. ### Legacy-Migration `MapBaseStyle.fromKey()` übersetzt alle alten gespeicherten Keys automatisch: | Alter Key | Neuer Stil | |-----------|------------| | `"satellite"` | `MODERN_2D` | | `"terrain_3d"` | `CITY_3D` | | `"topo"` | `OUTDOOR` | | `"perspective"` | `CITY_3D` | Die alten Stub-Methoden `setCustomSatelliteUrl()`, `setCustomTopoUrl()`, `setCustomTerrainDemUrl()` bleiben in `MapStyleStore` erhalten (no-op) um Compile-Fehler in bestehenden Aufrufern zu vermeiden. --- ## Geänderte Dateien ### `app/build.gradle.kts` - `versionCode = 91` - `versionName = "2.5.37"` ### `app/src/main/kotlin/de/waypointaudio/data/MapStyleSettings.kt` - Vollständige Neufassung der `MapBaseStyle`-Enum: neue Werte OUTDOOR, CITY_3D, CLASSIC - Legacy-Enum-Werte SATELLITE, TERRAIN_3D, TOPO, PERSPECTIVE bleiben als benannte Konstanten für Migration - `fromKey()`: robuste Legacy-Migration aller alten Werte - Legacy-Stub-Methoden in `MapStyleStore` ### `app/src/main/kotlin/de/waypointaudio/ui/MapLayerPanel.kt` - Chip-Auswahl: MODERN_2D, DARK, OUTDOOR, CITY_3D, CLASSIC (kein SATELLITE) - Icon für CITY_3D: `Icons.Filled.LocationCity` (ersetzt `Satellite`-Import) - Info-Blöcke für alle 5 Stile ### `app/src/main/kotlin/de/waypointaudio/ui/ExplorerScreenMapLibre.kt` - Style-Switcher `LaunchedEffect`: `Style.Builder().fromUri(url)` für alle Vektorstile - `buildClassicOsmStyleJson()`: OSM-Raster-JSON, nur noch für CLASSIC verwendet - `addBuildingExtrusionIfAvailable(style)`: Gebäude-Extrusion für CITY_3D - Initialer Map-Load: gleiche Style-URL-Logik wie Style-Switcher - `onStyleReady`-Callback für Extrusion + Kamera-Pitch ### `app/src/main/res/values/strings.xml` - Neue Strings für Map-Stil-Labels und Info-Texte - Version-Hinweis für v2.5.37 --- ## Technische Details - **MapLibre Android SDK**: 11.5.0 (`org.maplibre.gl:android-sdk:11.5.0`) - **OpenMapTiles-Schema**: Building Source `"openmaptiles"`, Source-Layer `"building"` - **compileSdk**: 35, **minSdk**: 26, **targetSdk**: 35 - **Java**: OpenJDK 21 - **Build-Toolchain**: Android SDK `/home/user/tools/android-sdk` - **Signing**: APK Signature Scheme v2, Keystore `GPS2Audio_release_keystore_v2.jks` --- ## OpenFreeMap-Hinweise - Alle Stile von [openfreemap.org](https://openfreemap.org) sind kostenlos, ohne API-Key, ohne Rate-Limit - Verfügbare Stile: `liberty`, `positron`, `dark` - Liberty ist der vollständigste/aktivste Stil (Outdoor-Charakter) - Positron ist minimal/hell — ideal als MODERN_2D und CITY_3D-Basis - Tile-Hosting läuft auf eigener Infrastruktur von OpenFreeMap (community-finanziert) - Style-URLs sind stabil und langfristig gedacht --- ## Nicht umgesetzt (bewusst ausgelassen) - **Satellit**: Kein UI-Eintrag, kein aktiver Modus — nur Legacy-Migration - **Gitea-Veröffentlichung**: Nicht durchgeführt (explizite Benutzeranweisung) - **ABI-only APK**: Nicht erstellt — nur universelle APK