Initial release of GPS2Audio
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
package de.waypointaudio
|
||||
|
||||
import android.Manifest
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import de.waypointaudio.ui.MapScreen
|
||||
import de.waypointaudio.ui.PermissionRequiredScreen
|
||||
import de.waypointaudio.ui.WaypointListScreen
|
||||
import de.waypointaudio.ui.theme.WaypointAudioTheme
|
||||
import de.waypointaudio.viewmodel.WaypointViewModel
|
||||
|
||||
/**
|
||||
* Hauptaktivität der App.
|
||||
*
|
||||
* Navigation:
|
||||
* "list" → WaypointListScreen (Startbildschirm)
|
||||
* "map" → MapScreen (osmdroid Kartenansicht)
|
||||
*
|
||||
* Berechtigungslogik:
|
||||
* - Nur ACCESS_FINE_LOCATION und ACCESS_COARSE_LOCATION sind zwingend erforderlich
|
||||
* (für Standort-Button und Karte). Ohne diese wird der PermissionScreen gezeigt.
|
||||
* - POST_NOTIFICATIONS und Audiozugriff werden separat angefragt, blockieren
|
||||
* aber nicht die Hauptoberfläche.
|
||||
*/
|
||||
class MainActivity : ComponentActivity() {
|
||||
|
||||
private val viewModel: WaypointViewModel by viewModels()
|
||||
|
||||
/** Nur Standortberechtigungen steuern, ob die App-UI angezeigt wird. */
|
||||
private val locationPermissionsGranted = mutableStateOf(false)
|
||||
|
||||
// Launcher für Standortberechtigungen (zwingend erforderlich)
|
||||
private val locationPermissionLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.RequestMultiplePermissions()
|
||||
) { results ->
|
||||
// Mindestens ACCESS_COARSE_LOCATION muss gewährt sein
|
||||
val coarseGranted = results[Manifest.permission.ACCESS_COARSE_LOCATION] == true
|
||||
val fineGranted = results[Manifest.permission.ACCESS_FINE_LOCATION] == true
|
||||
locationPermissionsGranted.value = coarseGranted || fineGranted
|
||||
// Nach Gewährung von Standort: optionale Berechtigungen separat anfragen
|
||||
if (locationPermissionsGranted.value) {
|
||||
requestOptionalPermissions()
|
||||
}
|
||||
}
|
||||
|
||||
// Launcher für optionale Berechtigungen (Benachrichtigungen, Audio)
|
||||
private val optionalPermissionLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.RequestMultiplePermissions()
|
||||
) { /* optional – kein Block der Hauptoberfläche */ }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// Standortberechtigungen prüfen und ggf. anfordern
|
||||
checkAndRequestLocationPermissions()
|
||||
|
||||
setContent {
|
||||
WaypointAudioTheme(darkTheme = isSystemInDarkTheme()) {
|
||||
val locationGranted by locationPermissionsGranted
|
||||
|
||||
if (locationGranted) {
|
||||
val navController = rememberNavController()
|
||||
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = "list"
|
||||
) {
|
||||
composable("list") {
|
||||
WaypointListScreen(
|
||||
viewModel = viewModel,
|
||||
onNavigateToMap = { navController.navigate("map") }
|
||||
)
|
||||
}
|
||||
composable("map") {
|
||||
MapScreen(
|
||||
viewModel = viewModel,
|
||||
onNavigateBack = { navController.popBackStack() }
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PermissionRequiredScreen(
|
||||
onPermissionsGranted = { checkAndRequestLocationPermissions() }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
// Beim Zurückkehren aus den Einstellungen erneut prüfen
|
||||
locationPermissionsGranted.value = hasLocationPermission()
|
||||
if (locationPermissionsGranted.value) {
|
||||
requestOptionalPermissions()
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Berechtigungslogik
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
private fun checkAndRequestLocationPermissions() {
|
||||
if (hasLocationPermission()) {
|
||||
locationPermissionsGranted.value = true
|
||||
requestOptionalPermissions()
|
||||
} else {
|
||||
locationPermissionLauncher.launch(
|
||||
arrayOf(
|
||||
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||
Manifest.permission.ACCESS_COARSE_LOCATION
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Prüft ob mindestens grobe oder feine Standortberechtigung vorhanden ist. */
|
||||
private fun hasLocationPermission(): Boolean {
|
||||
val fine = ContextCompat.checkSelfPermission(
|
||||
this, Manifest.permission.ACCESS_FINE_LOCATION
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
val coarse = ContextCompat.checkSelfPermission(
|
||||
this, Manifest.permission.ACCESS_COARSE_LOCATION
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
return fine || coarse
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionale Berechtigungen (Benachrichtigungen, Audiozugriff) anfragen,
|
||||
* nachdem Standortberechtigung gewährt wurde.
|
||||
* Diese blockieren NICHT die Haupt-UI.
|
||||
*/
|
||||
private fun requestOptionalPermissions() {
|
||||
val toRequest = buildList {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
if (ContextCompat.checkSelfPermission(
|
||||
this@MainActivity, Manifest.permission.POST_NOTIFICATIONS
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
add(Manifest.permission.POST_NOTIFICATIONS)
|
||||
}
|
||||
if (ContextCompat.checkSelfPermission(
|
||||
this@MainActivity, Manifest.permission.READ_MEDIA_AUDIO
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
add(Manifest.permission.READ_MEDIA_AUDIO)
|
||||
}
|
||||
} else {
|
||||
if (ContextCompat.checkSelfPermission(
|
||||
this@MainActivity, Manifest.permission.READ_EXTERNAL_STORAGE
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
add(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (toRequest.isNotEmpty()) {
|
||||
optionalPermissionLauncher.launch(toRequest.toTypedArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user