diff options
| author | Claudomator Agent <agent@claudomator> | 2026-03-13 19:54:43 +0000 |
|---|---|---|
| committer | Claudomator Agent <agent@claudomator> | 2026-03-13 19:54:43 +0000 |
| commit | 72ab76835dec92ea30c2d26009e3576aa8f1dbc7 (patch) | |
| tree | d696d00ca523a2ae3d63fd575058c09e4ec5cb91 /android-app/app/src/main/kotlin/com/example/androidapp | |
| parent | 0b3fc43df0f522a9d2b308c79b35870e3afb08db (diff) | |
Implement GPS navigation with position, SOG, and COG
Diffstat (limited to 'android-app/app/src/main/kotlin/com/example/androidapp')
| -rw-r--r-- | android-app/app/src/main/kotlin/com/example/androidapp/LocationService.kt | 54 | ||||
| -rw-r--r-- | android-app/app/src/main/kotlin/com/example/androidapp/MainActivity.kt | 64 |
2 files changed, 118 insertions, 0 deletions
diff --git a/android-app/app/src/main/kotlin/com/example/androidapp/LocationService.kt b/android-app/app/src/main/kotlin/com/example/androidapp/LocationService.kt new file mode 100644 index 0000000..346fdfe --- /dev/null +++ b/android-app/app/src/main/kotlin/com/example/androidapp/LocationService.kt @@ -0,0 +1,54 @@ +package com.example.androidapp + +import android.annotation.SuppressLint +import android.content.Context +import android.location.Location +import android.os.Looper +import com.google.android.gms.location.* +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.callbackFlow + +data class GpsData( + val latitude: Double, + val longitude: Double, + val speedOverGround: Float, // m/s + val courseOverGround: Float // degrees +) + +class LocationService(private val context: Context) { + + private val fusedLocationClient: FusedLocationProviderClient = + LocationServices.getFusedLocationProviderClient(context) + + @SuppressLint("MissingPermission") // Permissions handled by the calling component (Activity/Fragment) + fun getLocationUpdates(): Flow<GpsData> = callbackFlow { + val locationRequest = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 1000) + .setMinUpdateIntervalMillis(500) + .build() + + val locationCallback = object : LocationCallback() { + override fun onLocationResult(locationResult: LocationResult) { + locationResult.lastLocation?.let { location -> + val gpsData = GpsData( + latitude = location.latitude, + longitude = location.longitude, + speedOverGround = location.speed, + courseOverGround = location.bearing + ) + trySend(gpsData) + } + } + } + + fusedLocationClient.requestLocationUpdates( + locationRequest, + locationCallback, + Looper.getMainLooper() + ) + + awaitClose { + fusedLocationClient.removeLocationUpdates(locationCallback) + } + } +} diff --git a/android-app/app/src/main/kotlin/com/example/androidapp/MainActivity.kt b/android-app/app/src/main/kotlin/com/example/androidapp/MainActivity.kt new file mode 100644 index 0000000..1d41f4a --- /dev/null +++ b/android-app/app/src/main/kotlin/com/example/androidapp/MainActivity.kt @@ -0,0 +1,64 @@ +package com.example.androidapp + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import org.maplibre.android.MapLibre +import org.maplibre.android.maps.MapView +import org.maplibre.android.maps.Style + +class MainActivity : AppCompatActivity() { + + private var mapView: MapView? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + // MapLibre access token only needed for Mapbox styles, but good practice to initialize + MapLibre.getInstance(this) + setContentView(R.layout.activity_main) + + mapView = findViewById(R.id.mapView) + mapView?.onCreate(savedInstanceState) + mapView?.getMapAsync { maplibreMap -> + maplibreMap.setStyle(Style.Builder() + .addSource(RasterSource("noaa-enc-source", + TileSet("2.0.0", "asset://noaa_enc.mbtiles"))) + .addLayer(RasterLayer("noaa-enc-layer", "noaa-enc-source")) + ) + } + } + + override fun onStart() { + super.onStart() + mapView?.onStart() + } + + override fun onResume() { + super.onResume() + mapView?.onResume() + } + + override fun onPause() { + super.onPause() + mapView?.onPause() + } + + override fun onStop() { + super.onStop() + mapView?.onStop() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView?.onSaveInstanceState(outState) + } + + override fun onLowMemory() { + super.onLowMemory() + mapView?.onLowMemory() + } + + override fun onDestroy() { + super.onDestroy() + mapView?.onDestroy() + } +} |
