diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/data/LocationRepository.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/data/LocationRepository.kt index 72a90e2ba1ac635becd95bf9214c4c7b388ff148..130fa44964367cea8084d5dcf8ffa17733d5027f 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/data/LocationRepository.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/data/LocationRepository.kt @@ -54,7 +54,7 @@ class LocationRepository @Inject constructor( private companion object { private const val LOCATION_REQUEST_INTERVAL_MS = 15000L // 15 seconds private const val LOCATION_REQUEST_TIMEOUT_MS = 5000L // 5 seconds - private const val CONTINUOUS_LOCATION_UPDATE_INTERVAL_MS = 5000L // 5 seconds + private const val CONTINUOUS_LOCATION_UPDATE_INTERVAL_MS = 1000L // 1 second private const val CONTINUOUS_LOCATION_UPDATE_DISTANCE_M = 5f // 5 meters private const val GPS_PROVIDER_TIMEOUT_MS = 10_000L // 10 seconds - discard fused locations if fused has updated within this timeout @@ -130,6 +130,10 @@ class LocationRepository @Inject constructor( } } + fun getLastLocation(): Location? { + return lastRequestedLocation + } + fun fromNameAndLatLng(name: String?, latLng: LatLng): Place { return Place( name = name ?: context.getString(R.string.unnamed_location), diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/routing/FerrostarWrapper.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/routing/FerrostarWrapper.kt index 8f2ec23e6708e10ca2139ad700de9c4af68303d5..34920236158a1a9b18ba7eb7756545e751435691 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/routing/FerrostarWrapper.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/routing/FerrostarWrapper.kt @@ -20,25 +20,40 @@ package earth.maps.cardinal.routing import android.content.Context import com.stadiamaps.ferrostar.composeui.notification.DefaultForegroundNotificationBuilder -import com.stadiamaps.ferrostar.core.AndroidSystemLocationProvider import com.stadiamaps.ferrostar.core.AndroidTtsObserver import com.stadiamaps.ferrostar.core.FerrostarCore +import com.stadiamaps.ferrostar.core.LocationProvider +import com.stadiamaps.ferrostar.core.LocationUpdateListener import com.stadiamaps.ferrostar.core.http.OkHttpClientProvider import com.stadiamaps.ferrostar.core.service.FerrostarForegroundServiceManager import com.stadiamaps.ferrostar.core.service.ForegroundServiceManager +import com.stadiamaps.ferrostar.core.toUserLocation +import earth.maps.cardinal.data.LocationRepository +import earth.maps.cardinal.data.OrientationRepository import earth.maps.cardinal.data.RoutingMode import earth.maps.cardinal.data.room.RoutingProfileRepository +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import okhttp3.OkHttpClient import uniffi.ferrostar.CourseFiltering +import uniffi.ferrostar.Heading import uniffi.ferrostar.NavigationControllerConfig import uniffi.ferrostar.RouteAdapter import uniffi.ferrostar.RouteDeviationTracking +import uniffi.ferrostar.UserLocation import uniffi.ferrostar.WaypointAdvanceMode import uniffi.ferrostar.stepAdvanceDistanceEntryAndExit import uniffi.ferrostar.stepAdvanceDistanceToEndOfStep +import java.util.concurrent.Executor +import kotlin.time.Clock +import kotlin.time.ExperimentalTime +import kotlin.time.toJavaInstant class FerrostarWrapper( context: Context, + private val locationRepository: LocationRepository, + private val orientationRepository: OrientationRepository, private val mode: RoutingMode, private val localValhallaEndpoint: String, private val androidTtsObserver: AndroidTtsObserver, @@ -46,12 +61,52 @@ class FerrostarWrapper( routingOptions: RoutingOptions? = null ) { + private val coroutineScope = CoroutineScope(Dispatchers.Main) + private val foregroundServiceManager: ForegroundServiceManager = FerrostarForegroundServiceManager( context = context, DefaultForegroundNotificationBuilder(context) ) - private val locationProvider = AndroidSystemLocationProvider(context = context) + @OptIn(ExperimentalTime::class) + private val locationProvider = object: LocationProvider { + private val listeners = mutableListOf() + + override val lastLocation: UserLocation? + get() = locationRepository.getLastLocation()?.toUserLocation() + override val lastHeading: Heading? + get() { + val heading = ((orientationRepository.azimuth.value.toInt() + 360) % 360).toUShort() + return Heading( + heading, + 0u, + Clock.System.now().toJavaInstant() + ) + } + + init { + coroutineScope.launch { + locationRepository.locationFlow.collect { location -> + listeners.forEach { listener -> + location?.toUserLocation()?.let { userLocation -> + listener.onLocationUpdated(userLocation) + } + } + } + } + } + + override fun addListener( + listener: LocationUpdateListener, + executor: Executor + ) { + listeners.add(listener) + } + + override fun removeListener(listener: LocationUpdateListener) { + listeners.remove(listener) + } + } private var previousRouteOptions: RoutingOptions? = null var core = diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/routing/FerrostarWrapperRepository.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/routing/FerrostarWrapperRepository.kt index df65804a35d9e3bba4f2dfd0d55b210055a4bf67..4d5c0b73380af0be297366f1daf2969701c6881f 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/routing/FerrostarWrapperRepository.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/routing/FerrostarWrapperRepository.kt @@ -21,6 +21,8 @@ package earth.maps.cardinal.routing import android.content.Context import com.stadiamaps.ferrostar.core.AndroidTtsObserver import dagger.hilt.android.qualifiers.ApplicationContext +import earth.maps.cardinal.data.LocationRepository +import earth.maps.cardinal.data.OrientationRepository import earth.maps.cardinal.data.RoutingMode import earth.maps.cardinal.data.room.RoutingProfileRepository import javax.inject.Inject @@ -30,6 +32,8 @@ import javax.inject.Singleton class FerrostarWrapperRepository @Inject constructor( @param:ApplicationContext private val context: Context, + private val locationRepository: LocationRepository, + private val orientationRepository: OrientationRepository, private val routingProfileRepository: RoutingProfileRepository ) { lateinit var walking: FerrostarWrapper @@ -44,6 +48,8 @@ class FerrostarWrapperRepository @Inject constructor( fun setValhallaEndpoint(endpoint: String) { walking = FerrostarWrapper( context, + locationRepository, + orientationRepository, RoutingMode.PEDESTRIAN, endpoint, androidTtsObserver, @@ -51,6 +57,8 @@ class FerrostarWrapperRepository @Inject constructor( ) cycling = FerrostarWrapper( context, + locationRepository, + orientationRepository, RoutingMode.BICYCLE, endpoint, androidTtsObserver, @@ -58,6 +66,8 @@ class FerrostarWrapperRepository @Inject constructor( ) driving = FerrostarWrapper( context, + locationRepository, + orientationRepository, RoutingMode.AUTO, endpoint, androidTtsObserver, @@ -65,6 +75,8 @@ class FerrostarWrapperRepository @Inject constructor( ) truck = FerrostarWrapper( context, + locationRepository, + orientationRepository, RoutingMode.TRUCK, endpoint, androidTtsObserver, @@ -72,6 +84,8 @@ class FerrostarWrapperRepository @Inject constructor( ) motorScooter = FerrostarWrapper( context, + locationRepository, + orientationRepository, RoutingMode.MOTOR_SCOOTER, endpoint, androidTtsObserver, @@ -79,6 +93,8 @@ class FerrostarWrapperRepository @Inject constructor( ) motorcycle = FerrostarWrapper( context, + locationRepository, + orientationRepository, RoutingMode.MOTORCYCLE, endpoint, androidTtsObserver,