Duration Map

This commit is contained in:
Dimitris
2026-03-26 17:14:43 +01:00
parent a3370e42a8
commit aaa57c14b8
7 changed files with 7 additions and 364 deletions

View File

@@ -17,8 +17,8 @@ android {
applicationId = "com.kouros.navigation"
minSdk = 33
targetSdk = 36
versionCode = 82
versionName = "0.2.0.82"
versionCode = 83
versionName = "0.2.0.83"
base.archivesName = "navi-$versionName"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

View File

@@ -43,7 +43,6 @@ import com.google.android.gms.location.LocationServices
import com.kouros.data.R
import com.kouros.navigation.MainApplication.Companion.navigationViewModel
import com.kouros.navigation.car.TextToSpeechManager
import com.kouros.navigation.car.navigation.NavigationService
import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE
import com.kouros.navigation.data.Constants.INSTRUCTION_DISTANCE
import com.kouros.navigation.data.Constants.TAG
@@ -80,8 +79,6 @@ import kotlin.time.Duration.Companion.seconds
class MainActivity : ComponentActivity() {
var navigationService: NavigationService? = null
var isBound: Boolean = false
val routeData = MutableLiveData("")
val routeModel = RouteModel()
@@ -102,20 +99,6 @@ class MainActivity : ComponentActivity() {
}
}
// Monitors the state of the connection to the navigation service.
private val serviceConnection: ServiceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
val binder: NavigationService.LocalBinder = service as NavigationService.LocalBinder
navigationService = binder.service
isBound = true
}
override fun onServiceDisconnected(name: ComponentName?) {
navigationService = null
isBound = false
}
}
val cameraPosition = MutableLiveData(
CameraPosition(
zoom = 15.0, target = Position(latitude = 48.1857475, longitude = 11.5793627)
@@ -168,27 +151,6 @@ class MainActivity : ComponentActivity() {
}
}
override fun onStart() {
super.onStart()
Log.i(TAG, "In onStart()")
bindService(
Intent(this, NavigationService::class.java),
serviceConnection,
BIND_AUTO_CREATE
)
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 1)
}
override fun onStop() {
Log.i(TAG, "In onStop(). bound $isBound")
if (isBound) {
unbindService(serviceConnection)
isBound = false
navigationService = null
}
super.onStop()
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun StartScreen(
@@ -356,7 +318,6 @@ class MainActivity : ComponentActivity() {
routeModel.navState = routeModel.navState.copy(routingEngine = routingEngine)
routeModel.startNavigation(newRoute)
routeData.value = routeModel.curRoute.routeGeoJson
navigationService?.startNavigation()
}
fun stopNavigation(closeSheet: () -> Unit) {
closeSheet()
@@ -364,7 +325,6 @@ class MainActivity : ComponentActivity() {
getSettingsViewModel(applicationContext).onLastRouteChanged("")
routeData.value = ""
stepData.value = StepData("", "", 0.0, 0, 0, 0, 0.0)
navigationService?.stopNavigation()
}
fun textToSpeech() {

View File

@@ -137,7 +137,7 @@ class CarSensorManager(
carCompassListener
)
carSensors.addCarHardwareLocationListener(
CarSensors.UPDATE_RATE_FASTEST,
CarSensors.UPDATE_RATE_UI,
carContext.mainExecutor,
carLocationListener
)

View File

@@ -31,7 +31,6 @@ import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.ViewModelStoreOwner
import androidx.lifecycle.lifecycleScope
import com.kouros.data.R
import com.kouros.navigation.car.navigation.NavigationService
import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.car.screen.NavigationListener
import com.kouros.navigation.car.screen.NavigationScreen
@@ -44,9 +43,6 @@ internal class ClusterSession : Session(), NavigationListener {
var mNavigationCarSurface: SurfaceRenderer? = null
// A reference to the navigation service used to get location updates and routing.
var service: NavigationService? = null
var mSettingsAction: Action? = null
var routeModel = RouteCarModel()
@@ -94,9 +90,7 @@ internal class ClusterSession : Session(), NavigationListener {
override fun stopNavigation() {
if (service != null) {
service!!.stopNavigation()
}
}
override fun startNavigation() {

View File

@@ -32,7 +32,6 @@ import androidx.lifecycle.ViewModelStoreOwner
import androidx.lifecycle.asLiveData
import androidx.lifecycle.coroutineScope
import androidx.lifecycle.lifecycleScope
import com.kouros.navigation.car.navigation.NavigationService
import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.car.navigation.Simulation
import com.kouros.navigation.car.screen.NavigationListener
@@ -98,63 +97,11 @@ class NavigationSession : Session(), NavigationListener {
var navigationManagerStarted = false
var navigationService : NavigationService? = null
val serviceListener : NavigationService.Listener = object : NavigationService.Listener {
override fun navigationStateChanged(
isNavigating: Boolean,
isRerouting: Boolean,
hasArrived: Boolean,
destinations: MutableList<Destination?>?,
steps: MutableList<Step>?,
nextDestinationTravelEstimate: TravelEstimate?,
nextStepRemainingDistance: Distance?,
shouldShowNextStep: Boolean,
shouldShowLanes: Boolean,
junctionImage: CarIcon?
) {
//navigationScreen.updateTrip()
}
}
// Monitors the state of the connection to the Navigation service.
val serviceConnection: ServiceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
Log.i(TAG, "In onServiceConnected() Session component:$service")
val binder: NavigationService.LocalBinder = service as NavigationService.LocalBinder
navigationService = binder.service
navigationService!!.setCarContext(carContext, serviceListener)
}
override fun onServiceDisconnected(name: ComponentName?) {
Log.i(TAG, "In onServiceDisconnected() component: $name")
// Unhook map models here
navigationService!!.clearCarContext()
navigationService = null
}
}
/**
* Lifecycle observer for managing session lifecycle events.
* Cleans up resources when the session is destroyed.
*/
private val lifecycleObserver: LifecycleObserver = object : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
Log.i(TAG, "In onStart() Session")
carContext
.bindService(
Intent(carContext, NavigationService::class.java),
serviceConnection,
Context.BIND_AUTO_CREATE
)
}
override fun onStop(owner: LifecycleOwner) {
Log.i(TAG, "In onStop()")
carContext.unbindService(serviceConnection)
navigationService = null
}
override fun onDestroy(owner: LifecycleOwner) {
if (::navigationManager.isInitialized) {
@@ -485,7 +432,6 @@ class NavigationSession : Session(), NavigationListener {
surfaceRenderer.routeData.value = ""
surfaceRenderer.viewStyle = ViewStyle.VIEW
navigationScreen.navigationType = NavigationType.VIEW
navigationService!!.stopNavigation()
}
/**

View File

@@ -1,258 +0,0 @@
package com.kouros.navigation.car.navigation
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.ComponentName
import android.content.Intent
import android.graphics.BitmapFactory
import android.graphics.Color
import android.os.Binder
import android.os.IBinder
import android.util.Log
import androidx.car.app.CarContext
import androidx.car.app.model.CarIcon
import androidx.car.app.model.Distance
import androidx.car.app.navigation.NavigationManager
import androidx.car.app.navigation.model.Destination
import androidx.car.app.navigation.model.Step
import androidx.car.app.navigation.model.TravelEstimate
import androidx.car.app.notification.CarAppExtender
import androidx.car.app.notification.CarPendingIntent
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.kouros.data.R
import com.kouros.navigation.car.NavigationCarAppService
import com.kouros.navigation.data.Constants.TAG
import androidx.core.graphics.toColorInt
class NavigationService : Service() {
val DEEP_LINK_ACTION: String = ("com.kouros.navigation.car.navigation"
+ ".NavigationDeepLinkAction")
val channelId : String = "NavigationServiceChannel"
/** The identifier for the navigation notification displayed for the foreground service. */
val NAV_NOTIFICATION_ID: Int = 87356325
/** The identifier for the non-navigation notifications, such as a traffic accident warning. */
val NOTIFICATION_ID: Int = 71653346
// Constants for location broadcast
val PACKAGE_NAME: String =
"androidx.car.app.sample.navigation.common.nav.navigationservice"
val EXTRA_STARTED_FROM_NOTIFICATION: String = PACKAGE_NAME + ".started_from_notification"
val CANCEL_ACTION: String = "CANCEL"
private var notificationManager: NotificationManager? = null
private var carContext: CarContext? = null
private lateinit var listener: Listener
// Model for managing route state and navigation logic for Android Auto
var routeModel = RouteCarModel()
private lateinit var navigationManager: NavigationManager
private var navigationManagerInitialized = false
var binder: IBinder = LocalBinder()
override fun onBind(p0: Intent?): IBinder {
return binder
}
override fun onUnbind(intent: Intent): Boolean {
return true
}
/** A listener for the navigation state changes. */
interface Listener {
/** Callback called when the navigation state changes. */
fun navigationStateChanged(
isNavigating: Boolean,
isRerouting: Boolean,
hasArrived: Boolean,
destinations: MutableList<Destination?>?,
steps: MutableList<Step>?,
nextDestinationTravelEstimate: TravelEstimate?,
nextStepRemainingDistance: Distance?,
shouldShowNextStep: Boolean,
shouldShowLanes: Boolean,
junctionImage: CarIcon?
)
}
/**
* Class used for the client Binder. Since this service runs in the same process as its clients,
* we don't need to deal with IPC.
*/
inner class LocalBinder : Binder() {
val service: NavigationService
get() = this@NavigationService
}
override fun onCreate() {
Log.i(TAG, "In onCreate()");
createNotificationChannel();
}
/** Sets the [CarContext] to use while the service is connected. */
fun setCarContext(
carContext: CarContext,
listener: Listener
) {
Log.d(TAG, "in setCarContext")
this.carContext = carContext
navigationManagerInitialized = true
// navigationManager =
// carContext.getCarService(NavigationManager::class.java)
// navigationManager.setNavigationManagerCallback(
// object : NavigationManagerCallback {
// override fun onStopNavigation() {
// this@NavigationService.stopNavigation()
// }
//
// override fun onAutoDriveEnabled() {
// Log.d(TAG, "onAutoDriveEnabled called")
// CarToast.makeText(carContext, "Auto drive enabled", CarToast.LENGTH_LONG)
// .show()
// }
// })
this.listener = listener
// Uncomment if navigating
// mNavigationManager.navigationStarted();
}
/** Clears the currently used {@link CarContext}. */
fun clearCarContext() {
carContext = null;
// navigationManager.clearNavigationManagerCallback();
}
/** Starts navigation. */
fun startNavigation() {
Log.i(TAG, "Starting Navigation")
startService(Intent(applicationContext, NavigationService::class.java))
Log.i(TAG, "Starting foreground service")
startForeground(
NAV_NOTIFICATION_ID,
getNotification(
true,
showInCar = false,
navigatingDisplayTitle = getString(R.string.navigation_settings),
navigatingDisplayContent = null,
notificationIcon = R.drawable.navigation_48px
)
)
listener.navigationStateChanged(
isNavigating = false,
isRerouting = true,
hasArrived = false,
destinations = null,
steps = null,
nextDestinationTravelEstimate = null,
nextStepRemainingDistance = null,
shouldShowNextStep = false,
shouldShowLanes = false,
junctionImage = null
)
}
/** Starts navigation. */
fun stopNavigation() {
// if (navigationManagerInitialized)
// navigationManager.navigationEnded()
listener.navigationStateChanged(
false,
isRerouting = false,
hasArrived = false,
destinations = null,
steps = null,
nextDestinationTravelEstimate = null,
nextStepRemainingDistance = null,
shouldShowNextStep = false,
shouldShowLanes = false,
junctionImage = null,
)
stopForeground(STOP_FOREGROUND_REMOVE)
stopSelf()
}
private fun createNotificationChannel() {
notificationManager =
getSystemService(NotificationManager::class.java)
val name: CharSequence = getString(R.string.navigation_settings)
val serviceChannel =
NotificationChannel(
channelId,
name,
NotificationManager.IMPORTANCE_HIGH
)
notificationManager!!.createNotificationChannel(serviceChannel)
}
/** Returns the [NotificationCompat] used as part of the foreground service. */
private fun getNotification(
shouldNotify: Boolean,
showInCar: Boolean,
navigatingDisplayTitle: CharSequence?,
navigatingDisplayContent: CharSequence?,
notificationIcon: Int
): Notification {
val builder: NotificationCompat.Builder =
NotificationCompat.Builder(this, channelId)
//.setContentIntent(createMainActivityPendingIntent())
.setContentTitle(navigatingDisplayTitle)
.setContentText(navigatingDisplayContent)
.setOngoing(true)
.setCategory(NotificationCompat.CATEGORY_NAVIGATION)
.setOnlyAlertOnce(!shouldNotify) // Set the notification's background color on the car screen.
.setColor(
"#003000".toColorInt()
)
.setColorized(true)
.setSmallIcon(R.drawable.ic_pan_24)
.setLargeIcon(
BitmapFactory.decodeResource(resources, notificationIcon)
)
.setTicker(navigatingDisplayTitle)
.setWhen(System.currentTimeMillis())
builder.setChannelId(channelId)
builder.setPriority(NotificationManager.IMPORTANCE_HIGH)
if (showInCar) {
val intent = Intent(Intent.ACTION_VIEW)
.setComponent(ComponentName(this, NavigationCarAppService::class.java))
.setData(NavigationCarAppService().createDeepLinkUri(Intent.ACTION_VIEW))
builder.extend(
CarAppExtender.Builder()
.setImportance(NotificationManagerCompat.IMPORTANCE_HIGH)
.setContentIntent(
CarPendingIntent.getCarApp(
this, intent.hashCode(),
intent,
0
)
)
.build()
)
}
return builder.build()
}
// private fun createMainActivityPendingIntent(): PendingIntent? {
// val intent: Intent = Intent(this, MainActivity::class.java)
// intent.putExtra(EXTRA_STARTED_FROM_NOTIFICATION, true)
// return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)
// }
}

View File

@@ -141,8 +141,9 @@ fun duration(
val cameraDuration = if ((lastBearing - bearing).absoluteValue > 20.0) {
2.seconds
} else {
val updateDuration = java.time.Duration.between(LocalDateTime.now(), lastLocationUpdate)
((updateDuration!!.toMillis().absoluteValue * 1.2).toDuration(DurationUnit.MILLISECONDS))
1.seconds
//val updateDuration = java.time.Duration.between(LocalDateTime.now(), lastLocationUpdate)
//((updateDuration!!.toMillis().absoluteValue * 1.2).toDuration(DurationUnit.MILLISECONDS))
}
return cameraDuration
}