I have an app that does a simple textbook navigator.geoLocation.watchPosition(...) that works great in iOS 5.x both in Safari and as a web app (using apple-mobile-web-app-ca
This is not exactly an answer as it seems like Home Screen apps in ios6 has some bug related to GeoLocation, but I found the following link very helpful. It explains that as Home Screen apps are now stored like native apps, they have their own storage/caching.
Geolocation works on the first iteration but fails to update from then on. the work around is to remove the following meta tag so that Home Screens app run in Browser mode (I am not sure if it is exactly call a Browser mode). The app will unfortunately render with the browser headers and footers, but GeoLocationwill be working again.
<meta content="yes" name="apple-mobile-web-app-capable" />
iOS 6 Geolocation and Local Data Storage
"Data in Home Screen apps are now stored like native apps. Native apps each have their own sandbox where their data is stored, backed up and restored to. Prior to iOS 6, Home Screen apps shared data with the same app running in the browser. If the user cleared the cache in the browser, the Home Screen version of the app would lose its data too.With iOS 6, Home Screen apps’ data gets saved to a sandbox just like native apps. Backups and restores handle the data properly, and clear cache in the browser will not affect them."
It appears it only works once, then any secondary calls fail. One alternative is to cache the result and use the cached result if you have one, though this means you can't have an app that follows someone's position.
The good news is: I've done it... I've figured it out. The bad news is: somebody smarter than me is going to have to tell you why this works, whereas any other variation of this solution or any of the other solutions offered don't work. This was a hard-fought victory but I'm too embarrassed to say how many hours (days) it took me to figure this out. Without further ado:
if (window.navigator.geolocation) {
var accuracyThreshold = 100,
timeout = 10 * 1000,
watchID = navigator.geolocation.watchPosition(function(position) {
$('#latitude').val(position.coords.latitude); // set your latitude value here
$('#longitude').val(position.coords.longitude); // set your longitude value here
// if the returned distance accuracy is less than your pre-defined accuracy threshold,
// then clear the timeout below and also clear the watchPosition to prevent it from running continuously
position.coords.accuracy < accuracyThreshold && (clearTimeout(delayClear), navigator.geolocation.clearWatch(watchID))
}, function(error) {
// if it fails to get the return object (position), clear the timeout
// and cancel the watchPosition() to prevent it from running continuously
clearTimeout(delayClear);
navigator.geolocation.clearWatch(watchID);
// make the error message more human-readable friendly
var errMsg;
switch (error.code) {
case '0':
errMsg = 'Unknown Error';
break;
case '1':
errMsg = 'Location permission denied by user.';
break;
case '2':
errMsg = 'Position is not available';
break;
case '3':
errMsg = 'Request timeout';
break;
}
}, {
enableHighAccuracy: true,
timeout: timeout,
maximumAge: 0
}),
delayClear = setTimeout(function() {
navigator.geolocation.clearWatch(watchID);
}, timeout + 1E3); // make this setTimeout delay one second longer than your watchPosition() timeout
}
else {
throw new Error("Geolocation is not supported.");
}
Note: for some reason, this doesn't seem to work as consistently if the execution of this code it delayed at some point after initially launching the app. So, this is the FIRST thing I execute in my initialization method.
Note: The only other thing I've added to my app is, when I need to use the geolocation data (which, for me, takes place after the initialization of several other Classes/Object Literals), is to check for the latitude/longitude values. If they exist, continue; If not, run the above geolocation method again, then continue.
Note: One of the things that threw me for a long time was that I only needed to get the current position of the user. I didn't need to track the users' movements. I kept trying different iterations of this with the getCurrentPosition() method. For whatever reason, it doesn't work. So, this is the solution I came up with. Run it like you're going to track the users location (to get their location in the first place), then once you've gotten their location, clear the watchPosition ID to prevent it from tracking them. If you need to track their location as it changes over time, you can of course... not clear the watchPosition ID.
HTH. From everything I've been reading, there are a lot of developers who need this functionality to work for their mission-critical apps. If this solution doesn't work for you, I'm not sure what other direction I can give. Having said that, I've tested this several hundred times and this successfully retrieves the users' location in a WebApp (navigator.standalone) on iOS 6.
You must take care of non secure content loaded. For me loading all javascript, images and css from secure context solved the problem with safari.
I can confirm I get the same problem when running my web app in fullscreen.
Interestingly, when Safari in Fullscreen asked permission to use my location, the website title was 'web' rather than the title of the website, as in previous versions of iOS.
Removing the "apple-mobile-web-app-capable" meta tag is fine, and it works, but only if you "Add to Homescreen" again. We have ~7000 daily users who have already added our icon to their homescreen. Getting them to do so again, then potentially again when a fix is implimented isn't great.
seems to be fixed in iOS 6.1, finally! See my site www.slople.com where it works again under 6.1