I have found a workaround for this. It turns out that you can implement the functionality of watchposition by repeatedly polling navigator.geolocation.getCurrentPosition. Set maximumAge to 0 so that you don't get a cached result. This should keep the GPS "hot".
In my implementation, function getLocation sets everything up (including saving a global callback function) and ends by calling getLocation0. Helper function getLocation0 has a single line that calls navigator.geolocation.getCurrentPosition, with getLocation1 as the immediate callback. This third function, getLocation1, checks to see if the accuracy is within the specified threshold or if we are past the specified timeout. If either of these conditions is true, we are done. Otherwise, we set a timeout that will go to getLocation0 after a specified time period, such as 500 ms.
This is simplified from code that is considerably more complex, and it is likely that I have broken it in the process, but hopefully you can get the general idea and adapt for your own use.
geolocate = (function () {
// PRIVATE
var lat, // Current latitude
lon, // Current longitude
acc, // Most recent accuracy reading
callback, // Call this external function after updating location
thresh, // accuracy threshhold for watchPosition, in meters
giveUp; // Time at which to quit trying to get a more accurate geolocation reading
// This function is called to report any geolocation errors we may get from our requests
function displayError (error) {
// Display error and cancel watch, if applicable
alert ('Geolocation error [code=' + error.code + ', message="' + error.message + ']"');
};
// PUBLIC
var geolocate = {};
geolocate.lat = function () { return lat; };
geolocate.lon = function () { return lon; };
geolocate.getLocation0 = function () {
navigator.geolocation.getCurrentPosition( geolocate.getLocation1, displayError, {enableHighAccuracy:true, maximumAge:0} );
}
geolocate.getLocation1 = function (position) {
var now = new Date();
if (Math.round(position.coords.accuracy) <= thresh || now >= giveUp) {
// display.message('Got it! Accuracy = ' + Math.round(position.coords.accuracy) + 'm');
lat = position.coords.latitude;
lon = position.coords.longitude;
acc = position.coords.accuracy;
callback(); // Success! Now do whatever we were supposed to do next
} else {
setTimeout(geolocate.getLocation0, 500);
timeLeft = Math.round((giveUp.getTime() - now.getTime()) / 1000),
// display.message('Accuracy = ' + Math.round(position.coords.accuracy) + 'm; ' + timeLeft + 's left');
}
}
geolocate.getLocation = function (hook, accuracy, timeout) {
if (navigator.geolocation) {
// Process parameters and initialize variables
callback = hook;
giveUp = new Date();
giveUp.setTime(giveUp.getTime() + timeout*1000); // Give up after 'timeout' seconds
geolocate.getLocation0();
}
};
return geolocate;
}() );
Example call:
geolocate.getAccurateLocation(myFunction, 50, 10);