package de.waypointaudio import android.app.Application import android.app.NotificationChannel import android.app.NotificationManager import de.waypointaudio.license.LicenseStatusProvider /** * Application-Klasse – initialisiert globale Ressourcen. * * v2.5.29 — Lizenz-Persistenz-Fix: * Beim Start des App-Prozesses wird die Lizenz sofort aus dem persistenten * Speicher geladen (LicenseStatusProvider.reload auf einem Hintergrundthread). * * Hintergrund: LicenseStatusProvider ist ein Kotlin-object (Prozess-Singleton). * Nach einem APK-Update startet Android einen neuen Prozess — das Singleton * ist dann frisch initialisiert mit "Keine Lizenz" als Standardwert. * Die Lizenzdatei liegt in filesDir/license/ und überlebt APK-Updates; sie muss * aber aktiv geladen werden. Bisher geschah das nur, wenn der Nutzer den * Über-Dialog öffnete. Durch das Vorladen hier ist der Status beim ersten * Compose-Render bereits korrekt gesetzt. * * Implementierung: Thread (kein Coroutine-Framework nötig in Application.onCreate), * um keine Blockierung des Hauptthreads durch Datei-I/O zu verursachen. * LicenseStatusProvider.reload() ist thread-safe (MutableState-Update ist * Compose-intern threadsicher; UI rekomponiert beim nächsten Frame). */ class WaypointApp : Application() { override fun onCreate() { super.onCreate() createNotificationChannels() initMapLibre() // v2.5.29 — Lizenzstatus vorladen, bevor die UI rendert. // Läuft auf einem Hintergrundthread, um Datei-I/O vom Main-Thread fernzuhalten. // ensureLoaded() ist @Synchronized, also Race-frei, auch wenn AboutDialog // gleichzeitig aufgerufen wird. Thread { LicenseStatusProvider.ensureLoaded(applicationContext) }.start() } /** * v2.4.0 — MapLibre Native Android SDK initialisieren (AKTIVER Renderer). * * Ab v2.4.0 rendert der Explorer mit MapLibre Native (siehe * ExplorerScreenMapLibre.kt). Init ohne API-Key, ohne Telemetrie. Tiles * werden direkt vom Endgerät geladen (OSM Standard bzw. ESRI World Imagery * oder eigene Tile-URL für Satellit). * * Wenn die Initialisierung fehlschlägt (selten — fehlende native .so), * bleibt der MapLibre-Renderer nicht nutzbar. Als interner Fallback ist * der osmdroid-basierte [ui.ExplorerScreen] im Quelltext erhalten. */ private fun initMapLibre() { runCatching { org.maplibre.android.MapLibre.getInstance(this) }.onFailure { e -> android.util.Log.w("WaypointApp", "MapLibre init übersprungen: ${e.message}") } } private fun createNotificationChannels() { val channel = NotificationChannel( "waypoint_service_channel", "Wegpunkt-Ortungsdienst", NotificationManager.IMPORTANCE_LOW ).apply { description = "Läuft im Hintergrund, um Wegpunkte zu erkennen" setShowBadge(false) } getSystemService(NotificationManager::class.java) .createNotificationChannel(channel) } }