Accessing the GPS in iPhone Safari

Finally with the release of the 3.0 firmware update to the iPhone we now have access to the GPS coordinates in Safari. Using the W3C Geolocation API we can access the users position much the same way a native app would. The user can either allow or disallow the current websites’ access to your location.

This demo will need the iPhone 3G with the 3.0 firmware update or Firefox 3.5 in order to work. The iPhone will give the better results as it has access to the GPS where as Firefox depends on the hardware available.

Some hurdles

You may have noticed that I’m not using Google or Yahoo Maps APIs to plot my location, this is due to both having restrictions on using it in conjunction with real time locations. In Google Maps Terms of Use.

use the Service or Content with any products, systems, or applications for or in connection with (i) real time navigation or route guidance, including but not limited to turn-by-turn route guidance that is synchronized to the position of a user’s sensor-enabled device; or (ii) any systems or functions for automatic or autonomous control of vehicle behaviour.

Yahoo’s terms are a bit different they still restrict use of real time location abilities to be no younger than 6 hours, essentially making the safari’s location awareness a no go zone for these 2 services.

…use the Yahoo! Maps APIs with location information that is less than 6 hours old and derived from a GPS device or any other location sensing device;

CloudMade to the rescue

Thanks to CloudMade who is putting a rock solid set of tools and API’s in various languages so we can access the OpenStreetMap map data. Only difference is that these maps are created by the community and are licensed under the Creative Commons Attribution/ShareAlike licence, version 2 which means there are no such restrictions that we would of had with Google or Yahoo maps. I highly recommend you read where they are heading in terms of their licensing and help in giving back to their community by creating maps.

How it works

Now we have a maps API where we won’t be abusing the terms of use by using it in conjunction with real time locations. We’ll get stuck into how to use the W3C Geolocation API.

Request the users location

navigator.geolocation.getCurrentPosition(success, fail);

The above line will try to obtain the users current location using the getCurrentPosition method this can be passed up to 3 arguments; the success callback function, the error callback function and the position options: enableHighAccurracy, timeout & maximumAge.

Upon successfully obtaining the users location the success function will get passed the position object which will contain the coords and timestamp attributes. The coords attribute is the one we need to extract information about the user location and has the following properties available:

  • latitude
  • longitude
  • altitude
  • accuracy
  • altitudeAccuracy
  • heading
  • speed
navigator.geolocation.getCurrentPosition(success, fail);
// success callback, gets passed position object
success(position) // 'position' can be named anything
	alert("Your latitude: " + position.coords.latitude + "longitude: "
 		+ position.coords.longitude);

Not all of the geolocation information in the coords attribute is available to the iPhone, heading and speed currently return null but I suspect that both will be functional in the iPhone 3G S thanks to the compass and coreLocation updates. Both these attributes still return null on the iPhone 3GS which is surprising. Speed can alternatively be calculated by using the Haversine formula to obtain the distance travelled between two points which can then be used to compare time and distance to make a pretty accurate speed approximation.

The options available as the 3rd argument that can be passed to the getCurrentPosition method are:

  • enableHighAccuracy
  • timeout
  • maximumAge

These options can help in forcing the error callback and having a fallback option if the request cannot be obtained before the timeout ends or the location wasn’t obtained within the maximumAge set. enableHighAccuracy will force the GPS to get the most accurate results possible this will take longer and chew through the battery.

navigator.geolocation.getCurrentPosition(success, fail,{maximumAge: 300000, timeout:0});

Both maximumAge and timeout are expressed in milliseconds. This is basically saying get the last known location that is no older than 5 minutes, if no position is found timeout immediately and fire the error callback function.

Updating location

Getting the users initial location is great and all but what we really need is a way to get constant updates of any changes in the users’ location. Thankfully the geolocation API also has the watchPosition method which will fire upon a change in the users’ location.

var updateLocation = navigator.geolocation.watchPosition(success, fail);

This, like the getCurrentPosition method, takes the same arguments the only difference above is that I have stored the watchPosition method in a variable, this is so we can cancel it at anytime if we no longer need to watch for any changes in position.


This will cancel the watchPosition and stop it from firing the success or error callback. It works in much the same way the clearTimeout method works for the setTimeout method.

Handling errors

If something goes wrong with obtaining the users location e.g. the user decides not to share their location to your web app. We have the error callback so we can handle the situations that might occur and present useful actions or information back to the user.

The PositionError interface has 4 possible scenarios:

  • UNKNOWN_ERROR (code 0)
  • TIMEOUT (code 3)

We have 2 attributes on the error callback available which are code & message these will return either the code number 0-3 or the message.

navigator.geolocation.getCurrentPosition(success, fail);
// fail callback, gets passed error object
fail(error) // 'error' can be named anything
	switch(error.code) // Returns 0-3
		case 0:
			// Unknown error alert error message

		case 1:
			// Permission denied alert error message
		... etc

Just the beginning

The iPhone 3.0 release isn’t the only browser to support Geolocation API, currently Firefox 3.5, Opera 10 beta and Opera Mobile 9.7 beta though this is speculation. I’m sure the other browser vendors will follow in their new releases.