React Native expo-location: How to make the background location service update more often?

Please provide the following:

  1. SDK Version: 4.7.3
  2. Platforms(Android/iOS/web/all): React Native (Android & iOS), but so far this is just a small personal test project so practically just Android
  3. Add the appropriate “Tag” based on what Expo library you have a question on.

I’m building a sports app with Expo / React Native and trying to figure out a good way to track user location while the app is in the background. I have built a solution with expo-location (Location - Expo Documentation) which successfully receives location updates, and I even managed to send the location updates to the UI with the help of an EventEmitter.

Now the problem here is, the Expo Location task keeps the location updates deferred for a VERY long time (like 12 minutes) before sending a location update to the UI. This is despite setting all the relevant options to zero or very small.

I would love to use Expo Location because I got it mostly working, but unbelievably it seems that the library lacks an option/tool to force the background task to send updates often enough (like once in 5 seconds).

I would be grateful if anyone had a solution to really making the Expo background location send updates often enough. Now it sends updates “when I feel like it”, about once in 5 or 12 minutes, despite setting all the relevant options and parameters I found in the documentation.

I already came to the conclusion that Expo background location is practically broken and I should switch to another location library (GitHub - mauron85/react-native-background-geolocation: Background and foreground geolocation plugin for React Native. Tracks user when app is running in background.). However I’m using Expo managed workflow and installing this mauron85 location library (otherwise really promising) doesn’t work, because it requires setting manually dependencies → I need to eject from Expo managed workflow → ejecting breaks my project structure in a way I don’t know how to solve. Really frustrating!

Relevant parts of my code:

top part:

import * as Location from 'expo-location';
import * as TaskManager from 'expo-task-manager';
import EventEmitter from 'EventEmitter'

const locationEmitter = new EventEmitter();

const BACKGROUND_LOCATION_TRACKER = 'BACKGROUND_LOCATION_TRACKER'
const LOCATION_UPDATE = 'LOCATION_UPDATE'

componentDidMount after requesting location permissions:

await Location.startLocationUpdatesAsync(BACKGROUND_LOCATION_TRACKER, {
            accuracy: LocationAccuracy.BestForNavigation,
            timeInterval: 0,  // all set to 0 to make it update as often as possible!!! doesn't help
            distanceInterval: 0,
            deferredUpdatesInterval: 0, 
            deferredUpdatesDistance: 0,
            showsBackgroundLocationIndicator: true,
            foregroundService: {
                notificationTitle: 'title',
                notificationBody: 'recording',
                notificationColor: '#008000',
            },
            // pausesUpdatesAutomatically: true,

        });

    locationEmitter.on(LOCATION_UPDATE, (locationData) => {
        console.log('locationEmitter locationUpdate fired! locationData: ', locationData);
        let coordinatesAmount = locationData.newRouteCoordinates.length - 1;
        this.setState({
            latitude: locationData.newRouteCoordinates[coordinatesAmount - 1].latitude,
            longitude: locationData.newRouteCoordinates[coordinatesAmount - 1].longitude,
            routeCoordinates: this.state.routeCoordinates.concat(locationData.newRouteCoordinates)
        })
    })

define location task:

TaskManager.defineTask(BACKGROUND_LOCATION_TRACKER, async ({ data, error }) => {
    if (error) {
        console.error(error);
        return;
    }

    if (data) {
        const { locations } = data;
        console.log('backgroundLocationTracker received new locations: ', locations)

        // const [location] = locations;
        const locationsLength = locations.length;

        const newRouteCoordinates = [];
        // const totalNewDistance = 0.0;

        for (i = 0; i < locationsLength; i++) {
            const { latitude, longitude } = locations[i].coords;
            const tempCoords = {
                latitude,
                longitude,
            };
            newRouteCoordinates.push(tempCoords);
            // totalNewDistance += GLOBAL.screen1.calcDistance(newRouteCoordinates[i], newRouteCoordinates[i - 1])  
        };

        console.log('backgroundLocationTracker: latitude ', locations[locationsLength - 1].coords.latitude,
            ', longitude: ', locations[locationsLength - 1].coords.longitude, ', routeCoordinates: ', newRouteCoordinates,
            ', prevLatLng: ', newRouteCoordinates[locationsLength - 1]);

        let locationData = { newRouteCoordinates }

        locationEmitter.emit(LOCATION_UPDATE, locationData)

    }

});

As I said, it all WORKS (!) in the sense that I do get location updates from the background to the UI. The only problem here is that I can’t figure out how to make the background task send location updates more often! It just keeps collecting a huge batch of 50+ location updates for even 10+ minutes before it bothers to send them to the UI!

All help appreciated, thanks.

Bump. I also need to get this working. I can track once the app is in the foreground but doesn’t look like the background tracking is updating correctly

1 Like