For the complete documentation index, see llms.txt. This page is also available as Markdown.

📱Android / iOS

Compass supports Geolocation on Android and iOS by using the built in location services.

To use the Geolocator, it requires the user to provide permission. This is handled automatically when you start tracking or attempt to get the current location.

Make sure you read the Android and iOS documentation to fully understand how the location services work.

If your project supports both Mobile and other targets, you need to configure your setup to provide a Geolocator for each platform. Check out Mixed platformsfor more information.

Usage

Follow these steps to create a Geolocator

Create Locator

Geolocator is powered by the Locator object:

val locator: Locator = MobileLocator()
val locator: Locator = Locator.mobile()

Create Geolocator

Then you can use that to create the Geolocator object:

val geolocator: Geolocator = Geolocator(locator)

Or you can use an extension function to skip the Locator step:

val geolocator: Geolocator = Geolocator()
val geolocator: Geolocator = MobileGeolocator()
val geolocator: Geolocator = Geolocator.mobile()

Permissions

The user needs to grant permission in order to get location data.

On Android there are no further steps required, but on iOS you need to edit your info.plist, see Android / iOS to learn more.

When you attempt to access the location, Compass will automatically ask the user for permission.

Precise and approximate location

A granted permission does not mean the app can read a precise location. The user can allow location while withholding precision, on Android by answering "Approximate" and on iOS by turning Precise Location off, and the fixes that follow are accurate to kilometres rather than metres. Priority.HighAccuracy does not override that, the system clamps the request.

LocationPermissionController.grantedAccuracy() reports which of the two the app currently holds. It reads the current state and never prompts.

Google Play Services on Android

On Android there are two ways to read a location, and you can pick which one you want.

geolocation-mobile uses the built-in LocationManager and doesn't depend on Google Play Services. It works on every Android device, including ones without Play Services, and it's safe to use in a copyleft licensed app.

geolocation-android-gms adds the Play Services fused location provider, which combines GPS, Wi-Fi, cell and sensors to get better locations while using less battery. It pulls in the closed source play-services-location library.

Using the fused provider

Add the artifact to your Android source set, that's the only step:

Your common code doesn't change. MobileLocator() and Geolocator.mobile() will prefer the fused provider, and fall back to LocationManager on devices where Play Services is missing or out of date:

If you want the fused provider and nothing else, so that a device without Play Services fails instead of falling back, the artifact also has Android-only entry points:

Which one to use

  • You want the best accuracy and battery usage, and depending on Play Services is fine, then add geolocation-android-gms.

  • You can't have proprietary dependencies, maybe you're shipping to F-Droid or your app is GPL licensed, then you don't need to do anything since geolocation-mobile already covers you.

  • You want to support devices without Play Services, but still get the fused locations where they exist, then add geolocation-android-gms and the fallback is handled for you.

What changes without Play Services

Location still works, but the two sources aren't identical.

The accuracy will differ. On API 31 and above the platform has a fused provider of its own, which Compass uses, and it's close to the Play Services one. Below API 31 there is no fused source, so Compass picks GPS or network based on the request priority. Expect slower first locations and more variance there.

isAvailable() reports whether location services are turned on, while the Play Services version also checks the request settings.

The interval option is honoured by both, see below.

Get location

Now you can follow the steps in Geolocator

Request options

LocationRequest carries more than the priority. Two of its options behave in ways worth knowing about on mobile.

interval

The gap between location updates while tracking, defaulting to 5 seconds.

On Android this is passed to the location provider, and the minimum update interval is held to the same value. Without that the provider is free to deliver updates at twice the rate you asked for whenever another app is already using location. That applies to both the built-in LocationManager and the fused provider.

CoreLocation has no time based equivalent, it reports a fix whenever it has one, so on iOS the interval is applied to the updates as they come out. The first update after track always arrives, later ones are dropped until the interval has elapsed. The rate CoreLocation itself runs at is unchanged, so this costs no extra battery, and it does not make updates arrive any sooner than CoreLocation produces them.

maximumAge

How old a cached location may be and still satisfy current(), in milliseconds. It defaults to 0, which always requests a fresh fix.

Set it and current() will hand back the last known location when that location is young enough, which is immediate rather than the seconds a fresh fix takes. Age is the only criteria, matching the W3C Geolocation API option it is modelled on, so a cached fix that is less accurate than you asked for still counts. If nothing suitable is cached, a fresh location is requested as usual.

Last updated

Was this helpful?