Testing, Remove ObjectBox
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
package com.kouros.navigation.car
|
||||
|
||||
import android.location.Location
|
||||
import android.location.LocationManager
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.kouros.navigation.utils.GeoUtils
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.maplibre.geojson.Point
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class GeoUtilsTest {
|
||||
|
||||
@Test
|
||||
fun snapLocation() {
|
||||
val location = Location(LocationManager.GPS_PROVIDER)
|
||||
location.latitude = 48.18600
|
||||
location.longitude = 11.57844
|
||||
|
||||
val stepCoordinates = listOf(
|
||||
Point.fromLngLat(11.57841, 48.18557),
|
||||
Point.fromLngLat(11.57844, 48.18566),
|
||||
Point.fromLngLat(11.57848, 48.18595),
|
||||
Point.fromLngLat(11.57848, 48.18604),
|
||||
Point.fromLngLat(11.57857, 48.18696),
|
||||
)
|
||||
val result = GeoUtils.snapLocation(location, stepCoordinates)
|
||||
assertEquals(result.latitude, 48.18599999996868, 0.0001)
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `createCenterLocation calculates center of GeoJSON`() {
|
||||
val geoJson =
|
||||
"""{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[11.0,48.0]},"properties":{}},{"type":"Feature","geometry":{"type":"Point","coordinates":[11.1,48.1]},"properties":{}}]}"""
|
||||
|
||||
val result = GeoUtils.createCenterLocation(geoJson)
|
||||
|
||||
// Center should be roughly halfway between the two points
|
||||
assertEquals(48.05, result.latitude, 0.01)
|
||||
assertEquals(11.05, result.longitude, 0.01)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.kouros.navigation.car
|
||||
|
||||
import android.location.Location
|
||||
import android.location.LocationManager
|
||||
import androidx.car.app.navigation.model.Maneuver
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.kouros.data.R
|
||||
import com.kouros.navigation.data.Constants.homeHohenwaldeck
|
||||
import com.kouros.navigation.data.Constants.homeVogelhart
|
||||
import com.kouros.navigation.data.RouteEngine
|
||||
import com.kouros.navigation.data.tomtom.TomTomRepository
|
||||
import com.kouros.navigation.model.NavigationViewModel
|
||||
import com.kouros.navigation.model.RouteModel
|
||||
import com.kouros.navigation.utils.getSettingsRepository
|
||||
import com.kouros.navigation.utils.location
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Before
|
||||
import kotlin.collections.forEach
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class RouteModelTest {
|
||||
|
||||
val routeModel = RouteModel()
|
||||
val location = Location(LocationManager.GPS_PROVIDER)
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
val repository = getSettingsRepository(appContext)
|
||||
runBlocking { repository.setRoutingEngine(RouteEngine.TOMTOM.ordinal) }
|
||||
val routeJson = appContext.resources.openRawResource(R.raw.tomom_routing)
|
||||
val routeJsonString = routeJson.bufferedReader().use { it.readText() }
|
||||
assertNotEquals("", routeJsonString)
|
||||
routeModel.navState = routeModel.navState.copy(routingEngine = RouteEngine.TOMTOM.ordinal)
|
||||
routeModel.startNavigation(routeJsonString)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun checkRoute() {
|
||||
assertEquals(true, routeModel.isNavigating())
|
||||
assertEquals(routeModel.curRoute.summary.distance, 11116.0, 10.0)
|
||||
assertEquals(routeModel.curRoute.summary.duration, 1148.0, 10.0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun checkDeparture() {
|
||||
location.latitude = 48.185569
|
||||
location.longitude = 11.579034
|
||||
routeModel.updateLocation(location, NavigationViewModel(TomTomRepository()))
|
||||
val stepData = routeModel.currentStep()
|
||||
assertEquals(stepData.currentManeuverType, Maneuver.TYPE_TURN_NORMAL_RIGHT)
|
||||
assertEquals(stepData.instruction, "Silcherstraße")
|
||||
assertEquals(stepData.leftStepDistance, 70.0, 1.0)
|
||||
val nextStepData = routeModel.nextStep()
|
||||
assertEquals(nextStepData.currentManeuverType, Maneuver.TYPE_TURN_NORMAL_RIGHT)
|
||||
assertEquals(nextStepData.instruction, "Schmalkaldener Straße")
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun checkSchmalkadener20() {
|
||||
location.latitude = 48.187057
|
||||
location.longitude = 11.576652
|
||||
routeModel.updateLocation(location, NavigationViewModel(TomTomRepository()))
|
||||
val stepData = routeModel.currentStep()
|
||||
assertEquals(stepData.currentManeuverType, Maneuver.TYPE_TURN_NORMAL_RIGHT)
|
||||
assertEquals(stepData.instruction, "Schmalkaldener Straße")
|
||||
assertEquals(stepData.leftStepDistance, 0.0, 1.0)
|
||||
val nextStepData = routeModel.nextStep()
|
||||
assertEquals(nextStepData.currentManeuverType, Maneuver.TYPE_TURN_NORMAL_RIGHT)
|
||||
assertEquals(nextStepData.instruction, "Ingolstädter Straße")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun checkIngol() {
|
||||
location.latitude = 48.180555
|
||||
location.longitude = 11.585125
|
||||
routeModel.updateLocation(location, NavigationViewModel(TomTomRepository()))
|
||||
val stepData = routeModel.currentStep()
|
||||
assertEquals(stepData.currentManeuverType, Maneuver.TYPE_STRAIGHT)
|
||||
assertEquals(stepData.instruction, "Ingolstädter Straße")
|
||||
assertEquals(stepData.leftStepDistance, 350.0, 1.0)
|
||||
val nextStepData = routeModel.nextStep()
|
||||
assertEquals(nextStepData.currentManeuverType, Maneuver.TYPE_TURN_NORMAL_LEFT)
|
||||
assertEquals(nextStepData.instruction, "Schenkendorfstraße")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun checkIngol2() {
|
||||
location.latitude = 48.179286
|
||||
location.longitude = 11.585258
|
||||
location.bearing = 180.0F
|
||||
routeModel.updateLocation(location, NavigationViewModel(TomTomRepository()))
|
||||
val stepData = routeModel.currentStep()
|
||||
assertEquals(stepData.currentManeuverType, Maneuver.TYPE_TURN_NORMAL_LEFT)
|
||||
assertEquals(stepData.instruction, "Schenkendorfstraße")
|
||||
assertEquals(stepData.leftStepDistance, 240.0, 1.0)
|
||||
assertEquals(stepData.lane.size, 4)
|
||||
assertEquals(stepData.lane.first().valid, true)
|
||||
assertEquals(stepData.lane.last().valid, false)
|
||||
val nextStepData = routeModel.nextStep()
|
||||
assertEquals(nextStepData.currentManeuverType, Maneuver.TYPE_KEEP_LEFT)
|
||||
assertEquals(nextStepData.instruction, "Schenkendorfstraße")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun checkDestination() {
|
||||
location.latitude = homeHohenwaldeck.latitude
|
||||
location.longitude = homeHohenwaldeck.longitude
|
||||
routeModel.updateLocation(location, NavigationViewModel(TomTomRepository()))
|
||||
val stepData = routeModel.nextStep()
|
||||
assertEquals(stepData.currentManeuverType, Maneuver.TYPE_DESTINATION_LEFT)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun simulate() {
|
||||
for ((index, waypoint) in routeModel.curRoute.waypoints.withIndex()) {
|
||||
val curLocation = location(waypoint[0], waypoint[1])
|
||||
if (routeModel.isNavigating()) {
|
||||
if (index in 0..routeModel.curRoute.waypoints.size) {
|
||||
routeModel.updateLocation(curLocation, NavigationViewModel(TomTomRepository()))
|
||||
val stepData = routeModel.currentStep()
|
||||
val nextData = routeModel.nextStep()
|
||||
println("${stepData.leftStepDistance} : ${stepData.instruction} ${stepData.currentManeuverType} : ${nextData.instruction} ${nextData.currentManeuverType}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,6 @@ import com.kouros.navigation.car.screen.SearchScreen
|
||||
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.ObjectBox
|
||||
import com.kouros.navigation.data.RouteEngine
|
||||
import com.kouros.navigation.data.osrm.OsrmRepository
|
||||
import com.kouros.navigation.data.tomtom.TomTomRepository
|
||||
@@ -119,19 +118,26 @@ class NavigationSession : Session(), NavigationScreen.Listener {
|
||||
*/
|
||||
fun onConnectionStateUpdated(connectionState: Int) {
|
||||
routeModel.navState = routeModel.navState.copy(carConnection = connectionState)
|
||||
if (::carSensorManager.isInitialized) {
|
||||
carSensorManager.updateConnectionState(connectionState)
|
||||
}
|
||||
when (connectionState) {
|
||||
CarConnection.CONNECTION_TYPE_NOT_CONNECTED -> Unit
|
||||
CarConnection.CONNECTION_TYPE_NATIVE -> {
|
||||
ObjectBox.init(carContext)
|
||||
navigationScreen.checkPermission("android.car.permission.CAR_SPEED")
|
||||
if (carContext.checkSelfPermission("android.car.permission.CAR_SPEED") == PackageManager.PERMISSION_GRANTED) {
|
||||
if (::carSensorManager.isInitialized) {
|
||||
carSensorManager.updateConnectionState(connectionState)
|
||||
}
|
||||
}
|
||||
}
|
||||
CarConnection.CONNECTION_TYPE_PROJECTION -> {
|
||||
navigationScreen.checkPermission("com.google.android.gms.permission.CAR_SPEED")
|
||||
if (carContext.checkSelfPermission("com.google.android.gms.permission.CAR_SPEED") == PackageManager.PERMISSION_GRANTED) {
|
||||
if (::carSensorManager.isInitialized) {
|
||||
carSensorManager.updateConnectionState(connectionState)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -318,13 +324,11 @@ class NavigationSession : Session(), NavigationScreen.Listener {
|
||||
* Snaps location to route and checks for deviation requiring reroute.
|
||||
*/
|
||||
private fun handleNavigationLocation(location: Location) {
|
||||
routeModel.navState = routeModel.navState.copy(travelMessage = "${location.latitude} ${location.longitude}")
|
||||
navigationScreen.updateTrip(location)
|
||||
|
||||
if (routeModel.navState.arrived) return
|
||||
|
||||
val snappedLocation = snapLocation(location, routeModel.route.maneuverLocations())
|
||||
val distance = location.distanceTo(snappedLocation)
|
||||
|
||||
when {
|
||||
distance > MAXIMAL_ROUTE_DEVIATION -> {
|
||||
navigationScreen.calculateNewRoute(routeModel.navState.destination)
|
||||
@@ -342,8 +346,8 @@ class NavigationSession : Session(), NavigationScreen.Listener {
|
||||
* Stops active navigation and clears route state.
|
||||
* Called when user exits navigation or arrives at destination.
|
||||
*/
|
||||
override fun stopNavigation(context: CarContext) {
|
||||
routeModel.stopNavigation(context)
|
||||
override fun stopNavigation() {
|
||||
routeModel.stopNavigation()
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import androidx.car.app.AppManager
|
||||
import androidx.car.app.CarContext
|
||||
import androidx.car.app.SurfaceCallback
|
||||
import androidx.car.app.SurfaceContainer
|
||||
import androidx.car.app.connection.CarConnection
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -31,7 +30,6 @@ import com.kouros.navigation.car.map.cameraState
|
||||
import com.kouros.navigation.car.map.getPaddingValues
|
||||
import com.kouros.navigation.car.navigation.RouteCarModel
|
||||
import com.kouros.navigation.data.Constants.homeVogelhart
|
||||
import com.kouros.navigation.data.ObjectBox
|
||||
import com.kouros.navigation.data.RouteEngine
|
||||
import com.kouros.navigation.model.BaseStyleModel
|
||||
import com.kouros.navigation.model.RouteModel
|
||||
@@ -292,7 +290,8 @@ class SurfaceRenderer(
|
||||
currentSpeed,
|
||||
speed!!,
|
||||
width,
|
||||
height
|
||||
height,
|
||||
0.0
|
||||
)
|
||||
}
|
||||
LaunchedEffect(position, viewStyle) {
|
||||
|
||||
@@ -116,7 +116,7 @@ fun MapLibre(
|
||||
|
||||
@Composable
|
||||
fun RouteLayer(routeData: String?, trafficData: Map<String, String>) {
|
||||
if (routeData != null && routeData.isNotEmpty()) {
|
||||
if (!routeData.isNullOrEmpty()) {
|
||||
val routes = rememberGeoJsonSource(GeoJsonData.JsonString(routeData))
|
||||
LineLayer(
|
||||
id = "routes-casing",
|
||||
@@ -184,7 +184,7 @@ fun RouteLayer(routeData: String?, trafficData: Map<String, String>) {
|
||||
|
||||
@Composable
|
||||
fun RouteLayerPoint(routeData: String?) {
|
||||
if (routeData != null && routeData.isNotEmpty()) {
|
||||
if (!routeData.isNullOrEmpty()) {
|
||||
val routes = rememberGeoJsonSource(GeoJsonData.JsonString(routeData))
|
||||
val img = image(painterResource(R.drawable.ic_favorite_filled_white_24dp), drawAsSdf = true)
|
||||
SymbolLayer(
|
||||
@@ -209,11 +209,11 @@ fun RouteLayerPoint(routeData: String?) {
|
||||
|
||||
fun trafficColor(key: String): Expression<ColorValue> {
|
||||
when (key) {
|
||||
"queuing" -> return const(Color(0xFFD24417))
|
||||
"queuing" -> return const(Color(0xFFC46E53))
|
||||
"stationary" -> return const(Color(0xFFFF0000))
|
||||
"heavy" -> return const(Color(0xFF6B0404))
|
||||
"slow" -> return const(Color(0xFFC41F1F))
|
||||
"roadworks" -> return const(Color(0xFF7A631A))
|
||||
"slow" -> return const(Color(0xFFBD2525))
|
||||
"roadworks" -> return const(Color(0xFF725A0F))
|
||||
}
|
||||
return const(Color.Blue)
|
||||
}
|
||||
@@ -291,7 +291,8 @@ fun DrawNavigationImages(
|
||||
speed: Float?,
|
||||
maxSpeed: Int,
|
||||
width: Int,
|
||||
height: Int
|
||||
height: Int,
|
||||
lat: Double?
|
||||
) {
|
||||
NavigationImage(padding, width, height)
|
||||
if (speed != null) {
|
||||
@@ -300,26 +301,26 @@ fun DrawNavigationImages(
|
||||
if (speed != null && maxSpeed > 0 && (speed * 3.6) > maxSpeed) {
|
||||
MaxSpeed(width, height, maxSpeed)
|
||||
}
|
||||
//DebugInfo(width, height, routeModel)
|
||||
//DebugInfo(width, height, lat!!)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NavigationImage(padding: PaddingValues, width: Int, height: Int) {
|
||||
val imageSize = (height / 8)
|
||||
val color = remember { NavigationColor }
|
||||
val navigationColor = remember { NavigationColor }
|
||||
Box(contentAlignment = Alignment.Center, modifier = Modifier.padding(padding)) {
|
||||
Canvas(
|
||||
modifier = Modifier
|
||||
.size(imageSize.dp, imageSize.dp)
|
||||
) {
|
||||
scale(scaleX = 1f, scaleY = 0.7f) {
|
||||
drawCircle(Color.DarkGray.copy(alpha = 0.3f))
|
||||
drawCircle(navigationColor.copy(alpha = 0.3f))
|
||||
}
|
||||
}
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.navigation_48px),
|
||||
"Navigation",
|
||||
tint = color.copy(alpha = 0.7f),
|
||||
tint = navigationColor.copy(alpha = 0.7f),
|
||||
modifier = Modifier
|
||||
.size(imageSize.dp, imageSize.dp)
|
||||
.scale(scaleX = 1f, scaleY = 0.7f),
|
||||
@@ -453,7 +454,7 @@ private fun MaxSpeed(
|
||||
fun DebugInfo(
|
||||
width: Int,
|
||||
height: Int,
|
||||
routeModel: RouteModel,
|
||||
latitude: Double,
|
||||
|
||||
) {
|
||||
Box(
|
||||
@@ -465,19 +466,18 @@ fun DebugInfo(
|
||||
contentAlignment = Alignment.CenterStart
|
||||
) {
|
||||
val textMeasurerLocation = rememberTextMeasurer()
|
||||
val location = routeModel.navState.currentLocation.latitude.toString()
|
||||
val styleSpeed = TextStyle(
|
||||
fontSize = 26.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = Color.Black,
|
||||
)
|
||||
val textLayoutLocation = remember(location) {
|
||||
textMeasurerLocation.measure(location, styleSpeed)
|
||||
val textLayoutLocation = remember(latitude.toString()) {
|
||||
textMeasurerLocation.measure(latitude.toString(), styleSpeed)
|
||||
}
|
||||
Canvas(modifier = Modifier.fillMaxSize()) {
|
||||
drawText(
|
||||
textMeasurer = textMeasurerLocation,
|
||||
text = location,
|
||||
text = latitude.toString(),
|
||||
style = styleSpeed,
|
||||
topLeft = Offset(
|
||||
x = center.x - textLayoutLocation.size.width / 2,
|
||||
|
||||
@@ -1,18 +1,3 @@
|
||||
/*
|
||||
* Copyright 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.kouros.navigation.car.navigation
|
||||
|
||||
import android.location.Location
|
||||
@@ -138,9 +123,9 @@ class RouteCarModel() : RouteModel() {
|
||||
var laneImageAdded = false
|
||||
stepData.lane.forEach {
|
||||
if (it.indications.isNotEmpty() && it.valid) {
|
||||
Collections.sort<String>(it.indications)
|
||||
val sorted = it.indications.sorted()
|
||||
var direction = ""
|
||||
it.indications.forEach { it2 ->
|
||||
sorted.forEach { it2 ->
|
||||
direction = if (direction.isEmpty()) {
|
||||
it2.trim()
|
||||
} else {
|
||||
@@ -212,7 +197,6 @@ class RouteCarModel() : RouteModel() {
|
||||
.addAction(dismissAction).setCallback(object : AlertCallback {
|
||||
override fun onCancel(reason: Int) {
|
||||
}
|
||||
|
||||
override fun onDismiss() {
|
||||
}
|
||||
}).build()
|
||||
|
||||
@@ -24,22 +24,25 @@ import androidx.car.app.navigation.model.MessageInfo
|
||||
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
|
||||
import com.kouros.navigation.car.navigation.RouteCarModel
|
||||
import com.kouros.navigation.car.screen.observers.NavigationObserverCallback
|
||||
import com.kouros.navigation.car.screen.observers.NavigationObserverManager
|
||||
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.nominatim.SearchResult
|
||||
import com.kouros.navigation.data.overpass.Elements
|
||||
import com.kouros.navigation.model.NavigationViewModel
|
||||
import com.kouros.navigation.utils.GeoUtils
|
||||
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 kotlinx.coroutines.runBlocking
|
||||
import java.time.Duration
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneOffset
|
||||
@@ -51,58 +54,67 @@ class NavigationScreen(
|
||||
private var routeModel: RouteCarModel,
|
||||
private var listener: Listener,
|
||||
private val navigationViewModel: NavigationViewModel
|
||||
) :
|
||||
Screen(carContext) {
|
||||
) : Screen(carContext), NavigationObserverCallback {
|
||||
|
||||
/** A listener for navigation start and stop signals. */
|
||||
interface Listener {
|
||||
/** Stops navigation. */
|
||||
fun stopNavigation(context: CarContext)
|
||||
fun stopNavigation()
|
||||
}
|
||||
|
||||
val backGroundColor = CarColor.BLUE
|
||||
|
||||
var currentNavigationLocation = Location(LocationManager.GPS_PROVIDER)
|
||||
var recentPlace = Place()
|
||||
var navigationType = NavigationType.VIEW
|
||||
|
||||
var lastTrafficDate: LocalDateTime? = LocalDateTime.of(1960, 6, 21, 0, 0)
|
||||
val observer = Observer<String> { route ->
|
||||
var lastCameraSearch = 0
|
||||
var speedCameras = listOf<Elements>()
|
||||
|
||||
val observerManager = NavigationObserverManager(navigationViewModel, this)
|
||||
|
||||
init {
|
||||
observerManager.attachAllObservers(this)
|
||||
lifecycleScope.launch {
|
||||
getSettingsViewModel(carContext).routingEngine.collect {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NavigationObserverCallback implementations
|
||||
override fun onRouteReceived(route: String) {
|
||||
if (route.isNotEmpty()) {
|
||||
val repository = getSettingsRepository(carContext)
|
||||
val routingEngine = runBlocking { repository.routingEngineFlow.first() }
|
||||
routeModel.navState = routeModel.navState.copy(routingEngine = routingEngine)
|
||||
navigationType = NavigationType.NAVIGATION
|
||||
routeModel.startNavigation(route, carContext)
|
||||
routeModel.startNavigation(route)
|
||||
if (routeModel.hasLegs()) {
|
||||
getSettingsViewModel(carContext).onLastRouteChanged(route)
|
||||
}
|
||||
surfaceRenderer.setRouteData()
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
val recentObserver = Observer<Place> { lastPlace ->
|
||||
if (!routeModel.isNavigating()) {
|
||||
recentPlace = lastPlace
|
||||
navigationType = NavigationType.RECENT
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
val trafficObserver = Observer<Map<String, String>> { traffic ->
|
||||
surfaceRenderer.setTrafficData(traffic)
|
||||
override fun isNavigating(): Boolean = routeModel.isNavigating()
|
||||
|
||||
override fun onRecentPlaceReceived(place: Place) {
|
||||
recentPlace = place
|
||||
navigationType = NavigationType.RECENT
|
||||
invalidate()
|
||||
}
|
||||
|
||||
val placeObserver = Observer<SearchResult> { searchResult ->
|
||||
val place = Place(
|
||||
name = searchResult.displayName,
|
||||
street = searchResult.address.road,
|
||||
city = searchResult.address.city,
|
||||
latitude = searchResult.lat.toDouble(),
|
||||
longitude = searchResult.lon.toDouble(),
|
||||
category = Constants.CONTACTS,
|
||||
postalCode = searchResult.address.postcode
|
||||
)
|
||||
override fun onTrafficReceived(traffic: Map<String, String>) {
|
||||
surfaceRenderer.setTrafficData(traffic)
|
||||
}
|
||||
|
||||
override fun onPlaceSearchResultReceived(place: Place) {
|
||||
navigateToPlace(place)
|
||||
}
|
||||
|
||||
var lastCameraSearch = 0
|
||||
|
||||
var speedCameras = listOf<Elements>()
|
||||
val speedObserver = Observer<List<Elements>> { cameras ->
|
||||
override fun onSpeedCamerasReceived(cameras: List<Elements>) {
|
||||
speedCameras = cameras
|
||||
val coordinates = mutableListOf<List<Double>>()
|
||||
cameras.forEach {
|
||||
@@ -112,21 +124,12 @@ class NavigationScreen(
|
||||
surfaceRenderer.speedCamerasData.value = speedData
|
||||
}
|
||||
|
||||
val maxSpeedObserver = Observer<Int> { speed ->
|
||||
override fun onMaxSpeedReceived(speed: Int) {
|
||||
surfaceRenderer.maxSpeed.value = speed
|
||||
}
|
||||
|
||||
init {
|
||||
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)
|
||||
navigationViewModel.maxSpeed.observe(this, maxSpeedObserver)
|
||||
lifecycleScope.launch {
|
||||
getSettingsViewModel(carContext).routingEngine.collect {
|
||||
}
|
||||
}
|
||||
override fun invalidateScreen() {
|
||||
invalidate()
|
||||
}
|
||||
|
||||
override fun onGetTemplate(): Template {
|
||||
@@ -151,7 +154,7 @@ class NavigationScreen(
|
||||
.setDestinationTravelEstimate(routeModel.travelEstimate(carContext))
|
||||
.setActionStrip(actionStripBuilder.build())
|
||||
.setMapActionStrip(mapActionStripBuilder().build())
|
||||
.setBackgroundColor(CarColor.GREEN)
|
||||
.setBackgroundColor(backGroundColor)
|
||||
.build()
|
||||
}
|
||||
|
||||
@@ -208,7 +211,7 @@ class NavigationScreen(
|
||||
)
|
||||
.build()
|
||||
)
|
||||
.setBackgroundColor(CarColor.GREEN)
|
||||
.setBackgroundColor(CarColor.SECONDARY)
|
||||
.setActionStrip(actionStripBuilder.build())
|
||||
.setMapActionStrip(mapActionStripBuilder().build())
|
||||
.build()
|
||||
@@ -243,7 +246,7 @@ class NavigationScreen(
|
||||
return NavigationTemplate.Builder()
|
||||
.setNavigationInfo(RoutingInfo.Builder().setLoading(true).build())
|
||||
.setActionStrip(actionStripBuilder.build())
|
||||
.setBackgroundColor(CarColor.GREEN)
|
||||
.setBackgroundColor(backGroundColor)
|
||||
.build()
|
||||
}
|
||||
|
||||
@@ -447,7 +450,7 @@ class NavigationScreen(
|
||||
fun navigateToPlace(place: Place) {
|
||||
navigationType = NavigationType.VIEW
|
||||
val location = location(place.longitude, place.latitude)
|
||||
navigationViewModel.saveRecent(place)
|
||||
navigationViewModel.saveRecent(carContext, place)
|
||||
currentNavigationLocation = location
|
||||
navigationViewModel.loadRoute(
|
||||
carContext,
|
||||
@@ -461,7 +464,7 @@ class NavigationScreen(
|
||||
|
||||
fun stopNavigation() {
|
||||
navigationType = NavigationType.VIEW
|
||||
listener.stopNavigation(carContext)
|
||||
listener.stopNavigation()
|
||||
surfaceRenderer.routeData.value = ""
|
||||
lastCameraSearch = 0
|
||||
invalidate()
|
||||
@@ -502,7 +505,7 @@ class NavigationScreen(
|
||||
}
|
||||
updateSpeedCamera(location)
|
||||
with(routeModel) {
|
||||
updateLocation(carContext, location, navigationViewModel)
|
||||
updateLocation( location, navigationViewModel)
|
||||
if ((navState.maneuverType == Maneuver.TYPE_DESTINATION
|
||||
|| navState.maneuverType == Maneuver.TYPE_DESTINATION_LEFT
|
||||
|| navState.maneuverType == Maneuver.TYPE_DESTINATION_RIGHT
|
||||
@@ -510,6 +513,7 @@ class NavigationScreen(
|
||||
&& routeCalculator.leftStepDistance() < DESTINATION_ARRIVAL_DISTANCE
|
||||
) {
|
||||
stopNavigation()
|
||||
getSettingsViewModel(carContext).onLastRouteChanged("")
|
||||
navState = navState.copy(arrived = true)
|
||||
surfaceRenderer.routeData.value = ""
|
||||
navigationType = NavigationType.ARRIVAL
|
||||
|
||||
@@ -89,7 +89,7 @@ class PlaceListScreen(
|
||||
""
|
||||
}
|
||||
val row = Row.Builder()
|
||||
.setImage(contactIcon(it.avatar, it.category))
|
||||
// .setImage(contactIcon(it.avatar, it.category))
|
||||
.setTitle("$street ${it.city}")
|
||||
.setOnClickListener {
|
||||
val place = Place(
|
||||
@@ -101,7 +101,7 @@ class PlaceListScreen(
|
||||
it.postalCode,
|
||||
it.city,
|
||||
it.street,
|
||||
avatar = null
|
||||
// avatar = null
|
||||
)
|
||||
screenManager
|
||||
.pushForResult(
|
||||
@@ -162,7 +162,7 @@ class PlaceListScreen(
|
||||
)
|
||||
)
|
||||
.setOnClickListener {
|
||||
navigationViewModel.deletePlace(place)
|
||||
navigationViewModel.deletePlace(carContext, place)
|
||||
CarToast.makeText(
|
||||
carContext,
|
||||
R.string.recent_Item_deleted, CarToast.LENGTH_LONG
|
||||
|
||||
@@ -29,7 +29,11 @@ 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.NavigationViewModel
|
||||
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.runBlocking
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
|
||||
@@ -48,7 +52,10 @@ class RoutePreviewScreen(
|
||||
val navigationMessage = NavigationMessage(carContext)
|
||||
val observer = Observer<String> { route ->
|
||||
if (route.isNotEmpty()) {
|
||||
routeModel.startNavigation(route, carContext)
|
||||
val repository = getSettingsRepository(carContext)
|
||||
val routingEngine = runBlocking { repository.routingEngineFlow.first() }
|
||||
routeModel.navState = routeModel.navState.copy(routingEngine = routingEngine)
|
||||
routeModel.startNavigation(route)
|
||||
surfaceRenderer.setPreviewRouteData(routeModel)
|
||||
invalidate()
|
||||
}
|
||||
@@ -163,7 +170,7 @@ class RoutePreviewScreen(
|
||||
CarToast.LENGTH_SHORT
|
||||
)
|
||||
.show()
|
||||
navigationViewModel.saveFavorite(destination)
|
||||
navigationViewModel.saveFavorite(carContext, destination)
|
||||
invalidate()
|
||||
}
|
||||
.build()
|
||||
@@ -171,7 +178,7 @@ class RoutePreviewScreen(
|
||||
private fun deleteFavoriteAction(): Action = Action.Builder()
|
||||
.setOnClickListener {
|
||||
if (isFavorite) {
|
||||
navigationViewModel.deleteFavorite(destination)
|
||||
navigationViewModel.deleteFavorite(carContext,destination)
|
||||
}
|
||||
isFavorite = !isFavorite
|
||||
finish()
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
package com.kouros.navigation.car
|
||||
|
||||
import com.kouros.navigation.data.valhalla.ValhallaRepository
|
||||
import com.kouros.navigation.model.RouteModel
|
||||
import com.kouros.navigation.model.NavigationViewModel
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ViewModelTest {
|
||||
|
||||
val repo = ValhallaRepository()
|
||||
val navigationViewModel = NavigationViewModel(repo)
|
||||
val model = RouteModel()
|
||||
|
||||
@Test
|
||||
fun routeViewModelTest() {
|
||||
|
||||
// val fromLocation = Location(LocationManager.GPS_PROVIDER)
|
||||
// fromLocation.isMock = true
|
||||
// fromLocation.latitude = homeLocation.latitude
|
||||
// fromLocation.longitude = homeLocation.longitude
|
||||
// val toLocation = Location(LocationManager.GPS_PROVIDER)
|
||||
// toLocation.isMock = true
|
||||
// toLocation.latitude = home2Location.latitude
|
||||
// toLocation.longitude = home2Location.longitude
|
||||
//
|
||||
// val route = repo.getRoute(fromLocation, toLocation, SearchFilter())
|
||||
//model.startNavigation(route)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user