> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mentraglass.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Location

> Access user's GPS location from smart glasses

Access the user's GPS coordinates to build location-aware apps on MentraOS using the `LocationManager`.

## Quick Start

### Subscribe to Location Stream

Get continuous location updates as the user moves:

```typescript theme={null}
protected async onSession(session: AppSession, sessionId: string, userId: string) {
  // Subscribe to continuous location updates
  const unsubscribe = session.location.subscribeToStream(
    { accuracy: "standard" },
    (data) => {
      const { latitude, longitude, accuracy } = data;
      
      session.logger.info(`Location: ${latitude}, ${longitude}, accuracy: ${accuracy}m`);
    }
  );
  
  // Cleanup when done
  // unsubscribe();
}
```

### Get Latest Location (One-Time Poll)

Request a single location fix without subscribing to a stream:

```typescript theme={null}
protected async onSession(session: AppSession, sessionId: string, userId: string) {
  try {
    const location = await session.location.getLatestLocation({
      accuracy: "high"
    });
    
    session.logger.info(`Got location: ${location.latitude}, ${location.longitude}`);
  } catch (error) {
    session.logger.error("Failed to get location:", error);
  }
}
```

***

## LocationManager API

The SDK provides `session.location` with three main methods:

| Method                                | Parameters                                               | Returns                         | Description                                |
| ------------------------------------- | -------------------------------------------------------- | ------------------------------- | ------------------------------------------ |
| `subscribeToStream(options, handler)` | `{ accuracy: string }`, `(data: LocationUpdate) => void` | `() => void` (cleanup function) | Subscribe to continuous location updates   |
| `unsubscribeFromStream()`             | None                                                     | `void`                          | Unsubscribe from the location stream       |
| `getLatestLocation(options)`          | `{ accuracy: string }`                                   | `Promise<LocationUpdate>`       | One-time location poll (15 second timeout) |

***

## Accuracy Tiers

Choose the accuracy tier based on your app's needs. Higher accuracy tiers provide more precise location data but drain more battery.

| Accuracy Tier       | Description                        | Update Frequency | Battery Impact | Use Case                       |
| ------------------- | ---------------------------------- | ---------------- | -------------- | ------------------------------ |
| `"realtime"`        | Highest precision, fastest updates | Very High        | High           | Navigation, real-time tracking |
| `"high"`            | High precision GPS                 | High             | Medium-High    | Precise location features      |
| `"tenMeters"`       | \~10m accuracy                     | Medium           | Medium         | Local place detection          |
| `"standard"`        | Default accuracy (balanced)        | Medium           | Low-Medium     | General location features      |
| `"hundredMeters"`   | \~100m accuracy                    | Low              | Low            | City-level features            |
| `"kilometer"`       | \~1km accuracy                     | Very Low         | Very Low       | Regional features              |
| `"threeKilometers"` | \~3km accuracy                     | Very Low         | Very Low       | Wide-area features             |
| `"reduced"`         | Battery-saving mode                | Minimal          | Minimal        | Background location            |

**Example:**

```typescript theme={null}
// High accuracy for precise features
session.location.subscribeToStream(
  { accuracy: "high" },
  handler
);

// Lower accuracy for battery efficiency
session.location.subscribeToStream(
  { accuracy: "hundredMeters" },
  handler
);
```

***

## LocationUpdate Data Structure

The `LocationUpdate` interface contains location data:

| Field           | Type     | Required | Description                         |
| --------------- | -------- | -------- | ----------------------------------- |
| `latitude`      | `number` | ✅        | Latitude in decimal degrees         |
| `longitude`     | `number` | ✅        | Longitude in decimal degrees        |
| `accuracy`      | `number` | ✅        | Accuracy in meters                  |
| `altitude`      | `number` | ❌        | Elevation in meters above sea level |
| `timestamp`     | `Date`   | ✅        | When the location was captured      |
| `correlationId` | `string` | ❌        | Used for tracking poll requests     |

**TypeScript Interface:**

```typescript theme={null}
interface LocationUpdate {
  latitude: number;
  longitude: number;
  accuracy: number;
  altitude?: number;
  timestamp: Date;
  correlationId?: string;
}
```

***

## Usage Examples

### Display Location on Dashboard

