Reference version

This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

Expo Location (next) iconExpo Location (next)

A library that provides access to the device's location.

Android
iOS
Recommended version:
~58.0.14

expo-location/next reads the device's location once, watches it while the app is open, and receives it in the background. On Android, it also lets you pick the location provider.

Installation

Terminal
- npx expo install expo-location
- yarn expo install expo-location
- pnpm expo install expo-location
- bun expo install expo-location

If you are installing this in an existing React Native app, make sure to install expo in your project.

Usage

Request the precise location

By default, a permission request asks for the precise location. On Android, this requests ACCESS_FINE_LOCATION. On iOS, when the user has turned Precise Location off for the app, the request also shows the system prompt for temporary full accuracy.

import { Location, LocationAccuracy } from 'expo-location/next'; async function requestPreciseLocation() { const { granted, accuracy } = await Location.requestForegroundPermissions(); if (!granted) { return; } if (accuracy === LocationAccuracy.REDUCED) { // The user declined precise location. Positions are accurate to kilometers, not meters. } const position = await Location.getPosition(); if (!position) { return; } const { coordinates, horizontalAccuracy } = position; console.log(coordinates, horizontalAccuracy); }

The iOS prompt shows a default message, which the locationFullAccuracyPermission config plugin option can replace.

Request an approximate location

An approximate location is accurate to kilometers rather than meters. To get it, request the permission with accuracy: RequestPermissionsAccuracyOption.REDUCED.

On Android, this requests only ACCESS_COARSE_LOCATION, so the permission dialog does not offer the precise location.

On iOS, the app does not ask to upgrade to the precise location. To make the approximate location the default in the permission dialog, set isIosReducedAccuracyByDefault to true in the config plugin. If the app never asks for the precise location, also set locationFullAccuracyPermission to false to omit the purpose string of the temporary full accuracy prompt:

app.json
{ "expo": { "plugins": [ [ "expo-location", { "isIosReducedAccuracyByDefault": true, "locationFullAccuracyPermission": false } ] ] } }

Then request reduced accuracy:

import { Location, RequestPermissionsAccuracyOption } from 'expo-location/next'; async function requestApproximateLocation() { const { granted } = await Location.requestForegroundPermissions({ accuracy: RequestPermissionsAccuracyOption.REDUCED, }); if (!granted) { return; } const position = await Location.getPosition(); if (!position) { return; } const { coordinates, horizontalAccuracy } = position; console.log(coordinates, horizontalAccuracy); }
Get the position once

getPosition resolves with a single fix. It returns a cached fix when one is younger than maxCachedAge. Otherwise, it waits up to timeout seconds for a new one and falls back to the last known location when none arrives. Both values are in seconds. Check timestamp when freshness matters.

import { Location, LocationProfile } from 'expo-location/next'; async function getFreshPosition() { const position = await Location.getPosition({ maxCachedAge: 30, timeout: 15, profile: LocationProfile.DEFAULT, }); if (!position) { console.log('No location available'); return null; } const ageSeconds = (Date.now() - position.timestamp) / 1000; if (ageSeconds > 30) { console.log(`Fell back to a fix from ${Math.round(ageSeconds)} seconds ago`); } return position; }
Handle a denied permission

When the user denies the permission, canAskAgain tells whether the system shows the dialog again. When it is false, the only way to grant the permission is the system settings, so send the user there.

import { Location } from 'expo-location/next'; import { Linking } from 'react-native'; async function ensureForegroundPermission() { const permission = await Location.requestForegroundPermissions(); if (permission.granted) { return true; } if (!permission.canAskAgain) { await Linking.openSettings(); } return false; }
Request the background permission

On Android, the background permission requires the foreground permission first. Receiving positions in the background also needs the background permission declared on Android and the background mode on iOS. Enable both in the config plugin:

app.json
{ "expo": { "plugins": [ [ "expo-location", { "isIosBackgroundLocationEnabled": true, "isAndroidBackgroundLocationEnabled": true } ] ] } }

On Android 11 and later, the system opens the app's settings page instead of a dialog. The request resolves when the user comes back.

On iOS, the request shows the Change to Always Allow dialog. Answering Keep Only While Using resolves with status: "denied" and scope: "whenInUse", because the foreground permission stays granted.

import { Location, LocationScope } from 'expo-location/next'; async function requestBackgroundPermission() { const { granted } = await Location.requestForegroundPermissions(); if (!granted) { return false; } const { scope } = await Location.requestBackgroundPermissions(); return scope === LocationScope.ALWAYS; }
Show live position on a screen

watchPosition returns a handle that controls the native watcher. Pause it when the screen loses focus, resume it when the screen is back, and dispose it when the screen unmounts. A screen that loses focus stays mounted behind another tab, a pushed screen, or a modal. On Android, the watcher also pauses on its own while the app is in the background.

import { Location, LocationProfile, PositionWatchHandle } from 'expo-location/next'; import { useFocusEffect } from 'expo-router'; import { useCallback, useEffect, useRef } from 'react'; export default function LiveMapScreen() { const watcher = useRef<PositionWatchHandle | null>(null); useEffect(() => { watcher.current = Location.watchPosition({ profile: LocationProfile.OTHER_NAVIGATION, onPosition: position => console.log(position.coordinates), onError: error => console.warn(error.message), }); return () => { watcher.current?.dispose(); watcher.current = null; }; }, []); useFocusEffect( useCallback(() => { watcher.current?.resume(); return () => watcher.current?.pause(); }, []) ); return null; }
Handle location services turned off

Location services are a device-wide switch, separate from the app's permission. With services off, no app receives a position. On Android, enableLocationServices asks the user to turn them on: Google Play services shows an in-app prompt, and the Android provider opens the system settings. On iOS, only the user can turn them on in Settings.

import { Location } from 'expo-location/next'; import { Alert, Platform } from 'react-native'; async function ensureLocationServices() { if (Location.hasLocationServicesEnabled()) { return true; } if (Platform.OS === 'android') { return Location.enableLocationServices(); } Alert.alert( 'Location Services are off', 'Turn them on in Settings > Privacy & Security > Location Services.' ); return false; }
Receive positions in the background

To receive positions while the app is in the background, define a task with defineLocationTask at the top level of a module. Then start the delivery with LocationUpdatesHandle. This requires expo-task-manager, the background permission, ACCESS_BACKGROUND_LOCATION declared on Android, and the location background mode on iOS. Enable the last two in the config plugin:

app.json
{ "expo": { "plugins": [ [ "expo-location", { "isIosBackgroundLocationEnabled": true, "isAndroidBackgroundLocationEnabled": true } ] ] } }
locationTask.ts
import { defineLocationTask } from 'expo-location/next'; defineLocationTask({ onPosition: position => { console.log('Background position', position.coordinates); }, onError: error => { console.warn('Background updates failed', error.message); }, });

Import that module from the root layout, so the task exists on every launch, including the relaunch after the system terminated the app:

app/_layout.tsx
import '../locationTask';

Then control the delivery from a screen:

app/index.tsx
import { Location, LocationProfile, LocationScope, LocationUpdatesHandle, } from 'expo-location/next'; import { useEffect, useState } from 'react'; import { Button, View } from 'react-native'; const locationUpdates = new LocationUpdatesHandle().withProfile(LocationProfile.LOW_POWER); export default function TrackingScreen() { const [isTracking, setIsTracking] = useState(false); useEffect(() => { locationUpdates.hasStarted().then(setIsTracking); }, []); async function start() { const foreground = await Location.requestForegroundPermissions(); if (!foreground.granted) { return; } const { scope } = await Location.requestBackgroundPermissions(); if (scope !== LocationScope.ALWAYS) { return; } await locationUpdates.start(); setIsTracking(true); } async function stop() { await locationUpdates.stop(); setIsTracking(false); } return ( <View> <Button title={isTracking ? 'Stop tracking' : 'Start tracking'} onPress={isTracking ? stop : start} /> </View> ); }

Both sides default to the same task name, so you can omit it. To run several tasks, give each task its own name and pass that name to both defineLocationTask and the LocationUpdatesHandle constructor.

API

import { Location } from 'expo-location/next';

Hooks

useBackgroundLocationPermissions(options)

Android
iOS
ParameterType
options(optional)PermissionHookOptions<RequestPermissionsOptions>

Checks or requests the background location permission from a component. See Request the background permission.

Returns:
[LocationPermissionResponse | null, RequestPermissionMethod<LocationPermissionResponse>, GetPermissionMethod<LocationPermissionResponse>]

Example

const [foreground, requestForeground] = useForegroundLocationPermissions(); const [background, requestBackground] = useBackgroundLocationPermissions(); if (!foreground?.granted) { return <Button title="Allow location" onPress={requestForeground} />; } if (background?.scope !== LocationScope.ALWAYS) { return <Button title="Allow background location" onPress={requestBackground} />; }

useForegroundLocationPermissions(options)

Android
iOS
ParameterType
options(optional)PermissionHookOptions<RequestPermissionsOptions>

Checks or requests the foreground location permission from a component. See Request the precise location.

Returns:
[LocationPermissionResponse | null, RequestPermissionMethod<LocationPermissionResponse>, GetPermissionMethod<LocationPermissionResponse>]

Example

const [permission, requestPermission] = useForegroundLocationPermissions(); if (!permission?.granted) { return <Button title="Allow location" onPress={requestPermission} />; }

useLocationServices()

Android
iOS

Tracks whether location services are on, re-reading the switch every time the app returns to the foreground. enable calls enableLocationServices, so it works on Android only. See Handle location services turned off.

Returns:
[enabled: boolean, enable: undefined]

Example

const [enabled, enable] = useLocationServices(); if (!enabled) { return <Button title="Turn on location services" onPress={enable} />; }

Classes

LocationProvider

Android

The backends that can serve positions on Android. The default tries Google Play services first and falls back to the Android framework, so most apps never need this. Pass the result to setLocationProvider.

LocationProvider Methods

Android()

Android

The Android framework LocationManager, available without Google Play services.

Returns:
SharedRef<'LocationProvider'>

Fallback(providers)

Android
ParameterTypeDescription
providersSharedRef[]

The providers to try, most preferred first.


Tries the providers in order and uses the first one that can serve the request.

Returns:
SharedRef<'LocationProvider'>

Gms()

Android

The fused location provider from Google Play services.

Returns:
SharedRef<'LocationProvider'>

LocationUpdatesHandle

Android
iOS

Starts and stops the delivery of positions to the task defined with defineLocationTask. The delivery is registered with the system, so it outlives the JS context: it survives the app moving to the background and, with the background permission, the app being terminated.

On Android, positions keep arriving after the app process ended. Requires the background permission.

On iOS, positions come from CLLocationUpdate.liveUpdates. Requires the location background mode and the foreground permission.

See Receive positions in the background.

LocationUpdatesHandle Methods

hasStarted()

Android
iOS

Checks whether the delivery is registered with the system. It stays registered across app restarts, so check it on launch before calling start() again.

Returns:
Promise<boolean>

start()

Android
iOS

Registers the delivery with the system and starts sending positions to the task.

Returns:
Promise<void>

stop()

Android
iOS

Unregisters the delivery. Positions stop arriving and the app is no longer relaunched for them.

Returns:
Promise<void>

withProfile(profile)

Android
iOS
ParameterType
profileLocationProfile

Stages the profile for the next start(). It has no effect on a delivery that is already running; call stop() and start() again to apply it.

Returns:
this

The same handle, for chaining.

PositionWatchHandle

Android
iOS

Controls a running position watcher. Use watchPosition() to create one.

See Show live position on a screen.

PositionWatchHandle Methods

addListener(onPosition, onError)

Android
iOS
ParameterTypeDescription
onPosition(position: Position) => void

Called when a new position is delivered.

onError(optional)(error: PositionWatchError) => void

Called when an error occurs.


Subscribes to the position and error events. One watcher can have multiple listeners.

Returns:
EventSubscription

A subscription object with a remove method that stops listening for changes.

dispose()

Android
iOS

Removes all listeners and releases the native watcher.

Returns:
void

pause()

Android
iOS

Stops delivering positions and releases the system request, keeping the watcher for resume().

Returns:
void

restart()

Android
iOS

Subscribes again with the settings staged by withProfile() and withInterval(). It does not resume a paused watcher.

Returns:
boolean

false when the provider rejects the request right away. Later failures arrive through onError.

resume()

Android
iOS

Requests positions again after pause().

Returns:
boolean

false when the provider rejects the request right away. Later failures, including every failure on iOS and with Google Play services, arrive through onError.

status()

Android
iOS

Reads the current flags of the watcher.

withInterval(intervalSeconds)

Android
iOS
ParameterTypeDescription
intervalSecondsnumber

A finite number of seconds, 0 or greater. Throws for other values.


Stages the time between two delivered positions, in seconds. It has no effect until restart(). Positions arrive less often when the system has no new fix. 0 delivers every position the system produces.

On Android, it replaces the update interval the profile requests from the provider. On iOS, the system decides the rate and positions that arrive sooner than the interval are dropped.

Returns:
this

The same handle, for chaining.

withProfile(profile)

Android
iOS
ParameterType
profileLocationProfile

Stages a new profile for the watcher. It has no effect until restart().

Returns:
this

The same handle, for chaining.

Methods

defineLocationTask(options)

Android
iOS
ParameterTypeDescription
optionsLocationTaskOptions

The task name and the callbacks for positions and errors.


Defines the task that receives the positions started with LocationUpdatesHandle. Wraps TaskManager.defineTask, so call it in the global scope of a module imported at startup. See Receive positions in the background.

Returns:
void

Namespaces

Location

Android
iOS

Location Methods

enableLocationServices()

Android

Asks the user to turn location services on. With the GMS provider, this is an in-app dialog; with the Android provider, it opens the system Settings and resolves when the user returns. Resolves with true when services are already on. See Handle location services turned off.

Returns:
Promise<boolean>

A promise that resolves to true when services are on after the user answered.

getBackgroundPermissions()

Android
iOS

Checks the background location permission without asking the user.

A promise that resolves to the current permission. scope is always when it is granted.

getForegroundPermissions()

Android
iOS

Checks the foreground location permission without asking the user.

A promise that resolves to the current permission, including its scope and accuracy.

getPosition(getPositionOptions)

Android
iOS
ParameterTypeDescription
getPositionOptions(optional)GetPositionOptions

The options for the location request.


Resolves with a single fix. It returns a cached fix when one is younger than maxCachedAge. Otherwise, it waits up to timeout seconds for a new one and falls back to the last known location when none arrives. With timeout 0, it returns the last known location right away. Check timestamp when freshness matters.

Returns:
Promise<Position | null>

A promise that resolves to the position, or null when the device has none.

Example

const position = await Location.getPosition({ maxCachedAge: 60, timeout: 10 }); if (!position) { console.log('No location available'); return; } const ageSeconds = (Date.now() - position.timestamp) / 1000; if (ageSeconds > 60) { console.log( `Last known location from ${Math.round(ageSeconds)} s ago, no fresh fix within the timeout` ); } console.log(position.coordinates.latitude, position.coordinates.longitude);

getSelectedLocationProviderName()

Android

Gets the name of the provider currently serving positions: GMS, Android, or the chain of a fallback, such as the default Fallback: GMS -> Android.

Returns:
string

hasLocationServicesEnabled()

Android
iOS

Checks whether location services are turned on for the whole device. This is the system toggle, not the app's permission: with services off, no app receives a position even when its permission is granted. See Handle location services turned off.

Returns:
boolean

requestBackgroundPermissions(options)

Android
iOS
ParameterTypeDescription
options(optional)RequestPermissionsOptions

The accuracy to ask for


Asks the user for permission to read the location while the app is in the background. On Android, it requires the foreground permission first. On iOS, answering Keep Only While Using resolves with status denied and scope whenInUse.

See Request the background permission.

A promise that resolves to the permission after the user answered.

requestForegroundPermissions(options)

Android
iOS
ParameterTypeDescription
options(optional)RequestPermissionsOptions

The accuracy to ask for.


Asks the user for permission to read the location while the app is in the foreground. Shows the system dialog only while the permission is undetermined; afterwards it resolves with the current state, so check canAskAgain to know whether the user has to go to the system settings.

See Request the precise location and Handle a denied permission.

A promise that resolves to the permission after the user answered.

setLocationProvider(provider)

Android
ParameterTypeDescription
providerSharedRef<'LocationProvider'>

A provider from LocationProvider.


Selects the provider that serves all later location requests.

Returns:
void

watchPosition(options)

Android
iOS
ParameterTypeDescription
optionsWatchPositionParams

The profile and the callbacks for positions and errors.


Starts watching the position and returns the handle that controls the watcher.

See Show live position on a screen.

The handle for controlling the watcher.

Example

const watcher = Location.watchPosition({ profile: LocationProfile.FITNESS, onPosition: (position) => console.log(position.coordinates), onError: (error) => console.warn(error.code, error.message), }); // When the positions are no longer needed: watcher.dispose();

Types

Coordinates

Android
iOS

A set of coordinates expressed in decimal degrees.

Example

{ latitude: 40.7128, longitude: -74.0060 }
PropertyTypeDescription
latitudenumber
-
longitudenumber
-

GetPositionOptions

Android
iOS

Options for getPosition.

PropertyTypeDescription
maxCachedAge(optional)number

The maximum age of a cached location that may be returned. Expressed in seconds.

If no new fix arrives within the timeout, getPosition returns the cached location regardless of its age.

Default:0
profile(optional)LocationProfile

The use case the fix is for. It changes the way the location is requested from the OS and can affect accuracy and power usage. On iOS, a reduced accuracy authorization limits the fix whatever the profile; see Request an approximate location.

Default:LocationProfile.DEFAULT
timeout(optional)number

The maximum time to wait for a new location fix. Expressed in seconds.

With a timeout of 0, getPosition returns the last known location, if available.

On Android, the providers cap it at 30 seconds.

Default:30

LocationPermissionResponse

Android
iOS

Returned by the permission functions, with the location-specific scope and accuracy.

Type: PermissionResponse extended by:

PropertyTypeDescription
accuracyLocationAccuracy

Whether the app receives the precise or an approximate location.

scopeLocationScope

When the app can read the location: always, only while in use, or not at all.

LocationTaskOptions

Android
iOS

The parameters of defineLocationTask.

PropertyTypeDescription
onError(optional)(error: TaskManagerError) => void

Called when the task receives an error instead of a position.

onPosition(position: Position) => void

Called with every position delivered to the task.

taskName(optional)string

The name of the task. Must match the name passed to the LocationUpdatesHandle constructor; both default to the same name.

Position

Android
iOS

A single location fix.

Example

{ coordinates: { latitude: 50.0614, longitude: 19.9372 }, horizontalAccuracy: 12.5, // meters timestamp: 1791277756380, // milliseconds since the Unix epoch altitude: 253.1, // meters above the WGS 84 ellipsoid mslAltitude: 212.4, // meters above mean sea level verticalAccuracy: 4.8, // meters mocked: false, heading: 87.3, // degrees clockwise from true north, course over ground headingAccuracy: 5, // degrees speed: 1.4, // meters per second speedAccuracy: 0.3, // meters per second }
PropertyTypeDescription
altitudenumber | null

Height above the WGS 84 ellipsoid, in meters.

coordinatesCoordinates

The latitude and longitude of the fix, in degrees.

headingnumber | null

The direction in which the device is traveling, in degrees clockwise from true north, from 0 to 360. It is unrelated to the device's orientation.

headingAccuracynumber | null
Only for: 
Android 8+
iOS

The uncertainty of heading, in degrees.

horizontalAccuracynumber | null

The radius around coordinates within which the device is, in meters.

mockedboolean

Whether the fix comes from a simulated source, such as a simulator or a mock location app.

On Android it maps to Location.isMock on Android 12 and later and to Location.isFromMockProvider() on earlier versions; on iOS to CLLocation.sourceInformation.isSimulatedBySoftware.

mslAltitudenumber | null
Only for: 
Android 14+
iOS

Height above mean sea level, in meters.

speednumber | null

The speed, in meters per second.

speedAccuracynumber | null
Only for: 
Android 8+
iOS

The uncertainty of speed, in meters per second.

timestampnumber

When the fix was taken, in milliseconds since the Unix epoch. Check it when the position must be fresh, because a fix can be older than the moment it was delivered.

verticalAccuracynumber | null
Only for: 
Android 8+
iOS

The uncertainty of altitude and mslAltitude, in meters.

PositionUpdate

Android
iOS

One positionChanged event from the native watcher: a position or an error, never both.

Type: object shaped as below:

PropertyTypeDescription
dataPosition
-
errornull
-

Or object shaped as below:

PropertyTypeDescription
datanull
-
errorPositionWatchError
-

PositionWatchError

Android
iOS

The reason a watcher stopped delivering positions, passed to onError.

PropertyTypeDescription
codestring

A stable identifier of the failure, for branching in code.

messagestring

A description of the failure, for logs and error screens.

PositionWatchStatus

Android
iOS

A snapshot of the watcher's flags, returned by status().

PropertyTypeDescription
isHandleAliveboolean

Whether the handle can still be brought back to sending. False only once released.

isInForegroundboolean

Whether the app is in the foreground. On Android, the watcher holds the system request only while it is true.

isPausedboolean

Whether pause() was called and resume() was not called yet.

isStartedboolean

Whether delivery has been started. On Android, it is true while at least one listener is attached.

isSubscribedboolean

Whether the provider is feeding positions right now.

RequestPermissionsOptions

Android
iOS
PropertyTypeDescription
accuracy(optional)RequestPermissionsAccuracyOption

The accuracy to ask for. Ignored by requestBackgroundPermissions on Android.

Default:RequestPermissionsAccuracyOption.FULL

WatchPositionParams

Android
iOS

The parameters of watchPosition.

PropertyTypeDescription
onError(optional)(error: PositionWatchError) => void

Called when the watcher cannot deliver positions, for example when the provider refuses the request after the app returns to the foreground.

onPosition(position: Position) => void

Called with every delivered position.

profile(optional)LocationProfile

The use case the positions are for. It selects the accuracy and the update rate.

Default:LocationProfile.DEFAULT

Enums

LocationAccuracy

Android
iOS

FULL

LocationAccuracy.FULL = "full"

The app receives the precise location.

On Android, ACCESS_FINE_LOCATION is granted.

On iOS, Precise Location is turned on for the app.

NOT_GRANTED

LocationAccuracy.NOT_GRANTED = "notGranted"

The app cannot read the location.

REDUCED

LocationAccuracy.REDUCED = "reduced"

The app receives an approximate location, accurate to kilometers rather than meters.

On Android, only ACCESS_COARSE_LOCATION is granted.

On iOS, Precise Location is turned off for the app.

LocationProfile

Android
iOS

A use case that each platform turns into an accuracy, an update interval, and a power budget.

On Android it maps to a LocationRequest priority and interval.

On iOS 17 and later it maps to a CLLocationUpdate.LiveConfiguration; on earlier versions to a CLLocationManager activity type with the best available accuracy.

AIRBORNE

LocationProfile.AIRBORNE = "airborne"

Flying, such as in a plane or a glider.

On Android, high accuracy with updates about every second.

On iOS, CLLocationUpdate.LiveConfiguration.airborne.

AUTOMOTIVE_NAVIGATION

LocationProfile.AUTOMOTIVE_NAVIGATION = "automotiveNavigation"

Turn-by-turn navigation in a vehicle.

On Android, high accuracy with updates about every second.

On iOS, CLLocationUpdate.LiveConfiguration.automotiveNavigation.

DEFAULT

LocationProfile.DEFAULT = "default"

General-purpose positioning, for anything the other profiles do not cover.

On Android, balanced priority with updates about every 5 seconds.

On iOS, CLLocationUpdate.LiveConfiguration.default.

FITNESS

LocationProfile.FITNESS = "fitness"

Workout tracking such as running or cycling.

On Android, high accuracy with updates about every 2 seconds.

On iOS, CLLocationUpdate.LiveConfiguration.fitness.

LOW_POWER

LocationProfile.LOW_POWER = "lowPower"

Coarse position at the lowest power use.

On Android, low-power priority with updates about every 60 seconds, which the provider can delay by up to 5 minutes and deliver in batches.

On iOS, kilometer accuracy with a 3 km distance filter, on every iOS version.

OTHER_NAVIGATION

LocationProfile.OTHER_NAVIGATION = "otherNavigation"

Navigation on foot, by bike, or on water.

On Android, high accuracy with updates about every 2 seconds.

On iOS, CLLocationUpdate.LiveConfiguration.otherNavigation.

LocationScope

Android
iOS

ALWAYS

LocationScope.ALWAYS = "always"

On Android, ACCESS_BACKGROUND_LOCATION is granted.

On iOS, the authorization is Always.

NOT_GRANTED

LocationScope.NOT_GRANTED = "notGranted"

The app cannot read the location.

WHEN_IN_USE

LocationScope.WHEN_IN_USE = "whenInUse"

On Android, ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION is granted, but not ACCESS_BACKGROUND_LOCATION.

On iOS, the authorization is When In Use.

RequestPermissionsAccuracyOption

Android
iOS

The accuracy a permission request asks for.

FULL

RequestPermissionsAccuracyOption.FULL = "full"

Asks for the precise location.

On Android, requests ACCESS_FINE_LOCATION together with ACCESS_COARSE_LOCATION.

On iOS, when the app holds a reduced accuracy, shows the system prompt for temporary full accuracy after the permission is granted. The prompt needs the purpose string the config plugin writes by default; locationFullAccuracyPermission: false removes it and skips the prompt.

REDUCED

RequestPermissionsAccuracyOption.REDUCED = "reduced"

Asks for an approximate location only.

On Android, requests ACCESS_COARSE_LOCATION alone, so the system dialog does not offer the precise option.

On iOS, never asks to raise a reduced accuracy.

Permissions

Android

Installing expo-location adds the following permissions:

  • ACCESS_COARSE_LOCATION: for the approximate device location
  • ACCESS_FINE_LOCATION: for the precise device location

The following permissions are optional and enabled through the config plugin:

  • ACCESS_BACKGROUND_LOCATION: to read the location while the app is in the background or closed. Enabling it in a new build requires submitting the app for review.
Android permissionDescription

ACCESS_COARSE_LOCATION

Allows an app to access approximate location.

ACCESS_FINE_LOCATION

Allows an app to access precise location.

ACCESS_BACKGROUND_LOCATION

Allows an app to access location in the background.

iOS

This library uses the following Info.plist keys. The config plugin writes a default value for each of them except NSLocationDefaultAccuracyReduced.

Info.plist keyDescription

NSLocationWhenInUseUsageDescription

A message that tells the user why the app is requesting access to the user’s location information while the app is running in the foreground.

NSLocationAlwaysAndWhenInUseUsageDescription

A message that tells the user why the app is requesting access to the user’s location information at all times.

NSLocationTemporaryUsageDescriptionDictionary

A dictionary of purpose strings shown when the app asks for temporary full accuracy. expo-location/next uses the ExpoLocationFullAccuracy key, written by the locationFullAccuracyPermission plugin option.

NSLocationDefaultAccuracyReduced

A boolean that makes the permission dialog offer the approximate location by default. Set by the isIosReducedAccuracyByDefault plugin option.