Zoeken op website

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.tsx
import { 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