Skip navigation

geolocation doesn't work with iOS 6 web apps!

14648 Views 69 Replies Latest reply: Mar 10, 2014 11:49 PM by gt21 RSS Branched to a new discussion.
  • Thomas Quartus Level 1 Level 1 (0 points)
    Currently Being Moderated
    Dec 22, 2012 12:01 AM (in response to MikeAtNextBus)

    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); 
    
  • Thomas Quartus Level 1 Level 1 (0 points)
    Currently Being Moderated
    Dec 22, 2012 8:33 PM (in response to Thomas Quartus)

    Update: The above "workaround" requires removing

      <meta name="apple-mobile-web-app-capable" content="yes" /> or changing this setting to "no". Otherwise subsequent calls to navigator.geolocation.getCurrentPosition never invoke the callback.

     

    It also requires calculating speed directly from observations.

     

    Agree with all that this is a huge, awful, major bug. And another reminder that poor Apple just can't seem to get geolocation right these days. (In working on this, I keep linking to Apple maps and can't help but notice that somehow they have got the cul-de-sac running right through our neighbor's house...) (Sigh.)

  • Allartk Level 1 Level 1 (0 points)
    Currently Being Moderated
    Dec 28, 2012 1:49 PM (in response to MikeAtNextBus)

    I still hope apple will fix this, otherwise we are forced to consider Ios products not supported..

     

    It shouldn't matter, but we have 100 000 - 500 000 page views a day.

  • Tools Dept. Level 1 Level 1 (0 points)
    Currently Being Moderated
    Jan 18, 2013 5:12 PM (in response to MikeAtNextBus)

    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, here's a link to the solution. http://stackoverflow.com/a/14410106/818266

  • aesculus Level 1 Level 1 (0 points)
    Currently Being Moderated
    Jan 18, 2013 7:56 PM (in response to Tools Dept.)

    Well the fix did not work for me.  Maybe I did not follow the instructions completely but I think I did and I did the initialization in the windows.load event so it was early (but maybe not early enough?).

     

    One thing I noticed independantly of your code that I never really noticed before. After you call the watchPosition then the clearWatch does not seem to work.  I run the clearWatch periodically when I leave my maps pages and on a non home screen version the navigation icon on the top of the phone disappears.  On a home screen app (same app just bookmarked to the home screen) it never goes away. And yes I did validate that it was being called with an alert just before the statement and making sure the watchID was initialized too.

     

    So there is still some pretty broken stuff in iOS 6.

  • siasd Level 1 Level 1 (0 points)
    Currently Being Moderated
    Jan 28, 2013 1:09 PM (in response to MikeAtNextBus)

    Tested 6.1 and it seems that this problem has been fix in this release

  • XCTrails Level 1 Level 1 (0 points)

    Hmm, this is strange. 6.1 doesn't make any difference for me, at least not with my yet unmodified watchposition code which used to work on iOS 5.

     

    @siasd: are you implying that watchPosition works properly for you in 6.1 ?

  • mark00153 Level 1 Level 1 (0 points)
    Currently Being Moderated
    Feb 5, 2013 1:50 PM (in response to XCTrails)

    the issue remains in IOS6.1

  • aesculus Level 1 Level 1 (0 points)
    Currently Being Moderated
    Feb 5, 2013 5:49 PM (in response to mark00153)

    Its working fine for me. My app is back to iOS 5 days.

  • XCTrails Level 1 Level 1 (0 points)
    Currently Being Moderated
    Feb 5, 2013 10:51 PM (in response to aesculus)

    This is encouraging ... Are you using watchPosition or getPosition ? Are you willing to share the respective code fragment ?

  • renevoorburg Level 1 Level 1 (0 points)
    Currently Being Moderated
    Feb 5, 2013 11:35 PM (in response to XCTrails)

    watchPosition now works in iOS 6.1 as it did in iOS5

     

    See for example http://vici.org/mobile.php

  • XCTrails Level 1 Level 1 (0 points)
    Currently Being Moderated
    Feb 6, 2013 2:57 AM (in response to renevoorburg)

    I tested your map and it only updates for a while. In your case, I think as soon as watchPosition has reached its timeout, then it throws a timeout error and stops. My understanding so far was that one has to explicitly call clearWatch to stop watchPosition from firing events. (in my app, I do this whenever I call watchPosition again).

     

    I've experimented a bit with my code and tried to call watchPosition again as soon as the timeout happens, but this doesn't work reliably. Subsequent calls to watchPosition in a loaded page sometimes get valid positions, sometimes not (i.e. the accuracy is way off). At that point, I can only reset by killing Safari and loading the page again, just re-loading the page doesn't help.

     

    Quite frustrating considering that this worked reliable on iOS5

  • XCTrails Level 1 Level 1 (0 points)
    Currently Being Moderated
    Feb 6, 2013 6:26 AM (in response to XCTrails)

    Ok, I now tried the approach with the timer controlled getCurrentPosition instead of watchPosition, same effect. Works for the first time, on subsequent calls (i.e. to refresh a changed position) it delivers results with a bad accuracy.

     

    There is something else I observed, though: If I task switch to the builtin maps app in that situation, maps freezes for some seconds, then has a proper position. Switching back to the webapp, I can now retrieve a valid position again.

     

    If I run an app like MotionX-GPS in the background and set it to not turn of the GPS at all when backgrounded, all is fine, I can update the position in the webapp as often as I want.

     

    So it seems to me as if the JS calls somehow leave the GPS in a strange state or fail to "wake it up" - apparently native apps or a browser restart reinitialize it but repeated calls via the navigator.geolocation interface don't.

     

    So as far as I'm concerned this interface is still broken unless you only call it once (or maybe a couple of times, eventually it will fail).

     

    Message was edited by: XCTrails

  • aesculus Level 1 Level 1 (0 points)
    Currently Being Moderated
    Feb 6, 2013 7:10 PM (in response to XCTrails)

    I am using a modifed version that was described by

     

    http://stackoverflow.com/a/14410106/818266

     

    I did not try the version I had using the older pre iOS 6 code. Note this did not work for me before iOS 6.1.

     

    I took the device out today for a test and at first every few minutes it did bounce around the true location by about 1/8 of a mile but then it seemed to settle down.  I think it did this before iOS 6.

Actions

More Like This

  • Retrieving data ...

Bookmarked By (5)

Legend

  • This solved my question - 10 points
  • This helped me - 5 points
This site contains user submitted content, comments and opinions and is for informational purposes only. Apple disclaims any and all liability for the acts, omissions and conduct of any third parties in connection with or related to your use of the site. All postings and use of the content on this site are subject to the Apple Support Communities Terms of Use.