Mobile GPS Navigation App with JSF

I’ve created various sample mobile apps before such as Translator, Weather, News, Notes, Twitter Client and Mobile Chat (powered by PrimeFaces/Atmosphere Push infastructre) etc. Since these are webapps tuned for mobile app look and feel, I was wondering the limits of a mobile webapp compared to a native app. Geolocation and GPS support might sound like one of these limitations but well, it is not🙂 As a proof of concept for a PrimeFaces/TouchFaces app I’ve created the PathFinder, A mobile GPS Navigation app for iphone.

To begin with here’s the final output; There’re two screens, one is for map with directions and other is for settings. Click images for higher resolution.

pf1 pf1 pf1

See it in action

I’ve recorded a short screencast as well running the PathFinder on iPhone Emulator.

All of this is basically a simple JSF page; pathfinder.jsf

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<f:view xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:p="http://primefaces.prime.com.tr/ui"
	xmlns:i="http://primefaces.prime.com.tr/touch"
	contentType="text/html">

	<i:application icon="/images/touch/mapicon.png">
		<f:facet name="meta">
			<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=true&amp;key=ABQIAAAAfC5eyG3CuuRKtsMbGj42fhThrJrTqAJnkzhJQxjbFhIXTdSD6xRglAovT0AWB71tfpSZxEd9pJoxwQ" type="text/javascript"></script>
			<script type="text/javascript">

				PathFinder = {

						init : function() {
							map = new GMap2(document.getElementById("map"));
							map.setUIToDefault();

				        	navigator.geolocation.getCurrentPosition(
						        function(position) {
							        lat = position.coords.latitude;
							        lng = position.coords.longitude;
							        var center = new GLatLng(position.coords.latitude, position.coords.longitude);
							        map.setCenter(center, 15);
							        map.addOverlay(new GMarker(center));
							        geocoder = new GClientGeocoder();
							        directions = new GDirections(map, document.getElementById('route'));
						        });
						},

						findAndGo : function() {
							var address = document.getElementById('address').value;
							geocoder.getLatLng(address,function(point) {
								 if (!point) {
						              alert(address + " not found");
						          } else {
						              directions.load("from " + lat + " " + lng + " to " + point.lat() + " " + point.lng());
						           }
							});
						}
					};

				if(!navigator.geolocation) {
					alert('Error: PathFinder requires a GPS capable device.');
				} else {
					window.onload = PathFinder.init;
				}

			</script>
			<meta content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" name="cube"/>
		</f:facet>

		<i:view id="home" title="PathFinder">
			<f:facet name="rightNavBar">
				<i:navBarControl label="Settings" view="settings" type="button" effect="cube"/>
			</f:facet>

			<h:form prependId="false">
				<i:tableView>
					<i:rowGroup display="edgetoedge">
						<div id="map" style="width:100%;height:285px;"></div>
					</i:rowGroup>

					<i:rowGroup>
						<i:rowItem>
							<h:inputText id="address"/>
						</i:rowItem>
					</i:rowGroup>

					<p:commandLink style="margin:10px 10px;" styleClass="whiteButton" value="#" onclick="PathFinder.findAndGo();return false;">Find and Go!</p:commandLink>

					<i:rowGroup>
							<i:rowItem>
								<div id="route"></div>
							</i:rowItem>
					</i:rowGroup>
				</i:tableView>
			</h:form>

		</i:view>

		<i:view id="settings" title="Settings">
			<f:facet name="leftNavBar">
				<i:navBarControl label="Home" view="home" />
			</f:facet>

			<h:form prependId="false">
				<i:tableView>

					<i:rowGroup>
						<i:rowItem>
							<h:outputText value="Transport" />
							<h:selectOneMenu>
								<f:selectItem itemLabel="Driving" itemValue="d" />
								<f:selectItem itemLabel="Walking" itemValue="w" />
							</h:selectOneMenu>
						</i:rowItem>

						<i:rowItem>
							<h:outputText value="Traffic" />
							<i:switch id="traffic"/>
						</i:rowItem>
					</i:rowGroup>

				</i:tableView>

				<p:commandLink style="margin:0 10px;" styleClass="whiteButton" value="#" onclick="TouchFaces.goBack();">Save</p:commandLink>

			</h:form>

		</i:view>

	</i:application>

</f:view>

That’s just it, now you have a GPS enabled navigation app with a couple of lines. Let’s breakdown the important points to see how it works;

* GEOLocation info is provided by mobile safari, navigation geolocation api is an HTML5 feature supported by major browsers like Safari and Firefox (no IE of course). When you run the application, safari asks for a confirmation since the app tries to access hardware information and on page load places a markers on map with the geo location info.

* Once we have the location, it’s trivial to place a map and do some gmap api coding. ‘Find and Go’ button simply does a geocoding and retrieves the latitude and longitude, with that it asks gmap api for directions and updates the map. Update happens in 5 seconds with the updated geo location info.

* A settings view is also added, I left out the implementation of settings UI but it helps to demonstrate how easy it can be to create another UI for customizations.

Summary

PathFinder is a simple reference app, things can be done with PrimeFaces is limitless. For example, since PrimeFaces also supports Ajax Push, it would be so easy to create location based mobile Comet applications as well.

Finally one thing I’d like to emphasize again, what PrimeFaces has so far (70+ Ajax Components, Ajax Push/Comet, Lightweight design, TouchFaces, GPS enabled apps, …) is just the beginning.

One Response to Mobile GPS Navigation App with JSF

  1. Benoît CORNILLIAT says:

    Hi,
    thanks for this valuable presentation. I have 2 questions :

    1 – on 3GS iPhone, is there a way to access compass/magnetometer as done for GPS location ?

    2 – is the HTML 5 geolocation API supported on other smartphones (Androïd, Nokia, BBerry, …) ?

%d bloggers like this: