mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 12:07:28 +00:00
Support Google Play Services fused location backend
This commit is contained in:
+1
-1
@@ -25,7 +25,7 @@ class DefaultUserLocationStateFactory : UserLocationState.Factory {
|
||||
@Composable
|
||||
override fun create(hasLocationPermission: Boolean): UserLocationState {
|
||||
val locationProvider = if (hasLocationPermission) {
|
||||
rememberPlatformLocationProvider()
|
||||
rememberLocationProvider()
|
||||
} else {
|
||||
rememberNotGrantedLocationProvider()
|
||||
}
|
||||
|
||||
+36
-6
@@ -26,9 +26,12 @@ import androidx.core.location.LocationListenerCompat
|
||||
import androidx.core.location.LocationManagerCompat
|
||||
import androidx.core.location.LocationRequestCompat
|
||||
import androidx.core.os.ExecutorCompat
|
||||
import io.element.android.libraries.core.data.tryOrNull
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import org.maplibre.compose.location.AndroidLocationBackend
|
||||
import org.maplibre.compose.location.LocationAccuracy
|
||||
import org.maplibre.compose.location.LocationEvent
|
||||
import org.maplibre.compose.location.LocationProvider
|
||||
@@ -36,11 +39,33 @@ import org.maplibre.compose.location.LocationRequest
|
||||
import org.maplibre.compose.location.LocationUnavailableReason
|
||||
import org.maplibre.compose.location.asMapLibreLocation
|
||||
import org.maplibre.spatialk.units.extensions.inMeters
|
||||
import java.util.ServiceLoader
|
||||
|
||||
/**
|
||||
* Creates the location provider to use.
|
||||
*
|
||||
* Mostly mirrors `createDefaultLocationProvider` from maplibre compose: any [AndroidLocationBackend]
|
||||
* registered through [ServiceLoader] takes precedence, highest [priority]
|
||||
* first. When no backend is available it falls back to [PlatformLocationProvider].
|
||||
*/
|
||||
fun createLocationProvider(context: Context): LocationProvider {
|
||||
val backend = tryOrNull {
|
||||
ServiceLoader.load(AndroidLocationBackend::class.java)
|
||||
.filter { it.isAvailable(context) }
|
||||
.minWithOrNull(compareByDescending<AndroidLocationBackend> { it.priority }.thenBy { it.id })
|
||||
}
|
||||
return backend?.createLocationProvider(context) ?: PlatformLocationProvider(context)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberLocationProvider(context: Context = LocalContext.current): LocationProvider {
|
||||
return remember(context) { createLocationProvider(context) }
|
||||
}
|
||||
|
||||
|
||||
class PlatformLocationProvider(
|
||||
private val context: Context,
|
||||
) : LocationProvider {
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
override fun updates(request: LocationRequest): Flow<LocationEvent> = callbackFlow {
|
||||
if (!context.hasLocationPermission()) {
|
||||
@@ -58,6 +83,7 @@ class PlatformLocationProvider(
|
||||
trySend(LocationEvent.Unavailable(LocationUnavailableReason.ServicesDisabled))
|
||||
}
|
||||
}
|
||||
|
||||
var registered = false
|
||||
|
||||
fun refreshRegistration() {
|
||||
@@ -126,7 +152,7 @@ class PlatformLocationProvider(
|
||||
close()
|
||||
}
|
||||
awaitClose {
|
||||
runCatching { context.unregisterReceiver(settingsReceiver) }
|
||||
tryOrNull { context.unregisterReceiver(settingsReceiver) }
|
||||
LocationManagerCompat.removeUpdates(locationManager, listener)
|
||||
}
|
||||
}
|
||||
@@ -155,9 +181,13 @@ private fun LocationAccuracy.toLocationRequestQuality(): Int = when (this) {
|
||||
LocationAccuracy.Low, LocationAccuracy.Lowest -> LocationRequestCompat.QUALITY_LOW_POWER
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberPlatformLocationProvider(context: Context = LocalContext.current): PlatformLocationProvider {
|
||||
return remember(context) {
|
||||
PlatformLocationProvider(context = context)
|
||||
class NotGrantedLocationProvider : LocationProvider {
|
||||
override fun updates(request: LocationRequest): Flow<LocationEvent> {
|
||||
return flowOf(LocationEvent.Unavailable(LocationUnavailableReason.PermissionDenied))
|
||||
}
|
||||
}
|
||||
@Composable
|
||||
|
||||
fun rememberNotGrantedLocationProvider(): NotGrantedLocationProvider {
|
||||
return remember { NotGrantedLocationProvider() }
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.location.impl.common.userlocation
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import org.maplibre.compose.location.LocationEvent
|
||||
import org.maplibre.compose.location.LocationProvider
|
||||
import org.maplibre.compose.location.LocationRequest
|
||||
import org.maplibre.compose.location.LocationUnavailableReason
|
||||
|
||||
class NotGrantedLocationProvider : LocationProvider {
|
||||
override fun updates(request: LocationRequest): Flow<LocationEvent> {
|
||||
return flowOf(LocationEvent.Unavailable(LocationUnavailableReason.PermissionDenied))
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberNotGrantedLocationProvider(): NotGrantedLocationProvider {
|
||||
return remember { NotGrantedLocationProvider() }
|
||||
}
|
||||
+2
-2
@@ -14,7 +14,7 @@ import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION
|
||||
import android.os.IBinder
|
||||
import androidx.core.app.ServiceCompat
|
||||
import dev.zacsweers.metro.Inject
|
||||
import io.element.android.features.location.impl.common.userlocation.PlatformLocationProvider
|
||||
import io.element.android.features.location.impl.common.userlocation.createLocationProvider
|
||||
import io.element.android.features.location.impl.di.LocationBindings
|
||||
import io.element.android.features.location.impl.live.notification.LiveLocationSharingNotificationCreator
|
||||
import io.element.android.libraries.architecture.bindings
|
||||
@@ -90,7 +90,7 @@ class LiveLocationSharingService : Service() {
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
private fun startLocationUpdatesListener() {
|
||||
Timber.d("LiveLocationSharingService listening to location updates")
|
||||
val locationProvider = PlatformLocationProvider(context = applicationContext)
|
||||
val locationProvider = createLocationProvider(context = applicationContext)
|
||||
appPreferencesStore.getLiveLocationMinimumDistanceInMetersUpdateFlow()
|
||||
.flatMapLatest { minDistanceMeters ->
|
||||
val locationRequest = LocationRequest(
|
||||
|
||||
Reference in New Issue
Block a user