# Maui Geolocation

> >

- **Type:** Skill
- **Install:** `agentstack add skill-davidortinau-maui-skills-maui-geolocation`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [davidortinau](https://agentstack.voostack.com/s/davidortinau)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [davidortinau](https://github.com/davidortinau)
- **Source:** https://github.com/davidortinau/maui-skills/tree/main/plugins/maui-skills/skills/maui-geolocation

## Install

```sh
agentstack add skill-davidortinau-maui-skills-maui-geolocation
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# .NET MAUI Geolocation

## Critical: Always Pass a CancellationToken

`GetLocationAsync` can hang indefinitely if GPS is off, the device is indoors,
or permissions are in a pending state. Always set a timeout.

```csharp
// ❌ 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);
```

---

## Accuracy vs. Battery Trade-off

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` |

---

## Platform Gotchas

### iOS 14 reduced accuracy

Users can grant "approximate" location (accuracy > 1 km). Your app receives
a location, but it may be useless for precision features.

- Check `location.Accuracy` — values > 100 m likely indicate reduced precision.
- Use `GeolocationRequest.RequestFullAccuracy` with a key matching
  `NSLocationTemporaryUsageDescriptionDictionary` in `Info.plist` to
  prompt for full accuracy.

### Android: mock locations in security-sensitive flows

```csharp
// ⚠️ Always check in security-sensitive flows (e.g., geofence, check-in)
if (location.IsFromMockProvider)
{
    // Reject — user is spoofing location
}
```

### Android: `Altitude` 0.0 is not sea level

Some Android devices return `0.0` for `Altitude` when the GPS has no
barometric sensor. Treat `0.0` as **"unknown"**, not sea level.

### Android 10+: background location requires separate permission

`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 `null`

This is expected on first boot or after a location-data reset. Always fall
back to `GetLocationAsync`:

```csharp
// ✅ Cache-first with fresh fallback
var location = await geolocation.GetLastKnownLocationAsync();
if (location is null || location.Timestamp ()` first, or
catch `PermissionException`. Calling `GetLocationAsync` without permission
throws on some platforms and returns `null` on others — inconsistent
behaviour across platforms.

---

## Continuous Listening: Don't Forget to Unsubscribe

Failing to remove the `LocationChanged` handler when stopping causes
continued GPS usage and battery drain.

```csharp
// ❌ 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;
}
```

---

## Checklist

- [ ] `CancellationToken` passed to every `GetLocationAsync` call
- [ ] Accuracy level matched to feature need (not blindly set to `Best`)
- [ ] `GetLastKnownLocationAsync` null-check with `GetLocationAsync` fallback
- [ ] Runtime permissions requested before first geolocation call
- [ ] `LocationChanged` handler removed when stopping continuous listening
- [ ] Android: `ACCESS_BACKGROUND_LOCATION` requested separately (if needed)
- [ ] iOS: `NSLocationTemporaryUsageDescriptionDictionary` added for full-accuracy prompt
- [ ] Android: `IsFromMockProvider` checked in security-sensitive flows

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [davidortinau](https://github.com/davidortinau)
- **Source:** [davidortinau/maui-skills](https://github.com/davidortinau/maui-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-davidortinau-maui-skills-maui-geolocation
- Seller: https://agentstack.voostack.com/s/davidortinau
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
