Geschwindigkeit und Anzeigen korrigiert
This commit is contained in:
Generated
+8
@@ -15,6 +15,14 @@
|
|||||||
</SelectionState>
|
</SelectionState>
|
||||||
<SelectionState runConfigName="gpstracker">
|
<SelectionState runConfigName="gpstracker">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
|
<DropdownSelection timestamp="2026-03-06T08:51:20.686825100Z">
|
||||||
|
<Target type="DEFAULT_BOOT">
|
||||||
|
<handle>
|
||||||
|
<DeviceId pluginId="PhysicalDevice" identifier="serial=28161JEEJR069K" />
|
||||||
|
</handle>
|
||||||
|
</Target>
|
||||||
|
</DropdownSelection>
|
||||||
|
<DialogSelection />
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
</selectionStates>
|
</selectionStates>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
@@ -25,15 +25,20 @@ class GPXManager(private val context: Context) {
|
|||||||
timeZone = TimeZone.getTimeZone("UTC")
|
timeZone = TimeZone.getTimeZone("UTC")
|
||||||
}.format(Date(location.time))
|
}.format(Date(location.time))
|
||||||
|
|
||||||
val trkpt = """
|
val sb = StringBuilder()
|
||||||
<trkpt lat="${location.latitude}" lon="${location.longitude}">
|
sb.append("<trkpt lat=\"${location.latitude}\" lon=\"${location.longitude}\">")
|
||||||
<ele>${location.altitude}</ele>
|
sb.append("<ele>${location.altitude}</ele>")
|
||||||
<time>$time</time>
|
sb.append("<time>$time</time>")
|
||||||
</trkpt>
|
if (location.speed > 0 || location.bearing > 0) {
|
||||||
""".trimIndent()
|
sb.append("<extensions>")
|
||||||
|
if (location.speed > 0) sb.append("<speed>${location.speed}</speed>")
|
||||||
|
if (location.bearing > 0) sb.append("<course>${location.bearing}</course>")
|
||||||
|
sb.append("</extensions>")
|
||||||
|
}
|
||||||
|
sb.append("</trkpt>")
|
||||||
|
|
||||||
val content = file.readText().removeSuffix(getGpxFooter())
|
val content = file.readText().removeSuffix(getGpxFooter())
|
||||||
file.writeText(content + trkpt + getGpxFooter())
|
file.writeText(content + sb.toString() + getGpxFooter())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,6 +50,12 @@ class GPXManager(private val context: Context) {
|
|||||||
return context.filesDir.listFiles { _, name -> name.endsWith(".gpx") }?.toList() ?: emptyList()
|
return context.filesDir.listFiles { _, name -> name.endsWith(".gpx") }?.toList() ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun deleteAllFiles(): Int {
|
||||||
|
val files = getAllFiles()
|
||||||
|
files.forEach { it.delete() }
|
||||||
|
return files.size
|
||||||
|
}
|
||||||
|
|
||||||
private fun getGpxHeader() = """
|
private fun getGpxHeader() = """
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<gpx version="1.1" creator="WearGPSTracker" xmlns="http://www.topografix.com/GPX/1/1">
|
<gpx version="1.1" creator="WearGPSTracker" xmlns="http://www.topografix.com/GPX/1/1">
|
||||||
|
|||||||
@@ -25,11 +25,14 @@ class TrackingService : Service() {
|
|||||||
private var startTime = 0L
|
private var startTime = 0L
|
||||||
private var lastLocation: Location? = null
|
private var lastLocation: Location? = null
|
||||||
private var job: Job? = null
|
private var job: Job? = null
|
||||||
|
private var speedSumKmh = 0.0
|
||||||
|
private var speedCount = 0
|
||||||
|
|
||||||
data class TrackingData(
|
data class TrackingData(
|
||||||
val durationSeconds: Long = 0,
|
val durationSeconds: Long = 0,
|
||||||
val distanceKm: Double = 0.0,
|
val distanceKm: Double = 0.0,
|
||||||
val speedKmh: Double = 0.0
|
val speedKmh: Double = 0.0,
|
||||||
|
val avgSpeedKmh: Double = 0.0
|
||||||
)
|
)
|
||||||
|
|
||||||
inner class LocalBinder : Binder() {
|
inner class LocalBinder : Binder() {
|
||||||
@@ -65,9 +68,16 @@ class TrackingService : Service() {
|
|||||||
lastLocation = location
|
lastLocation = location
|
||||||
val speedKmh = location.speed * 3.6
|
val speedKmh = location.speed * 3.6
|
||||||
|
|
||||||
|
if (speedKmh > 0) {
|
||||||
|
speedSumKmh += speedKmh
|
||||||
|
speedCount++
|
||||||
|
}
|
||||||
|
val avgSpeedKmh = if (speedCount > 0) speedSumKmh / speedCount else 0.0
|
||||||
|
|
||||||
_trackingState.value = currentData.copy(
|
_trackingState.value = currentData.copy(
|
||||||
distanceKm = newDistance,
|
distanceKm = newDistance,
|
||||||
speedKmh = speedKmh
|
speedKmh = speedKmh,
|
||||||
|
avgSpeedKmh = avgSpeedKmh
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +96,8 @@ class TrackingService : Service() {
|
|||||||
gpxManager.startNewSession()
|
gpxManager.startNewSession()
|
||||||
startTime = System.currentTimeMillis()
|
startTime = System.currentTimeMillis()
|
||||||
lastLocation = null
|
lastLocation = null
|
||||||
|
speedSumKmh = 0.0
|
||||||
|
speedCount = 0
|
||||||
_trackingState.value = TrackingData()
|
_trackingState.value = TrackingData()
|
||||||
|
|
||||||
val locationRequest = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 1000)
|
val locationRequest = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 1000)
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import androidx.activity.compose.rememberLauncherForActivityResult
|
|||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -154,16 +156,18 @@ fun TrackingScreen(navController: NavHostController) {
|
|||||||
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.Center
|
verticalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp)
|
||||||
) {
|
) {
|
||||||
val hours = trackingData.durationSeconds / 3600
|
val hours = trackingData.durationSeconds / 3600
|
||||||
val minutes = (trackingData.durationSeconds % 3600) / 60
|
val minutes = (trackingData.durationSeconds % 3600) / 60
|
||||||
val seconds = trackingData.durationSeconds % 60
|
val seconds = trackingData.durationSeconds % 60
|
||||||
val timeString = String.format("%02d:%02d:%02d", hours, minutes, seconds)
|
val timeString = String.format("%02d:%02d:%02d", hours, minutes, seconds)
|
||||||
|
|
||||||
Text(text = timeString, style = MaterialTheme.typography.display1)
|
Text(text = timeString, style = MaterialTheme.typography.title1)
|
||||||
Text(text = String.format("%.2f km", trackingData.distanceKm), style = MaterialTheme.typography.body1)
|
Text(text = String.format("%.2f km", trackingData.distanceKm), style = MaterialTheme.typography.body1)
|
||||||
Text(text = String.format("%.1f km/h", trackingData.speedKmh), style = MaterialTheme.typography.body1)
|
Text(text = String.format("%.1f km/h", trackingData.speedKmh), style = MaterialTheme.typography.body1)
|
||||||
|
Text(text = String.format("Ø %.1f km/h", trackingData.avgSpeedKmh), style = MaterialTheme.typography.body2)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
|
||||||
@@ -200,11 +204,47 @@ fun ActivitiesScreen(navController: NavHostController) {
|
|||||||
val gpxManager = remember { GPXManager(context) }
|
val gpxManager = remember { GPXManager(context) }
|
||||||
val syncManager = remember { WearSyncManager(context) }
|
val syncManager = remember { WearSyncManager(context) }
|
||||||
var count by remember { mutableIntStateOf(gpxManager.getActivitiesCount()) }
|
var count by remember { mutableIntStateOf(gpxManager.getActivitiesCount()) }
|
||||||
|
var showDeleteConfirm by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
if (showDeleteConfirm) {
|
||||||
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.Center
|
verticalArrangement = Arrangement.Center
|
||||||
|
) {
|
||||||
|
Text(text = "Alle löschen?", style = MaterialTheme.typography.title3)
|
||||||
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
val deleted = gpxManager.deleteAllFiles()
|
||||||
|
count = 0
|
||||||
|
showDeleteConfirm = false
|
||||||
|
Toast.makeText(context, "$deleted Aktivitäten gelöscht", Toast.LENGTH_SHORT).show()
|
||||||
|
},
|
||||||
|
colors = ButtonDefaults.buttonColors(backgroundColor = Color.Red),
|
||||||
|
modifier = Modifier.fillMaxWidth(0.8f)
|
||||||
|
) {
|
||||||
|
Text("Ja, löschen", color = Color.White)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
Button(
|
||||||
|
onClick = { showDeleteConfirm = false },
|
||||||
|
modifier = Modifier.fillMaxWidth(0.8f),
|
||||||
|
colors = ButtonDefaults.secondaryButtonColors()
|
||||||
|
) {
|
||||||
|
Text("Abbrechen")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val scrollState = rememberScrollState()
|
||||||
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier.verticalScroll(scrollState).padding(vertical = 16.dp)
|
||||||
) {
|
) {
|
||||||
Text(text = "$count Aktivitäten", style = MaterialTheme.typography.title3)
|
Text(text = "$count Aktivitäten", style = MaterialTheme.typography.title3)
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
@@ -230,6 +270,14 @@ fun ActivitiesScreen(navController: NavHostController) {
|
|||||||
Text("GPX Sync")
|
Text("GPX Sync")
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
Button(
|
||||||
|
onClick = { showDeleteConfirm = true },
|
||||||
|
modifier = Modifier.fillMaxWidth(0.8f),
|
||||||
|
colors = ButtonDefaults.buttonColors(backgroundColor = Color.Red)
|
||||||
|
) {
|
||||||
|
Text("Alle löschen", color = Color.White)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Button(
|
Button(
|
||||||
onClick = { navController.popBackStack() },
|
onClick = { navController.popBackStack() },
|
||||||
modifier = Modifier.fillMaxWidth(0.8f),
|
modifier = Modifier.fillMaxWidth(0.8f),
|
||||||
|
|||||||
Reference in New Issue
Block a user