```typescript theme={null}
protected async onSession(session: AppSession, sessionId: string, userId: string) {
  session.location.subscribeToStream(
    { accuracy: "standard" },
    (data) => {
      session.dashboard.content.writeToMain(
        `Lat: ${data.latitude.toFixed(4)}\n` +
        `Lon: ${data.longitude.toFixed(4)}\n` +
        `Accuracy: ${data.accuracy}m`
      );
    }
  );
}
```

### Show Location on Voice Command

```typescript theme={null}
protected async onToolCall(toolCall: ToolCall): Promise<string | undefined> {
  if (toolCall.toolId === "show_location") {
    const session = this.getSessionByUserId(toolCall.userId);
    
    try {
      const location = await session.location.getLatestLocation({
        accuracy: "high"
      });
      
      return `Your current location is ${location.latitude.toFixed(4)}, ${location.longitude.toFixed(4)} with ${location.accuracy}m accuracy`;
    } catch (error) {
      return "Could not get your current location";
    }
  }
}
```

### Cleanup Subscriptions

```typescript theme={null}
protected async onSession(session: AppSession, sessionId: string, userId: string) {
  const unsubscribe = session.location.subscribeToStream(
    { accuracy: "standard" },
    (data) => {
      // Handle location updates
    }
  );
  
  // Clean up when session ends
  session.events.on('disconnect', () => {
    unsubscribe();
  });
}
```

***

## Permissions

Location access requires the `location` permission in your app manifest. Configure this in the Developer Console at [console.mentra.glass](https://console.mentra.glass/apps).

<Warning>
  Users must grant location permission for your app to access GPS data. Always handle cases where location data is unavailable.
</Warning>

***

## Best Practices

**Choose appropriate accuracy:**

```typescript theme={null}
// Good - Use lowest accuracy needed
session.location.subscribeToStream(
  { accuracy: "hundredMeters" }, // Fine for city-level features
  handler
);

// Avoid - Don't use highest accuracy unless needed
session.location.subscribeToStream(
  { accuracy: "realtime" }, // Drains battery quickly
  handler
);
```

**Always unsubscribe when done:**

```typescript theme={null}
protected async onSession(session: AppSession, sessionId: string, userId: string) {
  const unsubscribe = session.location.subscribeToStream(
    { accuracy: "standard" },
    handler
  );
  
  // Important: Clean up to stop location updates
  session.events.on('disconnect', () => {
    unsubscribe();
  });
}
```

**Handle poll timeouts:**

```typescript theme={null}
try {
  const location = await session.location.getLatestLocation({ accuracy: "high" });
  // Use location
} catch (error) {
  // Handle timeout (after 15 seconds)
  session.logger.error("Location poll timed out");
}
```

**Check accuracy in handler:**

```typescript theme={null}
session.location.subscribeToStream(
  { accuracy: "standard" },
  (data) => {
    if (data.accuracy > 100) {
      session.logger.warn(`Low accuracy: ${data.accuracy}m`);
    }
    
    // Use location data
  }
);
```

***

## Error Handling

### Handling Stream Errors

```typescript theme={null}
protected async onSession(session: AppSession, sessionId: string, userId: string) {
  try {
    const unsubscribe = session.location.subscribeToStream(
      { accuracy: "standard" },
      (data) => {
        if (data.accuracy > 100) {
          session.logger.warn(`Low accuracy: ${data.accuracy}m`);
        }
      }
    );
  } catch (error) {
    session.logger.error("Failed to subscribe to location stream:", error);
  }
}
```

### Handling Poll Timeouts

```typescript theme={null}
try {
  const location = await session.location.getLatestLocation({ accuracy: "high" });
  session.logger.info(`Location: ${location.latitude}, ${location.longitude}`);
} catch (error) {
  session.logger.error("Location request failed:", error);
  // Provide fallback or notify user
}
```

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Permissions" icon="lock" href="/app-devs/core-concepts/permissions">
    Configure location permissions
  </Card>

  <Card title="Location Manager API" icon="book" href="/app-devs/reference/managers/location-manager">
    Complete API reference
  </Card>

  <Card title="Dashboard" icon="gauge" href="/app-devs/core-concepts/display/dashboard">
    Display location on dashboard
  </Card>

  <Card title="AI Tool Calls" icon="wrench" href="/app-devs/core-concepts/ai-tool-calls">
    Add voice commands for location (under maintenance, returning later in 2026)
  </Card>
</CardGroup>
