Handle unrecoverable location errors and stop sharing
This commit is contained in:
-1
@@ -58,7 +58,6 @@ class PlatformLocationProvider(
|
||||
) {
|
||||
throw PermissionException()
|
||||
}
|
||||
|
||||
val locationManager = context.getSystemService(LocationManager::class.java)
|
||||
val provider = PROVIDERS_BY_PRIORITY.firstOrNull { LocationManagerCompat.hasProvider(locationManager, it) }
|
||||
val locationFlow = if (provider != null) {
|
||||
|
||||
+5
@@ -133,6 +133,11 @@ class DefaultActiveLiveLocationShareManager(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun onUnrecoverableError() {
|
||||
Timber.d("ActiveLiveLocationShareManager unrecoverable error, stopping all shares")
|
||||
localSharingRoomIds.value.toList().forEach { stopShare(it) }
|
||||
}
|
||||
|
||||
override suspend fun onLocationUpdate(location: Location) {
|
||||
val activeSharesCount = localSharingRoomIds.value.size
|
||||
Timber.d("ActiveLiveLocationShareManager received location update for $activeSharesCount active share(s)")
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@ package io.element.android.features.location.impl.live.service
|
||||
|
||||
import io.element.android.features.location.api.Location
|
||||
|
||||
fun interface LiveLocationReceiver {
|
||||
interface LiveLocationReceiver {
|
||||
suspend fun onLocationUpdate(location: Location)
|
||||
suspend fun onUnrecoverableError() {}
|
||||
}
|
||||
|
||||
+11
@@ -77,6 +77,17 @@ class LiveLocationSharingCoordinator internal constructor(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun dispatchUnrecoverableError() {
|
||||
Timber.d("LiveLocationSharingCoordinator dispatching unrecoverable error")
|
||||
receivers.forEach { (sessionId, receiver) ->
|
||||
runCatchingExceptions {
|
||||
receiver.onUnrecoverableError()
|
||||
}.onFailure {
|
||||
Timber.e(it, "Failed to dispatch unrecoverable error for session $sessionId")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun dispatch(location: Location) {
|
||||
val currentTimeMillis = nowMillis()
|
||||
val millisSincePrevious = currentTimeMillis - lastDispatchMillis.load()
|
||||
|
||||
+18
-10
@@ -30,12 +30,15 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import org.maplibre.compose.location.DesiredAccuracy
|
||||
import org.maplibre.compose.location.PermissionException
|
||||
import org.maplibre.spatialk.units.extensions.inMeters
|
||||
import org.maplibre.spatialk.units.extensions.meters
|
||||
import timber.log.Timber
|
||||
@@ -48,7 +51,6 @@ class LiveLocationSharingService : Service() {
|
||||
@Inject lateinit var coordinator: LiveLocationSharingCoordinator
|
||||
@Inject lateinit var notificationCreator: LiveLocationSharingNotificationCreator
|
||||
@Inject lateinit var appPreferencesStore: AppPreferencesStore
|
||||
|
||||
@Inject lateinit var appForegroundStateService: AppForegroundStateService
|
||||
|
||||
@AppCoroutineScope
|
||||
@@ -62,8 +64,8 @@ class LiveLocationSharingService : Service() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
Timber.d("LiveLocationSharingService onCreate")
|
||||
bindings<LocationBindings>().inject(this)
|
||||
runCatchingExceptions {
|
||||
bindings<LocationBindings>().inject(this)
|
||||
appForegroundStateService.updateIsSharingLiveLocation(true)
|
||||
coroutineScope = appCoroutineScope.childScope(Dispatchers.Default, "LiveLocationSharingService")
|
||||
val notificationId = NotificationIdProvider.getForegroundServiceNotificationId(ForegroundServiceType.LIVE_LOCATION)
|
||||
@@ -81,6 +83,7 @@ class LiveLocationSharingService : Service() {
|
||||
startLocationUpdatesListener()
|
||||
}.onFailure {
|
||||
Timber.e(it, "Failed to start live location sharing service")
|
||||
appCoroutineScope.launch { coordinator.dispatchUnrecoverableError() }
|
||||
stopSelf()
|
||||
}
|
||||
}
|
||||
@@ -90,14 +93,19 @@ class LiveLocationSharingService : Service() {
|
||||
Timber.d("LiveLocationSharingService listening to location updates")
|
||||
appPreferencesStore.getLiveLocationMinimumDistanceInMetersUpdateFlow()
|
||||
.flatMapLatest { minDistanceMeters ->
|
||||
val locationProvider = PlatformLocationProvider(
|
||||
context = applicationContext,
|
||||
updateInterval = UPDATE_INTERVAL_IN_SECOND.seconds,
|
||||
minDistance = minDistanceMeters.meters,
|
||||
desiredAccuracy = DesiredAccuracy.Balanced,
|
||||
coroutineScope = coroutineScope
|
||||
)
|
||||
locationProvider.location
|
||||
try {
|
||||
PlatformLocationProvider(
|
||||
context = applicationContext,
|
||||
updateInterval = UPDATE_INTERVAL_IN_SECOND.seconds,
|
||||
minDistance = minDistanceMeters.meters,
|
||||
desiredAccuracy = DesiredAccuracy.Balanced,
|
||||
coroutineScope = coroutineScope
|
||||
).location
|
||||
} catch (exception: PermissionException) {
|
||||
Timber.e(exception, "Failed to create PlatformLocationProvider")
|
||||
coordinator.dispatchUnrecoverableError()
|
||||
emptyFlow()
|
||||
}
|
||||
}
|
||||
.filterNotNull()
|
||||
.map { location ->
|
||||
|
||||
Reference in New Issue
Block a user