wear und applaufen, allerdings wear ohne kmh
This commit is contained in:
@@ -4,11 +4,11 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "de.tstratmann.gpstracker_wear"
|
||||
namespace = "de.tstratmann.gpstracker"
|
||||
compileSdk = 36
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "de.tstratmann.gpstracker_wear"
|
||||
applicationId = "de.tstratmann.gpstracker"
|
||||
minSdk = 30
|
||||
targetSdk = 36
|
||||
versionCode = 1
|
||||
@@ -31,6 +31,7 @@ android {
|
||||
buildFeatures {
|
||||
compose = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -49,4 +50,4 @@ dependencies {
|
||||
implementation(libs.androidx.lifecycle.runtime.compose)
|
||||
|
||||
debugImplementation(libs.androidx.compose.ui.tooling)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-5
@@ -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())
|
||||
}
|
||||
+9
-10
@@ -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()
|
||||
+4
-5
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
-12
@@ -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
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user