7. Ask for the location permission
The permission prompt, the Info.plist entry, and Android permissions added for you.
// Managers deliver to the thread that made them: made on the main thread, kept here.const managers = new Map<number, CLLocationManager>();
// Kept while the permission prompt is on screen.let prompter: CLLocationManager | null = null;
// --- Android -----------------------------------------------------------------
function fromLocation(location: Location): Fix {…
let nextId = 1;
/** Shows the system's permission prompt on iOS. Android asks from JavaScript, with PermissionsAndroid. */export async function requestPermission(): Promise<void> { if (PLATFORM === "ios") { await main(() => { prompter = new CLLocationManager(); prompter.requestWhenInUseAuthorization(); }); }}
/** The last position the device knows, without waiting for a new one. */export async function lastFix(): Promise<Fix | null> { if (PLATFORM === "ios") {import { useEffect, useState } from "react";import { Text } from "react-native";import { stop, watch } from "./src/location.lucent";import { PermissionsAndroid, Platform, Text } from "react-native";import { requestPermission, stop, watch } from "./src/location.lucent";import { Trip, type TripSummary } from "./src/trip.lucent";
const trip = new Trip();
async function askForLocation(): Promise<void> { if (Platform.OS === "android") { await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION); } else { await requestPermission(); }}
export default function App() { const [summary, setSummary] = useState<TripSummary | null>(null);
useEffect(() => { const started = watch((fix) => { try { trip.add(fix); if (trip.count >= 2) setSummary(trip.summary()); } catch (e) { if ((e as { code?: string }).code !== "E_OUT_OF_ORDER") throw e; } }); const started = askForLocation().then(() => watch((fix) => { try { trip.add(fix); if (trip.count >= 2) setSummary(trip.summary()); } catch (e) { if ((e as { code?: string }).code !== "E_OUT_OF_ORDER") throw e; } }), ); return () => void started.then(stop); }, []);requestPermission shows the system's prompt. iOS shows it only if the app says why it needs the location, in Info.plist:
{ "expo": { "ios": { "infoPlist": { "NSLocationWhenInUseUsageDescription": "Trip Tracker records your route while you track a trip." } } }}<key>NSLocationWhenInUseUsageDescription</key><string>Trip Tracker records your route while you track a trip.</string>Android
Section titled “Android”There's nothing to add to the manifest. The SDK marks requestLocationUpdates with the location permissions it needs, and lucent build adds them to the native package's manifest, which Android merges into the app's.
Asking at run time is still up to the app: App.tsx does it with PermissionsAndroid, before watch.
Run it
Section titled “Run it”Rebuild the app, since Info.plist changed. It asks for the location, then tracks the trip.