Diverse Änderungen
This commit is contained in:
@@ -49,6 +49,7 @@
|
||||
<category android:name="androidx.car.app.category.WEATHER" />
|
||||
<category android:name="androidx.car.app.category.POI"/>
|
||||
<category android:name="androidx.car.app.category.NAVIGATION"/>
|
||||
<category android:name="androidx.car.app.category.FEATURE_CLUSTER"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
</application>
|
||||
|
||||
@@ -13,6 +13,7 @@ import androidx.car.app.CarContext
|
||||
import androidx.car.app.Screen
|
||||
import androidx.car.app.ScreenManager
|
||||
import androidx.car.app.Session
|
||||
import androidx.car.app.connection.CarConnection
|
||||
import androidx.car.app.hardware.CarHardwareManager
|
||||
import androidx.car.app.hardware.common.CarValue
|
||||
import androidx.car.app.hardware.common.OnCarDataAvailableListener
|
||||
@@ -36,6 +37,7 @@ 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
|
||||
@@ -48,7 +50,7 @@ import kotlinx.coroutines.awaitCancellation
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
import android.Manifest.permission
|
||||
|
||||
class NavigationSession : Session(), NavigationScreen.Listener {
|
||||
|
||||
@@ -82,14 +84,7 @@ class NavigationSession : Session(), NavigationScreen.Listener {
|
||||
}
|
||||
|
||||
override fun onDestroy(owner: LifecycleOwner) {
|
||||
val carInfo = carContext.getCarService(CarHardwareManager::class.java).carInfo
|
||||
val repository = getSettingsRepository(carContext)
|
||||
val useCarLocation = runBlocking { repository.carLocationFlow.first() }
|
||||
if (useCarLocation) {
|
||||
val carSensors = carContext.getCarService(CarHardwareManager::class.java).carSensors
|
||||
carSensors.removeCarHardwareLocationListener(carLocationListener)
|
||||
}
|
||||
carInfo.removeSpeedListener(carSpeedListener)
|
||||
removeSensors()
|
||||
Log.i(TAG, "In onDestroy()")
|
||||
val locationManager =
|
||||
carContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
||||
@@ -139,6 +134,24 @@ class NavigationSession : Session(), NavigationScreen.Listener {
|
||||
}
|
||||
}
|
||||
|
||||
fun onPermissionGranted(permission : Boolean) {
|
||||
addSensors(routeModel.navState.carConnection)
|
||||
}
|
||||
|
||||
fun onConnectionStateUpdated(connectionState: Int) {
|
||||
routeModel.navState = routeModel.navState.copy(carConnection = connectionState)
|
||||
when (connectionState) {
|
||||
CarConnection.CONNECTION_TYPE_NOT_CONNECTED -> "Not connected to a head unit"
|
||||
CarConnection.CONNECTION_TYPE_NATIVE -> {
|
||||
ObjectBox.init(carContext)
|
||||
navigationScreen.checkPermission("android.car.permission.CAR_SPEED")
|
||||
} // Automotive OS
|
||||
CarConnection.CONNECTION_TYPE_PROJECTION -> {
|
||||
"Connected to Android Auto"
|
||||
navigationScreen.checkPermission("com.google.android.gms.permission.CAR_SPEED")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateScreen(intent: Intent): Screen {
|
||||
|
||||
@@ -153,26 +166,23 @@ class NavigationSession : Session(), NavigationScreen.Listener {
|
||||
}
|
||||
}
|
||||
|
||||
// lifecycleScope.launch {
|
||||
|
||||
|
||||
//}
|
||||
|
||||
|
||||
navigationViewModel = getViewModel(carContext)
|
||||
|
||||
navigationViewModel.routingEngine.observe(this, ::onRoutingEngineStateUpdated)
|
||||
|
||||
navigationViewModel.permissionGranted.observe(this, ::onPermissionGranted)
|
||||
|
||||
routeModel = RouteCarModel()
|
||||
|
||||
CarConnection(carContext).type.observe(this, ::onConnectionStateUpdated)
|
||||
|
||||
surfaceRenderer = SurfaceRenderer(carContext, lifecycle, routeModel, viewModelStoreOwner)
|
||||
|
||||
navigationScreen =
|
||||
NavigationScreen(carContext, surfaceRenderer, routeModel, this, navigationViewModel)
|
||||
|
||||
if (carContext.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
if ( carContext.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
== PackageManager.PERMISSION_GRANTED
|
||||
&& carContext.checkSelfPermission("com.google.android.gms.permission.CAR_SPEED") == PackageManager.PERMISSION_GRANTED
|
||||
&& !useContacts
|
||||
|| (useContacts && carContext.checkSelfPermission(Manifest.permission.READ_CONTACTS)
|
||||
== PackageManager.PERMISSION_GRANTED)
|
||||
@@ -180,27 +190,24 @@ class NavigationSession : Session(), NavigationScreen.Listener {
|
||||
requestLocationUpdates()
|
||||
} else {
|
||||
// If we do not have the location permission, show the request permission screen.
|
||||
val permissions: MutableList<String?> = ArrayList()
|
||||
permissions.add(permission.ACCESS_FINE_LOCATION)
|
||||
val screenManager =
|
||||
carContext.getCarService(ScreenManager::class.java)
|
||||
screenManager
|
||||
.push(navigationScreen)
|
||||
return RequestPermissionScreen(
|
||||
carContext,
|
||||
mLocationPermissionCheckCallback = {
|
||||
permissionCheckCallback = {
|
||||
screenManager.pop()
|
||||
},
|
||||
mContactsPermissionCheckCallback = {
|
||||
screenManager.pop()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
addSensors()
|
||||
|
||||
return navigationScreen
|
||||
}
|
||||
|
||||
fun addSensors() {
|
||||
fun addSensors(connectionState: Int) {
|
||||
val carInfo = carContext.getCarService(CarHardwareManager::class.java).carInfo
|
||||
val repository = getSettingsRepository(carContext)
|
||||
val useCarLocation = runBlocking { repository.carLocationFlow.first() }
|
||||
@@ -215,7 +222,24 @@ class NavigationSession : Session(), NavigationScreen.Listener {
|
||||
carLocationListener
|
||||
)
|
||||
}
|
||||
carInfo.addSpeedListener(carContext.mainExecutor, carSpeedListener)
|
||||
if (connectionState == CarConnection.CONNECTION_TYPE_NATIVE
|
||||
|| connectionState == CarConnection.CONNECTION_TYPE_PROJECTION) {
|
||||
carInfo.addSpeedListener(carContext.mainExecutor, carSpeedListener)
|
||||
}
|
||||
}
|
||||
|
||||
fun removeSensors() {
|
||||
val carInfo = carContext.getCarService(CarHardwareManager::class.java).carInfo
|
||||
val repository = getSettingsRepository(carContext)
|
||||
val useCarLocation = runBlocking { repository.carLocationFlow.first() }
|
||||
if (useCarLocation) {
|
||||
val carSensors = carContext.getCarService(CarHardwareManager::class.java).carSensors
|
||||
carSensors.removeCarHardwareLocationListener(carLocationListener)
|
||||
}
|
||||
if (routeModel.navState.carConnection == CarConnection.CONNECTION_TYPE_NATIVE
|
||||
|| routeModel.navState.carConnection == CarConnection.CONNECTION_TYPE_PROJECTION) {
|
||||
carInfo.removeSpeedListener(carSpeedListener)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
@@ -277,6 +301,9 @@ class NavigationSession : Session(), NavigationScreen.Listener {
|
||||
}
|
||||
|
||||
fun updateLocation(location: Location) {
|
||||
if (location.hasBearing()) {
|
||||
routeModel.navState = routeModel.navState.copy(routeBearing = location.bearing)
|
||||
}
|
||||
if (routeModel.isNavigating()) {
|
||||
navigationScreen.updateTrip(location)
|
||||
if (!routeModel.navState.arrived) {
|
||||
|
||||
@@ -29,7 +29,6 @@ import com.kouros.navigation.car.map.DrawNavigationImages
|
||||
import com.kouros.navigation.car.map.MapLibre
|
||||
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.homeVogelhart
|
||||
import com.kouros.navigation.data.ObjectBox
|
||||
@@ -79,6 +78,7 @@ class SurfaceRenderer(
|
||||
val trafficData = MutableLiveData(emptyMap<String, String>())
|
||||
val speedCamerasData = MutableLiveData("")
|
||||
val speed = MutableLiveData(0F)
|
||||
|
||||
val maxSpeed = MutableLiveData(0)
|
||||
var viewStyle = ViewStyle.VIEW
|
||||
lateinit var centerLocation: Location
|
||||
@@ -175,14 +175,6 @@ class SurfaceRenderer(
|
||||
|
||||
}
|
||||
|
||||
fun onConnectionStateUpdated(connectionState: Int) {
|
||||
when (connectionState) {
|
||||
CarConnection.CONNECTION_TYPE_NOT_CONNECTED -> "Not connected to a head unit"
|
||||
CarConnection.CONNECTION_TYPE_PROJECTION -> "Connected to Android Auto"
|
||||
CarConnection.CONNECTION_TYPE_NATIVE -> ObjectBox.init(carContext) // Automotive OS
|
||||
}
|
||||
}
|
||||
|
||||
fun onBaseStyleStateUpdated(style: BaseStyle) {
|
||||
|
||||
}
|
||||
@@ -190,29 +182,24 @@ class SurfaceRenderer(
|
||||
@Composable
|
||||
fun MapView() {
|
||||
|
||||
|
||||
//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 showBuildings = settingsViewModel(carContext, viewModelStoreOwner).show3D.collectAsState().value
|
||||
val position: CameraPosition? by cameraPosition.observeAsState()
|
||||
val route: String? by routeData.observeAsState()
|
||||
val traffic: Map<String, String> ? by trafficData.observeAsState()
|
||||
val speedCameras: String? by speedCamerasData.observeAsState()
|
||||
val paddingValues = getPaddingValues(height, viewStyle)
|
||||
val cameraState = cameraState(paddingValues, position, tilt)
|
||||
val rememberBaseStyle = rememberBaseStyle(baseStyle)
|
||||
val baseStyle = BaseStyleModel().readStyle(carContext, darkMode, carContext.isDarkMode)
|
||||
|
||||
MapLibre(
|
||||
carContext,
|
||||
cameraState,
|
||||
rememberBaseStyle,
|
||||
baseStyle,
|
||||
route,
|
||||
traffic,
|
||||
viewStyle,
|
||||
speedCameras,
|
||||
false
|
||||
showBuildings
|
||||
)
|
||||
ShowPosition(cameraState, position, paddingValues)
|
||||
}
|
||||
@@ -226,12 +213,12 @@ class SurfaceRenderer(
|
||||
val cameraDuration =
|
||||
duration(viewStyle == ViewStyle.PREVIEW, position!!.bearing, lastBearing)
|
||||
val currentSpeed: Float? by speed.observeAsState()
|
||||
val maxSpeed: Int? by maxSpeed.observeAsState()
|
||||
val speed: Int? by maxSpeed.observeAsState()
|
||||
if (viewStyle == ViewStyle.VIEW || viewStyle == ViewStyle.PAN_VIEW) {
|
||||
DrawNavigationImages(
|
||||
paddingValues,
|
||||
currentSpeed,
|
||||
maxSpeed!!,
|
||||
speed!!,
|
||||
width,
|
||||
height
|
||||
)
|
||||
@@ -251,7 +238,6 @@ class SurfaceRenderer(
|
||||
}
|
||||
|
||||
override fun onCreate(owner: LifecycleOwner) {
|
||||
CarConnection(carContext).type.observe(owner, ::onConnectionStateUpdated)
|
||||
style.observe(owner, :: onBaseStyleStateUpdated)
|
||||
Log.i(TAG, "SurfaceRenderer created")
|
||||
carContext.getCarService(AppManager::class.java)
|
||||
@@ -281,15 +267,19 @@ class SurfaceRenderer(
|
||||
fun updateLocation(location: Location) {
|
||||
synchronized(this) {
|
||||
if (viewStyle == ViewStyle.VIEW || viewStyle == ViewStyle.PAN_VIEW) {
|
||||
val bearing = if (carOrientation == 999F)
|
||||
bearing(
|
||||
lastLocation,
|
||||
location,
|
||||
cameraPosition.value!!.bearing
|
||||
) else {
|
||||
val bearing = if (carOrientation == 999F) {
|
||||
if (location.hasBearing()) {
|
||||
location.bearing.toDouble()
|
||||
} else {
|
||||
bearing(
|
||||
lastLocation,
|
||||
location,
|
||||
cameraPosition.value!!.bearing
|
||||
)
|
||||
}
|
||||
} else {
|
||||
carOrientation.toDouble()
|
||||
}
|
||||
println("Bearing $bearing")
|
||||
val zoom = if (viewStyle == ViewStyle.VIEW) {
|
||||
calculateZoom(location.speed.toDouble())
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.kouros.navigation.car.map
|
||||
|
||||
import android.content.Context
|
||||
import android.location.Location
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -10,8 +9,6 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -26,18 +23,13 @@ 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.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.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
|
||||
@@ -89,7 +81,6 @@ fun cameraState(
|
||||
|
||||
@Composable
|
||||
fun MapLibre(
|
||||
context: Context,
|
||||
cameraState: CameraState,
|
||||
baseStyle: BaseStyle.Json,
|
||||
route: String?,
|
||||
@@ -229,15 +220,15 @@ fun trafficColor(key: String): Expression<ColorValue> {
|
||||
|
||||
@Composable
|
||||
fun AmenityLayer(routeData: String?) {
|
||||
if (routeData != null && routeData.isNotEmpty()) {
|
||||
if (!routeData.isNullOrEmpty()) {
|
||||
var color = const(Color.Red)
|
||||
var img = image(painterResource(R.drawable.local_pharmacy_48px), drawAsSdf = true)
|
||||
if (routeData.contains(Constants.CHARGING_STATION)) {
|
||||
color = const(Color.Green)
|
||||
color = const(Color(0xFF054603))
|
||||
img = image(painterResource(R.drawable.ev_station_48px), drawAsSdf = true)
|
||||
} else if (routeData.contains(Constants.FUEL_STATION)) {
|
||||
color = const(Color.Black)
|
||||
img = image(painterResource(R.drawable.local_gas_station_48px), drawAsSdf = true)
|
||||
color = const(Color.Blue)
|
||||
img = image(painterResource(R.drawable.local_gas_station_24), drawAsSdf = true)
|
||||
}
|
||||
val routes = rememberGeoJsonSource(GeoJsonData.JsonString(routeData))
|
||||
SymbolLayer(
|
||||
@@ -261,7 +252,7 @@ fun AmenityLayer(routeData: String?) {
|
||||
|
||||
@Composable
|
||||
fun SpeedCameraLayer(speedCameras: String?) {
|
||||
if (speedCameras != null && speedCameras.isNotEmpty()) {
|
||||
if (!speedCameras.isNullOrEmpty()) {
|
||||
val color = const(Color.Red)
|
||||
val cameraSource = rememberGeoJsonSource(GeoJsonData.JsonString(speedCameras))
|
||||
SymbolLayer(
|
||||
@@ -306,7 +297,7 @@ fun DrawNavigationImages(
|
||||
if (speed != null) {
|
||||
CurrentSpeed(width, height, speed, maxSpeed)
|
||||
}
|
||||
if (speed != null && maxSpeed > 0 && (speed * 3.6) > maxSpeed) {
|
||||
if (speed != null && maxSpeed > 0 && (speed * 3.6) > maxSpeed) {
|
||||
MaxSpeed(width, height, maxSpeed)
|
||||
}
|
||||
//DebugInfo(width, height, routeModel)
|
||||
@@ -497,14 +488,6 @@ fun DebugInfo(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberBaseStyle(baseStyle: BaseStyle.Json): BaseStyle.Json {
|
||||
val rememberBaseStyle by remember() {
|
||||
mutableStateOf(baseStyle)
|
||||
}
|
||||
return rememberBaseStyle
|
||||
}
|
||||
|
||||
fun getPaddingValues(height: Int, viewStyle: ViewStyle): PaddingValues {
|
||||
return when (viewStyle) {
|
||||
ViewStyle.VIEW, ViewStyle.PAN_VIEW -> PaddingValues(
|
||||
|
||||
@@ -76,7 +76,7 @@ class CategoriesScreen(
|
||||
|
||||
fun carIcon(context: CarContext, id: String): CarIcon {
|
||||
val resId = when (id) {
|
||||
FUEL_STATION -> R.drawable.local_gas_station_48px
|
||||
FUEL_STATION -> R.drawable.local_gas_station_24
|
||||
PHARMACY -> R.drawable.local_pharmacy_48px
|
||||
CHARGING_STATION -> R.drawable.ev_station_48px
|
||||
else -> {}
|
||||
|
||||
@@ -46,7 +46,7 @@ class DarkModeSettings(private val carContext: CarContext) : Screen(carContext)
|
||||
)
|
||||
.addItem(
|
||||
buildRowForTemplate(
|
||||
R.string.use_telephon_settings,
|
||||
R.string.use_car_settings,
|
||||
)
|
||||
)
|
||||
.setOnSelectedListener { index: Int ->
|
||||
@@ -74,14 +74,6 @@ class DarkModeSettings(private val carContext: CarContext) : Screen(carContext)
|
||||
|
||||
private fun onSelected(index: Int) {
|
||||
settingsViewModel.onDarkModeChanged(index)
|
||||
CarToast.makeText(
|
||||
carContext,
|
||||
(carContext
|
||||
.getString(R.string.display_settings)
|
||||
+ ":"
|
||||
+ " " + index), CarToast.LENGTH_LONG
|
||||
)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun buildRowForTemplate(title: Int): Row {
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package com.kouros.navigation.car.screen
|
||||
|
||||
import android.Manifest
|
||||
import android.content.pm.PackageManager
|
||||
import android.location.Location
|
||||
import android.location.LocationManager
|
||||
import android.os.CountDownTimer
|
||||
import android.os.Handler
|
||||
import androidx.car.app.CarContext
|
||||
import androidx.car.app.Screen
|
||||
import androidx.car.app.ScreenManager
|
||||
import androidx.car.app.model.Action
|
||||
import androidx.car.app.model.Action.FLAG_DEFAULT
|
||||
import androidx.car.app.model.ActionStrip
|
||||
@@ -80,7 +83,7 @@ class NavigationScreen(
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
val trafficObserver = Observer<Map<String, String> > { traffic ->
|
||||
val trafficObserver = Observer<Map<String, String>> { traffic ->
|
||||
surfaceRenderer.setTrafficData(traffic)
|
||||
invalidate()
|
||||
}
|
||||
@@ -111,6 +114,9 @@ class NavigationScreen(
|
||||
surfaceRenderer.speedCamerasData.value = speedData
|
||||
}
|
||||
|
||||
val maxSpeedObserver = Observer<Int> { speed ->
|
||||
surfaceRenderer.maxSpeed.value = speed
|
||||
}
|
||||
|
||||
init {
|
||||
navigationViewModel.route.observe(this, observer)
|
||||
@@ -118,6 +124,7 @@ class NavigationScreen(
|
||||
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 {
|
||||
}
|
||||
@@ -497,7 +504,7 @@ class NavigationScreen(
|
||||
}
|
||||
updateSpeedCamera(location)
|
||||
with(routeModel) {
|
||||
updateLocation(carContext,location, navigationViewModel)
|
||||
updateLocation(carContext, location, navigationViewModel)
|
||||
if ((navState.maneuverType == Maneuver.TYPE_DESTINATION
|
||||
|| navState.maneuverType == Maneuver.TYPE_DESTINATION_LEFT
|
||||
|| navState.maneuverType == Maneuver.TYPE_DESTINATION_RIGHT
|
||||
@@ -540,7 +547,7 @@ class NavigationScreen(
|
||||
val bearingSpeedCamera = if (camera.tags.direction != null) {
|
||||
try {
|
||||
camera.tags.direction!!.toFloat()
|
||||
} catch ( e: Exception) {
|
||||
} catch (e: Exception) {
|
||||
0F
|
||||
}
|
||||
} else {
|
||||
@@ -552,6 +559,29 @@ class NavigationScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun checkPermission(permission: String) {
|
||||
println("Car connection permission: $permission")
|
||||
if (carContext.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
|
||||
val permissions: MutableList<String?> = ArrayList()
|
||||
permissions.add(permission)
|
||||
val screenManager =
|
||||
carContext.getCarService(ScreenManager::class.java)
|
||||
screenManager
|
||||
.push(
|
||||
RequestPermissionScreen(
|
||||
carContext,
|
||||
permissionCheckCallback = {
|
||||
screenManager.pop()
|
||||
navigationViewModel.permissionGranted.value = true
|
||||
},
|
||||
permissions
|
||||
)
|
||||
)
|
||||
} else {
|
||||
navigationViewModel.permissionGranted.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class NavigationType {
|
||||
|
||||
@@ -16,7 +16,10 @@ import com.kouros.navigation.utils.getSettingsViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
class NavigationSettings(private val carContext: CarContext, private var navigationViewModel: NavigationViewModel) :
|
||||
class NavigationSettings(
|
||||
private val carContext: CarContext,
|
||||
private var navigationViewModel: NavigationViewModel
|
||||
) :
|
||||
Screen(carContext) {
|
||||
|
||||
private var motorWayToggleState = false
|
||||
@@ -79,6 +82,12 @@ class NavigationSettings(private val carContext: CarContext, private var navigat
|
||||
R.string.routing_engine
|
||||
)
|
||||
)
|
||||
.addItem(
|
||||
buildRowForScreenTemplate(
|
||||
PasswordSettings(carContext, navigationViewModel),
|
||||
R.string.tomtom_api_key
|
||||
)
|
||||
)
|
||||
return ListTemplate.Builder()
|
||||
.setSingleList(listBuilder.build())
|
||||
.setHeader(
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.kouros.navigation.car.screen
|
||||
|
||||
import androidx.car.app.CarContext
|
||||
import androidx.car.app.Screen
|
||||
import androidx.car.app.model.Action
|
||||
import androidx.car.app.model.InputCallback
|
||||
import androidx.car.app.model.ParkedOnlyOnClickListener
|
||||
import androidx.car.app.model.Template
|
||||
import androidx.car.app.model.signin.InputSignInMethod
|
||||
import androidx.car.app.model.signin.SignInTemplate
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.kouros.data.R
|
||||
import com.kouros.navigation.model.NavigationViewModel
|
||||
import com.kouros.navigation.utils.getSettingsViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class PasswordSettings(
|
||||
private val carContext: CarContext,
|
||||
private var navigationViewModel: NavigationViewModel
|
||||
) : Screen(carContext) {
|
||||
|
||||
var errorMessage: String? = null
|
||||
|
||||
val settingsViewModel = getSettingsViewModel(carContext)
|
||||
|
||||
init {
|
||||
lifecycleScope.launch {
|
||||
settingsViewModel.tomTomApiKey.collect {
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun onGetTemplate(): Template {
|
||||
val apiKey = settingsViewModel.tomTomApiKey.value
|
||||
val callback: InputCallback = object : InputCallback {
|
||||
override fun onInputSubmitted(text: String) {
|
||||
settingsViewModel.onTomTomApiKeyChanged(text)
|
||||
//errorMessage = carContext.getString(R.string.tomtom_api_key)
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
val builder = InputSignInMethod.Builder(callback)
|
||||
.setHint(apiKey)
|
||||
.setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD)
|
||||
if (errorMessage != null) {
|
||||
// builder.setErrorMessage(errorMessage)
|
||||
}
|
||||
val signInMethod = builder.build()
|
||||
|
||||
val pinSignInAction = Action.Builder()
|
||||
.setTitle(carContext.getString(R.string.stop_action_title))
|
||||
.setOnClickListener(ParkedOnlyOnClickListener.create {
|
||||
println("Sign")
|
||||
invalidate()
|
||||
})
|
||||
.build()
|
||||
return SignInTemplate.Builder(signInMethod)
|
||||
//.addAction(pinSignInAction)
|
||||
.setTitle(carContext.getString(R.string.settings_action_title))
|
||||
.setInstructions(
|
||||
carContext.getString(R.string.tomtom_api_key)
|
||||
)
|
||||
.setHeaderAction(Action.BACK)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
@@ -14,22 +14,26 @@ import androidx.car.app.model.Template
|
||||
/** Screen for asking the user to grant location permission. */
|
||||
class RequestPermissionScreen(
|
||||
carContext: CarContext,
|
||||
var mLocationPermissionCheckCallback: LocationPermissionCheckCallback,
|
||||
var mContactsPermissionCheckCallback: LocationPermissionCheckCallback,
|
||||
var permissionCheckCallback: PermissionCheckCallback,
|
||||
//var mContactsPermissionCheckCallback: LocationPermissionCheckCallback,
|
||||
val permissions: MutableList<String?> = ArrayList()
|
||||
) : Screen(carContext) {
|
||||
/** Callback called when the location permission is granted. */
|
||||
fun interface LocationPermissionCheckCallback {
|
||||
/** Callback called when the location permission is granted. */
|
||||
|
||||
/** Callback called when the permission is granted. */
|
||||
fun interface PermissionCheckCallback {
|
||||
/** Callback called when the permission is granted. */
|
||||
fun onPermissionGranted()
|
||||
}
|
||||
|
||||
override fun onGetTemplate(): Template {
|
||||
val permissions: MutableList<String?> = ArrayList()
|
||||
permissions.add(permission.ACCESS_FINE_LOCATION)
|
||||
permissions.add("com.google.android.gms.permission.CAR_SPEED")
|
||||
//permissions.add(permission.READ_CONTACTS)
|
||||
|
||||
val message = "This app needs access to location and to car speed"
|
||||
var message = ""
|
||||
if (permissions.contains(permission.ACCESS_FINE_LOCATION))
|
||||
message = "This app needs access to location and to car speed"
|
||||
if (permissions.contains("android.car.permission.CAR_SPEED"))
|
||||
message = "This app needs access to car speed"
|
||||
if (permissions.contains("com.google.android.gms.permission.CAR_SPEED"))
|
||||
message = "This app needs access to car speed"
|
||||
|
||||
val listener: OnClickListener = ParkedOnlyOnClickListener.create {
|
||||
carContext.requestPermissions(
|
||||
@@ -41,8 +45,8 @@ class RequestPermissionScreen(
|
||||
CarToast.LENGTH_LONG
|
||||
).show()
|
||||
if (!approved!!.isEmpty()) {
|
||||
mLocationPermissionCheckCallback.onPermissionGranted()
|
||||
mContactsPermissionCheckCallback.onPermissionGranted()
|
||||
permissionCheckCallback.onPermissionGranted()
|
||||
//mContactsPermissionCheckCallback.onPermissionGranted()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ class RoutePreviewScreen(
|
||||
|
||||
val itemListBuilder = ItemList.Builder()
|
||||
var i = 0
|
||||
routeModel.route.routes.forEach { it ->
|
||||
routeModel.route.routes.forEach { _ ->
|
||||
itemListBuilder.addItem(createRow(i++, navigateAction))
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ class RoutePreviewScreen(
|
||||
.build()
|
||||
|
||||
val message =
|
||||
if (routeModel.isNavigating() && routeModel.curRoute.waypoints!!.isNotEmpty()) {
|
||||
if (routeModel.isNavigating() && routeModel.curRoute.waypoints.isNotEmpty()) {
|
||||
createRouteText(0)
|
||||
} else {
|
||||
CarText.Builder("Wait")
|
||||
@@ -190,7 +190,7 @@ class RoutePreviewScreen(
|
||||
private fun createRouteText(index: Int): CarText {
|
||||
val time = routeModel.route.routes[index].summary.duration
|
||||
val length =
|
||||
BigDecimal(routeModel.route.routes[index].summary.distance).setScale(
|
||||
BigDecimal((routeModel.route.routes[index].summary.distance) / 1000).setScale(
|
||||
1,
|
||||
RoundingMode.HALF_EVEN
|
||||
)
|
||||
@@ -207,7 +207,7 @@ class RoutePreviewScreen(
|
||||
val titleText = "$index"
|
||||
return Row.Builder()
|
||||
.setTitle(route)
|
||||
.setOnClickListener(OnClickListener { onRouteSelected(index) })
|
||||
.setOnClickListener { onRouteSelected(index) }
|
||||
.addText(titleText)
|
||||
.addAction(action)
|
||||
.build()
|
||||
|
||||
@@ -73,14 +73,6 @@ class RoutingSettings(private val carContext: CarContext, private var navigation
|
||||
private fun onSelected(index: Int) {
|
||||
settingsViewModel.onRoutingEngineChanged(index)
|
||||
navigationViewModel.routingEngine.value = index
|
||||
CarToast.makeText(
|
||||
carContext,
|
||||
(carContext
|
||||
.getString(R.string.routing_engine)
|
||||
+ ":"
|
||||
+ " " + index), CarToast.LENGTH_LONG
|
||||
)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun buildRowForTemplate(title: Int): Row {
|
||||
|
||||
Reference in New Issue
Block a user