From aaa57c14b8c42181b6918267a8187a63e37fc635 Mon Sep 17 00:00:00 2001 From: Dimitris Date: Thu, 26 Mar 2026 17:14:43 +0100 Subject: [PATCH] Duration Map --- app/build.gradle.kts | 4 +- .../com/kouros/navigation/ui/MainActivity.kt | 40 --- .../kouros/navigation/car/CarSensorManager.kt | 2 +- .../kouros/navigation/car/ClusterSession.kt | 8 +- .../navigation/car/NavigationSession.kt | 54 ---- .../car/navigation/NavigationService.kt | 258 ------------------ .../navigation/utils/NavigationUtils.kt | 5 +- 7 files changed, 7 insertions(+), 364 deletions(-) delete mode 100644 common/car/src/main/java/com/kouros/navigation/car/navigation/NavigationService.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7bfce88..bfc4272 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -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" } diff --git a/app/src/main/java/com/kouros/navigation/ui/MainActivity.kt b/app/src/main/java/com/kouros/navigation/ui/MainActivity.kt index e64a985..a88cbdc 100644 --- a/app/src/main/java/com/kouros/navigation/ui/MainActivity.kt +++ b/app/src/main/java/com/kouros/navigation/ui/MainActivity.kt @@ -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() { diff --git a/common/car/src/main/java/com/kouros/navigation/car/CarSensorManager.kt b/common/car/src/main/java/com/kouros/navigation/car/CarSensorManager.kt index 3b56910..348e988 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/CarSensorManager.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/CarSensorManager.kt @@ -137,7 +137,7 @@ class CarSensorManager( carCompassListener ) carSensors.addCarHardwareLocationListener( - CarSensors.UPDATE_RATE_FASTEST, + CarSensors.UPDATE_RATE_UI, carContext.mainExecutor, carLocationListener ) diff --git a/common/car/src/main/java/com/kouros/navigation/car/ClusterSession.kt b/common/car/src/main/java/com/kouros/navigation/car/ClusterSession.kt index a837570..6521b21 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/ClusterSession.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/ClusterSession.kt @@ -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() { diff --git a/common/car/src/main/java/com/kouros/navigation/car/NavigationSession.kt b/common/car/src/main/java/com/kouros/navigation/car/NavigationSession.kt index 7cb4383..53a7e89 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/NavigationSession.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/NavigationSession.kt @@ -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?, - steps: MutableList?, - 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() } /** diff --git a/common/car/src/main/java/com/kouros/navigation/car/navigation/NavigationService.kt b/common/car/src/main/java/com/kouros/navigation/car/navigation/NavigationService.kt deleted file mode 100644 index 9027d3f..0000000 --- a/common/car/src/main/java/com/kouros/navigation/car/navigation/NavigationService.kt +++ /dev/null @@ -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?, - steps: MutableList?, - 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) -// } -} diff --git a/common/data/src/main/java/com/kouros/navigation/utils/NavigationUtils.kt b/common/data/src/main/java/com/kouros/navigation/utils/NavigationUtils.kt index fa14350..846aed8 100644 --- a/common/data/src/main/java/com/kouros/navigation/utils/NavigationUtils.kt +++ b/common/data/src/main/java/com/kouros/navigation/utils/NavigationUtils.kt @@ -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 }