expo-location
Localização em primeiro plano/segundo plano, geofencing e strings de divulgação para a App Store - o cookbook do expo-location para aplicativos de campo e entrega do Expo SDK 57.
Busque em todas as páginas da documentação
Localização em primeiro plano/segundo plano, geofencing e strings de divulgação para a App Store - o cookbook do expo-location para aplicativos de campo e entrega do Expo SDK 57.
Cartão de receita de referência rápida - pronto para copiar e colar.
npx expo install expo-location// app.config.ts - strings de divulgação (obrigatório para revisão da loja)
export default {
plugins: [
[
"expo-location",
{
locationWhenInUsePermission:
"O FieldTrack mostra locais de trabalho próximos enquanto você usa o aplicativo.",
locationAlwaysAndWhenInUsePermission:
"O FieldTrack registra as coordenadas de visita em segundo plano para que os supervisores vejam os horários de chegada.",
isIosBackgroundLocationEnabled: true,
isAndroidBackgroundLocationEnabled: true,
},
],
],
};import * as Location from "expo-location";
export async function requestForegroundLocation(): Promise<boolean> {
const { status } = await Location.requestForegroundPermissionsAsync();
return status === "granted";
}
export async function watchPosition(onUpdate: (loc: Location.LocationObject) => void) {
const granted = await requestForegroundLocation();
if (!granted) return null;
return await Location.watchPositionAsync(
{
accuracy: Location.Accuracy.Balanced,
distanceInterval: 25, // metros - reduz a rotatividade em comparação com timeInterval sozinho
timeInterval: 10_000,
},
onUpdate
);
}Quando usar isso:
Quando evitar:
Pin de mapa em primeiro plano, portão de permissão e fluxo de atualização em segundo plano com cópia de divulgação honesta.
npx expo install expo-location// src/location/LocationPermissionGate.tsx
import { useState } from "react";
import { Linking, Pressable, Text, View } from "react-native";
import * as Location from "expo-location";
type Props = {
onGranted: () => void;
needsBackground?: boolean;
};
export function LocationPermissionGate({ onGranted, needsBackground }: Props) {
const [denied, setDenied] = useState(false);
async function request() {
const fg = await Location.requestForegroundPermissionsAsync();
if (fg.status !== "granted") {
setDenied(true);
return;
}
if (needsBackground) {
const bg = await Location.requestBackgroundPermissionsAsync();
if (bg.status !== "granted") {
setDenied(true);
return;
}
}
onGranted();
}
return (
<View style={{ padding: 24, gap: 12 }}>
<Text style={{ fontWeight: "600" }}>Acesso à localização</Text>
<Text>
Anexamos GPS às fotos de inspeção para que disputas sejam resolvidas com prova
de presença no local.
{needsBackground
? " O acesso em segundo plano mantém os registros de visita precisos quando você muda de aplicativo."
: ""}
</Text>
<Pressable onPress={request}>
<Text style={{ color: "#2563eb" }}>Continuar</Text>
</Pressable>
{denied && (
<Pressable onPress={() => Linking.openSettings()}>
<Text>Abrir Configurações</Text>
</Pressable>
)}
</View>
);
}// src/location/useCurrentPosition.ts
import { useEffect, useState } from "react";
import * as Location from "expo-location";
export function useCurrentPosition(enabled: boolean) {
const [coords, setCoords] = useState<Location.LocationObjectCoords | null>(
null
);
useEffect(() => {
if (!enabled) return;
let subscription: Location.LocationSubscription | null = null;
(async () => {
subscription = await Location.watchPositionAsync(
{ accuracy: Location.Accuracy.Balanced, distanceInterval: 20 },
(loc) => setCoords(loc.coords)
);
})();
return () => subscription?.remove();
}, [enabled]);
return coords;
}// src/location/getOneShotPosition.ts
import * as Location from "expo-location";
export async function getOneShotPosition() {
const { status } = await Location.getForegroundPermissionsAsync();
if (status !== "granted") return null;
return Location.getCurrentPositionAsync({
accuracy: Location.Accuracy.Balanced,
});
}O que isso demonstra:
app.config.needsBackground é verdadeiro.| Nível | iOS | Android | Caso de uso |
|---|---|---|---|
| Primeiro Plano | Quando em Uso | Localização precisa | Mapas, marcação única |
| Segundo Plano | Sempre | Segundo plano + primeiro plano | Registros de visita com o aplicativo em segundo plano |
| Precisão reduzida | Aproximada (iOS 14+) | Opcional aproximado | Apenas recursos em nível de cidade |
Accuracy.Highest → Bloqueio de GPS, maior consumo de bateria
Accuracy.Balanced → Padrão para aplicativos de campo
Accuracy.Low → Nível de cidade, menor custodistanceInterval em vez de timeInterval agressivo - menos ativações do JavaScript.stopLocationUpdatesAsync ou remova a assinatura do watcher quando a tela for desmontada.// src/location/geofenceTask.ts - importação de escopo global na entrada
import * as Location from "expo-location";
import * as TaskManager from "expo-task-manager";
export const GEOFENCE_TASK = "site-geofence";
TaskManager.defineTask(GEOFENCE_TASK, ({ data, error }) => {
if (error) {
console.error(error);
return;
}
const { eventType, region } = data as Location.GeofencingEvent;
if (eventType === Location.GeofencingEventType.Enter) {
console.log("Entrou", region.identifier);
}
});await Location.startGeofencingAsync(GEOFENCE_TASK, [
{
identifier: "armazem-a",
latitude: 37.7749,
longitude: -122.4194,
radius: 200,
notifyOnEnter: true,
notifyOnExit: false,
},
]);| Chave | Plataforma | Exemplo |
|---|---|---|
locationWhenInUsePermission | Plugin iOS | Por que o acesso em primeiro plano ajuda |
locationAlwaysAndWhenInUsePermission | Plugin iOS | Por que o segundo plano é necessário |
ACCESS_BACKGROUND_LOCATION | Android | Mesma narrativa para revisores |
| API | Propósito |
|---|---|
requestForegroundPermissionsAsync | Permissão de uso em primeiro plano |
requestBackgroundPermissionsAsync | Sempre / segundo plano |
getCurrentPositionAsync | Coordenada única |
watchPositionAsync | Atualizações em streaming |
startGeofencingAsync | Entrada/saída de região |
reverseGeocodeAsync | Coordenadas → endereço (rede) |
subscription.remove() na limpeza do useEffect.TaskManager.defineTask no escopo do módulo.| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Apenas primeiro plano | Mapa e marcação única | Prova de presença no local com o aplicativo em segundo plano |
| Entrada manual de endereço | Usuários sensíveis à privacidade | Rastreamento de frota em tempo real |
| Geofencing | Alertas de entrada/saída de local | Precisão de sub-metro em ambientes internos |
| SDK de mapas de terceiros | Navegação curva a curva | Simples pino "onde estou" |
npx expo install expo-locationAdicione o plugin de configuração expo-location com strings de divulgação, depois npx expo prebuild ou build EAS.
isIosBackgroundLocationEnabled no plugin e UIBackgroundModes localização.Accuracy.Balanced - atualize para Highest apenas para requisitos abaixo de 10m.Highest globalmente.import { Linking } from "react-native";
await Linking.openSettings();reverseGeocodeAsync usa serviços de rede. Armazene em cache o último rótulo conhecido localmente para exibição offline.Versões da Stack: Esta página foi escrita para React 19.2.3, React Native 0.86.0 e Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026