npx claudepluginhub davidortinau/maui-skills --plugin maui-skillsThis skill uses the workspace's default tool permissions.
`GetLocationAsync` can hang indefinitely if GPS is off, the device is indoors,
Guides adding map controls, pins, polygons, polylines, geocoding, Google Maps API keys, and platform setup in .NET MAUI apps using Microsoft.Maui.Controls.Maps. Addresses common pitfalls like blank maps and crashes.
Enables device geolocation access in Tauri v2 apps using the official plugin, with permission handling, privacy controls, accuracy/frequency config, and opt-out defaults.
API reference for Core Location (iOS 17+): CLLocationUpdate live updates, CLMonitor geofencing, CLServiceSession authorization, background location.
Share bugs, ideas, or general feedback.
GetLocationAsync can hang indefinitely if GPS is off, the device is indoors,
or permissions are in a pending state. Always set a timeout.
// ❌ Hangs forever if no GPS fix is available
var location = await Geolocation.Default.GetLocationAsync(
new GeolocationRequest(GeolocationAccuracy.High));
// ✅ Times out after 30 seconds
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
var location = await Geolocation.Default.GetLocationAsync(
new GeolocationRequest(GeolocationAccuracy.High), cts.Token);
Use the lowest accuracy that satisfies your feature. Higher accuracy drains battery significantly faster — especially on Android.
| Use case | Recommended accuracy |
|---|---|
| City-level / weather | Lowest or Low |
| Nearby search / store finder | Medium |
| Turn-by-turn navigation | High or Best |
Users can grant "approximate" location (accuracy > 1 km). Your app receives a location, but it may be useless for precision features.
location.Accuracy — values > 100 m likely indicate reduced precision.GeolocationRequest.RequestFullAccuracy with a key matching
NSLocationTemporaryUsageDescriptionDictionary in Info.plist to
prompt for full accuracy.// ⚠️ Always check in security-sensitive flows (e.g., geofence, check-in)
if (location.IsFromMockProvider)
{
// Reject — user is spoofing location
}
Altitude 0.0 is not sea levelSome Android devices return 0.0 for Altitude when the GPS has no
barometric sensor. Treat 0.0 as "unknown", not sea level.
ACCESS_BACKGROUND_LOCATION must be requested separately from foreground
permissions and triggers a distinct system dialog. Requesting it together with
foreground permissions causes both to be denied on some devices.
GetLastKnownLocationAsync returns nullThis is expected on first boot or after a location-data reset. Always fall
back to GetLocationAsync:
// ✅ Cache-first with fresh fallback
var location = await geolocation.GetLastKnownLocationAsync();
if (location is null || location.Timestamp < DateTimeOffset.UtcNow.AddMinutes(-5))
{
location = await geolocation.GetLocationAsync(
new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10)), ct);
}
Call Permissions.RequestAsync<Permissions.LocationWhenInUse>() first, or
catch PermissionException. Calling GetLocationAsync without permission
throws on some platforms and returns null on others — inconsistent
behaviour across platforms.
Failing to remove the LocationChanged handler when stopping causes
continued GPS usage and battery drain.
// ❌ Forgetting to unsubscribe — GPS stays active
public void StopTracking()
{
Geolocation.Default.StopListeningForeground();
// LocationChanged handler still fires!
}
// ✅ Always remove the event handler
public void StopTracking()
{
Geolocation.Default.StopListeningForeground();
Geolocation.Default.LocationChanged -= OnLocationChanged;
}
CancellationToken passed to every GetLocationAsync callBest)GetLastKnownLocationAsync null-check with GetLocationAsync fallbackLocationChanged handler removed when stopping continuous listeningACCESS_BACKGROUND_LOCATION requested separately (if needed)NSLocationTemporaryUsageDescriptionDictionary added for full-accuracy promptIsFromMockProvider checked in security-sensitive flows