When hiring Engineers, I always look for evidence of pet projects, so recently I thought it was fair to create one of my own: GeoMeme, the fun way to measure and share real-time local twitter trends.
Visitors to GeoMeme choose a location on the map, and two search terms to compare. GeoMeme then measures and compares the number of matching tweets within the bounds of the map, based on public data from a number of mobile twitter apps.
As an example, GeoMeme can work out that ‘love’ beats ‘hate’ in Manhattan:
GeoMeme is a desktop web application and also a location-aware mobile web app for iPhone and Android phones.
Implementing the mobile version of GeoMeme as a web app has some advantages and disadvantages, compared to building native iPhone &/or Android applications.
Native apps are great because they currently offer the deepest integration to the full capability of the phone, for example using device APIs to access Contacts, the Camera Roll, an Accelerometer, or the GPS chip. For some applications, this deep device integration is essential and so a native application is beneficial.
On the other hand, emerging HTML5-based mobile browsers are aiming to standardise integration to such device APIs, starting with Geolocation APIs; meaning that location-aware mobile web apps are now becoming viable. Aligned with this development is the new version of the Google Maps API. v3 has been greatly simplified since v2, and is now optimized for use on mobile phones. Less is more.
The deciding factor for me choosing to build a mobile web app for GeoMeme rather than a native app was development speed. A mobile web app enjoys far greater code re-use from the desktop web version, and it is possible to push regular updates and improvements to users, without having to wait for appstore approval or for users to upgrade.
I believe this need for development speed is common among a good proportion of mobile apps that are still in ‘rapid iteration’ or ‘release early, release often’ mode, so this post is intended to share some of the techniques used in GeoMeme with developers wanting to build their own location-aware mobile web apps.
Let’s build an example location-aware mobile web app called ‘Here I Am!’, for the photographically challenged. The app will present some local photographs (from Panoramio) which can be shared with friends on Twitter or Facebook.
Where on earth is that mobile phone..?
The first job of a location-aware mobile app is to work out where on earth the mobile phone currently is. Unfortunately, at the time of writing, there is still no universally reliable and accurate solution for a mobile web app to detect the location of the mobile phone it is running on. However the following partial solutions can be combined to good effect:
a) Google Loader
Load the Google Maps v3 API using Google Loader:
<script type="text/javascript" src="http://www.google.com/jsapi?key=YOUR_API_KEY&autoload=%7Bmodules%3A%5B%7Bname%3A%22maps%22%2Cversion%3A3%2Cother_params%3A%22sensor%3Dtrue%22%7D%5D%7D"></script>
<script type="text/javascript">
google.setOnLoadCallback(function() {
// initialize the mobile map...
});
</script>
Google Loader requires developers to sign up for an API key, however the advantage of this approach is that the approximate location of the user is revealed, based on network IP address.
In the case of a mobile phone user, this network IP address often refers to the mobile operator’s internet gateway, which can be shared between a large number of subscribers spread over an entire country. This technique becomes more accurate for mobile phones which are connected to the internet via wi-fi rather than GPRS, or becomes less accurate for some phones (e.g. Blackberry) which can connect to the internet via international proxy servers.
Generally, this technique can be successful in working out which country the user is in, but cannot be assumed to be any more accurate than that.
Some example javascript to locate a map based on Google Loader:
if (typeof(google.loader.ClientLocation) != 'undefined') {
var lat = google.loader.ClientLocation.latitude;
var lng = google.loader.ClientLocation.longitude;
var position = new google.maps.LatLng(lat, lng);
map.setOptions({
center: position,
zoom: 10
});
}
b) W3C Geolocation API
The World Wide Web Consortium (W3C) has been working since 2008 to standardise web geolocation APIs.
Mobile Safari on iPhone (since OS3.0) already supports the emerging W3C standard, to expose location information derived from its GPS chip. The new Chrome mobile browser on Android (from 2.0 Eclair) will also support this standard. For example:
if (typeof(navigator.geolocation) != 'undefined') {
navigator.geolocation.getCurrentPosition(function(position) {
var lat = position.coords.latitude;
var lng = position.coords.longitude;
var position = new google.maps.LatLng(lat, lng);
map.setOptions({
center: position,
zoom: 15
});
});
}
The W3C Geolocation API looks likely to feature as part of HTML5 (the next major revision of HTML), and will also be supported by the next generation of Webkit-based mobile browsers, so expect this technique to start working on an increasing proportion of new mobile phones.
c) Google Gears for Mobile
Gears adds a number of HTML5 features, including a Geolocation API, to legacy web browsers. Although it is possible for Windows IE Mobile and Mobile Opera browsers to become location-aware in this way, the bigger opportunity here is that Android phones (from version 1.0 through 1.6) come with Gears already pre-installed. This means that we can detect the location of these Android phones with the following javascript:
if (typeof(google.gears) != 'undefined') {
var geo = google.gears.factory.create('beta.geolocation');
geo.getCurrentPosition(function(position) {
var lat = position.latitude;
var lng = position.longitude;
var position = new google.maps.LatLng(lat, lng);
map.setOptions({
center: position,
zoom: 15
});
});
}
Google Gears for Mobile works out the location of a mobile phone from the GPS chip in the phone, or by crowdsourcing the location of the cell-tower to which the mobile phone is connected.
… and fetch me some location-based content, fast!
Once your mobile web app is location-aware, the next thing to do is to retrieve some relevant content, based on current location. GeoMeme retrieves local tweets using the Twitter API, but for ‘Here I Am!’ we’ll retrieve local photos from Panoramio (see http://www.panoramio.com/api/ for details of the API).
Google Maps v3 API includes a convenient new ‘idle’ event which is fired when the map becomes idle after panning or zooming, or after automatic geo-location using the techniques above. By listening for this event, we can fetch the most popular local photos from Panoramio whenever the map is moved. For example:
google.maps.event.addListener(map, 'idle', function() {
loadPhotos();
});
function loadPhotos() {
var url = 'http://www.panoramio.com/map/get_panoramas.php?order=popularity&set=public&from=0&to=20&size=mini_square&callback=addPhotos';
var bounds = map.getBounds();
url += '&minx=' + bounds.getSouthWest().lng().toFixed(6) + '&miny=' + bounds.getSouthWest().lat().toFixed(6);
url += '&maxx=' + bounds.getNorthEast().lng().toFixed(6) + '&maxy=' + bounds.getNorthEast().lat().toFixed(6);
url += '&ts=' + new Date().getTime(); // prevent caching
// use JSONP to retrieve photo data
// and trigger a callback to addPhotos()
var script = document.createElement("script");
script.setAttribute("src", url);
script.setAttribute("type", "text/javascript");
document.body.appendChild(script);
}
The above code sends the resulting JSON data to the addPhotos() callback function, which handles the display of the photos on the map using Icons, another new feature of Google Maps v3 API.
For speed, we also implement a performance optimization here. Existing Icons are re-used, rather than simply removing and adding new Icons each time the map is relocated:
var markers = {};
function addPhotos(data) {
var new_markers = {};
for (var i = 0; i &lt; data.photos.length; i++) {
var photo = data.photos[i];
// for speed and to reduce flicker,
// reuse existing markers rather than removing and re-adding
if (photo.photo_id in markers) {
new_markers[photo.photo_id] = markers[photo.photo_id];
} else {
// create new marker
marker = new google.maps.Marker({
position: new google.maps.LatLng(photo.latitude, photo.longitude),
icon: photo.photo_file_url,
map: map
});
new_markers[photo.photo_id] = marker;
}
}
// remove old markers
for (var photo_id in markers) {
if (!(photo_id in new_markers)) {
markers[photo_id].setMap(null);
delete markers[photo_id];
}
}
markers = new_markers;
}
‘Here I Am!’ – a simple location-aware mobile web application
The final part of ‘Here I Am!’ is a feature to share one of the Panoramio photos to friends on Twitter or Facebook. This is done using ordinary web links to Twitter and Facebook share pages. No complex platform integration is required for web apps to do this because, as they say, “the web is the platform.” Simply click on a photo on the map and follow the prompts.
Visit http://j.mp/lbsdemo on your mobile phone to try out ‘Here I Am!’
The full source code of ‘Here I Am!’ (weighing in at just under 8Kb) can be located here.
The app has been tested to work on iPhone, iPod Touch, Android, and Symbian Series 60 (which remains – for now at least – the dominant device family for mobile data consumption).
I hope you enjoy using some of these ideas in your own location-aware mobile web apps.
This post is one of a series that aims to share some of the technology innovation that can be found in GeoMeme. Other posts cover topics such as using Google App Engine for scalable and fast hosting of your location-based content, and fast map re-location using Google Static Maps v2.

LinkedIn
Looks good with usual comment here that it's vendordependent. I use http://code.google.com/p/geomodel/ working on relaxing vendordepedence to mentioned here, w3c and other more technical than commercial specs.
regards
Looks good with usual comment here that it's vendordependent. I use http://code.google.com/p/geomodel/ working on relaxing vendordepedence to mentioned here, w3c and other more technical than commercial specs.
regards
Pingback: Techno Info » Blog Archive » See Twitter Trends Around Your Neighborhood with GeoMeme
Hi Bob,
Thank you for making the source code available. I have been playing with it and trying to make a Chrome extension. It works in Chrome and gets my google.loader.ClientLocation.latitude and longitude values. However, in the extension, it gets your default values which is returned by Google (google.loader.ClientLocation = {“latitude”:43.023,”longitude”:-81.202,”address”:{“city”:”London”,”region”:”ON”,”country”:”Canada”,”country_code”:”CA”}};).—Even though I change the locateMap() center value to “new google.maps.LatLng(37.642253,-77.57018)”.
I am not sure whether I am doing something wrong or maps api does not work correctly with chrome extensions.
Pingback: Fast map re-location using Google Static Maps v2 + geocoder | mobile geo social
Pingback: GeoMeme adds Google Buzz to detect real-time geo-located trends | mobile geo social
Pingback: Webmaster
How to recycle mobile phones for starters. Mobile phone recycling has become hugely popular now and there is a massive market for recycling mobile phones and other types of electrical gadgets online.