This commit is contained in:
Dimitris
2026-04-03 12:30:39 +02:00
parent 8af2d3ad0b
commit 2ce079a7c1
5 changed files with 117 additions and 95 deletions
@@ -61,6 +61,8 @@ import com.kouros.navigation.data.tomtom.TomTomRepository
import com.kouros.navigation.data.valhalla.ValhallaRepository
import com.kouros.navigation.model.NavigationViewModel
import com.kouros.navigation.model.RouteModel
import com.kouros.navigation.model.SettingsViewModel
import com.kouros.navigation.repository.SettingsRepository
import com.kouros.navigation.utils.GeoUtils
import com.kouros.navigation.utils.GeoUtils.snapLocation
import com.kouros.navigation.utils.NavigationUtils.getViewModel
@@ -90,7 +92,7 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
// Model for managing route state and navigation logic for Android Auto
lateinit var routeModel: RouteCarModel
var route = ""
var route = ""
// Main navigation screen displayed to the user
lateinit var navigationScreen: NavigationScreen
@@ -102,9 +104,12 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
lateinit var carSensorManager: CarSensorManager
// Manages device GPS location updates
val useDeviceLocationManager = false
lateinit var deviceLocationManager: DeviceLocationManager
lateinit var navigationManager: NavigationManager
var initialLocation = true;
// lateinit var navigationManager: NavigationManager
lateinit var textToSpeechManager: TextToSpeechManager
@@ -146,7 +151,20 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
shouldShowLanes: Boolean,
junctionImage: CarIcon?
) {
TODO("Not yet implemented")
}
override fun updateServiceLocation(location: Location) {
if (initialLocation) {
Log.d(TAG, "RecentPlaces $location")
navigationViewModel.loadRecentPlaces(
carContext,
location,
surfaceRenderer.carOrientation,
)
initialLocation = false
}
updateLocation(location)
}
}
@@ -167,6 +185,7 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
navigationService = null
}
}
/**
* Lifecycle observer for managing session lifecycle events.
* Cleans up resources when the session is destroyed.
@@ -200,9 +219,9 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
}
override fun onDestroy(owner: LifecycleOwner) {
if (::navigationManager.isInitialized) {
navigationManager.clearNavigationManagerCallback()
}
// if (::navigationManager.isInitialized) {
// navigationManager.clearNavigationManagerCallback()
// }
if (::carSensorManager.isInitialized) {
carSensorManager.cleanup()
}
@@ -249,6 +268,7 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
* Creates appropriate repository based on user selection.
*/
fun onRoutingEngineStateUpdated(routeEngine: Int) {
Log.d(TAG, "onRoutingEngineStateUpdated $routeEngine")
if (!::navigationViewModel.isInitialized || routeEngine != routingEngine) {
navigationViewModel = when (routeEngine) {
RouteEngine.VALHALLA.ordinal -> NavigationViewModel(ValhallaRepository())
@@ -359,26 +379,26 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
* Initializes managers for rendering, sensors, and location.
*/
private fun initializeManagers() {
navigationManager = carContext.getCarService(NavigationManager::class.java)
navigationManager.setNavigationManagerCallback(object : NavigationManagerCallback {
override fun onAutoDriveEnabled() {
// Called when the app should simulate navigation (e.g., for testing)
deviceLocationManager.stopLocationUpdates()
autoDriveEnabled = true
startNavigation()
CarToast.makeText(carContext, "Auto drive enabled", CarToast.LENGTH_LONG)
.show()
}
override fun onStopNavigation() {
// Called when the user stops navigation in the car screen
// Stop turn-by-turn logic and clean up
stopNavigation()
if (autoDriveEnabled) {
deviceLocationManager.startLocationUpdates()
}
}
})
// navigationManager = carContext.getCarService(NavigationManager::class.java)
// navigationManager.setNavigationManagerCallback(object : NavigationManagerCallback {
// override fun onAutoDriveEnabled() {
// // Called when the app should simulate navigation (e.g., for testing)
// //deviceLocationManager.stopLocationUpdates()
// autoDriveEnabled = true
// startNavigation()
// CarToast.makeText(carContext, "Auto drive enabled", CarToast.LENGTH_LONG)
// .show()
// }
//
// override fun onStopNavigation() {
// // Called when the user stops navigation in the car screen
// // Stop turn-by-turn logic and clean up
// stopNavigation()
// if (autoDriveEnabled) {
// //deviceLocationManager.startLocationUpdates()
// }
// }
// })
surfaceRenderer = SurfaceRenderer(carContext, lifecycle, viewModelStoreOwner, this)
carSensorManager = CarSensorManager(
@@ -389,19 +409,21 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
onSpeedUpdate = { speed -> surfaceRenderer.updateCarSpeed(speed) }
)
deviceLocationManager = DeviceLocationManager(
carContext = carContext,
lifecycleOwner = this,
shouldUseCarLocationFlow = carSensorManager.shouldUseCarLocation(),
onLocationUpdate = ::updateLocation,
onInitialLocation = { location ->
navigationViewModel.loadRecentPlaces(
carContext,
location,
surfaceRenderer.carOrientation,
)
}
)
if (useDeviceLocationManager) {
deviceLocationManager = DeviceLocationManager(
carContext = carContext,
lifecycleOwner = this,
shouldUseCarLocationFlow = carSensorManager.shouldUseCarLocation(),
onLocationUpdate = ::updateLocation,
onInitialLocation = { location ->
navigationViewModel.loadRecentPlaces(
carContext,
location,
surfaceRenderer.carOrientation,
)
}
)
}
textToSpeechManager = TextToSpeechManager(carContext)
@@ -435,7 +457,8 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
carContext.checkSelfPermission(permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED
return if (hasLocationPermission && hasContactsPermission) {
deviceLocationManager.startLocationUpdates()
if (useDeviceLocationManager)
deviceLocationManager.startLocationUpdates()
navigationScreen
} else {
showPermissionScreen()
@@ -509,6 +532,7 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
* Handles route snapping, deviation detection for rerouting, and map updates.
*/
fun updateLocation(location: Location) {
Log.d(TAG, "update location $location")
val streetName = if (routeModel.isNavigating()) {
routeModel.currentStep().street
} else {
@@ -657,10 +681,13 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
* Called when user starts navigation
*/
override fun startNavigation() {
if (useDeviceLocationManager)
deviceLocationManager.stopLocationUpdates()
Log.d(TAG, "startNavigation")
navigationService!!.startNavigation()
surfaceRenderer.navigation = true
surfaceRenderer.viewStyle = ViewStyle.VIEW
navigationManager.navigationStarted()
// navigationManager.navigationStarted()
navigationManagerStarted = true
if (autoDriveEnabled) {
simulation.startSimulation(
@@ -679,9 +706,12 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
*/
override fun stopNavigation() {
Log.d(TAG, "stopNavigation")
if (useDeviceLocationManager)
deviceLocationManager.startLocationUpdates()
navigationService!!.stopNavigation()
surfaceRenderer.navigation = false
routeModel.stopNavigation()
navigationManager.navigationEnded()
//navigationManager.navigationEnded()
if (autoDriveEnabled) {
simulation.stopSimulation()
autoDriveEnabled = false
@@ -697,7 +727,7 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
override fun updateTrip(trip: Trip) {
if (navigationManagerStarted) {
navigationManager.updateTrip(trip)
//navigationManager.updateTrip(trip)
}
}
@@ -372,6 +372,7 @@ class SurfaceRenderer(
* Uses car orientation sensor if available, otherwise falls back to location bearing.
*/
fun updateLocation(location: Location, streetName: String) {
Log.d(TAG, "updateLocation Surface $location $streetName")
synchronized(this) {
street.value = streetName
if (viewStyle == ViewStyle.VIEW || viewStyle == ViewStyle.PAN_VIEW) {
@@ -61,7 +61,6 @@ class NavigationService : Service() {
val simulation = Simulation()
private lateinit var listener: Listener
// Model for managing route state and navigation logic for Android Auto
@@ -149,49 +148,50 @@ class NavigationService : Service() {
) {
Log.d(TAG, "in setCarContext")
this.carContext = carContext
this.listener = listener
deviceLocationManager = DeviceLocationManagerService(
carContext = carContext,
onLocationUpdate = ::updateLocation,
onInitialLocation = { location ->
Log.d(TAG, "Initial location: $location")
updateLocation(location)
}
)
deviceLocationManager.startLocationUpdates()
navigationManagerInitialized = true
// navigationManager =
// carContext.getCarService(NavigationManager::class.java)
// navigationManager.setNavigationManagerCallback(object : NavigationManagerCallback {
// override fun onAutoDriveEnabled() {
// // Called when the app should simulate navigation (e.g., for testing)
// deviceLocationManager.stopLocationUpdates()
// autoDriveEnabled = true
//
// simulation()
//
// startNavigation()
// CarToast.makeText(carContext, "Auto drive enabled", CarToast.LENGTH_LONG)
// .show()
// }
//
// private fun simulation() {
// //simulation.gpxSimulation() {
// // listener.updateServiceLocation(it)
// //}
// }
//
// override fun onStopNavigation() {
// // Called when the user stops navigation in the car screen
// // Stop turn-by-turn logic and clean up
// stopNavigation()
// if (autoDriveEnabled) {
// deviceLocationManager.startLocationUpdates()
// }
// }
// })
navigationManager =
carContext.getCarService(NavigationManager::class.java)
navigationManager.setNavigationManagerCallback(object : NavigationManagerCallback {
override fun onAutoDriveEnabled() {
Log.d(TAG, "onAutoDriveEnabled")
// Called when the app should simulate navigation (e.g., for testing)
deviceLocationManager.stopLocationUpdates()
autoDriveEnabled = true
simulation()
//startNavigation()
CarToast.makeText(carContext, "Auto drive enabled", CarToast.LENGTH_LONG)
.show()
}
private fun simulation() {
simulation.gpxSimulation {
listener.updateServiceLocation(it)
}
}
override fun onStopNavigation() {
// Called when the user stops navigation in the car screen
// Stop turn-by-turn logic and clean up
stopNavigation()
if (autoDriveEnabled) {
deviceLocationManager.startLocationUpdates()
}
}
})
this.listener = listener
// Uncomment if navigating
// mNavigationManager.navigationStarted();
@@ -201,12 +201,12 @@ class NavigationService : Service() {
fun clearCarContext() {
Log.i(TAG, "clearContext");
carContext = null;
//navigationManager.clearNavigationManagerCallback();
navigationManager.clearNavigationManagerCallback();
}
/** Starts navigation. */
fun startNavigation() {
//deviceLocationManager.startLocationUpdates()
Log.i(TAG, "Starting Navigation")
startService(Intent(applicationContext, NavigationService::class.java))
Log.i(TAG, "Starting foreground service")
@@ -231,9 +231,8 @@ class NavigationService : Service() {
if (autoDriveEnabled) {
autoDriveEnabled = false
}
deviceLocationManager.stopLocationUpdates()
// if (navigationManagerInitialized)
// navigationManager.navigationEnded()
if (navigationManagerInitialized)
navigationManager.navigationEnded()
listener.navigationStateChanged(
false,
isRerouting = false,
@@ -246,20 +245,11 @@ class NavigationService : Service() {
shouldShowLanes = false,
junctionImage = null,
)
//stopForeground(STOP_FOREGROUND_REMOVE)
stopForeground(STOP_FOREGROUND_REMOVE)
stopSelf()
}
fun updateLocation(location: Location) {
Log.d(TAG, "Update location: $location")
if (autoDriveEnabled) {
}
listener.updateServiceLocation(location)
}
// private fun createMainActivityPendingIntent(): PendingIntent? {
// val intent: Intent = Intent(this, MainActivity::class.java)
// intent.putExtra(EXTRA_STARTED_FROM_NOTIFICATION, true)
// return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)
// }
}
@@ -138,7 +138,7 @@ class Simulation {
simulationJob?.cancel()
}
private fun gpxSimulation(
fun gpxSimulation(
updateLocation: (Location) -> Unit
) {
Runnable {
@@ -186,7 +186,7 @@ class Simulation {
if (duration > 100) {
// delay(duration / 4)
}
Thread.sleep(500)
Thread.sleep(2000)
lastTime = p.time
lastLocation = fakeLocation
}
@@ -85,6 +85,7 @@ open class NavigationScreen(
private var showAlternativeRoute = false
val observerRecentPlaces = Observer<List<Place>> { newPlaces ->
Log.d(TAG, "RecentPlaces $newPlaces")
recentPlaces.addAll(newPlaces)
if (newPlaces.isNotEmpty() && !tripSuggestionCalled) {
tripSuggestionCalled = true
@@ -99,6 +100,7 @@ open class NavigationScreen(
}
repository.tripSuggestionFlow.asLiveData().observe(this, Observer {
Log.d(TAG, "tripSuggestion $it")
navigationViewModel.recentPlaces.observe(this, observerRecentPlaces)
tripSuggestion = it
})
@@ -519,7 +521,6 @@ open class NavigationScreen(
this.shouldShowLanes = shouldShowLanes
this.junctionImage = junctionImage
this.backGroundColor = backGroundColor
navigationType = NavigationType.NAVIGATION
invalidate()
}