Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use SettingsClient on Android to detect if location is enabled #171

Merged
merged 2 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ internal class DefaultBrowserLocator : BrowserLocator {
)
override val locationUpdates: Flow<Location> = _locationUpdates

override fun isAvailable(): Boolean {
override suspend fun isAvailable(): Boolean {
return navigator?.geolocation != null
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ internal class AndroidLocator(
override val locationUpdates: Flow<Location> = locationManager.locationUpdates
.mapNotNull { result -> result.lastLocation?.toModel() }

override fun isAvailable(): Boolean {
override suspend fun isAvailable(): Boolean {
return locationManager.locationEnabled()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@ package dev.jordond.compass.geolocation.mobile.internal
import android.content.Context
import android.location.Location
import android.location.LocationManager
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.os.Looper
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationResult
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.LocationSettingsRequest
import com.google.android.gms.location.Priority.PRIORITY_BALANCED_POWER_ACCURACY
import com.google.android.gms.location.Priority.PRIORITY_HIGH_ACCURACY
import com.google.android.gms.location.Priority.PRIORITY_LOW_POWER
import com.google.android.gms.location.Priority.PRIORITY_PASSIVE
import com.google.android.gms.location.SettingsClient
import com.google.android.gms.tasks.CancellationTokenSource
import dev.jordond.compass.exception.NotFoundException
import kotlinx.coroutines.ExperimentalCoroutinesApi
Expand All @@ -33,11 +41,25 @@ internal class LocationManager(
LocationServices.getFusedLocationProviderClient(context)
}

fun locationEnabled(): Boolean {
val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
private val settingsClient: SettingsClient by lazy {
LocationServices.getSettingsClient(context)
}

suspend fun locationEnabled(): Boolean {
val request = LocationSettingsRequest.Builder().addAllLocationRequests(
listOf(
LocationRequest.Builder(PRIORITY_HIGH_ACCURACY, 1000).build(),
LocationRequest.Builder(PRIORITY_BALANCED_POWER_ACCURACY, 1000).build(),
LocationRequest.Builder(PRIORITY_PASSIVE, 1000).build(),
LocationRequest.Builder(PRIORITY_LOW_POWER, 1000).build(),
)
).build()

return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
|| locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
val result = runCatching {
settingsClient.checkLocationSettings(request).await()
}.isSuccess

return result || legacyLocationEnabled()
}

@OptIn(ExperimentalCoroutinesApi::class)
Expand Down Expand Up @@ -75,4 +97,16 @@ internal class LocationManager(
locationCallback = null
}
}

private fun legacyLocationEnabled(): Boolean {
val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager

val providers = listOfNotNull(
LocationManager.GPS_PROVIDER,
LocationManager.NETWORK_PROVIDER,
if (VERSION.SDK_INT >= VERSION_CODES.S) LocationManager.FUSED_PROVIDER else null,
)

return providers.any { locationManager.isProviderEnabled(it) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ internal class IosLocator(
}
}

override fun isAvailable(): Boolean {
override suspend fun isAvailable(): Boolean {
return CLLocationManager.locationServicesEnabled()
}

Expand Down
6 changes: 3 additions & 3 deletions compass-geolocation/api/android/compass-geolocation.api
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public abstract interface class dev/jordond/compass/geolocation/Geolocator {
public abstract fun current (Ldev/jordond/compass/Priority;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun getLocationUpdates ()Lkotlinx/coroutines/flow/Flow;
public abstract fun getTrackingStatus ()Lkotlinx/coroutines/flow/Flow;
public abstract fun isAvailable ()Z
public abstract fun isAvailable (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun startTracking (Ldev/jordond/compass/geolocation/LocationRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun stopTracking ()V
public abstract fun track (Ldev/jordond/compass/geolocation/LocationRequest;)Lkotlinx/coroutines/flow/Flow;
Expand Down Expand Up @@ -136,7 +136,7 @@ public abstract interface class dev/jordond/compass/geolocation/Locator {
public static final field Companion Ldev/jordond/compass/geolocation/Locator$Companion;
public abstract fun current (Ldev/jordond/compass/Priority;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun getLocationUpdates ()Lkotlinx/coroutines/flow/Flow;
public abstract fun isAvailable ()Z
public abstract fun isAvailable (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun stopTracking ()V
public abstract fun track (Ldev/jordond/compass/geolocation/LocationRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
Expand All @@ -153,7 +153,7 @@ public final class dev/jordond/compass/geolocation/NotSupportedLocator : dev/jor
public static final field INSTANCE Ldev/jordond/compass/geolocation/NotSupportedLocator;
public fun current (Ldev/jordond/compass/Priority;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun getLocationUpdates ()Lkotlinx/coroutines/flow/Flow;
public fun isAvailable ()Z
public fun isAvailable (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun stopTracking ()V
public fun track (Ldev/jordond/compass/geolocation/LocationRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
Expand Down
6 changes: 3 additions & 3 deletions compass-geolocation/api/jvm/compass-geolocation.api
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public abstract interface class dev/jordond/compass/geolocation/Geolocator {
public abstract fun current (Ldev/jordond/compass/Priority;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun getLocationUpdates ()Lkotlinx/coroutines/flow/Flow;
public abstract fun getTrackingStatus ()Lkotlinx/coroutines/flow/Flow;
public abstract fun isAvailable ()Z
public abstract fun isAvailable (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun startTracking (Ldev/jordond/compass/geolocation/LocationRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun stopTracking ()V
public abstract fun track (Ldev/jordond/compass/geolocation/LocationRequest;)Lkotlinx/coroutines/flow/Flow;
Expand Down Expand Up @@ -136,7 +136,7 @@ public abstract interface class dev/jordond/compass/geolocation/Locator {
public static final field Companion Ldev/jordond/compass/geolocation/Locator$Companion;
public abstract fun current (Ldev/jordond/compass/Priority;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun getLocationUpdates ()Lkotlinx/coroutines/flow/Flow;
public abstract fun isAvailable ()Z
public abstract fun isAvailable (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun stopTracking ()V
public abstract fun track (Ldev/jordond/compass/geolocation/LocationRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
Expand All @@ -153,7 +153,7 @@ public final class dev/jordond/compass/geolocation/NotSupportedLocator : dev/jor
public static final field INSTANCE Ldev/jordond/compass/geolocation/NotSupportedLocator;
public fun current (Ldev/jordond/compass/Priority;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun getLocationUpdates ()Lkotlinx/coroutines/flow/Flow;
public fun isAvailable ()Z
public fun isAvailable (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun stopTracking ()V
public fun track (Ldev/jordond/compass/geolocation/LocationRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public interface Geolocator {
*
* @return `true` if location services are available, `false` otherwise.
*/
public fun isAvailable(): Boolean
public suspend fun isAvailable(): Boolean

/**
* Get the current location.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public interface Locator {
/**
* Check if the platform supports geolocation.
*/
public fun isAvailable(): Boolean
public suspend fun isAvailable(): Boolean

/**
* Get the current location.
Expand Down Expand Up @@ -86,7 +86,7 @@ public interface PermissionLocator : Locator {
public object NotSupportedLocator : Locator {

override val locationUpdates: Flow<Location> = emptyFlow()
override fun isAvailable(): Boolean = false
override suspend fun isAvailable(): Boolean = false
override suspend fun current(priority: Priority): Location = throw NotSupportedException()
override suspend fun track(request: LocationRequest): Flow<Location> = emptyFlow()
override fun stopTracking() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ internal class DefaultGeolocator(

override val trackingStatus: Flow<TrackingStatus> = status

override fun isAvailable(): Boolean = locator.isAvailable()
override suspend fun isAvailable(): Boolean = locator.isAvailable()

override suspend fun current(priority: Priority): GeolocatorResult {
return handleResult { locator.current(priority) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ import kotlinx.coroutines.launch
class GeolocationModel(private val geolocator: Geolocator) : StateScreenModel<State>(State()) {

init {
val isAvailable = geolocator.isAvailable()
updateState { it.copy(locationServiceAvailable = isAvailable) }
screenModelScope.launch {
val isAvailable = geolocator.isAvailable()
updateState { it.copy(locationServiceAvailable = isAvailable) }
}

geolocator.trackingStatus
.onEach { status ->
Expand Down
Loading