This commit is contained in:
Dimitris
2026-03-23 07:10:26 +01:00
parent d1968cfa68
commit bc8a53a5d8
13 changed files with 78 additions and 59 deletions

View File

@@ -13,8 +13,8 @@ android {
applicationId = "com.kouros.navigation"
minSdk = 33
targetSdk = 36
versionCode = 73
versionName = "0.2.0.73"
versionCode = 76
versionName = "0.2.0.76"
base.archivesName = "navi-$versionName"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

View File

@@ -1,6 +1,7 @@
package com.kouros.navigation.car
import android.location.Location
import android.util.Log
import androidx.car.app.CarContext
import androidx.car.app.connection.CarConnection
import androidx.car.app.hardware.CarHardwareManager
@@ -14,6 +15,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.kouros.navigation.data.Constants.TAG
import com.kouros.navigation.utils.getSettingsRepository
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

View File

@@ -35,6 +35,7 @@ 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.Place
import com.kouros.navigation.data.RouteEngine
import com.kouros.navigation.data.osrm.OsrmRepository
import com.kouros.navigation.data.tomtom.TomTomRepository
@@ -140,7 +141,7 @@ class NavigationSession : Session(), NavigationListener {
* Initializes car hardware sensors if available.
*/
fun onPermissionGranted(permission: Boolean) {
if (::carSensorManager.isInitialized) {
if (::carSensorManager.isInitialized && permission) {
carSensorManager.updateConnectionState(routeModel.navState.carConnection)
}
}
@@ -333,7 +334,7 @@ class NavigationSession : Session(), NavigationListener {
private fun handleNavigateIntent(screenManager: ScreenManager) {
screenManager.popToRoot()
screenManager.pushForResult(
SearchScreen(carContext, surfaceRenderer, navigationViewModel, emptyList())
SearchScreen(carContext, surfaceRenderer, navigationViewModel, mutableListOf())
) { result ->
// Handle search result if needed
}

View File

@@ -68,7 +68,7 @@ class SurfaceRenderer(
var carOrientation = 999F
// Current camera position state for the map
private val cameraPosition = MutableLiveData(
val cameraPosition = MutableLiveData(
CameraPosition(
zoom = 16.0,
target = Position(latitude = homeVogelhart.latitude, longitude = homeVogelhart.longitude)
@@ -392,7 +392,6 @@ class SurfaceRenderer(
* Sets route data for active navigation and switches to VIEW mode.
*/
fun setRouteData() {
println("SetRouteData")
routeData.value = routeModel.curRoute.routeGeoJson
viewStyle = ViewStyle.VIEW
}
@@ -401,7 +400,7 @@ class SurfaceRenderer(
* Updates camera position with new bearing, zoom, and target.
* Posts update to LiveData for UI observation.
*/
private fun updateCameraPosition(bearing: Double, zoom: Double, target: Position, tilt: Double) {
fun updateCameraPosition(bearing: Double, zoom: Double, target: Position, tilt: Double) {
synchronized(this) {
cameraPosition.postValue(
cameraPosition.value!!.copy(
@@ -458,11 +457,6 @@ class SurfaceRenderer(
}
fun updateTrafficData(routeModel: RouteCarModel) {
}
/**
* Displays a specific location (e.g., amenity/POI) on the map.
*/

View File

@@ -4,11 +4,9 @@ import android.location.Location
import android.location.LocationManager
import android.os.CountDownTimer
import android.os.Handler
import android.util.Log
import androidx.car.app.CarContext
import androidx.car.app.Screen
import androidx.car.app.model.Action
import androidx.car.app.model.Action.FLAG_DEFAULT
import androidx.car.app.model.Action.FLAG_IS_PERSISTENT
import androidx.car.app.model.ActionStrip
import androidx.car.app.model.CarColor
@@ -40,19 +38,21 @@ import com.kouros.navigation.car.screen.observers.NavigationObserverManager
import com.kouros.navigation.car.screen.settings.SettingsScreen
import com.kouros.navigation.data.Constants
import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE
import com.kouros.navigation.data.Constants.ROUTE_UPDATE
import com.kouros.navigation.data.Constants.TILT
import com.kouros.navigation.data.Constants.TRAFFIC_UPDATE
import com.kouros.navigation.data.Place
import com.kouros.navigation.data.overpass.Elements
import com.kouros.navigation.model.NavigationViewModel
import com.kouros.navigation.model.RouteModel
import com.kouros.navigation.utils.GeoUtils
import com.kouros.navigation.utils.calculateZoom
import com.kouros.navigation.utils.formattedDistance
import com.kouros.navigation.utils.getSettingsRepository
import com.kouros.navigation.utils.getSettingsViewModel
import com.kouros.navigation.utils.location
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import org.maplibre.spatialk.geojson.Position
import java.time.Duration
import java.time.LocalDateTime
import java.time.ZoneOffset
@@ -74,14 +74,14 @@ open class NavigationScreen(
var currentNavigationLocation = Location(LocationManager.GPS_PROVIDER)
var recentPlaces = emptyList<Place>()
var recentPlaces = mutableListOf<Place>()
var recentPlace: Place = Place()
var navigationType = NavigationType.VIEW
var lastTrafficDate: LocalDateTime = LocalDateTime.MIN
var lastRouteDate: LocalDateTime = LocalDateTime.MIN
var lastRouteDate: LocalDateTime = LocalDateTime.now()
var lastCameraSearch = 0
var speedCameras = listOf<Elements>()
val observerManager = NavigationObserverManager(navigationViewModel, this)
@@ -103,7 +103,7 @@ open class NavigationScreen(
private var reRouteTimer: CountDownTimer? = null
val observerRecentPlaces = Observer<List<Place>> { newPlaces ->
recentPlaces = newPlaces
recentPlaces.addAll(newPlaces)
if (newPlaces.isNotEmpty() && !tripSuggestionCalled) {
tripSuggestionCalled = true
navigationType = NavigationType.RECENT
@@ -147,8 +147,7 @@ open class NavigationScreen(
createAction(
carContext,
R.drawable.search_48px,
FLAG_IS_PERSISTENT,
onClickAction = { startSearchScreen()}
onClickAction = { startSearchScreen() }
)
}, { settingsAction() })
return when (navigationType) {
@@ -165,7 +164,11 @@ open class NavigationScreen(
*/
private fun navigationTemplate(actionStripBuilder: ActionStrip.Builder): Template {
actionStripBuilder.addAction(
createAction(carContext, R.drawable.ic_close_white_24dp, FLAG_IS_PERSISTENT,{ stopNavigation() })
createAction(
carContext,
R.drawable.ic_close_white_24dp,
0,
{ stopNavigation() })
)
updateTrip()
return NavigationTemplate.Builder()
@@ -179,8 +182,8 @@ open class NavigationScreen(
surfaceRenderer.viewStyle,
{ zoomPlus() }, { zoomMinus() }, {
createAction(
carContext = carContext, R.drawable.ic_zoom_out_24,
FLAG_IS_PERSISTENT,
carContext = carContext, R.drawable.ic_pan_24,
0,
onClickAction = {
surfaceRenderer.viewStyle = ViewStyle.VIEW
invalidate()
@@ -204,7 +207,8 @@ open class NavigationScreen(
surfaceRenderer.viewStyle,
{ zoomPlus() }, { zoomMinus() }, {
createAction(
carContext = carContext, R.drawable.ic_zoom_out_24,
carContext = carContext, R.drawable.ic_pan_24,
0,
onClickAction = {
surfaceRenderer.viewStyle = ViewStyle.VIEW
invalidate()
@@ -264,7 +268,8 @@ open class NavigationScreen(
surfaceRenderer.viewStyle,
{ zoomPlus() }, { zoomMinus() }, {
createAction(
carContext = carContext, R.drawable.ic_zoom_out_24,
carContext = carContext, R.drawable.ic_pan_24,
0,
onClickAction = {
surfaceRenderer.viewStyle = ViewStyle.VIEW
invalidate()
@@ -286,7 +291,7 @@ open class NavigationScreen(
createAction(
carContext,
R.drawable.search_48px,
FLAG_IS_PERSISTENT,
0,
{ startSearchScreen() })
},
{ settingsAction() })
@@ -323,7 +328,13 @@ open class NavigationScreen(
mapActionStrip(
ViewStyle.VIEW,
{ settingsAction() },
{ createAction(carContext, R.drawable.search_48px, FLAG_IS_PERSISTENT,{ startSearchScreen() }) },
{
createAction(
carContext,
R.drawable.search_48px,
FLAG_IS_PERSISTENT,
{ startSearchScreen() })
},
{
createAction(
carContext = carContext, R.drawable.ic_zoom_out_24,
@@ -410,9 +421,15 @@ open class NavigationScreen(
* Creates an action to start the settings screen.
*/
private fun settingsAction(): Action {
// return Action.Builder()
// .setIcon(createCarIcon(carContext, R.drawable.settings_48px))
// .setOnClickListener {
// screenManager.push(SettingsScreen(carContext, navigationViewModel))
// }
// .build()
return createAction(
carContext, R.drawable.settings_48px,
FLAG_IS_PERSISTENT,
0,
onClickAction = {
screenManager.push(SettingsScreen(carContext, navigationViewModel))
}
@@ -425,7 +442,7 @@ open class NavigationScreen(
private fun zoomPlus(): Action {
return createAction(
carContext, R.drawable.ic_zoom_in_24,
FLAG_IS_PERSISTENT,
0,
onClickAction = {
surfaceRenderer.handleScale(1)
invalidate()
@@ -439,6 +456,7 @@ open class NavigationScreen(
private fun zoomMinus(): Action {
return createAction(
carContext, R.drawable.ic_zoom_out_24,
0,
onClickAction = {
surfaceRenderer.handleScale(-1)
invalidate()
@@ -497,6 +515,12 @@ open class NavigationScreen(
}
routeModel.navState = routeModel.navState.copy(destination = place)
surfaceRenderer.viewStyle = ViewStyle.VIEW
surfaceRenderer.updateCameraPosition(
0.0,
16.0,
Position(surfaceRenderer.lastLocation.longitude, surfaceRenderer.lastLocation.latitude),
TILT
)
invalidate()
}
@@ -550,7 +574,7 @@ open class NavigationScreen(
*/
fun updateTrip(location: Location) {
val current = LocalDateTime.now(ZoneOffset.UTC)
//checkRoute(current, location)
checkRoute(current, location)
checkTraffic(current, location)
updateSpeedCamera(location)
@@ -566,7 +590,8 @@ open class NavigationScreen(
*/
private fun checkRoute(current: LocalDateTime, location: Location) {
val duration = Duration.between(current, lastRouteDate)
if (duration.abs().seconds > ROUTE_UPDATE) {
val routeUpdate = routeModel.curRoute.summary.duration / 6
if (duration.abs().seconds > routeUpdate) {
lastRouteDate = current
val destination = location(
routeModel.navState.destination.longitude,
@@ -706,10 +731,11 @@ open class NavigationScreen(
* Update route and traffic data
*/
private fun updateRoute(route: String) {
val routeModel = RouteModel()
routeModel.navState = routeModel.navState.copy(routingEngine = routingEngine)
val newRouteModel = RouteModel()
newRouteModel.navState = routeModel.navState.copy(routingEngine = routingEngine)
navigationType = NavigationType.NAVIGATION
routeModel.startNavigation(route)
newRouteModel.startNavigation(route)
routeModel.curRoute.summary.trafficDelay = newRouteModel.curRoute.summary.trafficDelay
}
/**

View File

@@ -36,15 +36,13 @@ class PlaceListScreen(
private val surfaceRenderer: SurfaceRenderer,
private val category: String,
private val navigationViewModel: NavigationViewModel,
private val recentPlaces: List<Place>,
private val recentPlaces: MutableList<Place>,
) : Screen(carContext) {
val routeModel = RouteCarModel()
var place = Place()
var mPlaces = mutableListOf<Place>()
val repository = getSettingsRepository(carContext)
private var routingEngine = 0
@@ -149,7 +147,7 @@ class PlaceListScreen(
carContext,
R.string.recent_Item_deleted, CarToast.LENGTH_LONG
).show()
mPlaces.remove(place)
recentPlaces.remove(place)
invalidate()
}

View File

@@ -62,7 +62,6 @@ class RoutePreviewScreen(
private var isFavorite = false
val maxListItems: Int = 3
val navigationUtils = NavigationUtils(carContext)
val repository = getSettingsRepository(carContext)
@@ -245,6 +244,7 @@ class RoutePreviewScreen(
private fun zoomMinus(): Action {
return createAction(
carContext, R.drawable.ic_zoom_out_24,
FLAG_IS_PERSISTENT,
onClickAction = {
surfaceRenderer.handleScale(-1)
invalidate()
@@ -355,7 +355,6 @@ class RoutePreviewScreen(
private fun onRouteSelected(index: Int) {
routeModel.navState = routeModel.navState.copy(currentRouteIndex = index)
surfaceRenderer.setPreviewRouteData(routeModel)
surfaceRenderer.updateTrafficData(routeModel)
routeSelected = true
invalidate()
}

View File

@@ -28,7 +28,7 @@ class SearchScreen(
carContext: CarContext,
private var surfaceRenderer: SurfaceRenderer,
private val navigationViewModel: NavigationViewModel,
private val recentPlaces: List<Place>,
private val recentPlaces: MutableList<Place>,
) : Screen(carContext) {
var isSearchComplete: Boolean = false
@@ -52,7 +52,6 @@ class SearchScreen(
}
}
init {
navigationViewModel.searchPlaces.observe(this, observer)
}
@@ -182,6 +181,7 @@ class SearchScreen(
postalCode = result.address.postcode,
distance = result.distance
)
recentPlaces.add(place)
setResult(place)
finish()
}

View File

@@ -31,7 +31,6 @@ class NavigationSettings(
private var ferryToggleState = false
private var carLocationToggleState = false
val settingsViewModel = getSettingsViewModel(carContext)

View File

@@ -130,9 +130,8 @@ object Constants {
const val TRAFFIC_UPDATE = 300
const val ROUTE_UPDATE = 60
const val INSTRUCTION_DISTANCE = 50
const val GMS_CAR_SPEED_PERMISSION = "com.google.android.gms.permission.CAR_SPEED"
const val AUTOMOTIVE_CAR_SPEED_PERMISSION = "android.car.permission.CAR_SPEED"

View File

@@ -105,15 +105,6 @@ data class Route(
}
}
fun nextStep(add: Int): Step {
val nextIndex = currentStepIndex + add
return if (isRouteValid() && nextIndex < legs().first().steps.size) {
legs().first().steps[nextIndex]
} else {
currentStep()
}
}
fun maneuverLocations(): List<Point> {
val waypoints = currentStep().maneuver.waypoints
val points = mutableListOf<Point>()
@@ -123,4 +114,13 @@ data class Route(
}
return points
}
fun nextStep(add: Int): Step {
val nextIndex = currentStepIndex + add
return if (isRouteValid() && nextIndex < legs().first().steps.size) {
legs().first().steps[nextIndex]
} else {
currentStep()
}
}
}

View File

@@ -19,9 +19,9 @@ const val tomtomTrafficUrl = "https://api.tomtom.com/traffic/services/5/incident
private const val tomtomFields =
"{incidents{type,geometry{type,coordinates},properties{iconCategory,events{description}}}}"
const val useLocal = false
const val useLocal = true
const val useLocalTraffic = false
const val useLocalTraffic = true
class TomTomRepository : NavigationRepository() {

View File

@@ -4,6 +4,7 @@ import android.content.Context
import android.location.Location
import android.location.LocationManager
import androidx.car.app.model.Distance
import com.kouros.navigation.data.Constants.TILT
import com.kouros.navigation.data.RouteEngine
import com.kouros.navigation.data.osrm.OsrmRepository
import com.kouros.navigation.data.tomtom.TomTomRepository
@@ -93,7 +94,7 @@ fun calculateTilt(newZoom: Double, tilt: Double): Double =
0.0
} else {
if (tilt == 0.0) {
55.0
TILT
} else {
tilt
}