This commit is contained in:
Dimitris
2025-11-21 07:08:14 +01:00
parent 33f5ef4f34
commit b1a9a2c7fe
13 changed files with 711 additions and 454 deletions

View File

@@ -66,6 +66,8 @@ import org.koin.androidx.compose.koinViewModel
import org.maplibre.compose.camera.CameraPosition
import org.maplibre.compose.camera.rememberCameraState
import org.maplibre.compose.expressions.dsl.const
import org.maplibre.compose.layers.Anchor
import org.maplibre.compose.layers.CircleLayer
import org.maplibre.compose.layers.FillLayer
import org.maplibre.compose.layers.LineLayer
import org.maplibre.compose.location.DesiredAccuracy
@@ -375,7 +377,7 @@ class MainActivity : ComponentActivity() {
var snapedLocation = location
var bearing: Double
if (routeModel.isNavigating()) {
snapedLocation = snapLocation(location, routeModel.maneuverLocations())
snapedLocation = snapLocation(location, routeModel.route.maneuverLocations())
bearing = routeModel.currentStep().bearing
routeModel.updateLocation(snapedLocation)
instruction.value = routeModel.currentStep()

View File

@@ -35,7 +35,7 @@ class NavigationSession : Session() {
lateinit var surfaceRenderer: SurfaceRenderer
var locationIndex = 0
val test = false
val test = true
var mLocationListener: LocationListenerCompat = LocationListenerCompat { location: Location? ->
updateLocation(location)

View File

@@ -27,18 +27,22 @@ import androidx.lifecycle.setViewTreeLifecycleOwner
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.data.Constants
import com.kouros.navigation.data.Constants.SHOW_THREED_BUILDING
import com.kouros.navigation.model.RouteModel
import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue
import com.kouros.navigation.utils.NavigationUtils.snapLocation
import com.kouros.navigation.utils.calculateZoom
import org.maplibre.compose.camera.CameraPosition
import org.maplibre.compose.camera.rememberCameraState
import org.maplibre.compose.expressions.dsl.const
import org.maplibre.compose.layers.Anchor
import org.maplibre.compose.layers.FillLayer
import org.maplibre.compose.layers.LineLayer
import org.maplibre.compose.location.LocationPuckColors
import org.maplibre.compose.location.LocationPuckSizes
import org.maplibre.compose.map.MaplibreMap
import org.maplibre.compose.sources.GeoJsonData
import org.maplibre.compose.sources.Source
import org.maplibre.compose.sources.getBaseSource
import org.maplibre.compose.sources.rememberGeoJsonSource
import org.maplibre.compose.style.BaseStyle
@@ -176,7 +180,7 @@ class SurfaceRenderer(
baseStyle = BaseStyle.Uri(Constants.STYLE),
) {
getBaseSource(id = "openmaptiles")?.let { tiles ->
FillLayer(id = "example", visible = false, source = tiles, sourceLayer = "building")
BuildingLayer(tiles)
RouteLayer(route, previewRoute)
}
@@ -219,6 +223,20 @@ class SurfaceRenderer(
}
}
@Composable
fun BuildingLayer(tiles: Source) {
if (!getBooleanKeyValue(context = mCarContext, SHOW_THREED_BUILDING)) {
Anchor.Replace("building-3d") {
FillLayer(
id = "remove-building",
visible = false,
source = tiles,
sourceLayer = "building"
)
}
}
}
@Composable
fun RouteLayer(routeData: String?, previewRoute: String?) {
if (routeData!!.isNotEmpty()) {
@@ -285,7 +303,7 @@ class SurfaceRenderer(
var snapedLocation = location
var bearing: Double
if (routeModel.isNavigating()) {
snapedLocation = snapLocation(location, routeModel.maneuverLocations())
snapedLocation = snapLocation(location, routeModel.route.maneuverLocations())
bearing = routeModel.currentStep().bearing
} else {
bearing = cameraPosition.value!!.bearing

View File

@@ -0,0 +1,57 @@
package com.kouros.navigation.car.screen
import androidx.car.app.CarContext
import androidx.car.app.CarToast
import androidx.car.app.Screen
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.Row
import androidx.car.app.model.Template
import androidx.car.app.model.Toggle
import com.kouros.android.cars.carappservice.R
import com.kouros.navigation.data.Constants.SHOW_THREED_BUILDING
import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue
import com.kouros.navigation.utils.NavigationUtils.setBooleanKeyValue
class DisplaySettings(private val carContext: CarContext) : Screen(carContext) {
private var buildingToggleState = false
init {
buildingToggleState = getBooleanKeyValue(carContext, SHOW_THREED_BUILDING)
}
override fun onGetTemplate(): Template {
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)
}
buildingToggleState = !buildingToggleState
}.setChecked(buildingToggleState).build()
listBuilder.addItem(buildRowForTemplate(R.string.threed_building, buildingToggle))
return ListTemplate.Builder()
.setSingleList(listBuilder.build())
.setHeader(
Header.Builder()
.setTitle(carContext.getString(R.string.content_limits))
.setStartHeaderAction(Action.BACK)
.build()
)
.build()
}
private fun buildRowForTemplate(title: Int, toggle: Toggle): Row {
return Row.Builder()
.setTitle(carContext.getString(title))
.setToggle(toggle)
.build()
}
}

View File

@@ -61,6 +61,15 @@ class NavigationScreen(
//.setFlags(Action.FLAG_IS_PERSISTENT)
.build()
)
actionStripBuilder.addAction(
Action.Builder()
.setIcon(routeModel.createCarIcon(carContext, R.drawable.ic_favorite_white_24dp))
.setOnClickListener {
screenManager.push(SettingsScreen(carContext))
}
//.setFlags(Action.FLAG_IS_PERSISTENT)
.build()
)
return if (routeModel.isNavigating()) {
getNavigationTemplate(actionStripBuilder)
} else {
@@ -187,6 +196,24 @@ class NavigationScreen(
surfaceRenderer.handleScale(-1)
}
.build())
if (surfaceRenderer.panView)
{
actionStripBuilder.addAction(
Action.Builder()
.setIcon(
CarIcon.Builder(
IconCompat.createWithResource(
carContext,
R.drawable.ic_pan_24
)
)
.build()
).setOnClickListener {
surfaceRenderer.panView = false
}
.build()
)
}
return actionStripBuilder
}

View File

@@ -0,0 +1,58 @@
package com.kouros.navigation.car.screen
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.Header
import androidx.car.app.model.ItemList
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.DefaultLifecycleObserver
import com.kouros.android.cars.carappservice.R
import com.kouros.navigation.data.Constants.SHOW_THREED_BUILDING
import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue
import com.kouros.navigation.utils.NavigationUtils.setBooleanKeyValue
class NavigationSettings(private val carContext: CarContext) : Screen(carContext) {
override fun onGetTemplate(): Template {
val listBuilder = ItemList.Builder()
listBuilder.addItem(
buildRowForTemplate(
R.string.list_limit,
ConstraintManager.CONTENT_LIMIT_TYPE_LIST
)
)
return ListTemplate.Builder()
.setSingleList(listBuilder.build())
.setHeader(
Header.Builder()
.setTitle(carContext.getString(R.string.content_limits))
.setStartHeaderAction(Action.BACK)
.build()
)
.build()
}
private fun buildRowForTemplate(title: Int, contentLimitType: Int): Row {
return Row.Builder()
.setTitle(carContext.getString(title))
.addText(
carContext
.getCarService(ConstraintManager::class.java)
.getContentLimit(contentLimitType).toString()
)
.build()
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright 2022 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.screen
import android.content.Context
import androidx.car.app.CarContext
import androidx.car.app.CarToast
import androidx.car.app.Screen
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.Row
import androidx.car.app.model.Template
import androidx.car.app.model.Toggle
import androidx.core.content.edit
import com.kouros.android.cars.carappservice.R
import com.kouros.navigation.car.NavigationSession
/** A screen demonstrating selectable lists. */
class SettingsScreen(
carContext: CarContext,
) : Screen(carContext) {
override fun onGetTemplate(): Template {
val listBuilder = ItemList.Builder()
listBuilder.addItem(
buildRowForTemplate(
DisplaySettings(carContext),
R.string.display
)
)
listBuilder.addItem(
buildRowForTemplate(
NavigationSettings(carContext),
R.string.navigation_settings
)
)
return ListTemplate.Builder()
.setSingleList(listBuilder.build())
.setHeader(
Header.Builder()
.setTitle(
(carContext.getString(R.string.settings_action_title))
)
.setStartHeaderAction(Action.BACK)
.build()
)
.build()
}
private fun buildRowForTemplate(screen: Screen, title: Int): Row {
return Row.Builder()
.setTitle(carContext.getString(title))
.setOnClickListener { screenManager.push(screen) }
.setBrowsable(true)
.build()
}
}

View File

@@ -351,8 +351,9 @@
<string name="location_description_text_label" msgid="2779911545316756419">"Textlabel"</string>
<string name="parking_vs_driving_demo_title" msgid="3367862800135053111">"Demo: Parken im Vergleich zu Fahren"</string>
<string name="latest_feature_details" msgid="6843008350392721502">"Displays in Autos."</string>
<string name="latest_feature_title" msgid="7929405790070777460">"Neueste Funktionen"</string>
<string name="loading_toggle_enabled" msgid="8828072732804454994">"Laden aktiviert"</string>
<string name="navigation_settings" msgid="7929405790070777460">"Navigation"</string>
<string name="display">Anzeige</string>
<string name="threed_building" msgid="8828072732804454994">"3D Gebäude"</string>
<string name="loading_toggle_disabled" msgid="7689738885077382673">"Laden deaktiviert"</string>
<string name="loading_screen" msgid="4771507490730308794">"Ladebildschirm"</string>
<string name="vector_toggle_details" msgid="1301305340033556819">"Schieberegler zum Hinzufügen/Entfernen von Farben"</string>

View File

@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
<?xml version="1.0" encoding="utf-8"?><!--
Copyright (C) 2021 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
@@ -479,8 +478,9 @@
<string name="parking_vs_driving_demo_title">Parking Vs Driving Demo</string>
<string name="latest_feature_details">Cluster Displays in cars!</string>
<string name="latest_feature_title">Latest Features</string>
<string name="loading_toggle_enabled">Loading enabled</string>
<string name="navigation_settings">Navigation</string>
<string name="display">Display</string>
<string name="threed_building">3D Building</string>
<string name="loading_toggle_disabled">Loading disabled</string>
<string name="loading_screen">Loading screen</string>
<string name="vector_toggle_details">Toggle to add/remove color</string>

View File

@@ -118,7 +118,7 @@ data class ValhallaLocation (
object Constants {
const val STYLE: String = "https://kouros-online.de/liberty2"
const val STYLE: String = "https://kouros-online.de/liberty.json"
//baseStyle = BaseStyle.Uri("https://tiles.openfreemap.org/styles/liberty"),
const val TAG: String = "Navigation"
@@ -138,6 +138,11 @@ object Constants {
home2Location.latitude = 48.1164817
home2Location.longitude = 11.594322
}
const val SHARED_PREF_KEY = "NavigationPrefs"
const val SHOW_THREED_BUILDING = "Show3D"
}

View File

@@ -16,7 +16,7 @@ data class Route (
*
* @since 1.0.0
*/
val maneuvers: List<Maneuvers>,
var maneuvers: List<Maneuvers>,
/**
* The distance traveled from origin to destination.
@@ -43,8 +43,6 @@ data class Route (
val time: Double,
var routingManeuvers : List<Maneuvers>,
var routeGeoJson : String,
var currentIndex: Int
@@ -63,8 +61,6 @@ data class Route (
private lateinit var trip : Trip
private lateinit var routingManeuvers: List<Maneuvers>
private var routeGeoJson = ""
fun route (route: String ) = apply {
@@ -87,21 +83,22 @@ data class Route (
points.add(point)
}
pointLocations = points
val routings = mutableListOf<Maneuvers>()
for (maneuver in maneuvers) {
routings.add(maneuver)
}
this.routingManeuvers = routings
this.routeGeoJson = createGeoJson(waypoints)
return Route(
maneuvers, distance, waypoints, pointLocations, summary, trip, time, routingManeuvers, routeGeoJson, 0
maneuvers, distance, waypoints, pointLocations, summary, trip, time, routeGeoJson, 0
)
}
}
fun maneuverLocations(): List<Point> {
val beginShapeIndex = currentManeuver().beginShapeIndex
val endShapeIndex = currentManeuver().endShapeIndex
return pointLocations.subList(beginShapeIndex, endShapeIndex)
}
fun clear() {
waypoints = mutableListOf()
routingManeuvers = mutableListOf()
maneuvers = mutableListOf()
routeGeoJson = ""
}

View File

@@ -81,7 +81,6 @@ open class RouteModel() {
fun currentStep(): StepData {
val maneuver = route.currentManeuver()
var text = ""
println("Maneuver $maneuver")
if (maneuver.streetNames != null && maneuver.streetNames.isNotEmpty()) {
text = maneuver.streetNames[0]
}
@@ -156,16 +155,10 @@ open class RouteModel() {
return nearestLocation
}
fun maneuverLocations(): List<Point> {
val beginShapeIndex = route.currentManeuver().beginShapeIndex
val endShapeIndex = route.currentManeuver().endShapeIndex
return route.pointLocations.subList(beginShapeIndex, endShapeIndex)
}
fun travelLeftTime(): Double {
var timeLeft = 0.0
for (i in route.currentIndex + 1..<route.routingManeuvers.size) {
val maneuver = route.routingManeuvers[i]
for (i in route.currentIndex + 1..<route.maneuvers.size) {
val maneuver = route.maneuvers[i]
timeLeft += maneuver.time
}
if (endIndex > 0) {
@@ -180,7 +173,7 @@ open class RouteModel() {
/** Returns the current [Step] left distance in km. */
fun leftStepDistance(): Double {
val maneuver = route.routingManeuvers[route.currentIndex]
val maneuver = route.currentManeuver()
var leftDistance = maneuver.length
if (endIndex > 0) {
leftDistance = (distanceToStepEnd / 1000).toDouble()
@@ -190,12 +183,12 @@ open class RouteModel() {
fun travelLeftDistance(): Double {
var leftDistance = 0.0
for (i in route.currentIndex + 1..<route.routingManeuvers.size) {
val maneuver = route.routingManeuvers[i]
for (i in route.currentIndex + 1..<route.maneuvers.size) {
val maneuver = route.maneuvers[i]
leftDistance += maneuver.length
}
if (endIndex > 0) {
val maneuver = route.routingManeuvers[route.currentIndex]
val maneuver = route.currentManeuver()
val curDistance = maneuver.length
val percent = 100 * (endIndex - currentIndex) / (endIndex - beginIndex)
val time = curDistance * percent / 100
@@ -215,7 +208,6 @@ open class RouteModel() {
fun stopNavigation() {
route.clear()
navigating = false
//maneuverIndex = 0
currentIndex = 0
distanceToStepEnd = 0F
beginIndex = 0

View File

@@ -1,7 +1,11 @@
package com.kouros.navigation.utils
import android.content.Context
import android.location.Location
import android.location.LocationManager
import androidx.core.content.edit
import com.kouros.navigation.data.Constants.SHARED_PREF_KEY
import com.kouros.navigation.data.Constants.SHOW_THREED_BUILDING
import com.kouros.navigation.data.GeoJsonFeature
import com.kouros.navigation.data.GeoJsonFeatureCollection
import com.kouros.navigation.data.GeoJsonLineString
@@ -25,6 +29,28 @@ import kotlin.math.sin
object NavigationUtils {
fun getBooleanKeyValue(context: Context, key: String) : Boolean {
return context
.getSharedPreferences(
SHARED_PREF_KEY,
Context.MODE_PRIVATE
)
.getBoolean(key, false)
}
fun setBooleanKeyValue(context: Context, `val`: Boolean, key: String) {
context
.getSharedPreferences(
SHARED_PREF_KEY,
Context.MODE_PRIVATE
)
.edit {
putBoolean(
key, `val`
)
apply()
}
}
fun snapLocation(location: Location, stepCoordinates: List<Point>): Location {
val oldPoint = Point.fromLngLat(location.longitude, location.latitude)
if (stepCoordinates.size > 1) {