typescript - Expo krijgt locatie-updates op de achtergrond, ontvangt geen updates
Ik probeer de locatie op de achtergrond te krijgen en deze vervolgens naar mijn server te sturen. Ik heb elk antwoord op Stack Overflow en de officiële handleidingen gevolgd, maar bij mij vinden de updates gewoon niet plaats. Ik heb een eenvoudige setup, gebruikmakend van Expo SDK 48, en de officiële expo-task-manager met expo-location
Dus ik heb een component dat deze logica kapselt, het heet LocationTracker en via een useLocationTracker hook wikkel ik de logica
Hier is de daadwerkelijke logica useLocationTracker.ts
import { useEffect } from "react";
import * as Location from "expo-location";
import { LatLng } from "react-native-maps";
import * as TaskManager from "expo-task-manager";
import { LocationObject } from "expo-location";
import { logger } from "../logger";
type Callback = (coords: LatLng) => void;
const LOCATION_TRACKING_TASK = "location_tracking_task";
const executor: (body: TaskManager.TaskManagerTaskBody<object>) => void = (
body
) => {
const data = body.data as unknown as { locations: LocationObject[] };
const l = data?.locations[0];
console.log("location", l);
if (!l) return;
for (const callback of Object.values(locationCallbacks)) {
callback({
latitude: l.coords.latitude,
longitude: l.coords.longitude,
});
}
};
TaskManager.defineTask(LOCATION_TRACKING_TASK, executor);
const locationCallbacks: { [key: string]: Callback } = {};
function addLocationCallback(callback: Callback) {
const id = uuid() as string;
locationCallbacks[id] = callback;
return {
remove: () => {
delete locationCallbacks[id];
},
};
}
export const useLocationTracker = (
callback: Callback | null,
active: boolean = true
) => {
useEffect(() => {
if (!active) return;
if (!callback) return;
startTrackingLocation();
const subscription = addLocationCallback(callback);
return () => {
subscription.remove();
stopTrackingLocation();
};
}, [callback, active]);
async function startTrackingLocation() {
const { status: foregroundStatus } = await Location.requestForegroundPermissionsAsync();
if (foregroundStatus === 'granted') {
const { status: backgroundStatus } = await Location.requestBackgroundPermissionsAsync();
if (backgroundStatus === 'granted') {
try {
logger.info("starting location updates");
Location.startLocationUpdatesAsync(LOCATION_TRACKING_TASK, {
showsBackgroundLocationIndicator: true,
accuracy: Location.Accuracy.Highest,
distanceInterval: 10, // minimum change (in meters) betweens updates
deferredUpdatesInterval: 1000, // minimum interval (in milliseconds) between updates
timeInterval: 3000,
// foregroundService is how you get the task to be updated as often as would be if the app was open
foregroundService: {
notificationTitle: 'Using your location',
notificationBody: 'To turn off, go back to the app and switch something off.',
},
});
} catch (e) {
logger.error("failed to start location updates", e);
}
}
}
}
async function stopTrackingLocation() {
Location.hasStartedLocationUpdatesAsync(LOCATION_TRACKING_TASK).then((value) => {
if (value) {
logger.info("stopping location updates");
Location.stopLocationUpdatesAsync(LOCATION_TRACKING_TASK);
}
});
}
}
Hier is de component (zeer basic)
LocationTracker.tsximport { api } from "@employees/lib/api";
import { useLocationTracker } from "@employees/lib/hooks/useLocationTask";
import { logger } from "@employees/lib/logger";
import { useAppStore } from "@employees/lib/store";
import { Point } from "@safedriver/db";
import { useCallback } from "react";
export const LocationTracker = () => {
const { mutate, isLoading, isError } = api.employee.updateLocation.useMutation({
onSuccess: (data) => {
logger.info(new Date(), "updateLocation success", data)
}
})
const callback = useCallback((location: Point) => {
console.log("update location", location)
mutate({ location })
}, [mutate, shift]);
useLocationTracker(callback, true)
return null;
}
En deze component wordt op deze manier in mijn _layout.tsx gebruikt
export default function Layout() {
return (
<TRPCProvider>
<LocationTracker />
<SafeAreaProvider>
<Stack screenOptions={{ headerShown: false }} />
<StatusBar />
</SafeAreaProvider>
</TRPCProvider>
);
}
Ik heb getest om te controleren of de taak is geregistreerd en actief is, en dat is het, dus dat is niet de oorzaak van het probleem. Mijn setup is hetzelfde als de topantwoorden op Stack Overflow, mijn enige zorg is dat mijn setup met de hook en de component niet werkt vanwege een vreemd her-renderingsprobleem of iets dergelijks, aangezien de code zelf voor het locatie volgen correct zou moeten zijn.
De reden dat ik het probleem van opnieuw renderen overweeg, is omdat ik dit constant gelogd krijg
LOG [INFO] 53:52.699 Main - stopping location updates
LOG [INFO] 53:52.701 Main - starting location updates
LOG [INFO] 53:57.738 Main - stopping location updates
LOG [INFO] 53:57.740 Main - starting location updates
LOG [INFO] 54:03.2 Main - stopping location updates
LOG [INFO] 54:03.4 Main - starting location updates
LOG [INFO] 54:08.27 Main - stopping location updates
LOG [INFO] 54:08.29 Main - starting location updates
LOG [INFO] 54:13.81 Main - stopping location updates
LOG [INFO] 54:13.84 Main - starting location updates
LOG [INFO] 54:18.111 Main - stopping location updates
LOG [INFO] 54:18.113 Main - starting location updates