API
Simple functional API with direct calls and minimal abstractions
This API provides a straightforward approach to geolocation with direct function calls and a single hook for continuous tracking.
Find an API by task
For a 1.x application, complete Upgrade from 1.x first; the API reference is not a complete breaking-change checklist.
Design Philosophy
Simple and Direct:
- Direct function calls: No complex abstractions or classes
- Single hook: Only
useWatchPositionfor continuous tracking - No Provider required: Just call functions directly
- Automatic cleanup: Hook handles subscription lifecycle
Core Principles:
- Simple configuration: Call
setConfiguration()once at app startup - Direct function calls: Use
getCurrentPosition(),requestPermission()etc. - One hook for tracking:
useWatchPositionfor continuous updates - Type-safe: Full TypeScript support
- Battery efficient: Native subscriptions stop immediately when disabled
Configuration
Set global configuration once at app startup.
setConfiguration()
Options:
autoRequestPermission?: boolean- Deprecated compatibility option.setConfiguration()does not request permission; callrequestPermission()explicitly when the app is ready to show the native prompt.authorizationLevel?: 'whenInUse' | 'always' | 'auto'- iOS: Authorization levelenableBackgroundLocationUpdates?: boolean- iOS: Enable background locationlocationProvider?: 'playServices' | 'android' | 'auto'- Android:autoandplayServicesprefer Google Play Services fused location when available and fall back to Android's platform provider.androidforces the platformLocationManagerpath.
Type:
When to call:
- Once at app startup (e.g., in
App.tsxorindex.js) - Before making any location requests
Web behavior:
- Browser builds resolve the main package import to a web entry that uses
navigator.geolocation. setConfiguration()is a no-op on web. Browser permission prompts are driven bygetCurrentPosition()/watchPosition(), not by a standalone platform request API.authorizationLevel,enableBackgroundLocationUpdates, andlocationProviderare ignored on web.
Permission Functions
checkPermission()
Check current location permission status without requesting it.
Returns: Promise<PermissionStatus>
Permission Status:
'granted'- User granted location permission'denied'- User denied permission'restricted'- Permission restricted (iOS parental controls)'undetermined'- Permission not yet requested
getPermissionDetails()
Read the current foreground status, granted scope, accuracy authorization, and the next appropriate permission action without showing a prompt, opening settings, or acquiring a location.
Returns: Promise<PermissionDetails>
scopeisbackgroundonly when both foreground and background access are granted. Browser access is alwaysforeground.accuracyreports iOS precise/reduced and Android fine/approximate access. Browsers do not expose this distinction and returnunknown.canAskAgaindescribes whether another foreground system permission prompt is known to be possible. It does not describe a later background permission upgrade.nullmeans the platform cannot determine the answer without attempting a request.- Android exposes the same denied state before the first request and after
permanent denial through this read-only API. In that ambiguous state,
canAskAgainisnullandsettingsGuidanceisrequestPermissionOrReviewSettings. After a normal denial, Android's permission-rationale signal makes the state known requestable, socanAskAgainistrueand guidance isrequestPermission. - iOS returns
requestPermissionforundetermined,reviewSettingsfordenied, andmanagedRestrictionforrestricted. - Web uses the Permissions API when available. Without it, a successful
position/watch callback or permission-denied error is used as bounded
evidence for at most 30 seconds. A denial proves the current state but not
whether the browser will prompt again, so
canAskAgainremainsnulland guidance isrequestPermissionOrReviewSettings. An authoritative Permissions APIdeniedstate instead returnsfalseandreviewSettings. Without observed evidence, foreground prompt capability is also unknown. Withoutnavigator.geolocation, guidance isuseSupportedEnvironment.
requestPermission()
Request location permission from the user.
Returns: Promise<PermissionStatus>
Behavior:
- Shows system permission dialog if
undetermined - Returns immediately if already
grantedordenied - On iOS, uses
authorizationLevelfrom configuration - On web, triggers the browser prompt by making a one-shot
navigator.geolocation.getCurrentPosition()call, then returns the mapped browser permission state.
Location Functions
Android Provider and Settings
The provider/settings snapshot helpers introduced before 2.0 remain available.
watchProviderStatus() and the deterministic settings result are available in
2.0.
Use these helpers before user-facing precise-location flows where the app needs to know whether Android device settings can satisfy the request.
Functions:
hasServicesEnabled(): Promise<boolean>- Checks whether device-level location services are enabled.getProviderStatus(): Promise<LocationProviderStatus>- Returns provider state such aslocationServicesEnabled,gpsAvailable,networkAvailable,passiveAvailable, Android Google Play Services availability, and Google Location Accuracy when Google Play Services exposes it.watchProviderStatus(callback): string- Delivers an asynchronous initial provider snapshot and then only distinct readiness changes. Pass its token tounwatch()for cleanup. Available in 2.0.getLocationAvailability(): Promise<LocationAvailability>- Available sincev1.2. Android reads Fused Location availability whenlocationProvider: 'auto'orlocationProvider: 'playServices'is configured, then falls back to platform provider/service checks. iOS maps Core Location service and authorization state. When unavailable,reasonis a typedLocationAvailabilityReasoncode rather than platform-specific text.getLocationReadiness(): Promise<LocationReadiness>- Combines current permission, services, provider, availability, Play Services, Google Location Accuracy, and observed module-cache state into one read-only diagnosis. It returns stable remediation codes such asrequestPermission,requestPermissionOrReviewSettings,enableLocationServices,useSupportedEnvironment, andacquirePosition; it never requests permission, opens settings, starts location acquisition, or changes configuration. On Web,useSupportedEnvironmentmeans reopening the app in a secure context and a browser or WebView that exposes the Geolocation API. When the Permissions API cannot report state, Web treats a successful position observation as best-effort granted evidence for at most 30 seconds; a denial, missing Geolocation API, clock rollback, or expiry clears that inference. Android usesrequestPermissionOrReviewSettingsbecause its existing permission status cannot distinguish a first request from permanent denial; request permission first, then offer app settings if it remains denied. Google Play Services remediations are returned only whenlocationProvider: 'playServices'is explicitly configured; the defaultautoandandroidroutes can continue through Android platform providers.requestLocationSettingsDetailed(options?): Promise<LocationSettingsResult>- Checks the requested Android location settings and shows Android's native resolution dialog when available. Expected outcomes resolve assatisfied,cancelled,unavailable, oractivityMissing, together with the latest provider status. Request failures such as a concurrent request still reject.requestLocationSettings(options?): Promise<LocationSettingsResult>- The 2.0 method returns the same deterministic result. The detailed name is provided to make result handling explicit in code shared across release lines.
Both settings methods are Android-focused. On iOS they resolve with the current Core Location service status and do not show a settings dialog.
watchProviderStatus() only observes readiness: it does not request permission,
open settings, or start position updates. Android reacts to system provider and
location-mode broadcasts. iOS rechecks after authorization changes and when the
app becomes active, which covers returning from Settings. Browser builds recheck
when the page becomes visible or active. Provider-specific optional fields stay
undefined on platforms that cannot report them.
Android Reliability Notes
locationProvider: 'auto'andlocationProvider: 'playServices'prefer Google Play Services fused location when available and fall back to Android's platform provider.locationProvider: 'android'forces Android's platformLocationManagerpath.- Approximate/coarse location flows are supported through permissions and
Android
granularity. - Use
getLastKnownPosition()for a synchronous read of the module cache. UsegetLastKnownPositionAsync()to query native/provider caches without starting a fresh request. - Errors include
PLAY_SERVICE_NOT_AVAILABLE,SETTINGS_NOT_SATISFIED, andTIMEOUT.
Web Notes
Web support uses the browser standard navigator.geolocation API.
It requires a secure context (https://, localhost, or another browser-trusted
origin). Unsupported browsers or unavailable providers reject location requests
with POSITION_UNAVAILABLE.
Supported on web:
checkPermission()mapsnavigator.permissions.query({ name: 'geolocation' })togranted,denied, orundeterminedwhen the Permissions API is available.getPermissionDetails()enriches that read-only state with foreground scope and settings guidance. Browser accuracy authorization remainsunknown.requestPermission()performs a one-shot browser geolocation request because browsers do not expose a standalone geolocation permission request API.getCurrentPosition()usesnavigator.geolocation.getCurrentPosition()for ordinary requests. Whensignalis provided, it uses a one-shot browser watch so aborting can callclearWatch()immediately.watchPosition()wrapsnavigator.geolocation.watchPosition()and returns a string token.watchProviderStatus()reports whether browser geolocation is available and rechecks on page visibility/focus lifecycle events.unwatch()andstopObserving()clear position and provider-status watches.
Web option behavior:
accuracymaps to the browser's high-accuracy boolean.timeoutandmaximumAgeare forwarded to the browser.distanceFilteris applied in JavaScript for watch updates after the first emitted position.authorizationLevel,enableBackgroundLocationUpdates,locationProvider,interval,fastestInterval,useSignificantChanges, Android granularity options, and iOS tuning options are ignored because browsers do not provide matching controls.- Geocoding, heading, Android settings, and temporary full-accuracy APIs are
native-focused. On web, provider/status helpers return browser availability
where possible; unsupported sensor/geocoder calls reject with
POSITION_UNAVAILABLE.
getCurrentPosition()
Get current location (one-time request).
Parameters: options?: CurrentPositionOptions
Options:
timeout?: number- Request timeout in ms (default: 600000 / 10 min)maximumAge?: number- Max age of cached location in ms (default: 0)signal?: AbortSignal- Cancels only this request. A signal that is already aborted prevents native or browser location work from starting. The promise rejects with the exactsignal.reason; runtimes without a reason receive anAbortErrorfallback.accuracy?: { android?: 'high' | 'balanced' | 'low' | 'passive'; ios?: 'bestForNavigation' | 'best' | 'nearestTenMeters' | 'hundredMeters' | 'kilometer' | 'threeKilometers' | 'reduced' }- Platform-specific accuracy preset. 2.0 callers use this option;enableHighAccuracyremains only on/compat.granularity?: 'permission' | 'coarse' | 'fine'- Android-only request granularity, available sincev1.2.permissionfollows the granted permission level,coarseavoids fine GPS-only requests, andfinerequires fine location permission.waitForAccurateLocation?: boolean- Android-only Fused request tuning, available sincev1.2.maxUpdateAge?: number- Android-only maximum age for an initial update in ms, available sincev1.2.maxUpdateDelay?: number- Android-only maximum batching delay in ms, available sincev1.2.activityType?: 'other' | 'automotiveNavigation' | 'fitness' | 'otherNavigation' | 'airborne'- iOS Core Location activity type, available sincev1.2.pausesLocationUpdatesAutomatically?: boolean- iOS automatic pause behavior, available sincev1.2.showsBackgroundLocationIndicator?: boolean- iOS background location indicator, available sincev1.2. This only has a visible effect when the app has background location capability and permission.
Use accuracy when you need explicit platform-native behavior:
Use an AbortController when the screen or operation that owns a one-shot
request can end before location arrives:
Cancellation is isolated by request ID: aborting one concurrent request does
not cancel another request or an active watch. Omitting signal keeps the
existing one-shot native/browser path. The callback-based /compat API is
unchanged.
Android maps the presets to native accuracy/priority intent. With auto or
playServices, requests prefer Google Play Services fused location and use the
matching fused priority before platform fallback. With android, requests stay
on LocationManager: high prefers GPS with a network fallback, balanced
uses the network provider, low uses network/passive providers, and passive
only listens through the passive provider. iOS maps the presets to Core
Location desiredAccuracy constants.
iOS tuning options are applied to both one-time requests and watches through the shared Core Location manager configuration:
Use showsBackgroundLocationIndicator only after configuring background
location in the app target, including the location background mode and the
required Info.plist location usage descriptions.
Returns: Promise<GeolocationResponse>
Response:
Mock and provider metadata
mocked and provider are optional response metadata fields added in v1.2.
They describe the source of that particular position sample:
mockedreports whether the sample source identified it as simulated or supplied by a test provider. Native Android responses useLocation.isMock(orisFromMockProvideron older Android versions). Native iOS responses useCLLocation.sourceInformationwhen it is available on iOS 15 and later; otherwise the field can be absent.provideridentifies the Android provider route asfused,gps,network, orpassive. iOS and web returnunknownbecause those platforms do not expose an equivalent provider name through this API.- Web positions omit
mockedbecause the browser Geolocation API does not expose trustworthy simulation metadata. - The optional development-tools integration returns
mocked: truefor its injected JavaScript samples. That value identifies the tooling source; it is not native platform attestation.
Treat mocked as per-sample diagnostic evidence, not as an anti-fraud or
device-integrity guarantee. A missing value means the platform did not expose
the signal; it does not mean false. Likewise, provider describes the route
used for the sample and does not establish whether the coordinates should be
trusted.
The synchronous module cache returned by getLastKnownPosition() preserves
the metadata attached to the last position observed by this JavaScript module.
Disabling a mock-location app or simulator fixture cannot rewrite that cached
response, so it may still contain mocked: true. By contrast,
getLastKnownPositionAsync() converts a native cached sample when it is read
on Android or iOS; platform metadata is derived again and Android provider
can reflect the current query route. On web it filters the JavaScript module
cache, while the optional development-tools integration filters its configured
mock cache. Do not require an asynchronous native-cache response to be
identical to an earlier JavaScript response. Request or observe a newer sample
when application policy requires fresher evidence, and apply maximumAge when
reading the platform cache.
The /compat entry point keeps the
@react-native-community/geolocation response shape and does not include these
fields. Compat callers can opt into equivalent metadata by setting
includeExtraMetadata: true on compat getCurrentPosition() / watchPosition() calls.
Testing the signal naturally
- Test
mocked: truewith an emulator or simulator location fixture such as MaestrosetLocation. - Test
mocked: falseonly on a physical device receiving a real provider location, without coordinate injection. Do not manufacture the false branch by changing or hiding returned metadata. - Assert absence separately on platforms that cannot provide the signal; do
not convert an unavailable value to
false.
Error handling
Starting in 2.0, API errors use readable string discriminants. Keep
comparisons against the LocationErrorCodes members shown below instead of
copying their values. The additional native setup/provider members
(INTERNAL_ERROR, PLAY_SERVICE_NOT_AVAILABLE, and
SETTINGS_NOT_SATISFIED) were originally added in v1.2; 2.0 keeps those member
names while replacing every previous numeric value with a string.
The code is committed by the native layer before a LocationError is sent to
JS. Both watchPosition error callbacks and public Promise rejections from
getCurrentPosition/requestPermission receive the same { code, message }
shape; JS only relays that object and does not parse or reclassify native
messages.
The /compat API keeps the legacy numeric browser-style contract with only
PERMISSION_DENIED (1), POSITION_UNAVAILABLE (2), and TIMEOUT (3).
See 2.0 Error Migration for the 1.x-to-2.x mapping.
getLastKnownPosition() and getLastKnownPositionAsync()
getLastKnownPosition() synchronously reads the latest position observed by
this JavaScript module. It takes no options, never calls native code, and returns
undefined while that module-local cache is cold.
getLastKnownPositionAsync(options?: LastKnownPositionOptions) queries
native/provider cache-only sources using maximumAge, accuracy,
granularity, waitForAccurateLocation, and maxUpdateAge. Fresh/watch-only
options are intentionally excluded, and the call never falls through to a
fresh request. It resolves undefined when no cached location
satisfies the options, including a native POSITION_UNAVAILABLE result. Other
failures, such as permission denial, reject with LocationError
contract.
Geocoding APIs
Available since v1.2.
Use geocode() to convert a human-readable address into candidate coordinates,
and reverseGeocode() to convert coordinates into candidate address fields.
Both APIs use the platform geocoder, so result quality, language, network
behavior, and availability can differ between Android Geocoder and iOS
CLGeocoder.
geocode(address) rejects with INTERNAL_ERROR when address is blank.
reverseGeocode(coords) rejects with INTERNAL_ERROR when latitude or
longitude is non-finite or outside the valid coordinate range. Platform
geocoder service failures reject with the same { code, message }
LocationError shape as the rest of the API.
Heading APIs
Available since v1.2.
Use getHeading() for a single compass heading and watchHeading() for
continuous heading updates. Stop heading watches with the same unwatch(token)
API used by watchPosition().
Heading APIs require location permission and reject with the same
LocationError contract when permission is denied or heading sensors are not
available.
iOS Accuracy Authorization
Available since v1.2.
Use getAccuracyAuthorization() to read whether iOS currently grants full or
reduced location accuracy. Android maps fine permission to full, coarse-only
permission to reduced, and no location permission to unknown.
For iOS, requestTemporaryFullAccuracy(purposeKey) calls Core Location's
temporary full accuracy API. The purposeKey must exist in
NSLocationTemporaryUsageDescriptionDictionary in Info.plist, for example:
Passing an empty purposeKey rejects with INTERNAL_ERROR. Android does not
show a temporary accuracy prompt and resolves with the current mapped accuracy
authorization.
React Hook
useWatchPosition()
Watch for continuous location updates with automatic lifecycle management.
Options:
enabled?: boolean- Start/stop watching (default:false)accuracy?: { android?: 'high' | 'balanced' | 'low' | 'passive'; ios?: 'bestForNavigation' | 'best' | 'nearestTenMeters' | 'hundredMeters' | 'kilometer' | 'threeKilometers' | 'reduced' }- Platform-specific accuracy preset. 2.0 callers use this option;enableHighAccuracyremains only on/compat.granularity?: 'permission' | 'coarse' | 'fine'- Android-only request granularity, available sincev1.2waitForAccurateLocation?: boolean- Android-only high-accuracy initial update tuning, available sincev1.2maxUpdateAge?: number- Android-only maximum age for an initial update, available sincev1.2maxUpdateDelay?: number- Android-only batching delay, available sincev1.2maxUpdates?: number- Android-only watch update limit, available sincev1.2distanceFilter?: number- Minimum distance change in metersinterval?: number- Update interval in ms (Android)fastestInterval?: number- Fastest interval in ms (Android)timeout?: number- Request timeoutmaximumAge?: number- Max cached location ageuseSignificantChanges?: boolean- Use significant changes mode (iOS)activityType?: 'other' | 'automotiveNavigation' | 'fitness' | 'otherNavigation' | 'airborne'- iOS Core Location activity type, available sincev1.2pausesLocationUpdatesAutomatically?: boolean- iOS automatic pause behavior, available sincev1.2showsBackgroundLocationIndicator?: boolean- iOS background location indicator, available sincev1.2
Returns:
position: GeolocationResponse | null- Latest position (null if no update yet)error: LocationError | null- Error details if location watching failedisWatching: boolean- Whether currently watching
Key Features:
- ✅ Auto cleanup: Unsubscribes when component unmounts or
enabledbecomesfalse - ✅ Declarative: Toggle with
enabledprop - ✅ No watch ID management: Handled internally
- ✅ Battery efficient: Native subscription stops immediately when disabled
- ✅ Reactive: Changes to options restart the watch
Common Patterns:
- Toggle tracking:
- Conditional tracking (track only when screen is focused):
- Track only when permission granted:
Low-level Functions (Advanced)
For non-React code or advanced use cases, you can use the low-level watch API.
watchPosition()
Parameters:
onUpdate: (position: GeolocationResponse) => void- Success callbackonError?: (error: LocationError) => void- Error callbackoptions?: LocationRequestOptions- Location options
Returns: string - Subscription token
unwatch()
Stop a specific watch subscription.
getActiveWatches()
Read the active position and heading subscriptions without starting or changing location services:
See Watch observability for the native merge,
restart, automatic maxUpdates removal, and cleanup contracts.
stopObserving()
Stop ALL watch subscriptions immediately.
Advanced Patterns
Permission Check Before Location Request
Conditional Tracking Based on App State
TypeScript Support
All exports are fully typed:
NullableDouble is number | null. It is the shared scalar used by
GeolocationCoordinates.altitude, altitudeAccuracy, heading, and speed.
The deprecated 1.x configuration alias was removed in 2.0. Use
GeolocationConfiguration.
Type Inference
Functions and hooks provide full type inference:
Comparison with Compat API
Migration from Compat
Before (Compat API):
After:
Benefits:
- No watch ID management
- Automatic cleanup
- Declarative enable/disable
- Promise-based control flow and inferred results
