wear und applaufen, allerdings wear ohne kmh

This commit is contained in:
Thorsten
2026-03-06 08:20:54 +01:00
parent c2cfcda942
commit 3d2d68d145
40 changed files with 2847 additions and 172 deletions
@@ -1,4 +1,4 @@
package de.tstratmann.gpstracker_wear
package de.tstratmann.gpstracker
import android.content.Context
import android.location.Location
@@ -24,16 +24,14 @@ class GPXManager(private val context: Context) {
val time = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US).apply {
timeZone = TimeZone.getTimeZone("UTC")
}.format(Date(location.time))
val trkpt = """
<trkpt lat="${location.latitude}" lon="${location.longitude}">
<ele>${location.altitude}</ele>
<time>$time</time>
</trkpt>
""".trimIndent()
// This is a simple append, for a real app we'd want to handle the footer properly
// But for this exercise, we'll strip the footer, append, then re-add footer
val content = file.readText().removeSuffix(getGpxFooter())
file.writeText(content + trkpt + getGpxFooter())
}
@@ -1,4 +1,4 @@
package de.tstratmann.gpstracker_wear
package de.tstratmann.gpstracker
import android.app.*
import android.content.Intent
@@ -11,7 +11,6 @@ import com.google.android.gms.location.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import java.util.*
class TrackingService : Service() {
@@ -41,9 +40,9 @@ class TrackingService : Service() {
super.onCreate()
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
gpxManager = GPXManager(this)
createNotificationChannel()
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
locationResult.lastLocation?.let { location ->
@@ -55,17 +54,17 @@ class TrackingService : Service() {
private fun processLocation(location: Location) {
gpxManager.appendLocation(location)
val currentData = _trackingState.value
var newDistance = currentData.distanceKm
lastLocation?.let { last ->
newDistance += last.distanceTo(location) / 1000.0
}
lastLocation = location
val speedKmh = location.speed * 3.6 // m/s to km/h
val speedKmh = location.speed * 3.6
_trackingState.value = currentData.copy(
distanceKm = newDistance,
speedKmh = speedKmh
@@ -88,7 +87,7 @@ class TrackingService : Service() {
startTime = System.currentTimeMillis()
lastLocation = null
_trackingState.value = TrackingData()
val locationRequest = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 1000)
.setMinUpdateIntervalMillis(1000)
.build()
@@ -1,7 +1,6 @@
package de.tstratmann.gpstracker_wear
package de.tstratmann.gpstracker
import android.content.Context
import android.net.Uri
import android.util.Log
import com.google.android.gms.wearable.Asset
import com.google.android.gms.wearable.PutDataMapRequest
@@ -15,12 +14,12 @@ class WearSyncManager(private val context: Context) {
return try {
val bytes = file.readBytes()
val asset = Asset.createFromBytes(bytes)
val request = PutDataMapRequest.create("/gpx_export/${file.name}").apply {
dataMap.putAsset("gpx_file", asset)
dataMap.putLong("timestamp", System.currentTimeMillis())
}
val putDataRequest = request.asPutDataRequest().setUrgent()
Wearable.getDataClient(context).putDataItem(putDataRequest).await()
Log.d("WearSyncManager", "File synced: ${file.name}")
@@ -30,4 +29,4 @@ class WearSyncManager(private val context: Context) {
false
}
}
}
}
@@ -1,4 +1,4 @@
package de.tstratmann.gpstracker_wear.presentation
package de.tstratmann.gpstracker.presentation
import android.Manifest
import android.content.ComponentName
@@ -28,12 +28,11 @@ import androidx.wear.compose.material.*
import androidx.wear.compose.navigation.SwipeDismissableNavHost
import androidx.wear.compose.navigation.composable
import androidx.wear.compose.navigation.rememberSwipeDismissableNavController
import de.tstratmann.gpstracker_wear.GPXManager
import de.tstratmann.gpstracker_wear.TrackingService
import de.tstratmann.gpstracker_wear.WearSyncManager
import de.tstratmann.gpstracker_wear.presentation.theme.GPSTracker_WearTheme
import de.tstratmann.gpstracker.GPXManager
import de.tstratmann.gpstracker.TrackingService
import de.tstratmann.gpstracker.WearSyncManager
import de.tstratmann.gpstracker.presentation.theme.GPSTrackerTheme
import kotlinx.coroutines.launch
import java.util.*
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
@@ -47,7 +46,7 @@ class MainActivity : ComponentActivity() {
@Composable
fun WearApp() {
val navController = rememberSwipeDismissableNavController()
GPSTracker_WearTheme {
GPSTrackerTheme {
Scaffold(
timeText = { TimeText() }
) {
@@ -165,9 +164,9 @@ fun TrackingScreen(navController: NavHostController) {
Text(text = timeString, style = MaterialTheme.typography.display1)
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)
Spacer(modifier = Modifier.height(12.dp))
Button(
onClick = {
trackingService?.stopTracking()
@@ -184,7 +183,7 @@ fun TrackingScreen(navController: NavHostController) {
}
}
}
DisposableEffect(Unit) {
onDispose {
if (isBound) {
@@ -210,7 +209,7 @@ fun ActivitiesScreen(navController: NavHostController) {
Text(text = "$count Aktivitäten", style = MaterialTheme.typography.title3)
Spacer(modifier = Modifier.height(12.dp))
Button(
onClick = {
onClick = {
val files = gpxManager.getAllFiles()
if (files.isNotEmpty()) {
scope.launch {
@@ -240,4 +239,4 @@ fun ActivitiesScreen(navController: NavHostController) {
}
}
}
}
}
@@ -0,0 +1,13 @@
package de.tstratmann.gpstracker.presentation.theme
import androidx.compose.runtime.Composable
import androidx.wear.compose.material.MaterialTheme
@Composable
fun GPSTrackerTheme(
content: @Composable () -> Unit
) {
MaterialTheme(
content = content
)
}
@@ -1,17 +0,0 @@
package de.tstratmann.gpstracker_wear.presentation.theme
import androidx.compose.runtime.Composable
import androidx.wear.compose.material.MaterialTheme
@Composable
fun GPSTracker_WearTheme(
content: @Composable () -> Unit
) {
/**
* Empty theme to customize for your app.
* See: https://developer.android.com/jetpack/compose/designsystems/custom
*/
MaterialTheme(
content = content
)
}