Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

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

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 (https://docs.expo.io/versions/latest/sdk/location/#locationstartlocationupdatesasynctaskname-options) 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 (https://github.com/mauron85/react-native-background-geolocation). 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...