NavigationService
This commit is contained in:
@@ -0,0 +1,97 @@
|
|||||||
|
package com.kouros.navigation.car
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.location.Location
|
||||||
|
import android.location.LocationManager
|
||||||
|
import androidx.car.app.CarContext
|
||||||
|
import androidx.core.location.LocationListenerCompat
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
|
import com.kouros.navigation.car.navigation.NavigationService
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages device GPS location updates for navigation.
|
||||||
|
* Coordinates with car hardware sensors to avoid duplicate location sources.
|
||||||
|
*
|
||||||
|
* @param carContext The car context for accessing system services
|
||||||
|
* @param serviceOwner Owner of the lifecycle for coroutine management
|
||||||
|
* @param shouldUseCarLocationFlow Flow indicating whether car location hardware should be used
|
||||||
|
* @param onLocationUpdate Callback invoked when location updates are received
|
||||||
|
* @param onInitialLocation Callback invoked with the last known location when starting
|
||||||
|
*/
|
||||||
|
class DeviceLocationManagerService(
|
||||||
|
private val carContext: CarContext,
|
||||||
|
private val onLocationUpdate: (Location) -> Unit,
|
||||||
|
private val onInitialLocation: (Location) -> Unit
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val locationManager: LocationManager =
|
||||||
|
carContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
||||||
|
|
||||||
|
private var shouldUseDeviceLocation = true
|
||||||
|
private var isListening = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Location listener that receives GPS updates from the device.
|
||||||
|
* Only processes location if car location hardware is not being used.
|
||||||
|
*/
|
||||||
|
private val locationListener: LocationListenerCompat = LocationListenerCompat { location ->
|
||||||
|
if (shouldUseDeviceLocation) {
|
||||||
|
onLocationUpdate(location)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts requesting location updates from device GPS.
|
||||||
|
* Provides initial location via callback and then starts continuous updates.
|
||||||
|
*
|
||||||
|
* @param minTimeMs Minimum time interval between updates in milliseconds (default: 500ms)
|
||||||
|
* @param minDistanceM Minimum distance between updates in meters (default: 5m)
|
||||||
|
*/
|
||||||
|
@SuppressLint("MissingPermission")
|
||||||
|
fun startLocationUpdates(minTimeMs: Long = 1000, minDistanceM: Float = 1.0f) {
|
||||||
|
if (isListening) return
|
||||||
|
|
||||||
|
// Get and deliver last known location first
|
||||||
|
val lastLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
|
||||||
|
if (lastLocation != null) {
|
||||||
|
onInitialLocation(lastLocation)
|
||||||
|
onLocationUpdate(lastLocation)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start continuous location updates
|
||||||
|
locationManager.requestLocationUpdates(
|
||||||
|
LocationManager.GPS_PROVIDER,
|
||||||
|
minTimeMs,
|
||||||
|
minDistanceM,
|
||||||
|
locationListener
|
||||||
|
)
|
||||||
|
isListening = true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops receiving location updates from device GPS.
|
||||||
|
* Should be called when the session is destroyed to prevent memory leaks.
|
||||||
|
*/
|
||||||
|
fun stopLocationUpdates() {
|
||||||
|
if (!isListening) return
|
||||||
|
|
||||||
|
locationManager.removeUpdates(locationListener)
|
||||||
|
isListening = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if location updates are currently active.
|
||||||
|
*/
|
||||||
|
fun isListeningForUpdates(): Boolean = isListening
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user