Search code examples
cordovageolocationphonegap

Why does my PhoneGap location function return the position multiple times?


I have this function that is supposed to get higher accuracy GPS results:

navigator.geolocation.getAccurateCurrentPosition = function (geolocationSuccess, geolocationError, geoprogress, options) {
    var lastCheckedPosition,
        locationEventCount = 0,
        watchID,
        timerID;

    options = options || {};

    var checkLocation = function (position) {
        lastCheckedPosition = position;
        locationEventCount = locationEventCount + 1;
        // We ignore the first event unless it's the only one received because some devices seem to send a cached
        // location even when maxaimumAge is set to zero
        if ((position.coords.accuracy <= options.desiredAccuracy) && (locationEventCount > 1)) {
            clearTimeout(timerID);
            navigator.geolocation.clearWatch(watchID);
            foundPosition(position);
        } else {
            geoprogress(position);
        }
    };

    var stopTrying = function () {
        navigator.geolocation.clearWatch(watchID);
        foundPosition(lastCheckedPosition);
    };

    var onError = function (error) {
        clearTimeout(timerID);
        navigator.geolocation.clearWatch(watchID);
        geolocationError(error);
    };

    var foundPosition = function (position) {
        geolocationSuccess(position);
    };

    if (!options.maxWait)            options.maxWait = 10000; // Default 10 seconds
    if (!options.desiredAccuracy)    options.desiredAccuracy = 20; // Default 20 meters
    if (!options.timeout)            options.timeout = options.maxWait; // Default to maxWait

    options.maximumAge = 0; // Force current locations only
    options.enableHighAccuracy = true; // Force high accuracy (otherwise, why are you using this function?)

    watchID = navigator.geolocation.watchPosition(checkLocation, onError, options);
    timerID = setTimeout(stopTrying, options.maxWait); // Set a timeout that will abandon the location loop
};

Which I then call with:

navigator.geolocation.getAccurateCurrentPosition(onSuccess, onError, onProgress, {desiredAccuracy:20, maxWait:15000});

When it finds a position, it will fire geolocationSuccess(position); (the success from the above function. The problem is that in my PhoneGap application, it seems to be calling it multiple times often. Sometimes 4-5 times within the same second.

Why would that be? I am only initializing it once and it's not in any loop.


Solution

  • The author of the script answers your question on the github readme (emphasis is mine):

    A better way to do this is to use navigator.geolocation.watchPosition(). This method will do a callback every time the location changes or every time the device improves the accuracy (based on my observations). In my own testing with a freshly booted device, it will take between 2 and 6 callbacks to get to something highly accurate. This led me to write this very simple JavaScript function that uses watchPosition() in combination with a simple timer.

    So the author is using the geolocation watchPosition() method in this implementation. The callback from the watchPosition() method might get called several times if the position or the accuracy changes. See the documentation (emphasis is mine again):

    If the position data changes (either by device movement or if more accurate geo information arrives), you can set up a callback function that is called with that updated position information. This is done using the watchPosition() function, which has the same input parameters as getCurrentPosition(). The callback function is called multiple times, allowing the browser to either update your location as you move, or provide a more accurate location as different techniques are used to geolocate you. The error callback function, which is optional just as it is for getCurrentPosition(), can be called repeatedly.