CharlieW
11/20/2023, 6:18 PMactual class LocationProviderImpl : LocationProvider {
private val locationManager = CLLocationManager()
private class LocationDelegate : NSObject(), CLLocationManagerDelegateProtocol {
var onLocationUpdate: ((Location?) -> Unit)? = null
override fun locationManager(manager: CLLocationManager, didUpdateLocations: List<*>) {
//This is correctly called for the first few locations then stops
didUpdateLocations.firstOrNull()?.let {
val location = it as CLLocation
location.coordinate.useContents {
onLocationUpdate?.invoke(Location(latitude, longitude, it.altitude))
}
}
}
override fun locationManager(manager: CLLocationManager, didFailWithError: NSError) {
//This never gets called
onLocationUpdate?.invoke(null)
}
}
override fun getCurrentLocationAsFlow(): Flow<Location?> = callbackFlow {
locationManager.requestAlwaysAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = kCLDistanceFilterNone
val locationDelegate = LocationDelegate()
locationDelegate.onLocationUpdate = { location ->
trySend(
location
).isSuccess
}
locationManager.delegate = locationDelegate
locationManager.startUpdatingLocation()
awaitClose {
//This is never called
locationManager.stopUpdatingLocation()
}
}.flowOn(<http://Dispatchers.IO|Dispatchers.IO>)
fun requestBackground() {
locationManager.allowsBackgroundLocationUpdates = true
}
fun stopBackground() {
locationManager.allowsBackgroundLocationUpdates = false
}
fun stopLocationUpdates() {
locationManager.stopUpdatingLocation()
}
}
This is used as follows:
object GpsService {
private lateinit var locationClient: LocationProviderImpl
private var initialized = false
private var serviceScope = CoroutineScope(<http://Dispatchers.IO|Dispatchers.IO>)
fun initialize(appModule: AppModule) {
if (!initialized) {
locationClient = LocationProviderImpl()
}
}
fun startLocationListener() {
locationClient.getCurrentLocationAsFlow().cancellable()
.catch { e ->
e.printStackTrace()
}
.mapNotNull { it }
.onEach { location ->
// send location to view
_state.update {
it.copy(
currentLocation = location,
formattedAltitude = getFormattedAltitude(location.altitude)
)
}
}.launchIn(serviceScope)
}
I get no errors or warnings (and have set breakpoints / println()s all over the place) and no error or catch blocks ever get hit, I just stop getting any locations back after the first few. It was all working fine with Kotlin 1.8.2!ElliotSknr
12/01/2023, 1:13 PM