This commit is contained in:
Dimitris
2026-04-04 13:16:15 +02:00
parent 69b27d3b6c
commit b99ebfd36f
8 changed files with 145 additions and 96 deletions
@@ -6,7 +6,6 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.ServiceConnection import android.content.ServiceConnection
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.graphics.Color
import android.location.Location import android.location.Location
import android.os.IBinder import android.os.IBinder
import android.util.Log import android.util.Log
@@ -29,11 +28,8 @@ import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelStore import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.ViewModelStoreOwner import androidx.lifecycle.ViewModelStoreOwner
import androidx.lifecycle.asLiveData import androidx.lifecycle.asLiveData
import androidx.lifecycle.coroutineScope
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.kouros.navigation.car.navigation.NavigationService import com.kouros.navigation.car.navigation.NavigationService
import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.car.navigation.Simulation
import com.kouros.navigation.car.screen.NavigationListener import com.kouros.navigation.car.screen.NavigationListener
import com.kouros.navigation.car.screen.NavigationScreen import com.kouros.navigation.car.screen.NavigationScreen
import com.kouros.navigation.car.screen.NavigationType import com.kouros.navigation.car.screen.NavigationType
@@ -43,30 +39,22 @@ import com.kouros.navigation.car.screen.checkPermission
import com.kouros.navigation.car.screen.observers.NavigationObserverCallback import com.kouros.navigation.car.screen.observers.NavigationObserverCallback
import com.kouros.navigation.car.screen.observers.NavigationObserverManager import com.kouros.navigation.car.screen.observers.NavigationObserverManager
import com.kouros.navigation.data.Constants.AUTOMOTIVE_CAR_SPEED_PERMISSION import com.kouros.navigation.data.Constants.AUTOMOTIVE_CAR_SPEED_PERMISSION
import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE
import com.kouros.navigation.data.Constants.GMS_CAR_SPEED_PERMISSION import com.kouros.navigation.data.Constants.GMS_CAR_SPEED_PERMISSION
import com.kouros.navigation.data.Constants.INSTRUCTION_DISTANCE
import com.kouros.navigation.data.Constants.MAXIMAL_ROUTE_DEVIATION
import com.kouros.navigation.data.Constants.MAXIMAL_SNAP_CORRECTION
import com.kouros.navigation.data.Constants.TAG import com.kouros.navigation.data.Constants.TAG
import com.kouros.navigation.data.Constants.TRAFFIC_UPDATE import com.kouros.navigation.data.Constants.TRAFFIC_UPDATE
import com.kouros.navigation.data.Constants.homeHohenwaldeck import com.kouros.navigation.data.Constants.homeHohenwaldeck
import com.kouros.navigation.data.Place import com.kouros.navigation.data.Place
import com.kouros.navigation.data.RouteEngine import com.kouros.navigation.data.RouteEngine
import com.kouros.navigation.data.SearchFilter
import com.kouros.navigation.data.ViewStyle import com.kouros.navigation.data.ViewStyle
import com.kouros.navigation.data.osrm.OsrmRepository import com.kouros.navigation.data.osrm.OsrmRepository
import com.kouros.navigation.data.overpass.Elements import com.kouros.navigation.data.overpass.Elements
import com.kouros.navigation.data.tomtom.TomTomRepository import com.kouros.navigation.data.tomtom.TomTomRepository
import com.kouros.navigation.data.valhalla.ValhallaRepository import com.kouros.navigation.data.valhalla.ValhallaRepository
import com.kouros.navigation.model.NavigationViewModel import com.kouros.navigation.model.NavigationViewModel
import com.kouros.navigation.model.RouteModel
import com.kouros.navigation.model.SettingsViewModel import com.kouros.navigation.model.SettingsViewModel
import com.kouros.navigation.repository.SettingsRepository import com.kouros.navigation.repository.SettingsRepository
import com.kouros.navigation.utils.GeoUtils import com.kouros.navigation.utils.GeoUtils
import com.kouros.navigation.utils.GeoUtils.snapLocation
import com.kouros.navigation.utils.NavigationUtils.getViewModel import com.kouros.navigation.utils.NavigationUtils.getViewModel
import com.kouros.navigation.utils.formattedDistance
import com.kouros.navigation.utils.getSettingsRepository import com.kouros.navigation.utils.getSettingsRepository
import com.kouros.navigation.utils.getSettingsViewModel import com.kouros.navigation.utils.getSettingsViewModel
import com.kouros.navigation.utils.location import com.kouros.navigation.utils.location
@@ -115,8 +103,11 @@ class NavigationServiceSession : CarSession(), NavigationListener, NavigationObs
var speedCameras = listOf<Elements>() var speedCameras = listOf<Elements>()
var recentPlaces = mutableListOf<Place>()
var lastRouteDate: LocalDateTime = LocalDateTime.now() var lastRouteDate: LocalDateTime = LocalDateTime.now()
var destination = Place()
var notificationActive = false var notificationActive = false
var navigationService: NavigationService? = null var navigationService: NavigationService? = null
@@ -129,9 +120,9 @@ class NavigationServiceSession : CarSession(), NavigationListener, NavigationObs
hasArrived: Boolean, hasArrived: Boolean,
destinations: MutableList<Destination>, destinations: MutableList<Destination>,
steps: MutableList<Step>, steps: MutableList<Step>,
destinationTravelEstimate: TravelEstimate?, destinationTravelEstimate: TravelEstimate,
stepTravelEstimate: TravelEstimate?, stepTravelEstimate: TravelEstimate,
stepRemainingDistance: Distance?, stepRemainingDistance: Distance,
shouldShowNextStep: Boolean, shouldShowNextStep: Boolean,
shouldShowLanes: Boolean, shouldShowLanes: Boolean,
junctionImage: CarIcon?, junctionImage: CarIcon?,
@@ -142,11 +133,11 @@ class NavigationServiceSession : CarSession(), NavigationListener, NavigationObs
isNavigating = isNavigating, isNavigating = isNavigating,
isRerouting = isRerouting, isRerouting = isRerouting,
hasArrived = hasArrived, hasArrived = hasArrived,
destinationTravelEstimate = destinationTravelEstimate!!, destinationTravelEstimate = destinationTravelEstimate,
stepTravelEstimate = stepTravelEstimate!!, stepTravelEstimate = stepTravelEstimate,
destinations = destinations, destinations = destinations,
steps = steps, steps = steps,
stepRemainingDistance = stepRemainingDistance!!, stepRemainingDistance = stepRemainingDistance,
shouldShowNextStep = shouldShowNextStep, shouldShowNextStep = shouldShowNextStep,
shouldShowLanes = shouldShowLanes, shouldShowLanes = shouldShowLanes,
junctionImage = junctionImage, junctionImage = junctionImage,
@@ -162,12 +153,6 @@ class NavigationServiceSession : CarSession(), NavigationListener, NavigationObs
surfaceRenderer.carOrientation, surfaceRenderer.carOrientation,
) )
initialLocation = false initialLocation = false
navigationViewModel.loadRoute(
carContext,
location,
listOf(homeHohenwaldeck),
surfaceRenderer.carOrientation
)
} }
updateLocation(location) updateLocation(location)
} }
@@ -466,7 +451,7 @@ class NavigationServiceSession : CarSession(), NavigationListener, NavigationObs
private fun handleNavigateIntent(screenManager: ScreenManager) { private fun handleNavigateIntent(screenManager: ScreenManager) {
screenManager.popToRoot() screenManager.popToRoot()
screenManager.pushForResult( screenManager.pushForResult(
SearchScreen(carContext, surfaceRenderer, navigationViewModel, mutableListOf()) SearchScreen(carContext, surfaceRenderer, navigationViewModel, recentPlaces)
) { result -> ) { result ->
// Handle search result if needed // Handle search result if needed
} }
@@ -500,7 +485,6 @@ class NavigationServiceSession : CarSession(), NavigationListener, NavigationObs
updateBearing(location) updateBearing(location)
checkTraffic(LocalDateTime.now(ZoneOffset.UTC), location) checkTraffic(LocalDateTime.now(ZoneOffset.UTC), location)
surfaceRenderer.updateLocation(location, "") surfaceRenderer.updateLocation(location, "")
} }
/** /**
@@ -512,14 +496,13 @@ class NavigationServiceSession : CarSession(), NavigationListener, NavigationObs
} }
} }
/** /**
* Start navigation process. * Start navigation process.
* Called when user starts navigation * Called when user starts navigation
*/ */
override fun startNavigation() { override fun startNavigation() {
Log.d(TAG, "startNavigation") Log.d(TAG, "startNavigation")
navigationService!!.startNavigation(route) navigationService!!.startNavigation(route, destination)
if (notificationActive) if (notificationActive)
notificationManager.startNotificationService() notificationManager.startNotificationService()
} }
@@ -621,6 +604,14 @@ class NavigationServiceSession : CarSession(), NavigationListener, NavigationObs
surfaceRenderer.maxSpeed.value = speed surfaceRenderer.maxSpeed.value = speed
} }
override fun onRecentPlacesReceived(places: List<Place>) {
Log.d(TAG, "onRecentPlacesReceived ${places.size}")
recentPlaces = places.toMutableList()
navigationScreen.recentPlaces = places.toMutableList()
navigationScreen.invalidate()
}
override fun invalidateScreen() { override fun invalidateScreen() {
navigationScreen.invalidate() navigationScreen.invalidate()
} }
@@ -647,6 +638,7 @@ class NavigationServiceSession : CarSession(), NavigationListener, NavigationObs
} }
navigationViewModel.saveRecent(carContext, place) navigationViewModel.saveRecent(carContext, place)
destination = place
// routeModel.navState = routeModel.navState.copy(destination = place) // routeModel.navState = routeModel.navState.copy(destination = place)
if (preview.isEmpty()) { if (preview.isEmpty()) {
navigationViewModel.loadRoute( navigationViewModel.loadRoute(
@@ -752,6 +752,9 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
surfaceRenderer.maxSpeed.value = speed surfaceRenderer.maxSpeed.value = speed
} }
override fun onRecentPlacesReceived(places: List<Place>) {
}
override fun invalidateScreen() { override fun invalidateScreen() {
navigationScreen.invalidate() navigationScreen.invalidate()
} }
@@ -6,6 +6,7 @@ import android.app.NotificationManager
import android.app.Service import android.app.Service
import android.content.Intent import android.content.Intent
import android.location.Location import android.location.Location
import android.location.LocationManager
import android.os.Binder import android.os.Binder
import android.os.IBinder import android.os.IBinder
import android.text.TextUtils import android.text.TextUtils
@@ -16,6 +17,7 @@ import androidx.car.app.CarToast
import androidx.car.app.model.CarColor import androidx.car.app.model.CarColor
import androidx.car.app.model.CarIcon import androidx.car.app.model.CarIcon
import androidx.car.app.model.Distance import androidx.car.app.model.Distance
import androidx.car.app.model.Distance.UNIT_METERS
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
@@ -29,6 +31,7 @@ import com.kouros.navigation.car.screen.NavigationType
import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE
import com.kouros.navigation.data.Constants.MAXIMAL_ROUTE_DEVIATION import com.kouros.navigation.data.Constants.MAXIMAL_ROUTE_DEVIATION
import com.kouros.navigation.data.Constants.MAXIMAL_SNAP_CORRECTION import com.kouros.navigation.data.Constants.MAXIMAL_SNAP_CORRECTION
import com.kouros.navigation.data.Place
import com.kouros.navigation.model.NavigationViewModel import com.kouros.navigation.model.NavigationViewModel
import com.kouros.navigation.model.SettingsViewModel import com.kouros.navigation.model.SettingsViewModel
import com.kouros.navigation.repository.SettingsRepository import com.kouros.navigation.repository.SettingsRepository
@@ -37,6 +40,7 @@ import com.kouros.navigation.utils.NavigationUtils.getViewModel
import com.kouros.navigation.utils.formattedDistance import com.kouros.navigation.utils.formattedDistance
import com.kouros.navigation.utils.getSettingsRepository import com.kouros.navigation.utils.getSettingsRepository
import com.kouros.navigation.utils.getSettingsViewModel import com.kouros.navigation.utils.getSettingsViewModel
import com.kouros.navigation.utils.location
import kotlin.collections.copy import kotlin.collections.copy
import kotlin.compareTo import kotlin.compareTo
@@ -81,6 +85,8 @@ class NavigationService : Service() {
// Manages device GPS location updates // Manages device GPS location updates
lateinit var deviceLocationManager: DeviceLocationManagerService lateinit var deviceLocationManager: DeviceLocationManagerService
var currentLocation = location(0.0, 0.0)
lateinit var navigationViewModel: NavigationViewModel lateinit var navigationViewModel: NavigationViewModel
private lateinit var navigationManager: NavigationManager private lateinit var navigationManager: NavigationManager
@@ -97,16 +103,15 @@ class NavigationService : Service() {
hasArrived: Boolean, hasArrived: Boolean,
destinations: MutableList<Destination>, destinations: MutableList<Destination>,
steps: MutableList<Step>, steps: MutableList<Step>,
destinationTravelEstimate: TravelEstimate?, destinationTravelEstimate: TravelEstimate,
stepTravelEstimate: TravelEstimate?, stepTravelEstimate: TravelEstimate,
stepRemainingDistance: Distance?, stepRemainingDistance: Distance,
shouldShowNextStep: Boolean, shouldShowNextStep: Boolean,
shouldShowLanes: Boolean, shouldShowLanes: Boolean,
junctionImage: CarIcon?, junctionImage: CarIcon?,
backGroundColor: CarColor backGroundColor: CarColor
) )
fun updateServiceLocation(location: Location) fun updateServiceLocation(location: Location)
} }
@@ -225,29 +230,32 @@ class NavigationService : Service() {
} }
/** Starts navigation. */ /** Starts navigation. */
fun startNavigation(route: String) { fun startNavigation(route: String, destination: Place) {
Log.i(TAG, "Starting Navigation") Log.i(TAG, "Starting Navigation")
startService(Intent(applicationContext, NavigationService::class.java)) startService(Intent(applicationContext, NavigationService::class.java))
routeModel.navState = routeModel.navState.copy(destination = destination)
routeModel.navState = routeModel.navState.copy(routingEngine = 2) routeModel.navState = routeModel.navState.copy(routingEngine = 2)
routeModel.startNavigation(route) routeModel.startNavigation(route)
if (routeModel.isNavigating()) { if (routeModel.isNavigating()) {
// listener.navigationStateChanged( routeModel.updateLocation(currentLocation, navigationViewModel)
// isNavigating = true, listener.navigationStateChanged(
// isRerouting = true, isNavigating = true,
// hasArrived = false, isRerouting = false,
// destinations = emptyList<Destination>().toMutableList(), hasArrived = false,
// steps = emptyList<Step>().toMutableList(), destinations = mutableListOf(routeModel.getDestination()),
// destinationTravelEstimate = null, destinationTravelEstimate = routeModel.getTravelEstimateTrip(carContext!!),
// stepTravelEstimate = null, stepTravelEstimate = routeModel.getTravelEstimateStep(carContext!!),
// stepRemainingDistance = null, steps = routeModel.getSteps(carContext!!),
// shouldShowNextStep = false, stepRemainingDistance = routeModel.getDistance(),
// shouldShowLanes = false, shouldShowNextStep = false,
// junctionImage = null, shouldShowLanes = false,
// backGroundColor = CarColor.BLUE junctionImage = null,
// ) backGroundColor = routeModel.backGroundColor()
)
} }
} }
/** Starts navigation. */ /** Starts navigation. */
fun stopNavigation() { fun stopNavigation() {
if (autoDriveEnabled) { if (autoDriveEnabled) {
@@ -261,9 +269,9 @@ class NavigationService : Service() {
hasArrived = false, hasArrived = false,
destinations = emptyList<Destination>().toMutableList(), destinations = emptyList<Destination>().toMutableList(),
steps = emptyList<Step>().toMutableList(), steps = emptyList<Step>().toMutableList(),
destinationTravelEstimate = null, destinationTravelEstimate = routeModel.travelEstimate(carContext!!, 0.0, 0),
stepTravelEstimate = null, stepTravelEstimate = routeModel.travelEstimate(carContext!!, 0.0, 0),
stepRemainingDistance = null, stepRemainingDistance = Distance.create(0.0, UNIT_METERS),
shouldShowNextStep = false, shouldShowNextStep = false,
shouldShowLanes = false, shouldShowLanes = false,
junctionImage = null, junctionImage = null,
@@ -275,6 +283,7 @@ class NavigationService : Service() {
fun updateLocation(location: Location) { fun updateLocation(location: Location) {
Log.d(TAG, "updateLocation") Log.d(TAG, "updateLocation")
currentLocation = location
if (routeModel.isNavigating()) { if (routeModel.isNavigating()) {
routeModel.updateLocation(location, navigationViewModel) routeModel.updateLocation(location, navigationViewModel)
val snappedLocation = snapLocation(location, routeModel.route.maneuverLocations()) val snappedLocation = snapLocation(location, routeModel.route.maneuverLocations())
@@ -296,32 +305,17 @@ class NavigationService : Service() {
) { ) {
return return
} }
val travelEstimateTrip = routeModel.travelEstimateTrip(carContext!!, distanceMode)
val travelEstimateStep = routeModel.travelEstimateStep(carContext!!, distanceMode)
val steps = mutableListOf<Step>()
val destination = Destination.Builder()
.setName(routeModel.navState.destination.name)
.setAddress(routeModel.navState.destination.street)
.build()
val distance =
formattedDistance(0, routeModel.routeCalculator.leftStepDistance())
steps.add(routeModel.currentStep(carContext!!))
if (routeModel.navState.nextStep) {
steps.add(routeModel.nextStep(carContext = carContext!!))
}
listener.navigationStateChanged( listener.navigationStateChanged(
isNavigating = routeModel.isNavigating(), isNavigating = routeModel.isNavigating(),
isRerouting = false, isRerouting = false,
hasArrived = routeModel.isArrival(), hasArrived = routeModel.isArrival(),
destinationTravelEstimate = travelEstimateTrip, destinations = mutableListOf(routeModel.getDestination()),
stepTravelEstimate = travelEstimateStep, destinationTravelEstimate = routeModel.getTravelEstimateTrip(carContext!!),
destinations = mutableListOf(destination), stepTravelEstimate = routeModel.getTravelEstimateStep(carContext!!),
steps = steps, steps = routeModel.getSteps(carContext!!),
stepRemainingDistance = Distance.create(distance.first, distance.second), stepRemainingDistance = routeModel.getDistance(),
shouldShowNextStep = false, shouldShowNextStep = false,
shouldShowLanes = true, shouldShowLanes = false,
junctionImage = null, junctionImage = null,
backGroundColor = routeModel.backGroundColor() backGroundColor = routeModel.backGroundColor()
) )
@@ -330,15 +324,14 @@ class NavigationService : Service() {
* Updates the trip information and notifies the listener with a new Trip object. * Updates the trip information and notifies the listener with a new Trip object.
* This includes destination name, address, travel estimate, and loading status. * This includes destination name, address, travel estimate, and loading status.
*/ */
val tripBuilder = Trip.Builder() val tripBuilder = Trip.Builder()
tripBuilder.addDestination( tripBuilder.addDestination(
destination, routeModel.getDestination(),
travelEstimateTrip routeModel.getTravelEstimateTrip(carContext!!)
) )
tripBuilder.setLoading(false) tripBuilder.setLoading(false)
tripBuilder.setCurrentRoad(destination.name.toString()) tripBuilder.setCurrentRoad(routeModel.getDestination().name.toString())
tripBuilder.addStep(steps.first(), travelEstimateStep) tripBuilder.addStep(routeModel.getSteps(carContext!!).first(), routeModel.getTravelEstimateStep(carContext!!))
navigationManager.updateTrip(tripBuilder.build()) navigationManager.updateTrip(tripBuilder.build())
} }
@@ -18,6 +18,7 @@ import androidx.car.app.model.DateTimeWithZone
import androidx.car.app.model.Distance import androidx.car.app.model.Distance
import androidx.car.app.model.DurationSpan import androidx.car.app.model.DurationSpan
import androidx.car.app.model.ForegroundCarColorSpan import androidx.car.app.model.ForegroundCarColorSpan
import androidx.car.app.navigation.model.Destination
import androidx.car.app.navigation.model.Lane import androidx.car.app.navigation.model.Lane
import androidx.car.app.navigation.model.LaneDirection import androidx.car.app.navigation.model.LaneDirection
import androidx.car.app.navigation.model.Maneuver import androidx.car.app.navigation.model.Maneuver
@@ -99,7 +100,6 @@ class RouteCarModel : RouteModel() {
} }
fun travelEstimate(carContext: CarContext, timeLeft: Double, distanceMode: Int): TravelEstimate { fun travelEstimate(carContext: CarContext, timeLeft: Double, distanceMode: Int): TravelEstimate {
val timeToDestinationMillis = val timeToDestinationMillis =
TimeUnit.SECONDS.toMillis(timeLeft.toLong()) TimeUnit.SECONDS.toMillis(timeLeft.toLong())
val distance = formattedDistance(distanceMode, routeCalculator.travelLeftDistance()) val distance = formattedDistance(distanceMode, routeCalculator.travelLeftDistance())
@@ -134,6 +134,37 @@ class RouteCarModel : RouteModel() {
} }
return travelBuilder.build() return travelBuilder.build()
} }
fun getSteps(carContext: CarContext): MutableList<Step> {
val steps = mutableListOf<Step>()
steps.add(currentStep(carContext))
if (navState.nextStep) {
steps.add(nextStep(carContext = carContext))
}
return steps
}
fun getDistance(): Distance {
val distance =
formattedDistance(0, routeCalculator.leftStepDistance())
return Distance.create(distance.first, distance.second)
}
fun getTravelEstimateTrip(carContext: CarContext): TravelEstimate {
return travelEstimateTrip(carContext, 0)
}
fun getTravelEstimateStep(carContext: CarContext): TravelEstimate {
return travelEstimateStep(carContext, 0)
}
fun getDestination(): Destination {
return Destination.Builder()
.setName(navState.destination.name)
.setAddress(navState.destination.street)
.build()
}
private fun createDelay(delay: Int): CarText { private fun createDelay(delay: Int): CarText {
val delayBuilder = SpannableStringBuilder() val delayBuilder = SpannableStringBuilder()
delayBuilder.append( delayBuilder.append(
@@ -154,7 +154,8 @@ open class NavigationScreen(
.setDestinationTravelEstimate(destinationTravelEstimate) .setDestinationTravelEstimate(destinationTravelEstimate)
.setActionStrip(actionStripBuilder.build()) .setActionStrip(actionStripBuilder.build())
.setMapActionStrip( .setMapActionStrip(
mapActionStrip(carContext, mapActionStrip(
carContext,
surfaceRenderer.viewStyle, surfaceRenderer.viewStyle,
{ zoomPlus() }, { zoomMinus() }, { { zoomPlus() }, { zoomMinus() }, {
Action.Builder() Action.Builder()
@@ -175,7 +176,8 @@ open class NavigationScreen(
* Creates and returns a template for the default view state. * Creates and returns a template for the default view state.
*/ */
private fun navigationView(actionStripBuilder: ActionStrip.Builder): Template { private fun navigationView(actionStripBuilder: ActionStrip.Builder): Template {
val mapActionStrip = mapActionStrip(carContext, val mapActionStrip = mapActionStrip(
carContext,
surfaceRenderer.viewStyle, surfaceRenderer.viewStyle,
{ zoomPlus() }, { zoomMinus() }, { { zoomPlus() }, { zoomMinus() }, {
createAction( createAction(
@@ -241,7 +243,8 @@ open class NavigationScreen(
.setBackgroundColor(backGroundColor) .setBackgroundColor(backGroundColor)
.setActionStrip(actionStripBuilder.build()) .setActionStrip(actionStripBuilder.build())
.setMapActionStrip( .setMapActionStrip(
mapActionStrip(carContext, mapActionStrip(
carContext,
surfaceRenderer.viewStyle, surfaceRenderer.viewStyle,
{ zoomPlus() }, { zoomMinus() }, { { zoomPlus() }, { zoomMinus() }, {
createAction( createAction(
@@ -302,7 +305,8 @@ open class NavigationScreen(
val builder = MapWithContentTemplate.Builder() val builder = MapWithContentTemplate.Builder()
.setContentTemplate(contentTemplate) .setContentTemplate(contentTemplate)
.setActionStrip( .setActionStrip(
mapActionStrip(carContext, mapActionStrip(
carContext,
ViewStyle.VIEW, ViewStyle.VIEW,
{ settingsAction() }, { settingsAction() },
{ {
@@ -341,10 +345,12 @@ open class NavigationScreen(
*/ */
fun getRoutingInfo(): RoutingInfo { fun getRoutingInfo(): RoutingInfo {
val routingInfo = RoutingInfo.Builder() val routingInfo = RoutingInfo.Builder()
.setCurrentStep( if (steps.isNotEmpty()) {
routingInfo.setCurrentStep(
steps.first(), steps.first(),
stepRemainingDistance stepRemainingDistance
) )
}
if (shouldShowNextStep && steps.size > 1) { if (shouldShowNextStep && steps.size > 1) {
routingInfo.setNextStep(steps[1]) routingInfo.setNextStep(steps[1])
} }
@@ -492,7 +498,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.
*/ */
@@ -1,7 +1,6 @@
package com.kouros.navigation.car.screen.observers package com.kouros.navigation.car.screen.observers
import com.kouros.navigation.data.Place import com.kouros.navigation.data.Place
import com.kouros.navigation.data.nominatim.SearchResult
import com.kouros.navigation.data.overpass.Elements import com.kouros.navigation.data.overpass.Elements
/** /**
@@ -26,6 +25,8 @@ interface NavigationObserverCallback {
/** Called when max speed is updated */ /** Called when max speed is updated */
fun onMaxSpeedReceived(speed: Int) fun onMaxSpeedReceived(speed: Int)
fun onRecentPlacesReceived(places: List<Place>)
/** Called to request UI invalidation/refresh */ /** Called to request UI invalidation/refresh */
fun invalidateScreen() fun invalidateScreen()
@@ -19,12 +19,18 @@ class NavigationObserverManager(
val speedCameraObserver = SpeedCameraObserver(callback) val speedCameraObserver = SpeedCameraObserver(callback)
val maxSpeedObserver = MaxSpeedObserver(callback) val maxSpeedObserver = MaxSpeedObserver(callback)
val recentPlacesObserver = RecentPlacesObserver(callback)
fun attachAllObservers(session: CarSession) { fun attachAllObservers(session: CarSession) {
viewModel.route.observe(session, routeObserver) viewModel.route.observe(session, routeObserver)
viewModel.traffic.observe(session, trafficObserver) viewModel.traffic.observe(session, trafficObserver)
viewModel.placeLocation.observe(session, placeSearchObserver) viewModel.placeLocation.observe(session, placeSearchObserver)
viewModel.speedCameras.observe(session, speedCameraObserver) viewModel.speedCameras.observe(session, speedCameraObserver)
viewModel.maxSpeed.observe(session, maxSpeedObserver) viewModel.maxSpeed.observe(session, maxSpeedObserver)
viewModel.recentPlaces.observe(session, recentPlacesObserver)
} }
/** /**
@@ -0,0 +1,18 @@
package com.kouros.navigation.car.screen.observers
import androidx.lifecycle.Observer
import com.kouros.navigation.data.Place
/**
* Observer for route updates. Triggers navigation start when a non-empty route is received.
*/
class RecentPlacesObserver(
private val callback: NavigationObserverCallback
) : Observer<List<Place>> {
override fun onChanged(value: List<Place>) {
if (value.isNotEmpty()) {
callback.onRecentPlacesReceived(value)
}
}
}