DataStore Manager

This commit is contained in:
Dimitris
2026-02-20 07:20:04 +01:00
parent 65ff41995d
commit ebd97cf1c9
65 changed files with 7975 additions and 13716 deletions

View File

@@ -56,6 +56,7 @@ dependencies {
implementation(libs.androidx.material3)
implementation(libs.androidx.compose.ui.text)
implementation(libs.play.services.location)
implementation(libs.androidx.datastore.core)
androidTestImplementation(libs.androidx.junit)
testImplementation(libs.junit)
}

View File

@@ -2,6 +2,7 @@ package com.kouros.navigation.car
import android.Manifest
import android.annotation.SuppressLint
import android.app.Application
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
@@ -26,6 +27,9 @@ import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.ViewModelStoreOwner
import androidx.lifecycle.lifecycleScope
import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.car.screen.NavigationScreen
import com.kouros.navigation.car.screen.RequestPermissionScreen
@@ -35,13 +39,20 @@ 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.RouteEngine
import com.kouros.navigation.data.datastore.DataStoreManager
import com.kouros.navigation.data.osrm.OsrmRepository
import com.kouros.navigation.data.tomtom.TomTomRepository
import com.kouros.navigation.data.valhalla.ValhallaRepository
import com.kouros.navigation.model.ViewModel
import com.kouros.navigation.model.NavigationViewModel
import com.kouros.navigation.utils.GeoUtils.snapLocation
import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue
import com.kouros.navigation.utils.NavigationUtils.getViewModel
import com.kouros.navigation.utils.getSettingsRepository
import com.kouros.navigation.utils.getSettingsViewModel
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
class NavigationSession : Session(), NavigationScreen.Listener {
@@ -54,7 +65,8 @@ class NavigationSession : Session(), NavigationScreen.Listener {
lateinit var surfaceRenderer: SurfaceRenderer
var mLocationListener: LocationListenerCompat = LocationListenerCompat { location: Location? ->
val useCarLocation = getBooleanKeyValue(carContext, CAR_LOCATION)
val repository = getSettingsRepository(carContext)
val useCarLocation = runBlocking { repository.carLocationFlow.first() }
if (!useCarLocation) {
updateLocation(location!!)
}
@@ -75,7 +87,8 @@ class NavigationSession : Session(), NavigationScreen.Listener {
override fun onDestroy(owner: LifecycleOwner) {
val carInfo = carContext.getCarService(CarHardwareManager::class.java).carInfo
val useCarLocation = getBooleanKeyValue(carContext, CAR_LOCATION)
val repository = getSettingsRepository(carContext)
val useCarLocation = runBlocking { repository.carLocationFlow.first() }
if (useCarLocation) {
val carSensors = carContext.getCarService(CarHardwareManager::class.java).carSensors
carSensors.removeCarHardwareLocationListener(carLocationListener)
@@ -88,8 +101,9 @@ class NavigationSession : Session(), NavigationScreen.Listener {
}
}
lateinit var navigationViewModel: ViewModel
lateinit var navigationViewModel: NavigationViewModel
lateinit var viewModelStoreOwner : ViewModelStoreOwner
val carLocationListener: OnCarDataAvailableListener<CarHardwareLocation?> =
OnCarDataAvailableListener { data ->
if (data.location.status == CarValue.STATUS_SUCCESS) {
@@ -123,22 +137,39 @@ class NavigationSession : Session(), NavigationScreen.Listener {
fun onRoutingEngineStateUpdated(routeEngine : Int) {
navigationViewModel = when (routeEngine) {
RouteEngine.VALHALLA.ordinal -> ViewModel(ValhallaRepository())
RouteEngine.OSRM.ordinal -> ViewModel(OsrmRepository())
else -> ViewModel(TomTomRepository())
RouteEngine.VALHALLA.ordinal -> NavigationViewModel(ValhallaRepository())
RouteEngine.OSRM.ordinal -> NavigationViewModel(OsrmRepository())
else -> NavigationViewModel(TomTomRepository())
}
}
override fun onCreateScreen(intent: Intent): Screen {
viewModelStoreOwner = object : ViewModelStoreOwner {
override val viewModelStore = ViewModelStore()
}
lifecycleScope.launch {
try {
awaitCancellation()
} finally {
viewModelStoreOwner.viewModelStore.clear()
}
}
// lifecycleScope.launch {
//}
navigationViewModel = getViewModel(carContext)
navigationViewModel.routingEngine.observe(this, ::onRoutingEngineStateUpdated)
routeModel = RouteCarModel()
surfaceRenderer = SurfaceRenderer(carContext, lifecycle, routeModel)
surfaceRenderer = SurfaceRenderer(carContext, lifecycle, routeModel, viewModelStoreOwner)
navigationScreen =
NavigationScreen(carContext, surfaceRenderer, routeModel, this, navigationViewModel)
@@ -175,7 +206,8 @@ class NavigationSession : Session(), NavigationScreen.Listener {
fun addSensors() {
val carInfo = carContext.getCarService(CarHardwareManager::class.java).carInfo
val useCarLocation = getBooleanKeyValue(carContext, CAR_LOCATION)
val repository = getSettingsRepository(carContext)
val useCarLocation = runBlocking { repository.carLocationFlow.first() }
if (useCarLocation) {
val carSensors = carContext.getCarService(CarHardwareManager::class.java).carSensors
carSensors.addCompassListener(CarSensors.UPDATE_RATE_NORMAL,
@@ -269,8 +301,8 @@ class NavigationSession : Session(), NavigationScreen.Listener {
}
}
override fun stopNavigation() {
routeModel.stopNavigation()
override fun stopNavigation(context: CarContext) {
routeModel.stopNavigation(context)
}

View File

@@ -14,6 +14,7 @@ import androidx.car.app.connection.CarConnection
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.platform.ComposeView
@@ -21,6 +22,7 @@ import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModelStoreOwner
import androidx.lifecycle.setViewTreeLifecycleOwner
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
import com.kouros.navigation.car.map.DrawNavigationImages
@@ -29,21 +31,23 @@ import com.kouros.navigation.car.map.cameraState
import com.kouros.navigation.car.map.getPaddingValues
import com.kouros.navigation.car.map.rememberBaseStyle
import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.data.Constants
import com.kouros.navigation.data.Constants.ROUTING_ENGINE
import com.kouros.navigation.data.Constants.homeVogelhart
import com.kouros.navigation.data.ObjectBox
import com.kouros.navigation.data.RouteEngine
import com.kouros.navigation.data.tomtom.TrafficData
import com.kouros.navigation.model.BaseStyleModel
import com.kouros.navigation.model.RouteModel
import com.kouros.navigation.utils.NavigationUtils.getIntKeyValue
import com.kouros.navigation.utils.bearing
import com.kouros.navigation.utils.calculateTilt
import com.kouros.navigation.utils.calculateZoom
import com.kouros.navigation.utils.duration
import com.kouros.navigation.utils.getSettingsRepository
import com.kouros.navigation.utils.getSettingsViewModel
import com.kouros.navigation.utils.location
import com.kouros.navigation.utils.previewZoom
import com.kouros.navigation.utils.settingsViewModel
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import org.maplibre.compose.camera.CameraPosition
import org.maplibre.compose.camera.CameraState
import org.maplibre.compose.style.BaseStyle
@@ -52,7 +56,8 @@ import org.maplibre.spatialk.geojson.Position
class SurfaceRenderer(
private var carContext: CarContext, lifecycle: Lifecycle,
private var routeModel: RouteCarModel
private var routeModel: RouteCarModel,
private var viewModelStoreOwner: ViewModelStoreOwner
) : DefaultLifecycleObserver {
var lastLocation = location(0.0, 0.0)
@@ -187,9 +192,12 @@ class SurfaceRenderer(
@Composable
fun MapView() {
val darkMode = getIntKeyValue(carContext, Constants.DARK_MODE_SETTINGS)
val baseStyle = BaseStyleModel().readStyle(carContext, darkMode, carContext.isDarkMode)
//val appViewModel: AppViewModel = appViewModel(viewModelStoreOwner)
//val darkMode by appViewModel.darkMode.collectAsState()
val darkMode = settingsViewModel(carContext, viewModelStoreOwner).darkMode.collectAsState().value
val baseStyle = BaseStyleModel().readStyle(carContext, darkMode, carContext.isDarkMode)
val position: CameraPosition? by cameraPosition.observeAsState()
val route: String? by routeData.observeAsState()
val traffic: Map<String, String> ? by trafficData.observeAsState()
@@ -197,7 +205,17 @@ class SurfaceRenderer(
val paddingValues = getPaddingValues(height, viewStyle)
val cameraState = cameraState(paddingValues, position, tilt)
val rememberBaseStyle = rememberBaseStyle(baseStyle)
MapLibre(carContext, cameraState, rememberBaseStyle, route, traffic, viewStyle, speedCameras)
MapLibre(
carContext,
cameraState,
rememberBaseStyle,
route,
traffic,
viewStyle,
speedCameras,
false
)
ShowPosition(cameraState, position, paddingValues)
}
@@ -339,7 +357,8 @@ class SurfaceRenderer(
}
fun updateCarLocation(location: Location) {
val routingEngine = getIntKeyValue(carContext, ROUTING_ENGINE)
val repository = getSettingsRepository(carContext)
val routingEngine = runBlocking { repository.routingEngineFlow.first() }
if (routingEngine == RouteEngine.OSRM.ordinal) {
updateLocation(location)
}

View File

@@ -26,15 +26,18 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.kouros.data.R
import com.kouros.navigation.car.ViewStyle
import com.kouros.navigation.data.Constants
import com.kouros.navigation.data.Constants.SHOW_THREED_BUILDING
import com.kouros.navigation.data.NavigationColor
import com.kouros.navigation.data.RouteColor
import com.kouros.navigation.data.SpeedColor
import com.kouros.navigation.data.datastore.DataStoreManager
import com.kouros.navigation.model.RouteModel
import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue
import com.kouros.navigation.model.SettingsViewModel
import com.kouros.navigation.repository.SettingsRepository
import org.maplibre.compose.camera.CameraPosition
import org.maplibre.compose.camera.CameraState
import org.maplibre.compose.camera.rememberCameraState
@@ -92,7 +95,8 @@ fun MapLibre(
route: String?,
traffic: Map<String, String>?,
viewStyle: ViewStyle,
speedCameras: String? = ""
speedCameras: String? = "",
showBuildings: Boolean
) {
MaplibreMap(
options = MapOptions(
@@ -103,7 +107,7 @@ fun MapLibre(
baseStyle = baseStyle
) {
getBaseSource(id = "openmaptiles")?.let { tiles ->
if (!getBooleanKeyValue(context = context, SHOW_THREED_BUILDING)) {
if (!showBuildings) {
BuildingLayer(tiles)
}
if (viewStyle == ViewStyle.AMENITY_VIEW) {
@@ -553,3 +557,4 @@ fun PuckState(cameraState: CameraState, userLocationState: UserLocationState) {
)
}

View File

@@ -1,6 +1,5 @@
package com.kouros.navigation.car.screen
import android.location.Location
import androidx.car.app.CarContext
import androidx.car.app.Screen
import androidx.car.app.model.Action
@@ -14,17 +13,16 @@ import androidx.core.graphics.drawable.IconCompat
import com.kouros.data.R
import com.kouros.navigation.car.SurfaceRenderer
import com.kouros.navigation.car.ViewStyle
import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.data.Category
import com.kouros.navigation.data.Constants.CHARGING_STATION
import com.kouros.navigation.data.Constants.FUEL_STATION
import com.kouros.navigation.data.Constants.PHARMACY
import com.kouros.navigation.model.ViewModel
import com.kouros.navigation.model.NavigationViewModel
class CategoriesScreen(
private val carContext: CarContext,
private val surfaceRenderer: SurfaceRenderer,
private val viewModel: ViewModel,
private val navigationViewModel: NavigationViewModel,
) : Screen(carContext) {
var categories: List<Category> = listOf(
@@ -48,7 +46,7 @@ class CategoriesScreen(
carContext,
surfaceRenderer,
it.id,
viewModel
navigationViewModel
)
) { obj: Any? ->
if (obj != null) {

View File

@@ -1,6 +1,5 @@
package com.kouros.navigation.car.screen
import android.location.Location
import androidx.annotation.DrawableRes
import androidx.car.app.CarContext
import androidx.car.app.Screen
@@ -19,11 +18,10 @@ import androidx.lifecycle.Observer
import com.kouros.data.R
import com.kouros.navigation.car.SurfaceRenderer
import com.kouros.navigation.car.navigation.NavigationMessage
import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.data.Constants
import com.kouros.navigation.data.Place
import com.kouros.navigation.data.overpass.Elements
import com.kouros.navigation.model.ViewModel
import com.kouros.navigation.model.NavigationViewModel
import com.kouros.navigation.utils.GeoUtils.createPointCollection
import com.kouros.navigation.utils.location
import com.kouros.navigation.utils.round
@@ -33,7 +31,7 @@ class CategoryScreen(
private val carContext: CarContext,
private val surfaceRenderer: SurfaceRenderer,
private val category: String,
private val viewModel: ViewModel,
private val navigationViewModel: NavigationViewModel,
) : Screen(carContext) {
var elements = listOf<Elements>()
@@ -57,8 +55,8 @@ class CategoryScreen(
}
init {
viewModel.elements.observe(this, observer)
viewModel.getAmenities(category, surfaceRenderer.lastLocation)
navigationViewModel.elements.observe(this, observer)
navigationViewModel.getAmenities(category, surfaceRenderer.lastLocation)
}
@@ -130,7 +128,7 @@ class CategoryScreen(
row.addAction(
Action.Builder()
.setOnClickListener {
viewModel.loadRoute(
navigationViewModel.loadRoute(
carContext,
currentLocation = surfaceRenderer.lastLocation,
location(it.lon!!, it.lat!!),

View File

@@ -10,23 +10,27 @@ import androidx.car.app.model.ListTemplate
import androidx.car.app.model.Row
import androidx.car.app.model.SectionedItemList
import androidx.car.app.model.Template
import androidx.lifecycle.lifecycleScope
import com.kouros.data.R
import com.kouros.navigation.data.Constants.DARK_MODE_SETTINGS
import com.kouros.navigation.data.Constants.SHOW_THREED_BUILDING
import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue
import com.kouros.navigation.utils.NavigationUtils.getIntKeyValue
import com.kouros.navigation.utils.NavigationUtils.setBooleanKeyValue
import com.kouros.navigation.utils.NavigationUtils.setIntKeyValue
import com.kouros.navigation.utils.getSettingsViewModel
import kotlinx.coroutines.launch
class DarkModeSettings(private val carContext: CarContext) : Screen(carContext) {
private var darkModeSettings = 0
val settingsViewModel = getSettingsViewModel(carContext)
init {
darkModeSettings = getIntKeyValue(carContext, DARK_MODE_SETTINGS)
lifecycleScope.launch {
settingsViewModel.darkMode.collect {
invalidate()
}
}
}
override fun onGetTemplate(): Template {
darkModeSettings = settingsViewModel.darkMode.value
val templateBuilder = ListTemplate.Builder()
val radioList =
ItemList.Builder()
@@ -52,10 +56,12 @@ class DarkModeSettings(private val carContext: CarContext) : Screen(carContext)
.build()
return templateBuilder
.addSectionedList(SectionedItemList.create(
radioList,
carContext.getString(R.string.dark_mode)
))
.addSectionedList(
SectionedItemList.create(
radioList,
carContext.getString(R.string.dark_mode)
)
)
.setHeader(
Header.Builder()
.setTitle(carContext.getString(R.string.dark_mode))
@@ -67,7 +73,7 @@ class DarkModeSettings(private val carContext: CarContext) : Screen(carContext)
private fun onSelected(index: Int) {
setIntKeyValue(carContext, index, DARK_MODE_SETTINGS)
settingsViewModel.onDarkModeChanged(index)
CarToast.makeText(
carContext,
(carContext

View File

@@ -6,33 +6,34 @@ import androidx.car.app.model.Action
import androidx.car.app.model.Header
import androidx.car.app.model.ItemList
import androidx.car.app.model.ListTemplate
import androidx.car.app.model.OnClickListener
import androidx.car.app.model.Row
import androidx.car.app.model.Template
import androidx.car.app.model.Toggle
import androidx.lifecycle.lifecycleScope
import com.kouros.data.R
import com.kouros.navigation.data.Constants.SHOW_THREED_BUILDING
import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue
import com.kouros.navigation.utils.NavigationUtils.setBooleanKeyValue
import com.kouros.navigation.utils.getSettingsViewModel
import kotlinx.coroutines.launch
class DisplaySettings(private val carContext: CarContext) : Screen(carContext) {
private var buildingToggleState = false
val settingsViewModel = getSettingsViewModel(carContext)
init {
buildingToggleState = getBooleanKeyValue(carContext, SHOW_THREED_BUILDING)
lifecycleScope.launch {
settingsViewModel.threedBuilding.collect {
invalidate()
}
}
}
override fun onGetTemplate(): Template {
buildingToggleState = settingsViewModel.threedBuilding.value
val listBuilder = ItemList.Builder()
val buildingToggle: Toggle =
Toggle.Builder { checked: Boolean ->
if (checked) {
setBooleanKeyValue(carContext, true, SHOW_THREED_BUILDING)
} else {
setBooleanKeyValue(carContext, false, SHOW_THREED_BUILDING)
}
settingsViewModel.onThreedBuildingChanged(checked)
buildingToggleState = !buildingToggleState
}.setChecked(buildingToggleState).build()
listBuilder.addItem(buildRowForTemplate(R.string.threed_building, buildingToggle))

View File

@@ -22,6 +22,7 @@ import androidx.car.app.navigation.model.NavigationTemplate
import androidx.car.app.navigation.model.RoutingInfo
import androidx.core.graphics.drawable.IconCompat
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import com.kouros.data.R
import com.kouros.navigation.car.SurfaceRenderer
import com.kouros.navigation.car.ViewStyle
@@ -29,11 +30,18 @@ import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.data.Constants
import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE
import com.kouros.navigation.data.Place
import com.kouros.navigation.data.datastore.DataStoreManager
import com.kouros.navigation.data.nominatim.SearchResult
import com.kouros.navigation.data.overpass.Elements
import com.kouros.navigation.model.ViewModel
import com.kouros.navigation.model.NavigationViewModel
import com.kouros.navigation.repository.SettingsRepository
import com.kouros.navigation.utils.GeoUtils
import com.kouros.navigation.utils.getSettingsViewModel
import com.kouros.navigation.utils.location
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.time.Duration
import java.time.LocalDateTime
import java.time.ZoneOffset
import kotlin.math.absoluteValue
@@ -43,21 +51,21 @@ class NavigationScreen(
private var surfaceRenderer: SurfaceRenderer,
private var routeModel: RouteCarModel,
private var listener: Listener,
private val viewModel: ViewModel
private val navigationViewModel: NavigationViewModel
) :
Screen(carContext) {
/** A listener for navigation start and stop signals. */
interface Listener {
/** Stops navigation. */
fun stopNavigation()
fun stopNavigation(context: CarContext)
}
var currentNavigationLocation = Location(LocationManager.GPS_PROVIDER)
var recentPlace = Place()
var navigationType = NavigationType.VIEW
var lastTrafficDate = LocalDateTime.of(1960, 6, 21, 0, 0)
var lastTrafficDate: LocalDateTime? = LocalDateTime.of(1960, 6, 21, 0, 0)
val observer = Observer<String> { route ->
if (route.isNotEmpty()) {
navigationType = NavigationType.NAVIGATION
@@ -99,7 +107,7 @@ class NavigationScreen(
speedCameras = cameras
val coordinates = mutableListOf<List<Double>>()
cameras.forEach {
coordinates.add(listOf(it.lon!!, it.lat!!))
coordinates.add(listOf(it.lon, it.lat))
}
val speedData = GeoUtils.createPointCollection(coordinates, "radar")
surfaceRenderer.speedCamerasData.value = speedData
@@ -107,11 +115,15 @@ class NavigationScreen(
init {
viewModel.route.observe(this, observer)
viewModel.traffic.observe(this, trafficObserver);
viewModel.recentPlace.observe(this, recentObserver)
viewModel.placeLocation.observe(this, placeObserver)
viewModel.speedCameras.observe(this, speedObserver)
navigationViewModel.route.observe(this, observer)
navigationViewModel.traffic.observe(this, trafficObserver);
navigationViewModel.recentPlace.observe(this, recentObserver)
navigationViewModel.placeLocation.observe(this, placeObserver)
navigationViewModel.speedCameras.observe(this, speedObserver)
lifecycleScope.launch {
getSettingsViewModel(carContext).routingEngine.collect {
}
}
}
override fun onGetTemplate(): Template {
@@ -306,7 +318,7 @@ class NavigationScreen(
)
.setOnClickListener {
val navigateTo = location(recentPlace.longitude, recentPlace.latitude)
viewModel.loadRoute(
navigationViewModel.loadRoute(
carContext,
surfaceRenderer.lastLocation,
navigateTo,
@@ -349,7 +361,7 @@ class NavigationScreen(
return Action.Builder()
.setIcon(routeModel.createCarIcon(carContext, R.drawable.settings_48px))
.setOnClickListener {
screenManager.push(SettingsScreen(carContext, viewModel))
screenManager.push(SettingsScreen(carContext, navigationViewModel))
}
.build()
}
@@ -411,13 +423,13 @@ class NavigationScreen(
SearchScreen(
carContext,
surfaceRenderer,
viewModel
navigationViewModel
)
) { obj: Any? ->
if (obj != null) {
val place = obj as Place
if (place.longitude == 0.0) {
viewModel.findAddress(
navigationViewModel.findAddress(
"${obj.city} ${obj.street}},",
currentNavigationLocation
)
@@ -432,9 +444,9 @@ class NavigationScreen(
fun navigateToPlace(place: Place) {
navigationType = NavigationType.VIEW
val location = location(place.longitude, place.latitude)
viewModel.saveRecent(place)
navigationViewModel.saveRecent(place)
currentNavigationLocation = location
viewModel.loadRoute(
navigationViewModel.loadRoute(
carContext,
surfaceRenderer.lastLocation,
location,
@@ -446,7 +458,7 @@ class NavigationScreen(
fun stopNavigation() {
navigationType = NavigationType.VIEW
listener.stopNavigation()
listener.stopNavigation(carContext)
surfaceRenderer.routeData.value = ""
lastCameraSearch = 0
invalidate()
@@ -470,7 +482,7 @@ class NavigationScreen(
fun reRoute(destination: Place) {
val dest = location(destination.longitude, destination.latitude)
viewModel.loadRoute(
navigationViewModel.loadRoute(
carContext,
surfaceRenderer.lastLocation,
dest,
@@ -480,14 +492,14 @@ class NavigationScreen(
fun updateTrip(location: Location) {
val current = LocalDateTime.now(ZoneOffset.UTC)
val duration = java.time.Duration.between(current, lastTrafficDate)
val duration = Duration.between(current, lastTrafficDate)
if (duration.abs().seconds > 360) {
lastTrafficDate = current
viewModel.loadTraffic(carContext, location, surfaceRenderer.carOrientation)
navigationViewModel.loadTraffic(carContext, location, surfaceRenderer.carOrientation)
}
updateSpeedCamera(location)
with(routeModel) {
updateLocation(location, viewModel)
updateLocation(carContext,location, navigationViewModel)
if ((navState.maneuverType == Maneuver.TYPE_DESTINATION
|| navState.maneuverType == Maneuver.TYPE_DESTINATION_LEFT
|| navState.maneuverType == Maneuver.TYPE_DESTINATION_RIGHT
@@ -506,7 +518,7 @@ class NavigationScreen(
private fun updateSpeedCamera(location: Location) {
if (lastCameraSearch++ % 100 == 0) {
viewModel.getSpeedCameras(location, 5.0)
navigationViewModel.getSpeedCameras(location, 5.0)
}
if (speedCameras.isNotEmpty()) {
updateDistance(location)

View File

@@ -9,16 +9,14 @@ import androidx.car.app.model.ListTemplate
import androidx.car.app.model.Row
import androidx.car.app.model.Template
import androidx.car.app.model.Toggle
import androidx.lifecycle.lifecycleScope
import com.kouros.data.R
import com.kouros.navigation.data.Constants.AVOID_MOTORWAY
import com.kouros.navigation.data.Constants.AVOID_TOLLWAY
import com.kouros.navigation.data.Constants.CAR_LOCATION
import com.kouros.navigation.model.ViewModel
import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue
import com.kouros.navigation.utils.NavigationUtils.setBooleanKeyValue
import com.kouros.navigation.model.NavigationViewModel
import com.kouros.navigation.utils.getSettingsViewModel
import kotlinx.coroutines.launch
class NavigationSettings(private val carContext: CarContext, private var viewModel: ViewModel) :
class NavigationSettings(private val carContext: CarContext, private var navigationViewModel: NavigationViewModel) :
Screen(carContext) {
private var motorWayToggleState = false
@@ -27,25 +25,25 @@ class NavigationSettings(private val carContext: CarContext, private var viewMod
private var carLocationToggleState = false
val settingsViewModel = getSettingsViewModel(carContext)
init {
motorWayToggleState = getBooleanKeyValue(carContext, AVOID_MOTORWAY)
tollWayToggleState = getBooleanKeyValue(carContext, AVOID_MOTORWAY)
carLocationToggleState = getBooleanKeyValue(carContext, CAR_LOCATION)
lifecycleScope.launch {
settingsViewModel.avoidTollway.collect {
invalidate()
}
}
}
override fun onGetTemplate(): Template {
motorWayToggleState = settingsViewModel.avoidMotorway.value
tollWayToggleState = settingsViewModel.avoidTollway.value
carLocationToggleState = settingsViewModel.carLocation.value
val listBuilder = ItemList.Builder()
val highwayToggle: Toggle =
Toggle.Builder { checked: Boolean ->
if (checked) {
setBooleanKeyValue(carContext, true, AVOID_MOTORWAY)
} else {
setBooleanKeyValue(carContext, false, AVOID_MOTORWAY)
}
settingsViewModel.onAvoidMotorway(checked)
motorWayToggleState = !motorWayToggleState
}.setChecked(motorWayToggleState).build()
listBuilder.addItem(buildRowForTemplate(R.string.avoid_highways_row_title, highwayToggle))
@@ -53,22 +51,14 @@ class NavigationSettings(private val carContext: CarContext, private var viewMod
// Tollway
val tollwayToggle: Toggle =
Toggle.Builder { checked: Boolean ->
if (checked) {
setBooleanKeyValue(carContext, true, AVOID_TOLLWAY)
} else {
setBooleanKeyValue(carContext, false, AVOID_TOLLWAY)
}
settingsViewModel.onAvoidTollway(checked)
tollWayToggleState = !tollWayToggleState
}.setChecked(tollWayToggleState).build()
listBuilder.addItem(buildRowForTemplate(R.string.avoid_tolls_row_title, tollwayToggle))
val carLocationToggle: Toggle =
Toggle.Builder { checked: Boolean ->
if (checked) {
setBooleanKeyValue(carContext, true, CAR_LOCATION)
} else {
setBooleanKeyValue(carContext, false, CAR_LOCATION)
}
settingsViewModel.onCarLocation(checked)
carLocationToggleState = !carLocationToggleState
}.setChecked(carLocationToggleState).build()
@@ -81,7 +71,7 @@ class NavigationSettings(private val carContext: CarContext, private var viewMod
listBuilder.addItem(
buildRowForScreenTemplate(
RoutingSettings(carContext, viewModel),
RoutingSettings(carContext, navigationViewModel),
R.string.routing_engine
)
)

View File

@@ -1,6 +1,5 @@
package com.kouros.navigation.car.screen
import android.location.Location
import android.net.Uri
import android.text.Spannable
import android.text.SpannableString
@@ -25,14 +24,14 @@ import com.kouros.navigation.data.Constants.CONTACTS
import com.kouros.navigation.data.Constants.FAVORITES
import com.kouros.navigation.data.Constants.RECENT
import com.kouros.navigation.data.Place
import com.kouros.navigation.model.ViewModel
import com.kouros.navigation.model.NavigationViewModel
class PlaceListScreen(
private val carContext: CarContext,
private val surfaceRenderer: SurfaceRenderer,
private val category: String,
private val viewModel: ViewModel
private val navigationViewModel: NavigationViewModel
) : Screen(carContext) {
var places = listOf<Place>()
@@ -49,30 +48,30 @@ class PlaceListScreen(
init {
if (category == RECENT) {
viewModel.places.observe(this, observer)
navigationViewModel.places.observe(this, observer)
}
if (category == CONTACTS) {
viewModel.contactAddress.observe(this, observerAddress)
navigationViewModel.contactAddress.observe(this, observerAddress)
}
if (category == FAVORITES) {
viewModel.favorites.observe(this, observer)
navigationViewModel.favorites.observe(this, observer)
}
loadPlaces()
}
fun loadPlaces() {
if (category == RECENT) {
viewModel.loadRecentPlaces(
navigationViewModel.loadRecentPlaces(
carContext,
surfaceRenderer.lastLocation,
surfaceRenderer.carOrientation
)
}
if (category == CONTACTS) {
viewModel.loadContacts(carContext)
navigationViewModel.loadContacts(carContext)
}
if (category == FAVORITES) {
viewModel.loadFavorites(
navigationViewModel.loadFavorites(
carContext,
surfaceRenderer.lastLocation,
surfaceRenderer.carOrientation
@@ -110,7 +109,7 @@ class PlaceListScreen(
carContext,
surfaceRenderer,
place,
viewModel
navigationViewModel
)
) { obj: Any? ->
if (obj != null) {
@@ -163,7 +162,7 @@ class PlaceListScreen(
)
)
.setOnClickListener {
viewModel.deletePlace(place)
navigationViewModel.deletePlace(place)
CarToast.makeText(
carContext,
R.string.recent_Item_deleted, CarToast.LENGTH_LONG

View File

@@ -6,7 +6,6 @@ import androidx.annotation.DrawableRes
import androidx.car.app.CarContext
import androidx.car.app.CarToast
import androidx.car.app.Screen
import androidx.car.app.constraints.ConstraintManager
import androidx.car.app.model.Action
import androidx.car.app.model.Action.FLAG_DEFAULT
import androidx.car.app.model.ActionStrip
@@ -29,7 +28,7 @@ import com.kouros.navigation.car.SurfaceRenderer
import com.kouros.navigation.car.navigation.NavigationMessage
import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.data.Place
import com.kouros.navigation.model.ViewModel
import com.kouros.navigation.model.NavigationViewModel
import com.kouros.navigation.utils.location
import java.math.BigDecimal
import java.math.RoundingMode
@@ -39,7 +38,7 @@ class RoutePreviewScreen(
carContext: CarContext,
private var surfaceRenderer: SurfaceRenderer,
private var destination: Place,
private val viewModel: ViewModel
private val navigationViewModel: NavigationViewModel
) :
Screen(carContext) {
private var isFavorite = false
@@ -56,9 +55,9 @@ class RoutePreviewScreen(
}
init {
viewModel.previewRoute.observe(this, observer)
navigationViewModel.previewRoute.observe(this, observer)
val location = location(destination.longitude, destination.latitude)
viewModel.loadPreviewRoute(
navigationViewModel.loadPreviewRoute(
carContext,
surfaceRenderer.lastLocation,
location,
@@ -164,7 +163,7 @@ class RoutePreviewScreen(
CarToast.LENGTH_SHORT
)
.show()
viewModel.saveFavorite(destination)
navigationViewModel.saveFavorite(destination)
invalidate()
}
.build()
@@ -172,7 +171,7 @@ class RoutePreviewScreen(
private fun deleteFavoriteAction(): Action = Action.Builder()
.setOnClickListener {
if (isFavorite) {
viewModel.deleteFavorite(destination)
navigationViewModel.deleteFavorite(destination)
}
isFavorite = !isFavorite
finish()

View File

@@ -10,28 +10,28 @@ import androidx.car.app.model.ListTemplate
import androidx.car.app.model.Row
import androidx.car.app.model.SectionedItemList
import androidx.car.app.model.Template
import androidx.car.app.model.Toggle
import androidx.lifecycle.lifecycleScope
import com.kouros.data.R
import com.kouros.navigation.data.Constants.AVOID_MOTORWAY
import com.kouros.navigation.data.Constants.CAR_LOCATION
import com.kouros.navigation.data.Constants.ROUTING_ENGINE
import com.kouros.navigation.data.RouteEngine
import com.kouros.navigation.model.ViewModel
import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue
import com.kouros.navigation.utils.NavigationUtils.getIntKeyValue
import com.kouros.navigation.utils.NavigationUtils.setBooleanKeyValue
import com.kouros.navigation.utils.NavigationUtils.setIntKeyValue
import com.kouros.navigation.model.NavigationViewModel
import com.kouros.navigation.utils.getSettingsViewModel
import kotlinx.coroutines.launch
class RoutingSettings(private val carContext: CarContext, private var viewModel: ViewModel) : Screen(carContext) {
class RoutingSettings(private val carContext: CarContext, private var navigationViewModel: NavigationViewModel) : Screen(carContext) {
private var routingEngine = RouteEngine.OSRM.ordinal
val settingsViewModel = getSettingsViewModel(carContext)
init {
routingEngine = getIntKeyValue(carContext, ROUTING_ENGINE)
lifecycleScope.launch {
settingsViewModel.routingEngine.collect {
invalidate()
}
}
}
override fun onGetTemplate(): Template {
routingEngine = settingsViewModel.routingEngine.value
val templateBuilder = ListTemplate.Builder()
val radioList =
ItemList.Builder()
@@ -71,8 +71,8 @@ class RoutingSettings(private val carContext: CarContext, private var viewModel:
}
private fun onSelected(index: Int) {
setIntKeyValue(carContext, index, ROUTING_ENGINE)
viewModel.routingEngine.value = index
settingsViewModel.onRoutingEngineChanged(index)
navigationViewModel.routingEngine.value = index
CarToast.makeText(
carContext,
(carContext

View File

@@ -1,7 +1,6 @@
package com.kouros.navigation.car.screen
import android.annotation.SuppressLint
import android.location.Location
import androidx.car.app.CarContext
import androidx.car.app.Screen
import androidx.car.app.model.Action
@@ -16,18 +15,17 @@ import androidx.lifecycle.Observer
import com.kouros.data.R
import com.kouros.navigation.car.SurfaceRenderer
import com.kouros.navigation.car.ViewStyle
import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.data.Category
import com.kouros.navigation.data.Constants
import com.kouros.navigation.data.Place
import com.kouros.navigation.data.nominatim.SearchResult
import com.kouros.navigation.model.ViewModel
import com.kouros.navigation.model.NavigationViewModel
class SearchScreen(
carContext: CarContext,
private var surfaceRenderer: SurfaceRenderer,
private val viewModel: ViewModel,
private val navigationViewModel: NavigationViewModel,
) : Screen(carContext) {
var isSearchComplete: Boolean = false
@@ -47,7 +45,7 @@ class SearchScreen(
}
init {
viewModel.searchPlaces.observe(this, observer)
navigationViewModel.searchPlaces.observe(this, observer)
}
override fun onGetTemplate(): Template {
@@ -71,7 +69,7 @@ class SearchScreen(
CategoriesScreen(
carContext,
surfaceRenderer,
viewModel
navigationViewModel
)
) { obj: Any? ->
surfaceRenderer.viewStyle = ViewStyle.VIEW
@@ -87,7 +85,7 @@ class SearchScreen(
carContext,
surfaceRenderer,
it.id,
viewModel
navigationViewModel
)
) { obj: Any? ->
if (obj != null) {
@@ -115,7 +113,7 @@ class SearchScreen(
object : SearchCallback {
override fun onSearchSubmitted(searchTerm: String) {
isSearchComplete = true
viewModel.searchPlaces(searchTerm, surfaceRenderer.lastLocation)
navigationViewModel.searchPlaces(searchTerm, surfaceRenderer.lastLocation)
}
})
.setHeaderAction(Action.BACK)

View File

@@ -24,12 +24,12 @@ import androidx.car.app.model.ListTemplate
import androidx.car.app.model.Row
import androidx.car.app.model.Template
import com.kouros.data.R
import com.kouros.navigation.model.ViewModel
import com.kouros.navigation.model.NavigationViewModel
/** A screen demonstrating selectable lists. */
class SettingsScreen(
carContext: CarContext,
private var viewModel: ViewModel,
private var navigationViewModel: NavigationViewModel,
) : Screen(carContext) {
override fun onGetTemplate(): Template {
@@ -42,7 +42,7 @@ class SettingsScreen(
)
listBuilder.addItem(
buildRowForTemplate(
NavigationSettings(carContext, viewModel),
NavigationSettings(carContext, navigationViewModel),
R.string.navigation_settings
)
)

View File

@@ -2,7 +2,7 @@ package com.kouros.navigation.car
import com.kouros.navigation.data.valhalla.ValhallaRepository
import com.kouros.navigation.model.RouteModel
import com.kouros.navigation.model.ViewModel
import com.kouros.navigation.model.NavigationViewModel
import org.junit.Test
/**
@@ -12,7 +12,7 @@ import org.junit.Test
class ViewModelTest {
val repo = ValhallaRepository()
val viewModel = ViewModel(repo)
val navigationViewModel = NavigationViewModel(repo)
val model = RouteModel()
@Test