Location
Location wraps expo-location's foreground position: a position signal that a one-off
current() and a running start() both write to. Nothing is watched until you call one of them,
and the accuracy is explicit - GPS at navigation accuracy is a battery the user notices.
import { Location } from '@ng-native/expo';
inject(Location)Install
npx expo install expo-locationimport { Location } from '@ng-native/expo/location';The smallest thing that works
import { Component, inject, type OnDestroy } from '@angular/core';
import { Text } from '@ng-native/components';
import { Location } from '@ng-native/expo/location';
@Component({
selector: 'app-run',
imports: [Text],
template: `
@if (location.position(); as here) {
<text>{{ here.latitude }}, {{ here.longitude }}</text>
}
`,
})
export class Run implements OnDestroy {
protected readonly location = inject(Location);
private stop = () => {};
async start(): Promise<void> {
this.stop = await this.location.start({ accuracy: 'high', distance: 10 });
}
ngOnDestroy(): void {
this.stop();
}
}Reading a position
positionis a signal: null until something has been read, then the latest fix -latitude,longitude,altitude,accuracy,heading,speedandtimestamp.altitude,accuracy,headingandspeedare null where the platform does not know them.current(accuracy)reads the position once and returns it (or null, without the permission or the module).start({ accuracy, distance, interval })follows the position into the signal, resolving to the function that stops watching.distanceis meters moved before the next update;intervalis milliseconds between updates, Android only - iOS updates on distance moved, not on a timer.- The accuracy is a name, not Expo's numeric enum:
lowest,low,balanced(the default),high,highestornavigation. Worth choosing deliberately:navigationkeeps the GPS hot.
Both current() and start() ask for the foreground permission themselves, via
location.permission (see Permissions), and do nothing without it -
current() resolves to null, start() to a stop function that does nothing. Location in the
background is not wrapped by this service; use expo-location's own background API directly if
you need it.
Add to Info.plist:
<key>NSLocationWhenInUseUsageDescription</key>
<string>Allow this app to use your location</string>Android's ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION permissions are added automatically
by the module's config plugin.
An address and a point
geocode(address) answers the places an address could be, best match first, from the platform's
own geocoder, and reverseGeocode(coordinates) the addresses at a point. On iOS they ask for no
permission, since Apple's geocoder does not need one. On Android they ask for the foreground
permission as current() does, and answer an empty list without it, because expo-location
refuses to geocode there without it. Both answer an empty list for an address the geocoder does
not know, and off a device. In an app built without expo-location they throw
MissingModuleError, as the rest of the service does.
const [place] = await this.location.geocode('10 Downing Street, London');
if (place) this.marker.set(place); // { latitude, longitude }Without the module
On iOS and Android, a missing expo-location - never installed, or installed without the app being
rebuilt since - leaves the service made, so injecting it does not throw. A call, or a read of a
value only the module knows, throws a MissingModuleError. Its message names the module and the
commands that fix it; see
Using a module.
On the web, and in a test that provides no fake, permission reports denied with canAskAgain: false. current() resolves to null and start() to a stop function that does nothing, exactly as
though the permission had been refused.
Reference
Locationservice@ng-native/expoimport { Location } from '@ng-native/expo';Methods
current(accuracy: LocationAccuracy = 'balanced'): Promise<Position | null>Read the position once. Null without the permission or the module.
geocode(address: string): Promise<Coordinates[]> The places an address could be, best match first, from the platform's own geocoder. Empty for an address it does not know, and where the source has no geocoder, as off a device. On iOS it asks for no permission. Elsewhere it asks for the foreground permission first and is empty without it, since expo-location refuses to geocode on Android without it. An app built without expo-location throws MissingModuleError .
reverseGeocode(coordinates: Coordinates): Promise<Address[]> The addresses at a point. Empty, asking first, and throwing, where geocode is.
start(options: WatchOptions = {}): Promise<() => void>Follow the position into the signal. Resolves to the function that stops.