Duration Map

This commit is contained in:
Dimitris
2026-03-27 07:17:53 +01:00
parent 263b5b576d
commit 2348d3b633
8 changed files with 51 additions and 97 deletions

View File

@@ -17,8 +17,8 @@ android {
applicationId = "com.kouros.navigation" applicationId = "com.kouros.navigation"
minSdk = 33 minSdk = 33
targetSdk = 36 targetSdk = 36
versionCode = 83 versionCode = 84
versionName = "0.2.0.83" versionName = "0.2.0.84"
base.archivesName = "navi-$versionName" base.archivesName = "navi-$versionName"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
} }

View File

@@ -43,7 +43,6 @@ import com.google.android.gms.location.LocationServices
import com.kouros.data.R import com.kouros.data.R
import com.kouros.navigation.MainApplication.Companion.navigationViewModel import com.kouros.navigation.MainApplication.Companion.navigationViewModel
import com.kouros.navigation.car.TextToSpeechManager import com.kouros.navigation.car.TextToSpeechManager
import com.kouros.navigation.car.navigation.NavigationService
import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE
import com.kouros.navigation.data.Constants.INSTRUCTION_DISTANCE import com.kouros.navigation.data.Constants.INSTRUCTION_DISTANCE
import com.kouros.navigation.data.Constants.TAG import com.kouros.navigation.data.Constants.TAG
@@ -80,8 +79,6 @@ import kotlin.time.Duration.Companion.seconds
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
var navigationService: NavigationService? = null
var isBound: Boolean = false var isBound: Boolean = false
val routeData = MutableLiveData("") val routeData = MutableLiveData("")
val routeModel = RouteModel() val routeModel = RouteModel()
@@ -102,20 +99,6 @@ class MainActivity : ComponentActivity() {
} }
} }
// Monitors the state of the connection to the navigation service.
private val serviceConnection: ServiceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
val binder: NavigationService.LocalBinder = service as NavigationService.LocalBinder
navigationService = binder.service
isBound = true
}
override fun onServiceDisconnected(name: ComponentName?) {
navigationService = null
isBound = false
}
}
val cameraPosition = MutableLiveData( val cameraPosition = MutableLiveData(
CameraPosition( CameraPosition(
zoom = 15.0, target = Position(latitude = 48.1857475, longitude = 11.5793627) zoom = 15.0, target = Position(latitude = 48.1857475, longitude = 11.5793627)
@@ -168,27 +151,6 @@ class MainActivity : ComponentActivity() {
} }
} }
override fun onStart() {
super.onStart()
Log.i(TAG, "In onStart()")
bindService(
Intent(this, NavigationService::class.java),
serviceConnection,
BIND_AUTO_CREATE
)
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 1)
}
override fun onStop() {
Log.i(TAG, "In onStop(). bound $isBound")
if (isBound) {
unbindService(serviceConnection)
isBound = false
navigationService = null
}
super.onStop()
}
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun StartScreen( fun StartScreen(
@@ -356,7 +318,6 @@ class MainActivity : ComponentActivity() {
routeModel.navState = routeModel.navState.copy(routingEngine = routingEngine) routeModel.navState = routeModel.navState.copy(routingEngine = routingEngine)
routeModel.startNavigation(newRoute) routeModel.startNavigation(newRoute)
routeData.value = routeModel.curRoute.routeGeoJson routeData.value = routeModel.curRoute.routeGeoJson
navigationService?.startNavigation()
} }
fun stopNavigation(closeSheet: () -> Unit) { fun stopNavigation(closeSheet: () -> Unit) {
closeSheet() closeSheet()
@@ -364,7 +325,6 @@ class MainActivity : ComponentActivity() {
getSettingsViewModel(applicationContext).onLastRouteChanged("") getSettingsViewModel(applicationContext).onLastRouteChanged("")
routeData.value = "" routeData.value = ""
stepData.value = StepData("", "", 0.0, 0, 0, 0, 0.0) stepData.value = StepData("", "", 0.0, 0, 0, 0, 0.0)
navigationService?.stopNavigation()
} }
fun textToSpeech() { fun textToSpeech() {

View File

@@ -67,7 +67,7 @@ class DeviceLocationManager(
* @param minDistanceM Minimum distance between updates in meters (default: 5m) * @param minDistanceM Minimum distance between updates in meters (default: 5m)
*/ */
@SuppressLint("MissingPermission") @SuppressLint("MissingPermission")
fun startLocationUpdates(minTimeMs: Long = 500, minDistanceM: Float = 5f) { fun startLocationUpdates(minTimeMs: Long = 1000, minDistanceM: Float = 5f) {
if (isListening) return if (isListening) return
// Get and deliver last known location first // Get and deliver last known location first

View File

@@ -1,13 +1,9 @@
package com.kouros.navigation.car package com.kouros.navigation.car
import android.Manifest.permission import android.Manifest.permission
import android.content.ComponentName
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.ServiceConnection
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.location.Location import android.location.Location
import android.os.IBinder
import android.util.Log import android.util.Log
import androidx.car.app.CarContext import androidx.car.app.CarContext
import androidx.car.app.CarToast import androidx.car.app.CarToast
@@ -15,13 +11,11 @@ import androidx.car.app.Screen
import androidx.car.app.ScreenManager import androidx.car.app.ScreenManager
import androidx.car.app.Session import androidx.car.app.Session
import androidx.car.app.connection.CarConnection import androidx.car.app.connection.CarConnection
import androidx.car.app.model.CarIcon
import androidx.car.app.model.Distance import androidx.car.app.model.Distance
import androidx.car.app.navigation.NavigationManager import androidx.car.app.navigation.NavigationManager
import androidx.car.app.navigation.NavigationManagerCallback import androidx.car.app.navigation.NavigationManagerCallback
import androidx.car.app.navigation.model.Destination import androidx.car.app.navigation.model.Destination
import androidx.car.app.navigation.model.Step import androidx.car.app.navigation.model.Step
import androidx.car.app.navigation.model.TravelEstimate
import androidx.car.app.navigation.model.Trip import androidx.car.app.navigation.model.Trip
import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.LifecycleObserver
@@ -114,11 +108,13 @@ class NavigationSession : Session(), NavigationListener, NavigationObserverCallb
private var showTraffic = false; private var showTraffic = false;
private var distanceMode = 0
var lastCameraSearch = 0 var lastCameraSearch = 0
var speedCameras = listOf<Elements>() var speedCameras = listOf<Elements>()
var lastRouteDate: LocalDateTime = LocalDateTime.now() var lastRouteDate: LocalDateTime = LocalDateTime.now()
var navigationManagerStarted = false var navigationManagerStarted = false
/** /**
@@ -170,6 +166,10 @@ class NavigationSession : Session(), NavigationListener, NavigationObserverCallb
repository.trafficFlow.asLiveData().observe(this, Observer { repository.trafficFlow.asLiveData().observe(this, Observer {
showTraffic = it showTraffic = it
}) })
repository.distanceModeFlow.asLiveData().observe(this, Observer {
distanceMode = it
})
} }
/** /**
@@ -441,24 +441,33 @@ class NavigationSession : Session(), NavigationListener, NavigationObserverCallb
* Snaps location to route and checks for deviation requiring reroute. * Snaps location to route and checks for deviation requiring reroute.
*/ */
private fun handleNavigationLocation(location: Location) { private fun handleNavigationLocation(location: Location) {
routeModel.updateLocation(location, navigationViewModel)
if (routeModel.navState.arrived) return
if (guidanceAudio == 1) { if (guidanceAudio == 1) {
handleGuidanceAudio() handleGuidanceAudio()
} }
val streetName = routeModel.currentStep().street val streetName = routeModel.currentStep().street
val currentDate = LocalDateTime.now(ZoneOffset.UTC) val currentDate = LocalDateTime.now(ZoneOffset.UTC)
checkTraffic(currentDate, location) checkTraffic(currentDate, location)
updateSpeedCamera(location) updateSpeedCamera(location)
checkRoute(currentDate, location) checkRoute(currentDate, location)
routeModel.updateLocation(location, navigationViewModel)
checkArrival() checkArrival()
updateNavigationScreen()
updateTripNavigationScreen(location) snapLocation(location, streetName)
}
if (routeModel.navState.arrived) return /**
* Updates the surface renderer with snapped location and street name.
* Checks if maximal route deviation is exceeded and reroutes if needed.
*/
private fun snapLocation(location: Location, streetName: String) {
val snappedLocation = snapLocation(location, routeModel.route.maneuverLocations()) val snappedLocation = snapLocation(location, routeModel.route.maneuverLocations())
val distance = location.distanceTo(snappedLocation) val distance = location.distanceTo(snappedLocation)
when { when {
distance > MAXIMAL_ROUTE_DEVIATION -> { distance > MAXIMAL_ROUTE_DEVIATION -> {
stopNavigation()
navigationScreen.calculateNewRoute(routeModel.navState.destination) navigationScreen.calculateNewRoute(routeModel.navState.destination)
} }
@@ -472,19 +481,20 @@ class NavigationSession : Session(), NavigationListener, NavigationObserverCallb
} }
} }
fun updateTripNavigationScreen(location: Location) { /**
val travelEstimateTrip = routeModel.travelEstimateTrip(carContext, 0) * Updates the navigation screen with new trip information.
val travelEstimateStep = routeModel.travelEstimateStep(carContext, 0) */
val steps = mutableListOf<Step>() fun updateNavigationScreen() {
val street = if (routeModel.navState.destination.street != null) { if (routeModel.navState.destination.name.isEmpty()
routeModel.navState.destination.street!! && routeModel.navState.destination.street.isEmpty()) {
} else { return
// routeModel.navState.destination.name!!
"Street"
} }
val travelEstimateTrip = routeModel.travelEstimateTrip(carContext, distanceMode)
val travelEstimateStep = routeModel.travelEstimateStep(carContext, distanceMode)
val steps = mutableListOf<Step>()
val destination = Destination.Builder() val destination = Destination.Builder()
.setName(street) .setName(routeModel.navState.destination.name)
.setAddress(street) .setAddress(routeModel.navState.destination.street)
.build() .build()
val distance = val distance =
formattedDistance(0, routeModel.routeCalculator.leftStepDistance()) formattedDistance(0, routeModel.routeCalculator.leftStepDistance())
@@ -501,7 +511,7 @@ class NavigationSession : Session(), NavigationListener, NavigationObserverCallb
stepTravelEstimate = travelEstimateStep, stepTravelEstimate = travelEstimateStep,
destinations = mutableListOf(destination), destinations = mutableListOf(destination),
steps = steps, steps = steps,
nextStepRemainingDistance = Distance.create(distance.first, distance.second), stepRemainingDistance = Distance.create(distance.first, distance.second),
shouldShowNextStep = false, shouldShowNextStep = false,
shouldShowLanes = true, shouldShowLanes = true,
junctionImage = null, junctionImage = null,
@@ -603,7 +613,7 @@ class NavigationSession : Session(), NavigationListener, NavigationObserverCallb
} else { } else {
prepareRoute(route) prepareRoute(route)
} }
updateTripNavigationScreen(surfaceRenderer.lastLocation) updateNavigationScreen()
} }
} }
@@ -618,8 +628,7 @@ class NavigationSession : Session(), NavigationListener, NavigationObserverCallb
} }
surfaceRenderer.setRouteData(routeModel.curRoute.routeGeoJson) surfaceRenderer.setRouteData(routeModel.curRoute.routeGeoJson)
startNavigation() startNavigation()
updateTripNavigationScreen(surfaceRenderer.lastLocation) updateNavigationScreen()
//navigationScreen.updateTrip(surfaceRenderer.lastLocation)
} }
/** /**
@@ -630,8 +639,7 @@ class NavigationSession : Session(), NavigationListener, NavigationObserverCallb
newRouteModel.navState = routeModel.navState.copy(routingEngine = routingEngine) newRouteModel.navState = routeModel.navState.copy(routingEngine = routingEngine)
newRouteModel.startNavigation(route) newRouteModel.startNavigation(route)
routeModel.curRoute.summary.trafficDelay = newRouteModel.curRoute.summary.trafficDelay routeModel.curRoute.summary.trafficDelay = newRouteModel.curRoute.summary.trafficDelay
//navigationScreen.updateTrip(surfaceRenderer.lastLocation) updateNavigationScreen()
updateTripNavigationScreen(surfaceRenderer.lastLocation)
} }

View File

@@ -115,8 +115,9 @@ class Simulation {
updateLocation(fakeLocation) updateLocation(fakeLocation)
// Wait before moving to the next point (e.g., every 1 second) // Wait before moving to the next point (e.g., every 1 second)
if (duration > 100) { if (duration > 100) {
delay(duration / 4) // delay(duration / 4)
} }
delay(1000)
lastTime = p.time lastTime = p.time
lastLocation = fakeLocation lastLocation = fakeLocation
} }

View File

@@ -65,8 +65,6 @@ open class NavigationScreen(
val settingsViewModel = getSettingsViewModel(carContext) val settingsViewModel = getSettingsViewModel(carContext)
private var distanceMode = 0
private var tripSuggestion = false private var tripSuggestion = false
private var tripSuggestionCalled = false private var tripSuggestionCalled = false
@@ -76,25 +74,15 @@ open class NavigationScreen(
private var isNavigating = false private var isNavigating = false
private var isRerouting = false private var isRerouting = false
private var hasArrived = false private var hasArrived = false
private lateinit var destinations: MutableList<Destination> private lateinit var destinations: MutableList<Destination>
private lateinit var stepRemainingDistance: Distance private lateinit var stepRemainingDistance: Distance
private lateinit var destinationTravelEstimate: TravelEstimate private lateinit var destinationTravelEstimate: TravelEstimate
private lateinit var stepTravelEstimate: TravelEstimate private lateinit var stepTravelEstimate: TravelEstimate
private var shouldShowNextStep = false private var shouldShowNextStep = false
private var shouldShowLanes = false private var shouldShowLanes = false
private lateinit var steps: MutableList<Step> private lateinit var steps: MutableList<Step>
private var junctionImage: CarIcon? = null
var junctionImage: CarIcon? = null private var backGroundColor = CarColor.BLUE
var backGroundColor = CarColor.BLUE
val observerRecentPlaces = Observer<List<Place>> { newPlaces -> val observerRecentPlaces = Observer<List<Place>> { newPlaces ->
recentPlaces.addAll(newPlaces) recentPlaces.addAll(newPlaces)
if (newPlaces.isNotEmpty() && !tripSuggestionCalled) { if (newPlaces.isNotEmpty() && !tripSuggestionCalled) {
@@ -108,9 +96,6 @@ open class NavigationScreen(
lifecycleScope.launch { lifecycleScope.launch {
settingsViewModel.tripSuggestion.first() settingsViewModel.tripSuggestion.first()
} }
repository.distanceModeFlow.asLiveData().observe(this, Observer {
distanceMode = it
})
repository.tripSuggestionFlow.asLiveData().observe(this, Observer { repository.tripSuggestionFlow.asLiveData().observe(this, Observer {
navigationViewModel.recentPlaces.observe(this, observerRecentPlaces) navigationViewModel.recentPlaces.observe(this, observerRecentPlaces)
@@ -481,7 +466,6 @@ open class NavigationScreen(
* Initiates recalculation for a new route to the destination. * Initiates recalculation for a new route to the destination.
*/ */
fun calculateNewRoute(destination: Place) { fun calculateNewRoute(destination: Place) {
stopNavigation()
navigationType = NavigationType.REROUTE navigationType = NavigationType.REROUTE
invalidate() invalidate()
val mainThreadHandler = Handler(carContext.mainLooper) val mainThreadHandler = Handler(carContext.mainLooper)
@@ -511,7 +495,6 @@ open class NavigationScreen(
) )
} }
/** /**
* Updates navigation state with the current location, checks for arrival, and traffic updates. * Updates navigation state with the current location, checks for arrival, and traffic updates.
*/ */
@@ -523,7 +506,7 @@ open class NavigationScreen(
steps: MutableList<Step>, steps: MutableList<Step>,
destinationTravelEstimate: TravelEstimate, destinationTravelEstimate: TravelEstimate,
stepTravelEstimate: TravelEstimate, stepTravelEstimate: TravelEstimate,
nextStepRemainingDistance: Distance, stepRemainingDistance: Distance,
shouldShowNextStep: Boolean, shouldShowNextStep: Boolean,
shouldShowLanes: Boolean, shouldShowLanes: Boolean,
junctionImage: CarIcon?, junctionImage: CarIcon?,
@@ -534,7 +517,7 @@ open class NavigationScreen(
this.hasArrived = hasArrived this.hasArrived = hasArrived
this.destinations = destinations this.destinations = destinations
this.steps = steps this.steps = steps
stepRemainingDistance = nextStepRemainingDistance this.stepRemainingDistance = stepRemainingDistance
this.destinationTravelEstimate = destinationTravelEstimate this.destinationTravelEstimate = destinationTravelEstimate
this.stepTravelEstimate = stepTravelEstimate this.stepTravelEstimate = stepTravelEstimate
this.shouldShowNextStep = shouldShowNextStep this.shouldShowNextStep = shouldShowNextStep

View File

@@ -34,13 +34,13 @@ data class Places(
@Serializable @Serializable
data class Place( data class Place(
var id: Long = 0, var id: Long = 0,
var name: String? = null, var name: String = "",
var category: String? = null, var category: String = "",
var latitude: Double = 0.0, var latitude: Double = 0.0,
var longitude: Double = 0.0, var longitude: Double = 0.0,
var postalCode: String? = null, var postalCode: String = "",
var city: String? = null, var city: String = "",
var street: String? = null, var street: String = "",
var distance: Float = 0F, var distance: Float = 0F,
//var avatar: Uri? = null, //var avatar: Uri? = null,
var lastDate: Long = 0, var lastDate: Long = 0,

View File

@@ -3,7 +3,9 @@ package com.kouros.navigation.utils
import android.content.Context import android.content.Context
import android.location.Location import android.location.Location
import android.location.LocationManager import android.location.LocationManager
import android.util.Log
import androidx.car.app.model.Distance import androidx.car.app.model.Distance
import com.kouros.navigation.data.Constants.TAG
import com.kouros.navigation.data.Constants.TILT import com.kouros.navigation.data.Constants.TILT
import com.kouros.navigation.data.RouteEngine import com.kouros.navigation.data.RouteEngine
import com.kouros.navigation.data.osrm.OsrmRepository import com.kouros.navigation.data.osrm.OsrmRepository
@@ -141,7 +143,7 @@ fun duration(
val cameraDuration = if ((lastBearing - bearing).absoluteValue > 20.0) { val cameraDuration = if ((lastBearing - bearing).absoluteValue > 20.0) {
2.seconds 2.seconds
} else { } else {
1.seconds 1.2.seconds
//val updateDuration = java.time.Duration.between(LocalDateTime.now(), lastLocationUpdate) //val updateDuration = java.time.Duration.between(LocalDateTime.now(), lastLocationUpdate)
//((updateDuration!!.toMillis().absoluteValue * 1.2).toDuration(DurationUnit.MILLISECONDS)) //((updateDuration!!.toMillis().absoluteValue * 1.2).toDuration(DurationUnit.MILLISECONDS))
} }