HTML5 Inside - Geolocation

August 14, 2010

In this series I am going to write about the new whizz bang things which fall under the HTML5 umbrella. I am going to attempt to find out whether it is ‘hype or hardcore’.

Geolocation

Geolocation is the art of finding out where a user is. This can be as rough as country, or as fine grained as an exact latitude / longitude coordinate set.

Traditionally geolocation in the browser consisted of querying the user’s IP again a database. Usually this allowed you to find out what city a user was in. Nowadays, there is a geolocation API which is targetted specifically toward Mobile devices.

The W3C has an api for geolocation which is in draft stage at the time of writing.

odern versions of Firefox, Chrome, Safari and Opera offer geolocation support. As far as I am aware all of these browsers actually implement the geolocation by querying a service provided by google. The google gears (deprecated) geolocation api has been natively implemented by the major browsers.

How does the actual geolocation work?

Note: The API Described is the old gears API but as HTML Geolocation currently uses this it should be seen to be relatively similar.

An HTTP POST is made containing JSON data which looks like the following.

{
    "version": "1.1.0",
    "host": "maps.google.com",
    "home_mobile_country_code": 310,
    "home_mobile_network_code": 410,
    "radio_type": "gsm",
    "carrier": "Vodafone",
    "request_address": true,
    "address_language": "en_GB",
    "location": {
      "latitude": 51.0,
      "longitude": -0.1
    },
    "cell_towers": [
      {
        "cell_id": "42",
        "location_area_code": 415,
        "mobile_country_code": 310,
        "mobile_network_code": 410,
        "age": 0,
        "signal_strength": -60,
        "timing_advance": 5555
      },
      {
        "cell_id": "88",
        "location_area_code": 415,
        "mobile_country_code": 310,
        "mobile_network_code": 580,
        "age": 0,
        "signal_strength": -70,
        "timing_advance": 7777
      }
    ],
    "wifi_towers": [
      {
        "mac_address": "01-23-45-67-89-ab",
        "signal_strength": 8,
        "age": 0
      },
      {
        "mac_address": "01-23-45-67-89-ac",
        "signal_strength": 4,
        "age": 0
      }
    ]
  }

It has been designed to work with both mobile and wifi_enabled devices. The browser implementations map to native APIs on the device. So either a simple Lat/Lng is submitted potentially obtained from GPS (easy for google) or wifi_tower mac_addresses, or cell_tower information. Google can use this information to try to geocode a location.

The response is also in JSON. We love JSON here at simplyexcited, XML is dirty.

{
    "location": {
      "latitude": 51.0,
      "longitude": -0.1,
      "altitude": 30.1,
      "accuracy": 1200.1,
      "altitude_accuracy": 10.1,
      "address": {
        "street_number": "100",
        "street": "Amphibian Walkway",
        "postal_code": "94043",
        "city": "Mountain View",
        "county": "Mountain View County",
        "region": "California",
        "country": "United States of America",
        "country_code": "US"
      }
    }
  }

The old json api is readable on this wiki page

Why this is good.

The geolocation api allows you to build location aware web applications which have access to native location apis. Bringing native hardware to web applications makes the future bright and takes us to a more webby non-native future.

How do I use it then?

Google maps V3 API has a great example of geocoding to put your location on a map.

<!DOCTYPE html SYSTEM>
  <html>
  <head>
  <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  <title>Google Maps JavaScript API v3 Example: Map Geolocation</title>
  <link href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css" rel="stylesheet" type="text/css" />
  <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
  <script type="text/javascript" src="http://code.google.com/apis/gears/gears_init.js"></script>
  <script type="text/javascript">

  var initialLocation;
  var siberia = new google.maps.LatLng(60, 105);
  var newyork = new google.maps.LatLng(40.69847032728747, -73.9514422416687);
  var browserSupportFlag =  new Boolean();
  var map;
  var infowindow = new google.maps.InfoWindow();

  function initialize() {
    var myOptions = {
      zoom: 6,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

    // Try W3C Geolocation method (Preferred)
    if(navigator.geolocation) {
      browserSupportFlag = true;
      navigator.geolocation.getCurrentPosition(function(position) {
        initialLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
        contentString = "Location found using W3C standard";
        map.setCenter(initialLocation);
        infowindow.setContent(contentString);
        infowindow.setPosition(initialLocation);
        infowindow.open(map);
      }, function() {
        handleNoGeolocation(browserSupportFlag);
      });
    } else if (google.gears) {
      // Try Google Gears Geolocation
      browserSupportFlag = true;
      var geo = google.gears.factory.create('beta.geolocation');
      geo.getCurrentPosition(function(position) {
        initialLocation = new google.maps.LatLng(position.latitude,position.longitude);
        contentString = "Location found using Google Gears";
        map.setCenter(initialLocation);
        infowindow.setContent(contentString);
        infowindow.setPosition(initialLocation);
        infowindow.open(map);
      }, function() {
        handleNoGeolocation(browserSupportFlag);
      });
    } else {
      // Browser doesn't support Geolocation
      browserSupportFlag = false;
      handleNoGeolocation(browserSupportFlag);
    }
  }

  function handleNoGeolocation(errorFlag) {
    if (errorFlag == true) {
      initialLocation = newyork;
      contentString = "Error: The Geolocation service failed.";
    } else {
      initialLocation = siberia;
      contentString = "Error: Your browser doesn't support geolocation. Are you in Siberia?";
    }
    map.setCenter(initialLocation);
    infowindow.setContent(contentString);
    infowindow.setPosition(initialLocation);
    infowindow.open(map);
  }
  </script>
  </head>
  <body onload="initialize()">
    <div id="map_canvas"></div>

  </body>
  </html>

View the working example

Simplest working example

Stick this in your firebug console and run it.

if(navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
      alert("Your lat/lng pair is" + position.coords.latitude + ", " + position.coords.longitude);
    });
  } else {
    alert("Your browser does not support W3C geolocation.");
  }

Conclusion

So.. Geolocation. Hype or Hardcore? I think hardcore.